'use strict';

var jsxRuntime = require('react/jsx-runtime');
var React = require('react');
var utils = require('./utils-BhM0B89p.js');
var primitives_Field = require('./primitives/Field.js');
var primitives_InputGroup = require('./primitives/InputGroup.js');

const SIZE_CONFIG = {
  small: { group: "h-7", input: "text-xs px-2", addon: "px-1.5" },
  medium: { group: "h-8", input: "text-sm", addon: "px-2" },
  large: { group: "h-10", input: "text-sm", addon: "px-2.5" }
};

function toFixed(numStr, prec) {
  const num = Number(numStr);
  if (Number.isNaN(num)) return numStr;
  return num.toFixed(prec);
}
function formatWithPrecision(value, precision) {
  if (precision < 0 || !value) return value;
  const str = value.toString();
  const trimmed = str.trim();
  if (trimmed !== "" && !Number.isNaN(Number(trimmed)))
    return toFixed(str, precision);
  return str;
}
function enforceDecimalPrecision(value, precision) {
  if (precision < 0 || !value) return value;
  const valueStr = value.toString();
  if (precision === 0) return valueStr.split(".")[0];
  const regex = new RegExp(`^\\d*\\.?\\d{0,${precision}}$`);
  if (regex.test(valueStr)) return value;
  const parts = valueStr.split(".");
  if (parts.length === 1) return parts[0];
  return `${parts[0]}.${parts[1].substring(0, precision)}`;
}
function formatWithRejectCharsRegex(value, rejectCharsRegex) {
  if (!rejectCharsRegex) return value;
  const globalRegex = new RegExp(rejectCharsRegex, "g");
  return value.replace(globalRegex, "");
}
function getTrimmedValue(value, disableTrimOnBlur) {
  if (disableTrimOnBlur || typeof value !== "string") return value;
  return value.trim();
}
function preserveCursor(e, updateValueFn) {
  const input = e.target;
  const prevCursor = input.selectionStart;
  const prevValue = input.value;
  const updatedEvent = updateValueFn();
  const lengthDiff = input.value.length - prevValue.length;
  const newCursor = Math.max(0, (prevCursor ?? 0) + lengthDiff);
  requestAnimationFrame(() => {
    if (document.activeElement !== input) return;
    if (input.type === "number") return;
    input.setSelectionRange(newCursor, newCursor);
  });
  return updatedEvent;
}

