UNPKG

@1771technologies/lytenyte-pro

Version:

Blazingly fast headless React data grid with 100s of features.

146 lines (145 loc) 6.01 kB
import { useMemo } from "react"; import { useSmartSelect } from "../context.js"; import { isSelectableOption } from "./is-selectable-option.js"; export function useComboControls(setActiveChip, isMulti) { const { query, open, openOnClick, preventNextOpen, onOpenChange, setActiveId, container, onQueryChange, onOptionsChange, onOptionSelect, trigger, kindAndValue: { value }, rtl, closeKeys, openKeys, options, } = useSmartSelect(); return useMemo(() => { return { onClick: () => { if (!open && openOnClick && !preventNextOpen.current) { onOpenChange(true); } }, onFocus: () => { setActiveChip(null); }, onBlur: (e) => { if (e.currentTarget.contains(e.relatedTarget)) return; onOpenChange(false); return; }, value: query, onChange: (ev) => { onQueryChange(ev.target.value); if (!open) onOpenChange(true); }, onKeyDown: (e) => { if (!open && openKeys.includes(e.key)) { e.preventDefault(); e.stopPropagation(); onOpenChange(true); return; } if (open && closeKeys.includes(e.key)) { e.preventDefault(); e.stopPropagation(); onOpenChange(false); return; } if ((e.key === "Enter" || e.key === " ") && open) { e.preventDefault(); e.stopPropagation(); const active = container?.querySelector('[data-ln-active="true"]'); if (!active) return; const id = active.getAttribute("data-ln-smart-option"); const option = options.find((x) => x.id === id); if (!option) return; onOptionSelect(option); if (active.getAttribute("data-ln-close-on-select")) { onOpenChange(false); } return; } if (isMulti && query.length === 0) { const key = rtl ? "ArrowRight" : "ArrowLeft"; if (e.key === "Backspace") { const chips = Array.from(trigger.querySelectorAll("[data-ln-smart-select-chip]")); const lastChip = chips.at(-1); if (!lastChip) return; const id = lastChip.getAttribute("data-ln-smart-select-chip"); onOptionsChange(value.filter((x) => x.id !== id)); return; } if (e.key === key) { const chips = Array.from(trigger.querySelectorAll("[data-ln-smart-select-chip]")); const first = chips.at(-1); if (!first) return; first.focus(); onOpenChange(false); setActiveChip(first.getAttribute("data-ln-smart-select-chip")); return; } } if (e.key === "ArrowDown" && !open) { e.preventDefault(); e.stopPropagation(); onOpenChange(true); return; } if (!open || !container) return; if (e.key === "ArrowUp") { e.preventDefault(); e.stopPropagation(); const active = container.querySelector('[data-ln-active="true"]'); let current = active?.previousElementSibling; while (current && !isSelectableOption(current)) current = current.previousElementSibling; if (!current) { current = container.lastElementChild; while (current && !isSelectableOption(current)) current = current.previousElementSibling; } if (current) { setActiveId(current.getAttribute("data-ln-smart-option")); current.scrollIntoView({ block: "nearest" }); } return; } if (e.key === "ArrowDown") { e.preventDefault(); e.stopPropagation(); const active = container.querySelector('[data-ln-active="true"]'); let current = active?.nextElementSibling; while (current && !isSelectableOption(current)) current = current.nextElementSibling; if (!current) { current = container.firstElementChild; while (current && !isSelectableOption(current)) current = current.nextElementSibling; } if (current) { setActiveId(current.getAttribute("data-ln-smart-option")); current.scrollIntoView({ block: "nearest" }); } return; } }, }; }, [ closeKeys, container, isMulti, onOpenChange, onOptionSelect, onOptionsChange, onQueryChange, open, openKeys, openOnClick, options, preventNextOpen, query, rtl, setActiveChip, setActiveId, trigger, value, ]); }