{"version":3,"file":"SelectInput.mjs","sources":["../../../src/inputs/SelectInput/SelectInput.tsx"],"sourcesContent":["import mergeProps from 'merge-props';\nimport { useEffect, useRef, useState, useDeferredValue } from 'react';\nimport { Listbox as ListboxBase } from '@headlessui/react';\nimport { useScreenSize } from '../../common/hooks/useScreenSize';\nimport { Breakpoint } from '../../common/propsValues/breakpoint';\nimport { useEffectEvent } from '../../common/hooks/useEffectEvent';\nimport { useInputAttributes } from '../contexts';\n\nimport { SelectInputBottomSheet } from './BottomSheet';\nimport { SelectInputPopover } from './Popover';\nimport { SelectInputOptions } from './Options';\nimport { DefaultRenderTrigger } from './DefaultRenderTrigger';\n\nimport {\n  SelectInputOptionContentWithinTriggerContext,\n  SelectInputTriggerButtonPropsContext,\n} from './SelectInput.contexts';\nimport { searchableString, sortByRelevance } from './SelectInput.utils';\nimport { SelectInputProps } from './SelectInput.types';\n\nconst noop = () => {};\n\n/**\n * SelectInput component allows users to select an option from a dropdown list.\n * Supports filtering, multiple selection, and customization.\n */\nexport function SelectInput<T = string, M extends boolean = false>({\n  id: idProp,\n  parentId,\n  name,\n  multiple,\n  placeholder,\n  autocomplete,\n  items,\n  defaultValue,\n  value: controlledValue,\n  compareValues,\n  renderValue = String,\n  renderFooter,\n  renderTrigger = DefaultRenderTrigger,\n  filterable,\n  filterPlaceholder,\n  sortFilteredOptions,\n  disabled,\n  size = 'md',\n  className,\n  UNSAFE_triggerButtonProps,\n  triggerRef: externalTriggerRef,\n  onFilterChange = noop,\n  onChange,\n  onOpen,\n  onClose,\n  onClear,\n}: SelectInputProps<T, M>) {\n  const inputAttributes = useInputAttributes({ nonLabelable: true });\n  const id = idProp ?? inputAttributes.id;\n\n  const [open, setOpen] = useState(false);\n\n  const initialized = useRef(false);\n  const handleClose = useEffectEvent(onClose ?? (() => {}));\n  const handleOpen = useEffectEvent(onOpen ?? (() => {}));\n  useEffect(() => {\n    if (initialized.current) {\n      if (open) {\n        handleOpen?.();\n      } else {\n        handleClose?.();\n      }\n    } else {\n      initialized.current = true;\n    }\n  }, [handleClose, handleOpen, open]);\n\n  const [filterQuery, _setFilterQuery] = useState('');\n  const deferredFilterQuery = useDeferredValue(filterQuery);\n  const setFilterQuery = useEffectEvent((query: string) => {\n    _setFilterQuery(query);\n    if (query !== filterQuery) {\n      onFilterChange({\n        query,\n        queryNormalized: query ? searchableString(query) : null,\n      });\n    }\n  });\n\n  const internalTriggerRef = useRef<HTMLButtonElement | null>(null);\n\n  const screenSm = useScreenSize(Breakpoint.SMALL);\n  const OptionsOverlay = screenSm ? SelectInputPopover : SelectInputBottomSheet;\n\n  const searchInputRef = useRef<HTMLInputElement>(null);\n  const listboxRef = useRef<HTMLDivElement>(null);\n  const controllerRef = filterable ? searchInputRef : listboxRef;\n\n  /**\n   * Attempts to resolve the `listbox` label\n   * @see https://storybook.wise.design/?path=/docs/forms-selectinput-accessibility--docs#labelling\n   */\n  const getListBoxLabelProps = (): {\n    listBoxLabel?: string;\n    listBoxLabelledBy?: string;\n  } => {\n    if (UNSAFE_triggerButtonProps?.['aria-label']) {\n      return {\n        listBoxLabel: UNSAFE_triggerButtonProps['aria-label'],\n      };\n    }\n\n    if (UNSAFE_triggerButtonProps?.['aria-labelledby']) {\n      return {\n        listBoxLabelledBy: UNSAFE_triggerButtonProps['aria-labelledby'],\n      };\n    }\n\n    if (inputAttributes['aria-labelledby']) {\n      return {\n        listBoxLabelledBy: inputAttributes['aria-labelledby'],\n      };\n    }\n\n    return {};\n  };\n\n  return (\n    <ListboxBase\n      name={name}\n      multiple={multiple}\n      defaultValue={defaultValue as M extends true ? T[] : T}\n      value={controlledValue as M extends true ? T[] : T}\n      by={compareValues}\n      disabled={disabled}\n      onChange={\n        ((value) => {\n          if (!multiple) {\n            setOpen(false);\n          }\n          onChange?.(value);\n        }) satisfies SelectInputProps<T, M>['onChange']\n      }\n    >\n      {({ disabled: uiDisabled, value }) => {\n        const placeholderShown =\n          multiple && Array.isArray(value) ? value.length === 0 : value == null;\n        return (\n          <OptionsOverlay\n            placement=\"bottom-start\"\n            open={open}\n            renderTrigger={({ ref, getInteractionProps }) => (\n              <SelectInputTriggerButtonPropsContext.Provider\n                // eslint-disable-next-line react/jsx-no-constructed-context-values\n                value={{\n                  ref: (node) => {\n                    ref(node);\n                    if (externalTriggerRef) {\n                      // eslint-disable-next-line no-param-reassign\n                      externalTriggerRef.current = node;\n                    } else {\n                      internalTriggerRef.current = node;\n                    }\n                  },\n                  size,\n                  ...inputAttributes,\n                  ...UNSAFE_triggerButtonProps,\n                  id,\n                  ...mergeProps(\n                    {\n                      onClick: () => {\n                        setOpen((prev) => !prev);\n                      },\n                      onKeyDown: (event: React.KeyboardEvent) => {\n                        if (\n                          event.key === ' ' ||\n                          event.key === 'Enter' ||\n                          event.key === 'ArrowDown' ||\n                          event.key === 'ArrowUp'\n                        ) {\n                          setOpen((prev) => !prev);\n                        }\n                      },\n                    },\n                    getInteractionProps(),\n                  ),\n                }}\n              >\n                {renderTrigger({\n                  content: !placeholderShown ? (\n                    <SelectInputOptionContentWithinTriggerContext.Provider value>\n                      {multiple && Array.isArray(value)\n                        ? (value as readonly NonNullable<T>[])\n                            .map((option) => renderValue(option, true))\n                            .filter((node) => node != null)\n                            .join(', ')\n                        : renderValue(value as NonNullable<T>, true)}\n                    </SelectInputOptionContentWithinTriggerContext.Provider>\n                  ) : (\n                    placeholder\n                  ),\n                  placeholderShown,\n                  clear:\n                    onClear != null\n                      ? () => {\n                          onClear();\n                          (externalTriggerRef?.current ?? internalTriggerRef.current)?.focus({\n                            preventScroll: true,\n                          });\n                        }\n                      : undefined,\n                  disabled: uiDisabled,\n                  size,\n                  className,\n                })}\n              </SelectInputTriggerButtonPropsContext.Provider>\n            )}\n            initialFocusRef={controllerRef}\n            size={filterable ? 'lg' : 'md'}\n            padding=\"none\"\n            onClose={() => {\n              setOpen(false);\n            }}\n            onCloseEnd={() => {\n              setFilterQuery('');\n            }}\n          >\n            <SelectInputOptions\n              id={id ? `${id}Search` : undefined}\n              parentId={parentId}\n              items={items}\n              compareValues={compareValues}\n              renderValue={renderValue}\n              renderFooter={renderFooter}\n              filterable={filterable}\n              filterPlaceholder={filterPlaceholder}\n              sortFilteredOptions={sortFilteredOptions}\n              searchInputRef={searchInputRef}\n              listboxRef={listboxRef}\n              filterQuery={deferredFilterQuery}\n              autocomplete={autocomplete}\n              name={name}\n              onFilterChange={setFilterQuery}\n              onAutocompleteSelect={(matchedValue) => {\n                onChange?.(matchedValue as M extends true ? T[] : T);\n                if (!multiple) {\n                  setOpen(false);\n                }\n              }}\n              {...getListBoxLabelProps()}\n            />\n          </OptionsOverlay>\n        );\n      }}\n    </ListboxBase>\n  );\n}\n\n// Attach sortByRelevance to the component for convenience\nSelectInput.sortByRelevance = sortByRelevance;\n"],"names":["noop","SelectInput","id","idProp","parentId","name","multiple","placeholder","autocomplete","items","defaultValue","value","controlledValue","compareValues","renderValue","String","renderFooter","renderTrigger","DefaultRenderTrigger","filterable","filterPlaceholder","sortFilteredOptions","disabled","size","className","UNSAFE_triggerButtonProps","triggerRef","externalTriggerRef","onFilterChange","onChange","onOpen","onClose","onClear","inputAttributes","useInputAttributes","nonLabelable","open","setOpen","useState","initialized","useRef","handleClose","useEffectEvent","handleOpen","useEffect","current","filterQuery","_setFilterQuery","deferredFilterQuery","useDeferredValue","setFilterQuery","query","queryNormalized","searchableString","internalTriggerRef","screenSm","useScreenSize","Breakpoint","SMALL","OptionsOverlay","SelectInputPopover","SelectInputBottomSheet","searchInputRef","listboxRef","controllerRef","getListBoxLabelProps","listBoxLabel","listBoxLabelledBy","_jsx","ListboxBase","by","children","uiDisabled","placeholderShown","Array","isArray","length","placement","ref","getInteractionProps","SelectInputTriggerButtonPropsContext","Provider","node","mergeProps","onClick","prev","onKeyDown","event","key","content","SelectInputOptionContentWithinTriggerContext","map","option","filter","join","clear","focus","preventScroll","undefined","initialFocusRef","padding","onCloseEnd","SelectInputOptions","onAutocompleteSelect","matchedValue","sortByRelevance"],"mappings":"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"}