@1771technologies/lytenyte-pro
Version:
Blazingly fast headless React data grid with 100s of features.
127 lines (126 loc) • 5.35 kB
JavaScript
import { useMemo } from "react";
import { useSmartSelect } from "../context.js";
import { isSelectableOption } from "./is-selectable-option.js";
export function useSelectControls(isMulti, setActiveChip) {
const { open, onOpenChange, openOnClick, setActiveId, container, rtl, trigger, onOptionsChange, kindAndValue: { value }, openKeys, closeKeys, options, onOptionSelect, } = useSmartSelect();
return useMemo(() => {
return {
onClick: () => {
if (!open && openOnClick)
onOpenChange(true);
},
onBlur: (e) => {
if (e.currentTarget.contains(e.relatedTarget))
return;
onOpenChange(false);
return;
},
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) {
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 (!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,
open,
openKeys,
openOnClick,
options,
rtl,
setActiveChip,
setActiveId,
trigger,
value,
]);
}