{"version":3,"file":"use-virtualized-combobox.cjs","names":["getNextIndex","getPreviousIndex","getFirstIndex"],"sources":["../../../../src/components/Combobox/use-combobox/use-virtualized-combobox.ts"],"sourcesContent":["import { useCallback, useEffect, useRef } from 'react';\nimport { useUncontrolled } from '@mantine/hooks';\nimport { getFirstIndex, getNextIndex, getPreviousIndex } from './get-index/get-virtualized-index';\nimport { ComboboxDropdownEventSource, ComboboxStore } from './use-combobox';\n\nexport interface UseVirtualizedComboboxOptions {\n  /** Default value for `dropdownOpened`, `false` by default */\n  defaultOpened?: boolean;\n\n  /** Controlled `dropdownOpened` state */\n  opened?: boolean;\n\n  /** Called when `dropdownOpened` state changes */\n  onOpenedChange?: (opened: boolean) => void;\n\n  /** Called when dropdown closes */\n  onDropdownClose?: (eventSource: ComboboxDropdownEventSource) => void;\n\n  /** Called when dropdown opens */\n  onDropdownOpen?: (eventSource: ComboboxDropdownEventSource) => void;\n\n  /** Determines whether arrow key presses should loop though items (first to last and last to first), `true` by default */\n  loop?: boolean;\n\n  /** Function to determine whether the option is disabled */\n  isOptionDisabled?: (optionIndex: number) => boolean;\n\n  /** Total number of options in the virtualized list. Required for proper keyboard navigation and index calculations. */\n  totalOptionsCount: number;\n\n  /** Function that returns the id of the option at the given index. Required for setting aria attributes and element references. */\n  getOptionId: (index: number) => string | null;\n\n  /** Current selected option index. Must be controlled by parent component. */\n  selectedOptionIndex: number;\n\n  /** Callback to update the selected option index. Called when user navigates or selects options. */\n  setSelectedOptionIndex: (index: number) => void;\n\n  /** Currently active/highlighted option index. Used to determine which option to select when selectActiveOption is called. */\n  activeOptionIndex?: number;\n\n  /** Called when the selected option is submitted (e.g., via Enter key or clicking). Receives the selected option index. */\n  onSelectedOptionSubmit: (index: number) => void;\n}\n\nexport function useVirtualizedCombobox(\n  {\n    defaultOpened,\n    opened,\n    onOpenedChange,\n    onDropdownClose,\n    onDropdownOpen,\n    loop = true,\n    totalOptionsCount,\n    isOptionDisabled = () => false,\n    getOptionId,\n    selectedOptionIndex,\n    setSelectedOptionIndex,\n    activeOptionIndex,\n    onSelectedOptionSubmit,\n  }: UseVirtualizedComboboxOptions = {\n    totalOptionsCount: 0,\n    getOptionId: () => null,\n    selectedOptionIndex: -1,\n    setSelectedOptionIndex: () => {},\n    onSelectedOptionSubmit: () => {},\n  }\n): ComboboxStore {\n  const [dropdownOpened, setDropdownOpened] = useUncontrolled({\n    value: opened,\n    defaultValue: defaultOpened,\n    finalValue: false,\n    onChange: onOpenedChange,\n  });\n\n  const listId = useRef<string | null>(null);\n  const searchRef = useRef<HTMLInputElement | null>(null);\n  const targetRef = useRef<HTMLElement | null>(null);\n  const focusSearchTimeout = useRef<number>(-1);\n  const focusTargetTimeout = useRef<number>(-1);\n\n  const openDropdown: ComboboxStore['openDropdown'] = useCallback(\n    (eventSource = 'unknown') => {\n      if (!dropdownOpened) {\n        setDropdownOpened(true);\n        onDropdownOpen?.(eventSource);\n      }\n    },\n    [setDropdownOpened, onDropdownOpen, dropdownOpened]\n  );\n\n  const closeDropdown: ComboboxStore['closeDropdown'] = useCallback(\n    (eventSource = 'unknown') => {\n      if (dropdownOpened) {\n        setDropdownOpened(false);\n        onDropdownClose?.(eventSource);\n      }\n    },\n    [setDropdownOpened, onDropdownClose, dropdownOpened]\n  );\n\n  const toggleDropdown: ComboboxStore['toggleDropdown'] = useCallback(\n    (eventSource = 'unknown') => {\n      if (dropdownOpened) {\n        closeDropdown(eventSource);\n      } else {\n        openDropdown(eventSource);\n      }\n    },\n    [closeDropdown, openDropdown, dropdownOpened]\n  );\n\n  const selectOption = useCallback(\n    (index: number) => {\n      if (totalOptionsCount === 0) {\n        setSelectedOptionIndex(-1);\n        return null;\n      }\n\n      const nextIndex = index >= totalOptionsCount ? 0 : index < 0 ? totalOptionsCount - 1 : index;\n\n      if (isOptionDisabled(nextIndex)) {\n        return null;\n      }\n\n      setSelectedOptionIndex(nextIndex);\n      return getOptionId(nextIndex);\n    },\n    [totalOptionsCount, isOptionDisabled, setSelectedOptionIndex, getOptionId]\n  );\n\n  const selectActiveOption = useCallback(\n    () => selectOption(activeOptionIndex ?? 0),\n    [selectOption, activeOptionIndex]\n  );\n\n  const selectNextOption = useCallback(\n    () =>\n      selectOption(\n        getNextIndex({\n          currentIndex: selectedOptionIndex,\n          isOptionDisabled,\n          totalOptionsCount,\n          loop,\n        })\n      ),\n    [selectOption, selectedOptionIndex, isOptionDisabled, totalOptionsCount, loop]\n  );\n\n  const selectPreviousOption = useCallback(\n    () =>\n      selectOption(\n        getPreviousIndex({\n          currentIndex: selectedOptionIndex,\n          isOptionDisabled,\n          totalOptionsCount,\n          loop,\n        })\n      ),\n    [selectOption, selectedOptionIndex, isOptionDisabled, totalOptionsCount, loop]\n  );\n\n  const selectFirstOption = useCallback(\n    () => selectOption(getFirstIndex({ isOptionDisabled, totalOptionsCount })),\n    [selectOption, isOptionDisabled, totalOptionsCount]\n  );\n\n  const resetSelectedOption = useCallback(() => {\n    setSelectedOptionIndex(-1);\n  }, [setSelectedOptionIndex]);\n\n  const clickSelectedOption = useCallback(() => {\n    if (\n      selectedOptionIndex >= 0 &&\n      selectedOptionIndex < totalOptionsCount &&\n      !isOptionDisabled(selectedOptionIndex)\n    ) {\n      onSelectedOptionSubmit?.(selectedOptionIndex);\n    }\n  }, [selectedOptionIndex, totalOptionsCount, isOptionDisabled, onSelectedOptionSubmit]);\n\n  const setListId = useCallback((id: string) => {\n    listId.current = id;\n  }, []);\n\n  const focusSearchInput = useCallback(() => {\n    focusSearchTimeout.current = window.setTimeout(() => searchRef.current?.focus(), 0);\n  }, []);\n\n  const focusTarget = useCallback(() => {\n    focusTargetTimeout.current = window.setTimeout(() => targetRef.current?.focus(), 0);\n  }, []);\n\n  useEffect(\n    () => () => {\n      window.clearTimeout(focusSearchTimeout.current);\n      window.clearTimeout(focusTargetTimeout.current);\n    },\n    []\n  );\n\n  const getSelectedOptionIndex = useCallback(() => selectedOptionIndex, [selectedOptionIndex]);\n\n  const updateSelectedOptionIndex: ComboboxStore['updateSelectedOptionIndex'] = useCallback(\n    (index?: 'active' | 'selected' | number) => {\n      if (typeof index === 'number') {\n        setSelectedOptionIndex(index);\n      }\n\n      if (index === 'active' && typeof activeOptionIndex === 'number') {\n        setSelectedOptionIndex(activeOptionIndex);\n      }\n    },\n    [setSelectedOptionIndex, activeOptionIndex]\n  );\n\n  return {\n    dropdownOpened,\n    openDropdown,\n    closeDropdown,\n    toggleDropdown,\n\n    selectedOptionIndex,\n    getSelectedOptionIndex,\n    selectOption,\n    selectFirstOption,\n    selectActiveOption,\n    selectNextOption,\n    selectPreviousOption,\n    resetSelectedOption,\n    updateSelectedOptionIndex,\n\n    listId: listId.current,\n    setListId,\n    clickSelectedOption,\n\n    searchRef,\n    focusSearchInput,\n\n    targetRef,\n    focusTarget,\n  };\n}\n"],"mappings":"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"}