"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const jsxRuntime = require("react/jsx-runtime");
const React = require("react");
const clsx = require("clsx");
const reactNumberFormat_es = require("../../../../../../../react-number-format@5.4.2_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/react-number-format/dist/react-number-format.es.cjs");
const noop = require("../../core/utils/noop/noop.cjs");
const getSize = require("../../core/utils/get-size/get-size.cjs");
const createVarsResolver = require("../../core/styles-api/create-vars-resolver/create-vars-resolver.cjs");
const useResolvedStylesApi = require("../../core/styles-api/use-resolved-styles-api/use-resolved-styles-api.cjs");
const useStyles = require("../../core/styles-api/use-styles/use-styles.cjs");
const useProps = require("../../core/MantineProvider/use-props/use-props.cjs");
const factory = require("../../core/factory/factory.cjs");
const InputBase = require("../InputBase/InputBase.cjs");
const UnstyledButton = require("../UnstyledButton/UnstyledButton.cjs");
const NumberInputChevron = require("./NumberInputChevron.cjs");
const NumberInput_module_css = require("./NumberInput.module.css.cjs");
const useUncontrolled = require("../../../../../../../@mantine_hooks@7.15.2_react@18.3.1/node_modules/@mantine/hooks/esm/use-uncontrolled/use-uncontrolled.cjs");
const useMergedRef = require("../../../../../../../@mantine_hooks@7.15.2_react@18.3.1/node_modules/@mantine/hooks/esm/use-merged-ref/use-merged-ref.cjs");
const clamp = require("../../../../../../../@mantine_hooks@7.15.2_react@18.3.1/node_modules/@mantine/hooks/esm/utils/clamp/clamp.cjs");
const leadingDecimalZeroPattern = /^(0\.0*|-0(\.0*)?)$/;
const leadingZerosPattern = /^-?0\d+(\.\d+)?\.?$/;
function isNumberString(value) {
  return typeof value === "string" && value !== "" && !Number.isNaN(Number(value));
}
function canIncrement(value) {
  if (typeof value === "number") {
    return value < Number.MAX_SAFE_INTEGER;
  }
  return value === "" || isNumberString(value) && Number(value) < Number.MAX_SAFE_INTEGER;
}
function getDecimalPlaces(inputValue) {
  return inputValue.toString().replace(".", "").length;
}
function isValidNumber(floatValue, value) {
  return (typeof floatValue === "number" ? floatValue < Number.MAX_SAFE_INTEGER : !Number.isNaN(Number(floatValue))) && !Number.isNaN(floatValue) && getDecimalPlaces(value) < 14 && value !== "";
}
function isInRange(value, min, max) {
  if (value === void 0) {
    return true;
  }
  const minValid = min === void 0 || value >= min;
  const maxValid = max === void 0 || value <= max;
  return minValid && maxValid;
}
const defaultProps = {
  step: 1,
  clampBehavior: "blur",
  allowDecimal: true,
  allowNegative: true,
  withKeyboardEvents: true,
  allowLeadingZeros: true,
  trimLeadingZeroesOnBlur: true,
  startValue: 0
};
const varsResolver = createVarsResolver.createVarsResolver((_, { size }) => ({
  controls: {
    "--ni-chevron-size": getSize.getSize(size, "ni-chevron-size")
  }
}));
const NumberInput = factory.factory((_props, ref) => {
  const props = useProps.useProps("NumberInput", defaultProps, _props);
  const {
    className,
    classNames,
    styles,
    unstyled,
    vars,
    onChange,
    onValueChange,
    value,
    defaultValue,
    max,
    min,
    step,
    hideControls,
    rightSection,
    isAllowed,
    clampBehavior,
    onBlur,
    allowDecimal,
    decimalScale,
    onKeyDown,
    onKeyDownCapture,
    handlersRef,
    startValue,
    disabled,
    rightSectionPointerEvents,
    allowNegative,
    readOnly,
    size,
    rightSectionWidth,
    stepHoldInterval,
    stepHoldDelay,
    allowLeadingZeros,
    withKeyboardEvents,
    trimLeadingZeroesOnBlur,
    ...others
  } = props;
  const getStyles = useStyles.useStyles({
    name: "NumberInput",
    classes: NumberInput_module_css.default,
    props,
    classNames,
    styles,
    unstyled,
    vars,
    varsResolver
  });
  const { resolvedClassNames, resolvedStyles } = useResolvedStylesApi.useResolvedStylesApi({
    classNames,
    styles,
    props
  });
  const [_value, setValue] = useUncontrolled.useUncontrolled({
    value,
    defaultValue,
    finalValue: "",
    onChange
  });
  const shouldUseStepInterval = stepHoldDelay !== void 0 && stepHoldInterval !== void 0;
  const inputRef = React.useRef(null);
  const onStepTimeoutRef = React.useRef(null);
  const stepCountRef = React.useRef(0);
  const handleValueChange = (payload, event) => {
    if (event.source === "event") {
      setValue(
        isValidNumber(payload.floatValue, payload.value) && !leadingDecimalZeroPattern.test(payload.value) && !(allowLeadingZeros ? leadingZerosPattern.test(payload.value) : false) ? payload.floatValue : payload.value
      );
    }
    onValueChange == null ? void 0 : onValueChange(payload, event);
  };
  const getDecimalPlaces2 = (inputValue) => {
    const match = String(inputValue).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/);
    if (!match) {
      return 0;
    }
    return Math.max(0, (match[1] ? match[1].length : 0) - (match[2] ? +match[2] : 0));
  };
  const adjustCursor = (position) => {
    if (inputRef.current && typeof position !== "undefined") {
      inputRef.current.setSelectionRange(position, position);
    }
  };
  const incrementRef = React.useRef(noop.noop);
  incrementRef.current = () => {
    if (!canIncrement(_value)) {
      return;
    }
    let val;
    const currentValuePrecision = getDecimalPlaces2(_value);
    const stepPrecision = getDecimalPlaces2(step);
    const maxPrecision = Math.max(currentValuePrecision, stepPrecision);
    const factor = 10 ** maxPrecision;
    if (!isNumberString(_value) && (typeof _value !== "number" || Number.isNaN(_value))) {
      val = clamp.clamp(startValue, min, max);
    } else if (max !== void 0) {
      const incrementedValue = (Math.round(Number(_value) * factor) + Math.round(step * factor)) / factor;
      val = incrementedValue <= max ? incrementedValue : max;
    } else {
      val = (Math.round(Number(_value) * factor) + Math.round(step * factor)) / factor;
    }
    const formattedValue = val.toFixed(maxPrecision);
    setValue(parseFloat(formattedValue));
    onValueChange == null ? void 0 : onValueChange(
      { floatValue: parseFloat(formattedValue), formattedValue, value: formattedValue },
      { source: "increment" }
    );
    setTimeout(() => {
      var _a;
      return adjustCursor((_a = inputRef.current) == null ? void 0 : _a.value.length);
    }, 0);
  };
  const decrementRef = React.useRef(noop.noop);
  decrementRef.current = () => {
    if (!canIncrement(_value)) {
      return;
    }
    let val;
    const minValue = min !== void 0 ? min : !allowNegative ? 0 : Number.MIN_SAFE_INTEGER;
    const currentValuePrecision = getDecimalPlaces2(_value);
    const stepPrecision = getDecimalPlaces2(step);
    const maxPrecision = Math.max(currentValuePrecision, stepPrecision);
    const factor = 10 ** maxPrecision;
    if (!isNumberString(_value) && typeof _value !== "number" || Number.isNaN(_value)) {
      val = clamp.clamp(startValue, minValue, max);
    } else {
      const decrementedValue = (Math.round(Number(_value) * factor) - Math.round(step * factor)) / factor;
      val = minValue !== void 0 && decrementedValue < minValue ? minValue : decrementedValue;
    }
    const formattedValue = val.toFixed(maxPrecision);
    setValue(parseFloat(formattedValue));
    onValueChange == null ? void 0 : onValueChange(
      { floatValue: parseFloat(formattedValue), formattedValue, value: formattedValue },
      { source: "decrement" }
    );
    setTimeout(() => {
      var _a;
      return adjustCursor((_a = inputRef.current) == null ? void 0 : _a.value.length);
    }, 0);
  };
  const handleKeyDown = (event) => {
    onKeyDown == null ? void 0 : onKeyDown(event);
    if (readOnly || !withKeyboardEvents) {
      return;
    }
    if (event.key === "ArrowUp") {
      event.preventDefault();
      incrementRef.current();
    }
    if (event.key === "ArrowDown") {
      event.preventDefault();
      decrementRef.current();
    }
  };
  const handleKeyDownCapture = (event) => {
    onKeyDownCapture == null ? void 0 : onKeyDownCapture(event);
    if (event.key === "Backspace") {
      const input = inputRef.current;
      if (input.selectionStart === 0 && input.selectionStart === input.selectionEnd) {
        event.preventDefault();
        window.setTimeout(() => adjustCursor(0), 0);
      }
    }
  };
  useMergedRef.assignRef(handlersRef, { increment: incrementRef.current, decrement: decrementRef.current });
  const onStepHandleChange = (isIncrement) => {
    if (isIncrement) {
      incrementRef.current();
    } else {
      decrementRef.current();
    }
    stepCountRef.current += 1;
  };
  const onStepLoop = (isIncrement) => {
    onStepHandleChange(isIncrement);
    if (shouldUseStepInterval) {
      const interval = typeof stepHoldInterval === "number" ? stepHoldInterval : stepHoldInterval(stepCountRef.current);
      onStepTimeoutRef.current = window.setTimeout(() => onStepLoop(isIncrement), interval);
    }
  };
  const onStep = (event, isIncrement) => {
    var _a;
    event.preventDefault();
    (_a = inputRef.current) == null ? void 0 : _a.focus();
    onStepHandleChange(isIncrement);
    if (shouldUseStepInterval) {
      onStepTimeoutRef.current = window.setTimeout(() => onStepLoop(isIncrement), stepHoldDelay);
    }
  };
  const onStepDone = () => {
    if (onStepTimeoutRef.current) {
      window.clearTimeout(onStepTimeoutRef.current);
    }
    onStepTimeoutRef.current = null;
    stepCountRef.current = 0;
  };
  const controls = /* @__PURE__ */ jsxRuntime.jsxs("div", { ...getStyles("controls"), children: [
    /* @__PURE__ */ jsxRuntime.jsx(
      UnstyledButton.UnstyledButton,
      {
        ...getStyles("control"),
        tabIndex: -1,
        "aria-hidden": true,
        disabled: disabled || typeof _value === "number" && max !== void 0 && _value >= max,
        mod: { direction: "up" },
        onMouseDown: (event) => event.preventDefault(),
        onPointerDown: (event) => {
          onStep(event, true);
        },
        onPointerUp: onStepDone,
        onPointerLeave: onStepDone,
        children: /* @__PURE__ */ jsxRuntime.jsx(NumberInputChevron.NumberInputChevron, { direction: "up" })
      }
    ),
    /* @__PURE__ */ jsxRuntime.jsx(
      UnstyledButton.UnstyledButton,
      {
        ...getStyles("control"),
        tabIndex: -1,
        "aria-hidden": true,
        disabled: disabled || typeof _value === "number" && min !== void 0 && _value <= min,
        mod: { direction: "down" },
        onMouseDown: (event) => event.preventDefault(),
        onPointerDown: (event) => {
          onStep(event, false);
        },
        onPointerUp: onStepDone,
        onPointerLeave: onStepDone,
        children: /* @__PURE__ */ jsxRuntime.jsx(NumberInputChevron.NumberInputChevron, { direction: "down" })
      }
    )
  ] });
  return /* @__PURE__ */ jsxRuntime.jsx(
    InputBase.InputBase,
    {
      component: reactNumberFormat_es.NumericFormat,
      allowNegative,
      className: clsx(NumberInput_module_css.default.root, className),
      size,
      ...others,
      readOnly,
      disabled,
      value: _value,
      getInputRef: useMergedRef.useMergedRef(ref, inputRef),
      onValueChange: handleValueChange,
      rightSection: hideControls || readOnly || !canIncrement(_value) ? rightSection : rightSection || controls,
      classNames: resolvedClassNames,
      styles: resolvedStyles,
      unstyled,
      __staticSelector: "NumberInput",
      decimalScale: allowDecimal ? decimalScale : 0,
      onKeyDown: handleKeyDown,
      onKeyDownCapture: handleKeyDownCapture,
      rightSectionPointerEvents: rightSectionPointerEvents ?? (disabled ? "none" : void 0),
      rightSectionWidth: rightSectionWidth ?? `var(--ni-right-section-width-${size || "sm"})`,
      allowLeadingZeros,
      onBlur: (event) => {
        onBlur == null ? void 0 : onBlur(event);
        if (clampBehavior === "blur" && typeof _value === "number") {
          const clampedValue = clamp.clamp(_value, min, max);
          if (clampedValue !== _value) {
            setValue(clamp.clamp(_value, min, max));
          }
        }
        if (trimLeadingZeroesOnBlur && typeof _value === "string" && getDecimalPlaces2(_value) < 15) {
          const replaced = _value.replace(/^0+/, "");
          const parsedValue = parseFloat(replaced);
          setValue(
            Number.isNaN(parsedValue) || parsedValue > Number.MAX_SAFE_INTEGER ? replaced : clamp.clamp(parsedValue, min, max)
          );
        }
      },
      isAllowed: (val) => {
        if (clampBehavior === "strict") {
          if (isAllowed) {
            return isAllowed(val) && isInRange(val.floatValue, min, max);
          }
          return isInRange(val.floatValue, min, max);
        }
        return isAllowed ? isAllowed(val) : true;
      }
    }
  );
});
NumberInput.classes = { ...InputBase.InputBase.classes, ...NumberInput_module_css.default };
NumberInput.displayName = "@mantine/core/NumberInput";
exports.NumberInput = NumberInput;
