"use client";
import { jsx, jsxs } from "react/jsx-runtime";
import * as React from "react";
import { cn } from "@open-mercato/shared/lib/utils";
import { Input } from "./input.js";
import { Tag } from "./tag.js";
function escapeRegExp(input) {
  return input.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}
function buildSplitter(separator) {
  if (separator instanceof RegExp) {
    return separator.flags.includes("g") ? separator : new RegExp(separator.source, `${separator.flags}g`);
  }
  return new RegExp(escapeRegExp(separator), "g");
}
const TagInput = React.forwardRef(
  ({
    value: valueProp,
    onChange,
    placeholder,
    size = "default",
    disabled = false,
    maxTags,
    validate,
    separator = ",",
    allowDuplicates = false,
    className,
    id,
    name,
    "aria-label": ariaLabel,
    "aria-invalid": ariaInvalid,
    rightIcon
  }, ref) => {
    const [internalValue, setInternalValue] = React.useState([]);
    const [inputText, setInputText] = React.useState("");
    const [error, setError] = React.useState(null);
    const isControlled = valueProp !== void 0;
    const value = isControlled ? valueProp : internalValue;
    const commitValue = React.useCallback(
      (next) => {
        if (!isControlled) setInternalValue(next);
        onChange?.(next);
      },
      [isControlled, onChange]
    );
    const appendToList = React.useCallback(
      (current, rawTag) => {
        const tag = rawTag.trim();
        if (!tag) return null;
        if (!allowDuplicates && current.includes(tag)) return null;
        if (typeof maxTags === "number" && current.length >= maxTags) return null;
        if (validate) {
          const result = validate(tag);
          if (result === false) return null;
          if (typeof result === "string") return { next: current, errorText: result };
        }
        return { next: [...current, tag], errorText: null };
      },
      [allowDuplicates, maxTags, validate]
    );
    const tryAddTag = React.useCallback(
      (rawTag) => {
        const outcome = appendToList(value, rawTag);
        if (!outcome) return false;
        if (outcome.errorText !== null) {
          setError(outcome.errorText);
          return false;
        }
        setError(null);
        if (outcome.next !== value) commitValue(outcome.next);
        return outcome.next !== value;
      },
      [appendToList, commitValue, value]
    );
    const tryAddManyTags = React.useCallback(
      (rawTags) => {
        let acc = value;
        let pendingError = null;
        for (const raw of rawTags) {
          const outcome = appendToList(acc, raw);
          if (!outcome) continue;
          if (outcome.errorText !== null) {
            pendingError = outcome.errorText;
            continue;
          }
          acc = outcome.next;
        }
        if (acc !== value) commitValue(acc);
        if (pendingError !== null) setError(pendingError);
        else if (acc !== value) setError(null);
      },
      [appendToList, commitValue, value]
    );
    const removeTagAt = React.useCallback(
      (index) => {
        if (index < 0 || index >= value.length) return;
        const next = value.slice(0, index).concat(value.slice(index + 1));
        commitValue(next);
        setError(null);
      },
      [commitValue, value]
    );
    const splitter = React.useMemo(() => buildSplitter(separator), [separator]);
    const handleChange = (event) => {
      const text = event.target.value;
      splitter.lastIndex = 0;
      if (splitter.test(text)) {
        splitter.lastIndex = 0;
        const parts = text.split(splitter);
        const trailing = parts.pop() ?? "";
        tryAddManyTags(parts);
        setInputText(trailing);
        return;
      }
      setInputText(text);
      if (error) setError(null);
    };
    const handleKeyDown = (event) => {
      if (event.key === "Enter") {
        event.preventDefault();
        tryAddTag(inputText);
        setInputText("");
        return;
      }
      if (event.key === "Backspace" && inputText.length === 0 && value.length > 0) {
        event.preventDefault();
        removeTagAt(value.length - 1);
      }
    };
    const limitReached = typeof maxTags === "number" && value.length >= maxTags;
    return /* @__PURE__ */ jsxs("div", { className: cn("flex w-full flex-col gap-1", className), "data-slot": "tag-input", children: [
      /* @__PURE__ */ jsx(
        Input,
        {
          ref,
          type: "text",
          size,
          id,
          name,
          value: inputText,
          onChange: handleChange,
          onKeyDown: handleKeyDown,
          placeholder,
          disabled: disabled || limitReached,
          "aria-label": ariaLabel,
          "aria-invalid": ariaInvalid || Boolean(error) || void 0,
          rightIcon,
          "data-slot": "tag-input-field"
        }
      ),
      value.length > 0 ? /* @__PURE__ */ jsx(
        "div",
        {
          className: "flex flex-wrap items-center gap-2 pt-1",
          "data-slot": "tag-input-chips",
          children: value.map((tag, index) => /* @__PURE__ */ jsx(
            Tag,
            {
              variant: "default",
              shape: "square",
              disabled,
              onRemove: () => removeTagAt(index),
              removeAriaLabel: `Remove ${tag}`,
              children: tag
            },
            `${tag}-${index}`
          ))
        }
      ) : null,
      error ? /* @__PURE__ */ jsx(
        "p",
        {
          className: "text-xs text-status-error-text",
          role: "alert",
          "data-slot": "tag-input-error",
          children: error
        }
      ) : null
    ] });
  }
);
TagInput.displayName = "TagInput";
export {
  TagInput
};
//# sourceMappingURL=tag-input.js.map
