import { jsx, jsxs, Fragment } from "react/jsx-runtime";
import React__default from "react";
import { FaChevronDown } from "react-icons/fa";
import { ImCheckmark } from "react-icons/im";
import ReactSelect, { components } from "react-select";
import Creatable from "react-select/creatable";
import { useBindingState } from "../../form/hooks/useBindingState.js";
import { concat } from "../../utils/classNames.js";
import "../../utils/globals.js";
import { useContentMemo } from "../../hooks/useContentMemo.js";
import "zod";
import { useDidUpdateEffect } from "../../hooks/useDidUpdateEffect.js";
import { getContentFromOption } from "../../types/options.js";
import { onBlurWorkaround } from "../../workarounds/radixDialog.js";
import { useArmstrongConfig } from "../config/config.context.js";
import { Label } from "../label/label.component.js";
import { Spinner } from "../spinner/spinner.component.js";
import { StatusWrapper } from "../statusWrapper/statusWrapper.component.js";
import { ValidationErrors } from "../validationErrors/validationErrors.component.js";
import { isCreatingOption, isGroupedOptions, emptyStyles } from "./select.utils.js";
import "./select.theme.css.js";
const { DropdownIndicator, Option, ValueContainer } = components;
const ReactSelectComponent = React__default.forwardRef(({ className, bind, options, placeholder, validationMode, validationErrorMessages: errorMessages, errorIcon, ariaLabel, currentValue, onSelectOption, getOptionValue, clearable, disabled, searchable, dropdownIcon, loadingIcon, selectedIcon, position, formatOptionLabel, closeMenuOnSelect, displaySize, label, required, requiredIndicator, scrollValidationErrorsIntoView, statusPosition, pending, multi, allowCreate, createText, onOptionCreated, labelId, labelClassName, validationErrorsClassName, statusClassName, disableOnPending, hideIconOnStatus, leftOverlay, autoValidate, onInputChange, inputValue, caseSensitive, filterOption, isInModal, inModalZIndex, inModalPortalTarget, noOptionsMessage, ...nativeProps }, ref) => {
  const internalRef = React__default.useRef(null);
  React__default.useImperativeHandle(ref, () => internalRef.current, [internalRef]);
  const [value, setValue, bindConfig] = useBindingState(bind, {
    validationErrorMessages: errorMessages,
    validationMode,
    value: currentValue,
    onChange: onSelectOption,
    autoValidate,
    validationErrorIcon: errorIcon
  });
  const globals = useArmstrongConfig({
    validationMode: bindConfig.validationMode,
    requiredIndicator,
    scrollValidationErrorsIntoView,
    validationErrorIcon: bindConfig.validationErrorIcon,
    inputStatusPosition: statusPosition,
    inputDisplaySize: displaySize,
    hideInputErrorIconOnStatus: hideIconOnStatus,
    disableControlOnPending: disableOnPending,
    autoValidate: bindConfig.autoValidate
  });
  const handleChange = React__default.useCallback((newValue) => {
    if (!multi) {
      const singleValue = newValue;
      if (isCreatingOption(singleValue)) {
        setValue == null ? void 0 : setValue((onOptionCreated == null ? void 0 : onOptionCreated(singleValue.value)) ?? singleValue.value);
        return;
      }
      setValue == null ? void 0 : setValue(singleValue == null ? void 0 : singleValue.id);
    } else {
      const multiValue = newValue;
      setValue == null ? void 0 : setValue(multiValue == null ? void 0 : multiValue.map((v) => {
        if (isCreatingOption(v)) {
          return (onOptionCreated == null ? void 0 : onOptionCreated(v.value)) ?? v.value;
        }
        return v.id;
      }));
      setTimeout(() => {
        var _a;
        return (_a = internalRef.current) == null ? void 0 : _a.focus();
      }, 1);
    }
  }, [multi, setValue, onOptionCreated]);
  const selectedValue = React__default.useMemo(() => {
    const valueFinder = (incomingOptions) => {
      if (!multi) {
        return (incomingOptions == null ? void 0 : incomingOptions.find((o) => o.id === value)) ?? null;
      }
      return (value == null ? void 0 : value.map((v) => (incomingOptions == null ? void 0 : incomingOptions.find((o) => o.id === v)) ?? {
        id: v,
        content: v,
        wasCreated: true
      })) ?? null;
    };
    if (isGroupedOptions(options)) {
      return valueFinder(options.map((o) => o.options).flat(1));
    }
    return valueFinder(options);
  }, [multi, options, value]);
  const valueGetter = React__default.useCallback((option) => {
    var _a, _b;
    if (isCreatingOption(option)) {
      return option.value;
    }
    return ((_a = getOptionValue == null ? void 0 : getOptionValue(option)) == null ? void 0 : _a.toString()) ?? ((_b = option.id) == null ? void 0 : _b.toString()) ?? "";
  }, [getOptionValue]);
  const labelGetter = React__default.useCallback((option) => {
    if (isCreatingOption(option)) {
      return `${createText} ${option.value}`;
    }
    return (formatOptionLabel == null ? void 0 : formatOptionLabel(option)) ?? getContentFromOption(option);
  }, [createText, formatOptionLabel]);
  const filterOptionInner = React__default.useCallback((option, incomingInputValue) => {
    var _a, _b;
    if (filterOption) {
      return filterOption(option.data, incomingInputValue);
    }
    if (caseSensitive) {
      return !!((_a = labelGetter(option.data)) == null ? void 0 : _a.toString().includes(incomingInputValue));
    }
    return !!((_b = labelGetter(option.data)) == null ? void 0 : _b.toString().toLowerCase().includes(incomingInputValue.toLowerCase()));
  }, [caseSensitive, filterOption, labelGetter]);
  const valueContent = useContentMemo(value);
  useDidUpdateEffect(() => {
    if (globals.autoValidate) {
      bindConfig.validate();
    }
    bindConfig.setTouched(true);
  }, [valueContent]);
  const showLeftOverlay = leftOverlay && (globals.inputStatusPosition !== "left" || !globals.hideInputErrorIconOnStatus || !pending && !bindConfig.shouldShowValidationErrorIcon);
  const valueContainer = React__default.useCallback((props) => {
    return jsx("div", { className: "arm-select-inner", "data-error-icon": globals.inputStatusPosition, children: jsxs(StatusWrapper, { error: !bindConfig.isValid, errorIcon: globals.validationErrorIcon, className: concat("arm-select-status", statusClassName), statusPosition: globals.inputStatusPosition, validationMode: globals.validationMode, children: [showLeftOverlay && jsx("div", { className: "arm-select-overlay arm-select-overlay-left", children: leftOverlay }), jsx(ValueContainer, { ...props })] }) });
  }, [
    bindConfig.isValid,
    globals.inputStatusPosition,
    globals.validationErrorIcon,
    globals.validationMode,
    leftOverlay,
    showLeftOverlay,
    statusClassName
  ]);
  const reactSelectProps = {
    isMulti: multi,
    className: "arm-select-input",
    classNamePrefix: "arm-select",
    onChange: handleChange,
    filterOption: filterOptionInner,
    options,
    placeholder,
    value: selectedValue,
    getOptionValue: valueGetter,
    formatOptionLabel: labelGetter,
    "aria-invalid": !bindConfig.isValid,
    "aria-label": ariaLabel,
    isClearable: clearable,
    isDisabled: disabled || pending && globals.disableControlOnPending ? true : void 0,
    isOptionDisabled: (o) => !!o.disabled,
    isLoading: pending,
    noOptionsMessage: (noOp) => (noOptionsMessage == null ? void 0 : noOptionsMessage(noOp.inputValue)) ?? "No options",
    isSearchable: searchable,
    menuPlacement: position,
    menuPortalTarget: isInModal ? inModalPortalTarget ?? document.body : void 0,
    styles: {
      ...emptyStyles(),
      ...isInModal ? {
        menuPortal: (base) => ({
          ...base,
          zIndex: inModalZIndex ?? 9999,
          pointerEvents: "all"
        })
      } : {}
    },
    onBlur: onBlurWorkaround,
    onInputChange,
    inputValue,
    components: {
      Option: (props) => {
        return jsx(Option, { ...props, children: jsxs(Fragment, { children: [labelGetter(props.data), props.isSelected && selectedIcon] }) });
      },
      DropdownIndicator: (props) => jsx(DropdownIndicator, { ...props, children: dropdownIcon }),
      LoadingIndicator: () => jsx(Spinner, { className: "arm-select-spinner", fillContainer: false, icon: loadingIcon }),
      ValueContainer: valueContainer
    },
    closeMenuOnSelect
  };
  return jsxs("div", { className: concat("arm-select-wrapper", className), "data-size": globals.inputDisplaySize, "data-multi": !!multi, "data-error": !bindConfig.isValid, ...nativeProps, children: [label && jsx(Label, { id: labelId, className: concat("arm-select-label", labelClassName), required, requiredIndicator: globals.requiredIndicator, displaySize: globals.inputDisplaySize, children: label }), allowCreate ? jsx(Creatable, { ref: internalRef, ...reactSelectProps }) : jsx(ReactSelect, { ref: internalRef, ...reactSelectProps }), !bindConfig.isValid && jsx(ValidationErrors, { "aria-label": "Error messages", className: concat("arm-select-validation-error-display", validationErrorsClassName), validationMode: globals.validationMode, scrollIntoView: globals.scrollValidationErrorsIntoView, validationErrors: bindConfig.validationErrorMessages || [] })] });
});
ReactSelectComponent.displayName = "ReactSelect";
ReactSelectComponent.defaultProps = {
  clearable: true,
  searchable: true,
  selectedIcon: jsx(ImCheckmark, {}),
  dropdownIcon: jsx(FaChevronDown, { size: 16 }),
  createText: "Create:"
};
const NativeSelect = React__default.forwardRef(({ validationMode, requiredIndicator, scrollValidationErrorsIntoView, errorIcon, validationErrorMessages, currentValue, onSelectOption, bind, className, displaySize, label, required, options, onChange, placeholderOption, placeholderOptionEnabled, disabled, statusPosition, dropdownIcon, labelId, labelClassName, validationErrorsClassName, statusClassName, hideIconOnStatus, leftOverlay, autoValidate, ...nativeProps }, ref) => {
  const internalRef = React__default.useRef(null);
  React__default.useImperativeHandle(ref, () => internalRef.current, [internalRef]);
  const [value, setValue, bindConfig] = useBindingState(bind, {
    validationErrorMessages,
    validationMode,
    value: currentValue,
    onChange: onSelectOption,
    validationErrorIcon: errorIcon,
    autoValidate
  });
  const globals = useArmstrongConfig({
    validationMode: bindConfig.validationMode,
    requiredIndicator,
    scrollValidationErrorsIntoView,
    validationErrorIcon: bindConfig.validationErrorIcon,
    inputStatusPosition: statusPosition,
    inputDisplaySize: displaySize,
    hideInputErrorIconOnStatus: hideIconOnStatus,
    autoValidate: bindConfig.autoValidate
  });
  const clearSelect = React__default.useCallback(() => {
    var _a;
    onSelectOption == null ? void 0 : onSelectOption(void 0);
    (_a = bind == null ? void 0 : bind.setValue) == null ? void 0 : _a.call(bind, void 0);
  }, [onSelectOption, bind]);
  const onChangeEvent = React__default.useCallback((event) => {
    if (onChange) {
      onChange(event);
    }
    const { value: newValue } = event.currentTarget;
    const selectedOption = options == null ? void 0 : options.find((option) => {
      var _a;
      return ((_a = option.id) == null ? void 0 : _a.toString()) === newValue;
    });
    if (selectedOption) {
      setValue == null ? void 0 : setValue(selectedOption.id);
      onSelectOption == null ? void 0 : onSelectOption(selectedOption.id);
    } else if (!newValue && placeholderOption && placeholderOptionEnabled) {
      clearSelect();
    }
  }, [onChange, options, placeholderOption, placeholderOptionEnabled, setValue, onSelectOption, clearSelect]);
  useDidUpdateEffect(() => {
    if (globals.autoValidate) {
      bindConfig.validate();
    }
    bindConfig.setTouched(true);
  }, [value]);
  const showLeftOverlay = leftOverlay && (globals.inputStatusPosition !== "left" || !globals.hideInputErrorIconOnStatus || !bindConfig.shouldShowValidationErrorIcon);
  return jsxs("div", { className: concat("arm-select-wrapper", "arm-select-native-wrapper", className), "data-size": displaySize, "data-error": !bindConfig.isValid, "data-disabled": !!disabled, "data-empty": !!value, children: [label && jsx(Label, { className: concat("arm-select-label"), required, requiredIndicator: globals.requiredIndicator, displaySize: globals.inputDisplaySize, children: label }), jsxs("div", { className: "arm-select-inner", "data-error-icon": statusPosition, "data-disabled": disabled, children: [jsxs(StatusWrapper, { error: !bindConfig.isValid, errorIcon: globals.validationErrorIcon, className: concat("arm-select-status", statusClassName), statusPosition: globals.inputStatusPosition, validationMode: globals.validationMode, children: [showLeftOverlay && jsx("div", { className: "arm-select-overlay arm-select-overlay-left", children: leftOverlay }), jsxs("select", { "data-left-overlay": !!showLeftOverlay, "data-right-overlay": !bindConfig.isValid, className: "arm-native-select", ...nativeProps, ref: internalRef, onChange: onChangeEvent, value: value ?? void 0, disabled, defaultValue: placeholderOption && !nativeProps.defaultValue && !value ? "" : nativeProps.defaultValue, children: [placeholderOption && jsx("option", { value: "", disabled: !placeholderOptionEnabled, children: placeholderOption }), options == null ? void 0 : options.map((option) => jsx("option", { value: option.id ?? void 0, disabled: option.disabled, ...option.htmlProps, children: getContentFromOption(option) }, option.id))] })] }), jsx("div", { className: "arm-native-indicators", children: jsx("div", { className: "arm-native-select-arrow", children: dropdownIcon }) })] }), !bindConfig.isValid && jsx(ValidationErrors, { "aria-label": "Error messages", className: "arm-select-validation-error-display", validationMode: globals.validationMode, scrollIntoView: globals.scrollValidationErrorsIntoView, validationErrors: bindConfig.validationErrorMessages || [] })] });
});
NativeSelect.displayName = "NativeSelect";
NativeSelect.defaultProps = {
  dropdownIcon: jsx(FaChevronDown, { size: 16 })
};
const Select = React__default.forwardRef((props, ref) => {
  return jsx(ReactSelectComponent, { ...props, multi: false, ref });
});
Select.displayName = "Select";
const MultiSelect = React__default.forwardRef((props, ref) => {
  return jsx(ReactSelectComponent, { ...props, multi: true, ref });
});
MultiSelect.displayName = "MultiSelect";
export {
  MultiSelect,
  NativeSelect,
  Select
};
//# sourceMappingURL=select.component.js.map
