'use strict';

var mergeProps = require('merge-props');
var React = require('react');
var react = require('@headlessui/react');
var neptuneTokens = require('@transferwise/neptune-tokens');
var useScreenSize = require('../../common/hooks/useScreenSize.js');
var useEffectEvent = require('../../common/hooks/useEffectEvent.js');
var contexts = require('../contexts.js');
var SelectInputBottomSheet = require('./BottomSheet/SelectInputBottomSheet.js');
var SelectInputPopover = require('./Popover/SelectInputPopover.js');
var SelectInputOptions = require('./Options/SelectInputOptions.js');
var jsxRuntime = require('react/jsx-runtime');
var SelectInputDefaultRenderTrigger = require('./DefaultRenderTrigger/SelectInputDefaultRenderTrigger.js');
var SelectInput_contexts = require('./SelectInput.contexts.js');
var SelectInput_utils = require('./SelectInput.utils.js');

function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }

var mergeProps__default = /*#__PURE__*/_interopDefault(mergeProps);

const noop = () => {};
/**
 * SelectInput component allows users to select an option from a dropdown list.
 * Supports filtering, multiple selection, and customization.
 */
function SelectInput({
  id: idProp,
  parentId,
  name,
  multiple,
  placeholder,
  autocomplete,
  items,
  defaultValue,
  value: controlledValue,
  compareValues,
  renderValue = String,
  renderFooter,
  renderTrigger = SelectInputDefaultRenderTrigger.DefaultRenderTrigger,
  filterable,
  filterPlaceholder,
  sortFilteredOptions,
  disabled,
  size = 'md',
  className,
  UNSAFE_triggerButtonProps,
  triggerRef: externalTriggerRef,
  onFilterChange = noop,
  onChange,
  onOpen,
  onClose,
  onClear
}) {
  const inputAttributes = contexts.useInputAttributes({
    nonLabelable: true
  });
  const id = idProp ?? inputAttributes.id;
  const [open, setOpen] = React.useState(false);
  const initialized = React.useRef(false);
  const handleClose = useEffectEvent.useEffectEvent(onClose ?? (() => {}));
  const handleOpen = useEffectEvent.useEffectEvent(onOpen ?? (() => {}));
  React.useEffect(() => {
    if (initialized.current) {
      if (open) {
        handleOpen?.();
      } else {
        handleClose?.();
      }
    } else {
      initialized.current = true;
    }
  }, [open]);
  const [filterQuery, _setFilterQuery] = React.useState('');
  const deferredFilterQuery = React.useDeferredValue(filterQuery);
  const previousFilterQueryRef = React.useRef(filterQuery);
  const setFilterQuery = React.useCallback(query => {
    _setFilterQuery(query);
    if (query !== previousFilterQueryRef.current) {
      onFilterChange({
        query,
        queryNormalized: query ? SelectInput_utils.searchableString(query) : null
      });
      previousFilterQueryRef.current = query;
    }
  }, [onFilterChange]);
  const internalTriggerRef = React.useRef(null);
  const searchInputRef = React.useRef(null);
  const listboxRef = React.useRef(null);
  const controllerRef = filterable ? searchInputRef : listboxRef;
  const screenSm = useScreenSize.useScreenSize(neptuneTokens.Breakpoint.SMALL);
  const OptionsOverlay = screenSm ? SelectInputPopover.SelectInputPopover : SelectInputBottomSheet.SelectInputBottomSheet;
  /**
   * Attempts to resolve the `listbox` label
   * @see https://storybook.wise.design/?path=/docs/forms-selectinput-accessibility--docs#labelling
   */
  const getListBoxLabelProps = () => {
    if (UNSAFE_triggerButtonProps?.['aria-label']) {
      return {
        listBoxLabel: UNSAFE_triggerButtonProps['aria-label']
      };
    }
    if (UNSAFE_triggerButtonProps?.['aria-labelledby']) {
      return {
        listBoxLabelledBy: UNSAFE_triggerButtonProps['aria-labelledby']
      };
    }
    if (inputAttributes['aria-labelledby']) {
      return {
        listBoxLabelledBy: inputAttributes['aria-labelledby']
      };
    }
    return {};
  };
  return /*#__PURE__*/jsxRuntime.jsx(react.Listbox, {
    name: name,
    multiple: multiple,
    defaultValue: defaultValue,
    value: controlledValue,
    by: compareValues,
    disabled: disabled,
    onChange: value => {
      if (!multiple) {
        setOpen(false);
      }
      onChange?.(value);
    },
    children: ({
      disabled: uiDisabled,
      value
    }) => {
      const placeholderShown = multiple && Array.isArray(value) ? value.length === 0 : value == null;
      return /*#__PURE__*/jsxRuntime.jsx(OptionsOverlay, {
        placement: "bottom-start",
        open: open,
        renderTrigger: ({
          ref,
          getInteractionProps
        }) => /*#__PURE__*/jsxRuntime.jsx(SelectInput_contexts.SelectInputTriggerButtonPropsContext.Provider, {
          // eslint-disable-next-line react/jsx-no-constructed-context-values
          value: {
            ref: node => {
              ref(node);
              if (externalTriggerRef) {
                // eslint-disable-next-line no-param-reassign
                externalTriggerRef.current = node;
              } else {
                internalTriggerRef.current = node;
              }
            },
            size,
            ...inputAttributes,
            ...UNSAFE_triggerButtonProps,
            id,
            ...mergeProps__default.default({
              onClick: () => {
                setOpen(prev => !prev);
              },
              onKeyDown: event => {
                if (event.key === ' ' || event.key === 'Enter' || event.key === 'ArrowDown' || event.key === 'ArrowUp') {
                  setOpen(prev => !prev);
                }
              }
            }, getInteractionProps())
          },
          children: renderTrigger({
            content: !placeholderShown ? /*#__PURE__*/jsxRuntime.jsx(SelectInput_contexts.SelectInputOptionContentWithinTriggerContext.Provider, {
              value: true,
              children: multiple && Array.isArray(value) ? value.map(option => renderValue(option, true)).filter(node => node != null).join(', ') : renderValue(value, true)
            }) : placeholder,
            placeholderShown,
            clear: onClear != null ? () => {
              onClear();
              (externalTriggerRef?.current ?? internalTriggerRef.current)?.focus({
                preventScroll: true
              });
            } : undefined,
            disabled: uiDisabled,
            size,
            className
          })
        }),
        initialFocusRef: controllerRef,
        size: filterable ? 'lg' : 'md',
        padding: "none",
        onClose: () => {
          setOpen(false);
        },
        onCloseEnd: () => {
          setFilterQuery('');
        },
        children: /*#__PURE__*/jsxRuntime.jsx(SelectInputOptions.SelectInputOptions, {
          id: id ? `${id}Search` : undefined,
          parentId: parentId,
          items: items,
          compareValues: compareValues,
          renderValue: renderValue,
          renderFooter: renderFooter,
          filterable: filterable,
          filterPlaceholder: filterPlaceholder,
          sortFilteredOptions: sortFilteredOptions,
          searchInputRef: searchInputRef,
          listboxRef: listboxRef,
          filterQuery: deferredFilterQuery,
          autocomplete: autocomplete,
          name: name,
          onFilterChange: setFilterQuery,
          onAutocompleteSelect: matchedValue => {
            onChange?.(matchedValue);
            if (!multiple) {
              setOpen(false);
            }
          },
          ...getListBoxLabelProps()
        })
      });
    }
  });
}
// Attach sortByRelevance to the component for convenience
SelectInput.sortByRelevance = SelectInput_utils.sortByRelevance;

exports.SelectInput = SelectInput;
//# sourceMappingURL=SelectInput.js.map
