import { j as jsxRuntimeExports, A as ActionButtonGroup, o as ActionButton, M as MathJax, e as Context } from "./doenetml-cB_aZGJ5.js";
import React__default, { useState, useRef, useEffect } from "react";
import { u as useDoenetRenderer } from "./useDoenetRenderer-DN3Z9CW3.js";
import { s as sizeToCSS } from "./css-BJLDLYRJ.js";
let round_to_decimals = (x, n) => {
  try {
    return Context.round_numbers_to_decimals(x, n).tree;
  } catch (_e) {
    return NaN;
  }
};
function generateNumericLabels(points, inputWidth, SVs) {
  let maxValueWidth;
  let maxAbs = Math.max(Math.abs(SVs.firstItem), Math.abs(SVs.lastItem));
  let magnitudeOfMaxAbs = Math.round(Math.log(maxAbs) / Math.log(10));
  if (maxAbs === 0) {
    magnitudeOfMaxAbs = 1;
  }
  let roundDecimals = 5 - magnitudeOfMaxAbs;
  if (points.length === 0) {
    let pointsToTest = [
      round_to_decimals(SVs.firstItem, roundDecimals),
      round_to_decimals(SVs.lastItem, roundDecimals)
    ];
    let numToTest = Math.min(SVs.numItems, 100);
    let dInd = Math.floor(SVs.numItems / numToTest);
    for (let i = 1; i < numToTest; i++) {
      pointsToTest.push(
        round_to_decimals(
          SVs.from + SVs.step * i * dInd,
          roundDecimals
        )
      );
    }
    maxValueWidth = findMaxValueWidth(pointsToTest, SVs);
  } else {
    let pointsToTest = points.map(
      (x) => round_to_decimals(x, roundDecimals)
    );
    maxValueWidth = findMaxValueWidth(pointsToTest, SVs);
  }
  const numItems = SVs.numItems;
  if (inputWidth >= maxValueWidth * numItems) {
    if (points.length === 0) {
      let labels = [];
      let maxAbs2 = Math.max(
        Math.abs(SVs.firstItem),
        Math.abs(SVs.lastItem)
      );
      let magnitudeOfMaxAbs2 = Math.round(Math.log(maxAbs2) / Math.log(10));
      if (maxAbs2 === 0) {
        magnitudeOfMaxAbs2 = 1;
      }
      let roundDecimals2 = 5 - magnitudeOfMaxAbs2;
      for (let index = 0; index < SVs.numItems; index++) {
        let point = round_to_decimals(
          SVs.from + SVs.step * index,
          roundDecimals2
        );
        labels.push({ value: index, label: point.toString() });
      }
      return labels;
    } else {
      return points.map((point, index) => ({
        value: index,
        label: point.toString()
      }));
    }
  } else if (inputWidth < maxValueWidth) {
    const leftPoint = points.length === 0 ? SVs.from : points[0];
    return [{ value: 0, label: leftPoint.toString() }];
  } else {
    if (points.length === 0) {
      let desiredNumberOfTicks = Math.floor(inputWidth / maxValueWidth);
      let tickSpan = SVs.lastItem - SVs.firstItem;
      let desiredDTick = tickSpan / (desiredNumberOfTicks + 1);
      let maxAbs2 = Math.max(
        Math.abs(SVs.firstItem),
        Math.abs(SVs.lastItem)
      );
      let magnitudeOfMaxAbs2 = Math.round(Math.log(maxAbs2) / Math.log(10));
      let roundDecimalsForTickSpacing = 1 - magnitudeOfMaxAbs2;
      let dTick = Math.max(
        round_to_decimals(desiredDTick, roundDecimalsForTickSpacing),
        10 ** -roundDecimalsForTickSpacing
      );
      let numberOfTicks = Math.floor(tickSpan / dTick) + 1;
      let roundDecimals2 = 5 - magnitudeOfMaxAbs2;
      return [...Array(numberOfTicks).keys()].map((i) => SVs.from + dTick * i).map((x) => ({
        value: Math.round((x - SVs.from) / SVs.step),
        label: round_to_decimals(x, roundDecimals2).toString()
      }));
    } else {
      let desiredNumberOfTicks = Math.max(
        2,
        Math.floor(inputWidth / maxValueWidth)
      );
      let dIndex = Math.ceil(
        (SVs.numItems - 1) / (desiredNumberOfTicks - 1) - 1e-10
      );
      let numberOfTicks = Math.floor((SVs.numItems - 1) / dIndex + 1e-10) + 1;
      let maxAbs2 = Math.max(
        Math.abs(SVs.firstItem),
        Math.abs(SVs.lastItem)
      );
      let magnitudeOfMaxAbs2 = Math.round(Math.log(maxAbs2) / Math.log(10));
      let roundDecimals2 = Math.max(0, 2 - magnitudeOfMaxAbs2);
      return [...Array(numberOfTicks).keys()].map((i) => Math.round(dIndex * i)).map((x) => ({
        value: x,
        label: round_to_decimals(
          points[x],
          roundDecimals2
        ).toString()
      }));
    }
  }
}
function findMaxValueWidth(points, SVs) {
  if (SVs.rotateTickLabels) {
    return 20;
  }
  let currWidth = points.reduce(function(a, b) {
    return +a > b.toString().length ? +a : b.toString().length;
  }, 1);
  return +currWidth * 13;
}
function generateTextLabels(points, inputWidth, SVs) {
  let maxValueWidth = findMaxValueWidth(points, SVs);
  const length = Object.keys(points).length;
  if (inputWidth >= maxValueWidth * length) {
    return points.map((point, index) => ({ value: index, label: point }));
  } else if (inputWidth >= 13 * 3 * length) {
    return points.map((point, index) => {
      const label = length === index + 1 || point.length < 3 ? point : point.substr(0, 3) + "...";
      return { value: index, label };
    });
  } else {
    return [{ value: 0, label: points[0] }];
  }
}
const slider = React__default.memo(function Slider(props) {
  let { id, SVs, actions, callAction } = useDoenetRenderer(props);
  Slider.baseStateVariable = "index";
  const [index, setIndex] = useState(SVs.index);
  const width = sizeToCSS(SVs.width);
  const [transient, setTransient] = useState(false);
  const [inputWidth, setInputWidth] = useState(0);
  const inputRef = useRef(null);
  useEffect(() => {
    if (inputRef.current) {
      setInputWidth(inputRef.current.offsetWidth);
    }
    const handleResize = () => {
      if (inputRef.current) {
        setInputWidth(inputRef.current.offsetWidth);
      }
    };
    window.addEventListener("resize", handleResize);
    return () => {
      window.removeEventListener("resize", handleResize);
    };
  }, []);
  useEffect(() => {
    setIndex(SVs.index);
  }, [SVs.index]);
  const changeValue = React__default.useCallback((v, isTransient) => {
    const index2 = Number(v);
    if (!(SVs.type === "text")) {
      const value = SVs.items.length === 0 ? SVs.from + SVs.step * index2 : Number(SVs.items[index2]);
      setIndex(index2);
      callAction({
        action: actions.changeValue,
        args: {
          value,
          transient: isTransient,
          skippable: isTransient
        },
        baseVariableValue: index2
      });
    } else {
      setIndex(index2);
      callAction({
        action: actions.changeValue,
        args: {
          value: SVs.items[index2],
          transient: isTransient,
          skippable: isTransient
        },
        baseVariableValue: index2
      });
    }
  }, []);
  if (SVs.hidden) {
    return null;
  }
  let labels;
  if (SVs.type === "text") {
    labels = generateTextLabels(SVs.items, inputWidth, SVs);
  } else {
    labels = generateNumericLabels(SVs.items, inputWidth, SVs);
  }
  let dataList;
  if (SVs.showTicks === false) {
    dataList = null;
  } else {
    const lastTickValue = labels[labels.length - 1]?.value ?? 0;
    const dataRatio = lastTickValue / (SVs.numItems - 1);
    const dataWidth = inputWidth * dataRatio;
    const dataListStyle = {
      display: "flex",
      flexDirection: "row",
      justifyContent: "space-between",
      width: dataWidth
    };
    const dataOptionStyle = {
      padding: "0",
      width: "20px",
      textAlign: "center"
    };
    if (SVs.rotateTickLabels) {
      dataListStyle.flexDirection = "column";
      dataListStyle.writingMode = "vertical-lr";
      delete dataOptionStyle.textAlign;
      delete dataOptionStyle.width;
    }
    dataList = /* @__PURE__ */ jsxRuntimeExports.jsx("datalist", { id: id + "-datalist", style: dataListStyle, children: labels.map(({ value, label }) => /* @__PURE__ */ jsxRuntimeExports.jsx(
      "option",
      {
        value,
        label,
        style: dataOptionStyle,
        onClick: (e) => {
          changeValue(
            e.target.value,
            false
          );
        }
      },
      value
    )) });
  }
  let myLabel = null;
  if (SVs.label) {
    let label = SVs.label;
    if (SVs.labelHasLatex) {
      label = /* @__PURE__ */ jsxRuntimeExports.jsx(MathJax, { hideUntilTypeset: "first", inline: true, dynamic: true, children: label });
    }
    if (SVs.showValue) {
      myLabel = /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
        label,
        " = " + SVs.valueForDisplay
      ] });
    } else {
      myLabel = label;
    }
  } else if (!SVs.label && SVs.showValue) {
    myLabel = SVs.valueForDisplay;
  } else {
    myLabel = null;
  }
  if (myLabel != null) {
    myLabel = /* @__PURE__ */ jsxRuntimeExports.jsx("div", { id: `${id}-label`, children: /* @__PURE__ */ jsxRuntimeExports.jsx("label", { htmlFor: id, children: myLabel }) });
  }
  let controls = "";
  if (SVs.showControls) {
    controls = /* @__PURE__ */ jsxRuntimeExports.jsxs(
      ActionButtonGroup,
      {
        style: { marginBottom: "12px", marginTop: "5px" },
        children: [
          /* @__PURE__ */ jsxRuntimeExports.jsx(
            ActionButton,
            {
              value: "Prev",
              onClick: () => {
                if (inputRef.current) {
                  inputRef.current.stepDown();
                  changeValue(inputRef.current.value, false);
                }
              },
              id: `${id}-prevbutton`,
              disabled: SVs.disabled || index === 0
            }
          ),
          /* @__PURE__ */ jsxRuntimeExports.jsx(
            ActionButton,
            {
              value: "Next",
              onClick: () => {
                if (inputRef.current) {
                  inputRef.current.stepUp();
                  changeValue(inputRef.current.value, false);
                }
              },
              id: `${id}-nextbutton`,
              disabled: SVs.disabled || index === SVs.numItems - 1
            }
          )
        ]
      }
    );
  }
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
    myLabel,
    /* @__PURE__ */ jsxRuntimeExports.jsx(
      "input",
      {
        ref: inputRef,
        id,
        type: "range",
        style: { width, margin: 0, maxWidth: "100%" },
        value: index,
        list: id + "-datalist",
        min: 0,
        max: SVs.numItems - 1,
        onInput: (e) => changeValue(e.target.value, transient),
        onMouseDown: () => setTransient(true),
        onMouseUp: (e) => {
          setTransient(false);
          changeValue(e.target.value, false);
        },
        disabled: SVs.disabled
      }
    ),
    dataList,
    controls
  ] });
});
export {
  slider as default
};
