@mantine/core
Version:
React components library focused on usability, accessibility and developer experience
166 lines (165 loc) • 7.51 kB
JavaScript
"use client";
require("../../../_virtual/_rolldown/runtime.cjs");
const require_find_element_in_shadow_dom = require("../../../core/utils/find-element-in-shadow-dom/find-element-in-shadow-dom.cjs");
const require_get_index = require("./get-index/get-index.cjs");
let react = require("react");
let _mantine_hooks = require("@mantine/hooks");
//#region packages/@mantine/core/src/components/Combobox/use-combobox/use-combobox.ts
function useCombobox({ defaultOpened, opened, onOpenedChange, onDropdownClose, onDropdownOpen, loop = true, scrollBehavior = "instant" } = {}) {
const [dropdownOpened, setDropdownOpened] = (0, _mantine_hooks.useUncontrolled)({
value: opened,
defaultValue: defaultOpened,
finalValue: false,
onChange: onOpenedChange
});
const listId = (0, react.useRef)(null);
const selectedOptionIndex = (0, react.useRef)(-1);
const searchRef = (0, react.useRef)(null);
const targetRef = (0, react.useRef)(null);
const focusSearchTimeout = (0, react.useRef)(-1);
const focusTargetTimeout = (0, react.useRef)(-1);
const selectedIndexUpdateTimeout = (0, react.useRef)(-1);
const openDropdown = (0, react.useCallback)((eventSource = "unknown") => {
if (!dropdownOpened) {
setDropdownOpened(true);
onDropdownOpen?.(eventSource);
}
}, [
setDropdownOpened,
onDropdownOpen,
dropdownOpened
]);
const closeDropdown = (0, react.useCallback)((eventSource = "unknown") => {
if (dropdownOpened) {
setDropdownOpened(false);
onDropdownClose?.(eventSource);
}
}, [
setDropdownOpened,
onDropdownClose,
dropdownOpened
]);
const toggleDropdown = (0, react.useCallback)((eventSource = "unknown") => {
if (dropdownOpened) closeDropdown(eventSource);
else openDropdown(eventSource);
}, [
closeDropdown,
openDropdown,
dropdownOpened
]);
const clearSelectedItem = (0, react.useCallback)(() => {
const root = require_find_element_in_shadow_dom.getRootElement(targetRef.current);
const selected = require_find_element_in_shadow_dom.findElementBySelector(`#${listId.current} [data-combobox-selected]`, root);
selected?.removeAttribute("data-combobox-selected");
selected?.removeAttribute("aria-selected");
}, []);
const selectOption = (0, react.useCallback)((index) => {
const root = require_find_element_in_shadow_dom.getRootElement(targetRef.current);
const list = require_find_element_in_shadow_dom.findElementBySelector(`#${listId.current}`, root);
const items = list ? require_find_element_in_shadow_dom.findElementsBySelector("[data-combobox-option]", list) : null;
if (!items) return null;
const nextIndex = index >= items.length ? 0 : index < 0 ? items.length - 1 : index;
selectedOptionIndex.current = nextIndex;
if (items?.[nextIndex] && !items[nextIndex].hasAttribute("data-combobox-disabled")) {
clearSelectedItem();
items[nextIndex].setAttribute("data-combobox-selected", "true");
items[nextIndex].setAttribute("aria-selected", "true");
items[nextIndex].scrollIntoView({
block: "nearest",
behavior: scrollBehavior
});
return items[nextIndex].id;
}
return null;
}, [scrollBehavior, clearSelectedItem]);
const selectActiveOption = (0, react.useCallback)(() => {
const root = require_find_element_in_shadow_dom.getRootElement(targetRef.current);
const activeOption = require_find_element_in_shadow_dom.findElementBySelector(`#${listId.current} [data-combobox-active]`, root);
if (activeOption) return selectOption(require_find_element_in_shadow_dom.findElementsBySelector(`#${listId.current} [data-combobox-option]`, root).findIndex((option) => option === activeOption));
return selectOption(0);
}, [selectOption]);
const selectNextOption = (0, react.useCallback)(() => {
const root = require_find_element_in_shadow_dom.getRootElement(targetRef.current);
const items = require_find_element_in_shadow_dom.findElementsBySelector(`#${listId.current} [data-combobox-option]`, root);
return selectOption(require_get_index.getNextIndex(selectedOptionIndex.current, items, loop));
}, [selectOption, loop]);
const selectPreviousOption = (0, react.useCallback)(() => {
const root = require_find_element_in_shadow_dom.getRootElement(targetRef.current);
const items = require_find_element_in_shadow_dom.findElementsBySelector(`#${listId.current} [data-combobox-option]`, root);
return selectOption(require_get_index.getPreviousIndex(selectedOptionIndex.current, items, loop));
}, [selectOption, loop]);
const selectFirstOption = (0, react.useCallback)(() => {
const root = require_find_element_in_shadow_dom.getRootElement(targetRef.current);
return selectOption(require_get_index.getFirstIndex(require_find_element_in_shadow_dom.findElementsBySelector(`#${listId.current} [data-combobox-option]`, root)));
}, [selectOption]);
const updateSelectedOptionIndex = (0, react.useCallback)((target = "selected", options) => {
if (typeof target === "number") {
selectedOptionIndex.current = target;
const root = require_find_element_in_shadow_dom.getRootElement(targetRef.current);
const items = require_find_element_in_shadow_dom.findElementsBySelector(`#${listId.current} [data-combobox-option]`, root);
if (options?.scrollIntoView) items[target]?.scrollIntoView({
block: "nearest",
behavior: scrollBehavior
});
return;
}
selectedIndexUpdateTimeout.current = window.setTimeout(() => {
const root = require_find_element_in_shadow_dom.getRootElement(targetRef.current);
const items = require_find_element_in_shadow_dom.findElementsBySelector(`#${listId.current} [data-combobox-option]`, root);
const index = items.findIndex((option) => option.hasAttribute(`data-combobox-${target}`));
selectedOptionIndex.current = index;
if (options?.scrollIntoView) items[index]?.scrollIntoView({
block: "nearest",
behavior: scrollBehavior
});
}, 0);
}, []);
const resetSelectedOption = (0, react.useCallback)(() => {
selectedOptionIndex.current = -1;
clearSelectedItem();
}, [clearSelectedItem]);
const clickSelectedOption = (0, react.useCallback)(() => {
const root = require_find_element_in_shadow_dom.getRootElement(targetRef.current);
(require_find_element_in_shadow_dom.findElementsBySelector(`#${listId.current} [data-combobox-option]`, root)?.[selectedOptionIndex.current])?.click();
}, []);
const setListId = (0, react.useCallback)((id) => {
listId.current = id;
}, []);
const focusSearchInput = (0, react.useCallback)(() => {
focusSearchTimeout.current = window.setTimeout(() => searchRef.current?.focus(), 0);
}, []);
const focusTarget = (0, react.useCallback)(() => {
focusTargetTimeout.current = window.setTimeout(() => targetRef.current?.focus(), 0);
}, []);
const getSelectedOptionIndex = (0, react.useCallback)(() => selectedOptionIndex.current, []);
(0, react.useEffect)(() => () => {
window.clearTimeout(focusSearchTimeout.current);
window.clearTimeout(focusTargetTimeout.current);
window.clearTimeout(selectedIndexUpdateTimeout.current);
}, []);
return {
dropdownOpened,
openDropdown,
closeDropdown,
toggleDropdown,
selectedOptionIndex: selectedOptionIndex.current,
getSelectedOptionIndex,
selectOption,
selectFirstOption,
selectActiveOption,
selectNextOption,
selectPreviousOption,
resetSelectedOption,
updateSelectedOptionIndex,
listId: listId.current,
setListId,
clickSelectedOption,
searchRef,
focusSearchInput,
targetRef,
focusTarget
};
}
//#endregion
exports.useCombobox = useCombobox;
//# sourceMappingURL=use-combobox.cjs.map