const Input = React.forwardRef(
  ({
    size = "medium",
    type = "text",
    label = "",
    error = "",
    helpText = "",
    prefix = null,
    suffix = null,
    disabled = false,
    nakedInput = false,
    contentSize,
    required = false,
    maxLength,
    unlimitedChars = false,
    rejectCharsRegex,
    disableTrimOnBlur = false,
    precision = -1,
    labelProps,
    className = "",
    onBlur,
    onChange,
    value: controlledValue,
    ...otherProps
  }, ref) => {
    const generatedId = React.useId();
    const id = otherProps.id ?? generatedId;
    const errorId = `error_${id}`;
    const helpTextId = `helpText_${id}`;
    const [valueInternal, setValueInternal] = React.useState(controlledValue);
    const isControlled = controlledValue !== void 0;
    const value = formatWithPrecision(controlledValue, precision) ?? valueInternal ?? "";
    const valueLength = value?.toString().length || 0;
    const isMaxLengthPresent = !!maxLength || maxLength === 0;
    const isCharacterLimitVisible = isMaxLengthPresent && valueLength >= maxLength * 0.85;
    const maxLengthError = unlimitedChars && valueLength > maxLength;
    const onChangeInternal = (e) => {
      if (!isControlled) {
        setValueInternal(e.target.value);
      }
      onChange?.(e);
    };
    const handleChange = (e) => {
      if (type === "file") {
        onChangeInternal(e);
        return;
      }
      let formattedValue = formatWithRejectCharsRegex(
        e.target.value,
        rejectCharsRegex
      );
      formattedValue = enforceDecimalPrecision(formattedValue, precision);
      if (formattedValue !== e.target.value) {
        preserveCursor(e, () => {
          const syntheticEvent = Object.create(e, {
            target: { value: { ...e.target, value: formattedValue } }
          });
          e.target.value = formattedValue;
          onChangeInternal(syntheticEvent);
          return syntheticEvent;
        });
      } else {
        onChangeInternal(e);
      }
    };
    const handleBlur = (e) => {
      if (type === "file") {
        onBlur?.(e);
        return;
      }
      const trimmedValue = getTrimmedValue(value, disableTrimOnBlur);
      const formattedValue = formatWithPrecision(trimmedValue, precision);
      if (formattedValue !== void 0 && formattedValue !== value) {
        e.target.value = formattedValue.toString();
        handleChange(e);
      }
      onBlur?.(e);
    };
    const handleWheel = (e) => {
      if (type === "number") e.target.blur();
    };
    const ariaDescribedBy = [error ? errorId : null, helpText ? helpTextId : null].filter(Boolean).join(" ") || void 0;
    const hasField = !!(label || error || helpText);
    const sizeConfig = SIZE_CONFIG[size];
    const inputGroup = /* @__PURE__ */ jsxRuntime.jsxs(
      primitives_InputGroup.InputGroup,
      {
        className: utils.cn(
          sizeConfig.group,
          nakedInput && "border-0 shadow-none has-[[data-slot=input-group-control]:focus-visible]:ring-0 has-[[data-slot=input-group-control]:focus-visible]:border-transparent",
          !!error && !nakedInput && "border-destructive ring-destructive/20 ring-3",
          !hasField && className
        ),
        children: [
          prefix && /* @__PURE__ */ jsxRuntime.jsx(primitives_InputGroup.InputGroupAddon, { align: "inline-start", className: sizeConfig.addon, children: /* @__PURE__ */ jsxRuntime.jsx(primitives_InputGroup.InputGroupText, { children: prefix }) }),
          /* @__PURE__ */ jsxRuntime.jsx(
            primitives_InputGroup.InputGroupInput,
            {
              ref,
              id,
              type,
              disabled,
              required,
              size: contentSize,
              "aria-invalid": !!error || void 0,
              "aria-describedby": ariaDescribedBy,
              className: utils.cn(sizeConfig.input, nakedInput && "px-0"),
              value,
              onBlur: handleBlur,
              onChange: handleChange,
              onWheel: handleWheel,
              ...isMaxLengthPresent && !unlimitedChars ? { maxLength } : {},
              ...otherProps
            }
          ),
          suffix && /* @__PURE__ */ jsxRuntime.jsx(primitives_InputGroup.InputGroupAddon, { align: "inline-end", className: sizeConfig.addon, children: /* @__PURE__ */ jsxRuntime.jsx(primitives_InputGroup.InputGroupText, { children: suffix }) })
        ]
      }
    );
    if (!hasField) {
      return inputGroup;
    }
    return /* @__PURE__ */ jsxRuntime.jsxs(
      primitives_Field.Field,
      {
        "data-disabled": disabled || void 0,
        "data-invalid": !!error || void 0,
        className,
        children: [
          (label || isCharacterLimitVisible) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
            label && /* @__PURE__ */ jsxRuntime.jsxs(primitives_Field.FieldLabel, { htmlFor: id, ...labelProps, children: [
              label,
              required && /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", className: "text-destructive", children: "*" })
            ] }),
            isCharacterLimitVisible && /* @__PURE__ */ jsxRuntime.jsxs(
              "span",
              {
                className: utils.cn(
                  "text-xs tabular-nums",
                  maxLengthError ? "text-destructive" : "text-muted-foreground"
                ),
                children: [
                  valueLength,
                  "/",
                  maxLength
                ]
              }
            )
          ] }),
          /* @__PURE__ */ jsxRuntime.jsxs(primitives_Field.FieldContent, { children: [
            inputGroup,
            !!error && /* @__PURE__ */ jsxRuntime.jsx(primitives_Field.FieldError, { id: errorId, children: error }),
            helpText && /* @__PURE__ */ jsxRuntime.jsx(primitives_Field.FieldDescription, { id: helpTextId, children: helpText })
          ] })
        ]
      }
    );
  }
);
Input.displayName = "Input";

exports.Input = Input;
//# sourceMappingURL=Input-CpuJXazH.js.map
