import { jsx, jsxs, Fragment } from "react/jsx-runtime";
import { cn, DecorativeIcon } from "@netlify/ui";
import { forwardRef, useState, cloneElement, createElement } from "react";
const inputTypes = {
  textarea: "textarea"
};
const noop = (_e) => {
};
const floatingTipWrapperCN = (absolute = false) => {
  return cn("tw-mr-0", "tw-relative", absolute && `tw-w-9/10 md:tw-w-auto`);
};
const floatingTipHelpTextCN = (absolute = false) => cn(
  "md:tw-absolute",
  "md:tw-items-center",
  "md:tw-pl-10",
  "md:tw-right-2",
  "md:tw-text-base",
  "md:tw-w-66",
  "tw-block",
  "tw-duration-250",
  "tw-ease-ease",
  "tw-h-9",
  "!tw-m-0",
  "tw-pl-0",
  "tw-static",
  "tw-text-sm",
  "tw-transition-opacity",
  "tw-w-auto",
  "md:tw-flex",
  absolute ? "tw-top-0 tw-h-auto tw--translate-y-2 tw-translate-x-full" : "tw--mt-px tw--translate-y-full tw-translate-x-full"
);
const formControlCN = cn(
  "tw-appearance-none",
  "tw-bg-white",
  "tw-border",
  "tw-border-gray-dark",
  "tw-box-border",
  "tw-flex",
  "tw-flex-1",
  "tw-font-medium",
  "tw-h-9",
  "tw-items-center",
  "tw-leading-very-chill",
  "tw-m-0",
  "tw-w-full",
  "tw-px-3.5",
  "tw-py-1.5",
  "tw-rounded-sm",
  "tw-shadow-none",
  "tw-text-base",
  "tw-text-black",
  "focus-within:tw-ring-2",
  "focus-within:tw-outline-none",
  "group-hover:tw-border-gray-darker",
  "group-hover:focus-within:tw-ring-2",
  "group-hover:focus-within:tw-outline-none",
  "dark:tw-border-gray-light",
  "dark:tw-bg-black",
  "dark:tw-text-white",
  "dark:focus-within:tw-border-gray-lightest",
  "dark:group-hover:tw-border-gray-lighter",
  "dark:group-hover:focus-within:tw-ring-2",
  "dark:group-hover:focus-within:tw-outline-none"
);
const helpTextCN = cn(
  "tw-text-gray-darker",
  "tw-block",
  "tw-text-sm",
  "tw-font-regular",
  "tw-max-w-170",
  "tw-my-1",
  "tw-mx-0.5",
  "[&>p:first-child]:tw-mt-0",
  "dark:tw-text-gray-lighter"
);
const prefixCN = cn(
  "tw-flex-none",
  "tw-leading-asleep",
  "tw-rounded-sm",
  "tw-whitespace-nowrap"
);
const suffixCN = cn(
  "tw--mr-2.5",
  "tw-flex-none",
  "tw-leading-asleep",
  "tw-px-2",
  "tw-rounded-bl-none",
  "tw-rounded-sm",
  "tw-rounded-tl-none",
  "tw-whitespace-nowrap"
);
const FormField = ({
  preventTyping = true,
  onFocus = noop,
  onBlur = noop,
  onChange = noop,
  absolute = false,
  className,
  checkbox = false,
  control,
  label,
  helpText,
  tooltip,
  controlled,
  error,
  type,
  defaultValue,
  placeholder,
  disabled,
  required,
  readOnly,
  prefix,
  suffix,
  onValidate,
  contentType = "text",
  focused = false,
  visuallyHideLabel = false,
  secondary,
  fullMaxWidth,
  floatingLabel = false,
  floatingTip = false,
  iconLabel,
  compact = false,
  helpTextTiny = false,
  pattern,
  value,
  leftLabel = false,
  ...restProps
}, forwardedRef) => {
  const inputId = restProps.id || `nf_field_${(control == null ? void 0 : control.props.name) || crypto.randomUUID()}`;
  const [id] = useState(inputId);
  const [focus, setFocus] = useState(false);
  const [valueState, setValue] = useState(controlled ? null : value);
  let inputRef = null;
  function allowsChange(valueToTest) {
    const preventChange = preventTyping && pattern && valueToTest && !new RegExp(pattern).test(
      valueToTest.trim ? valueToTest.trim() : valueToTest
    );
    return !preventChange;
  }
  function validate(value2) {
    const validation = onValidate ? onValidate(value2) : {};
    if (onValidate && inputRef) {
      inputRef.setCustomValidity(validation.error || "");
    }
    return validation;
  }
  function handleFocus(e) {
    setFocus(true);
    onFocus(e);
  }
  function handleBlur(e) {
    const currentValue2 = controlled ? value : valueState;
    if (typeof currentValue2 === "string") {
      const trimmed = currentValue2 && currentValue2.trim ? currentValue2.trim() : currentValue2;
      if (currentValue2 !== trimmed) {
        handleChange({ target: { name: e.target.name, value: trimmed } });
      }
    }
    setFocus(false);
    onBlur(e);
  }
  function handleChange(e) {
    const { value: targetValue } = e.target;
    if (!allowsChange(targetValue)) {
      return;
    }
    if (validate(targetValue).stopPropagation) {
      return;
    }
    if (!controlled) {
      setValue(targetValue);
    }
    onChange(e);
  }
  function setRef(ref) {
    inputRef = ref == null ? void 0 : ref.querySelector("input, textarea");
  }
  const currentValue = controlled ? value : valueState;
  let initialInputVal;
  if (defaultValue) {
    initialInputVal = void 0;
  } else if (currentValue || currentValue === 0) {
    initialInputVal = currentValue;
  } else {
    initialInputVal = "";
  }
  const descriptiveNodeId = `${id}__helper`;
  const ariaDescribedBy = helpText || error ? descriptiveNodeId : null;
  const input = control ? (
    // this spreads `id` into the child control input
    // so that the label's `for` attribute matches the input's `id` attribute
    // https://github.com/netlify/netlify-react-ui/pull/13789
    cloneElement(control, { id, "aria-describedby": ariaDescribedBy })
  ) : createElement(
    // @ts-expect-error
    inputTypes[type] || "input",
    {
      "aria-describedby": ariaDescribedBy,
      id,
      ref: forwardedRef,
      autoComplete: "off",
      autoCorrect: "off",
      autoCapitalize: "none",
      spellCheck: "false",
      ...restProps,
      type: type || "text",
      defaultValue,
      value: initialInputVal,
      placeholder,
      disabled,
      required,
      className: cn({
        "tw-cursor-not-allowed": disabled,
        "tw-font-mono": contentType === "code",
        "tw-flex-1 tw-bg-transparent tw-border-none tw-p-0 focus:tw-ring-0 dark:tw-bg-transparent dark:tw-border-none dark:focus:tw-ring-0": suffix || prefix
      }),
      readOnly,
      autoFocus: focused,
      onFocus: handleFocus,
      onBlur: handleBlur,
      onChange: handleChange
    },
    type === "textarea" ? currentValue : null
  );
  const floatingTransform = focus || prefix || defaultValue || currentValue || currentValue === 0 || placeholder || control;
  label = iconLabel ? /* @__PURE__ */ jsxs(Fragment, { children: [
    /* @__PURE__ */ jsx(
      DecorativeIcon,
      {
        name: iconLabel,
        width: 20,
        className: "placeholder tw-mt-2"
      }
    ),
    label && /* @__PURE__ */ jsx("span", { className: "tw-sr-only", children: label })
  ] }) : label;
  return /* @__PURE__ */ jsx(
    "div",
    {
      className: cn("tw-c-form-field tw-group", className, {
        "!tw-mt-9": floatingLabel && !iconLabel && !compact,
        "tw-mt-4": !!iconLabel || compact,
        "tw-mt-6": !iconLabel && !compact && !floatingLabel,
        "tw-opacity-54": disabled,
        "tw-inline": checkbox && error,
        "tw-max-w-100": fullMaxWidth,
        [floatingTipWrapperCN(absolute)]: floatingTip,
        "!tw-mt-0": leftLabel
      }),
      ref: setRef,
      children: /* @__PURE__ */ jsxs(
        "div",
        {
          className: cn(
            "form-field-container",
            leftLabel && "!tw-flex tw-w-full tw-flex-wrap"
          ),
          children: [
            label && /* @__PURE__ */ jsx(
              "div",
              {
                className: cn(
                  "tw-c-form-field-label",
                  leftLabel ? "tw-mr-6 tw-flex tw-w-full !tw-flex-[0_0_25%] tw-break-all tw-pt-2 tw-text-base !tw-font-regular !tw-text-gray-darkest after:tw-content-none dark:!tw-text-gray-lightest" : "tw-font-regular tw-text-gray-darker dark:tw-text-gray-lighter",
                  {
                    "tw-pb-[5px]": !leftLabel && !visuallyHideLabel,
                    "tw-leading-tight": floatingLabel,
                    "tw-pointer-events-none tw-cursor-text": floatingLabel && !floatingTransform,
                    "tw-cursor-not-allowed": disabled,
                    "!tw-sr-only": visuallyHideLabel,
                    "tw-absolute tw-hidden": secondary,
                    "tw-translate-z-0 tw-transition-ease tw-absolute tw-text-base tw-duration-200": floatingLabel,
                    // 16 * 0.875 = 14px
                    "tw-scale-[0.875] tw-translate-x-[-6%] tw--translate-y-[97%]": floatingTransform && floatingLabel,
                    "tw-translate-x-[calc(theme(spacing.4)-theme(borderWidth.DEFAULT))] tw-translate-y-2": !floatingTransform && floatingLabel
                  }
                ),
                children: /* @__PURE__ */ jsx(
                  "label",
                  {
                    className: cn({ "after:tw-content-colon": leftLabel }),
                    htmlFor: id,
                    children: label
                  }
                )
              }
            ),
            /* @__PURE__ */ jsxs("div", { className: cn(leftLabel && "tw-flex-1"), children: [
              prefix || suffix ? /* @__PURE__ */ jsxs("div", { className: cn(formControlCN), children: [
                !!prefix && /* @__PURE__ */ jsx("span", { className: prefixCN, children: prefix }),
                input,
                !!suffix && /* @__PURE__ */ jsx("span", { className: suffixCN, children: suffix })
              ] }) : input,
              !error && !leftLabel && tooltip,
              !error && helpText && /* @__PURE__ */ jsx(
                "div",
                {
                  id: descriptiveNodeId,
                  "data-testid": "help-text",
                  className: cn(helpTextCN, {
                    "tw-opacity-100": floatingTip && focus,
                    "tw-opacity-0": floatingTip && !focus,
                    [floatingTipHelpTextCN(absolute)]: floatingTip,
                    "!tw-text-xs": helpTextTiny,
                    "tw-cursor-not-allowed": disabled
                  }),
                  children: helpText
                }
              ),
              error && /* @__PURE__ */ jsx("div", { className: "tw-mx-0.5 tw-text-sm tw-my-1 tw-leading-6 tw-font-regular", children: error })
            ] })
          ]
        }
      )
    }
  );
};
const FormField$1 = forwardRef(FormField);
export {
  FormField$1 as default
};
//# sourceMappingURL=FormField.js.map
