UNPKG

@mantine/core

Version:

React components library focused on usability, accessibility and developer experience

153 lines (152 loc) 4.75 kB
"use client"; import { getFirstIndex, getNextIndex, getPreviousIndex } from "./get-index/get-virtualized-index.mjs"; import { useCallback, useEffect, useRef } from "react"; import { useUncontrolled } from "@mantine/hooks"; //#region packages/@mantine/core/src/components/Combobox/use-combobox/use-virtualized-combobox.ts function useVirtualizedCombobox({ defaultOpened, opened, onOpenedChange, onDropdownClose, onDropdownOpen, loop = true, totalOptionsCount, isOptionDisabled = () => false, getOptionId, selectedOptionIndex, setSelectedOptionIndex, activeOptionIndex, onSelectedOptionSubmit } = { totalOptionsCount: 0, getOptionId: () => null, selectedOptionIndex: -1, setSelectedOptionIndex: () => {}, onSelectedOptionSubmit: () => {} }) { const [dropdownOpened, setDropdownOpened] = useUncontrolled({ value: opened, defaultValue: defaultOpened, finalValue: false, onChange: onOpenedChange }); const listId = useRef(null); const searchRef = useRef(null); const targetRef = useRef(null); const focusSearchTimeout = useRef(-1); const focusTargetTimeout = useRef(-1); const openDropdown = useCallback((eventSource = "unknown") => { if (!dropdownOpened) { setDropdownOpened(true); onDropdownOpen?.(eventSource); } }, [ setDropdownOpened, onDropdownOpen, dropdownOpened ]); const closeDropdown = useCallback((eventSource = "unknown") => { if (dropdownOpened) { setDropdownOpened(false); onDropdownClose?.(eventSource); } }, [ setDropdownOpened, onDropdownClose, dropdownOpened ]); const toggleDropdown = useCallback((eventSource = "unknown") => { if (dropdownOpened) closeDropdown(eventSource); else openDropdown(eventSource); }, [ closeDropdown, openDropdown, dropdownOpened ]); const selectOption = useCallback((index) => { if (totalOptionsCount === 0) { setSelectedOptionIndex(-1); return null; } const nextIndex = index >= totalOptionsCount ? 0 : index < 0 ? totalOptionsCount - 1 : index; if (isOptionDisabled(nextIndex)) return null; setSelectedOptionIndex(nextIndex); return getOptionId(nextIndex); }, [ totalOptionsCount, isOptionDisabled, setSelectedOptionIndex, getOptionId ]); const selectActiveOption = useCallback(() => selectOption(activeOptionIndex ?? 0), [selectOption, activeOptionIndex]); const selectNextOption = useCallback(() => selectOption(getNextIndex({ currentIndex: selectedOptionIndex, isOptionDisabled, totalOptionsCount, loop })), [ selectOption, selectedOptionIndex, isOptionDisabled, totalOptionsCount, loop ]); const selectPreviousOption = useCallback(() => selectOption(getPreviousIndex({ currentIndex: selectedOptionIndex, isOptionDisabled, totalOptionsCount, loop })), [ selectOption, selectedOptionIndex, isOptionDisabled, totalOptionsCount, loop ]); const selectFirstOption = useCallback(() => selectOption(getFirstIndex({ isOptionDisabled, totalOptionsCount })), [ selectOption, isOptionDisabled, totalOptionsCount ]); const resetSelectedOption = useCallback(() => { setSelectedOptionIndex(-1); }, [setSelectedOptionIndex]); const clickSelectedOption = useCallback(() => { if (selectedOptionIndex >= 0 && selectedOptionIndex < totalOptionsCount && !isOptionDisabled(selectedOptionIndex)) onSelectedOptionSubmit?.(selectedOptionIndex); }, [ selectedOptionIndex, totalOptionsCount, isOptionDisabled, onSelectedOptionSubmit ]); const setListId = useCallback((id) => { listId.current = id; }, []); const focusSearchInput = useCallback(() => { focusSearchTimeout.current = window.setTimeout(() => searchRef.current?.focus(), 0); }, []); const focusTarget = useCallback(() => { focusTargetTimeout.current = window.setTimeout(() => targetRef.current?.focus(), 0); }, []); useEffect(() => () => { window.clearTimeout(focusSearchTimeout.current); window.clearTimeout(focusTargetTimeout.current); }, []); return { dropdownOpened, openDropdown, closeDropdown, toggleDropdown, selectedOptionIndex, getSelectedOptionIndex: useCallback(() => selectedOptionIndex, [selectedOptionIndex]), selectOption, selectFirstOption, selectActiveOption, selectNextOption, selectPreviousOption, resetSelectedOption, updateSelectedOptionIndex: useCallback((index) => { if (typeof index === "number") setSelectedOptionIndex(index); if (index === "active" && typeof activeOptionIndex === "number") setSelectedOptionIndex(activeOptionIndex); }, [setSelectedOptionIndex, activeOptionIndex]), listId: listId.current, setListId, clickSelectedOption, searchRef, focusSearchInput, targetRef, focusTarget }; } //#endregion export { useVirtualizedCombobox }; //# sourceMappingURL=use-virtualized-combobox.mjs.map