UNPKG

alinea

Version:
114 lines (112 loc) 3.11 kB
import "../../chunks/chunk-NZLE2WMY.js"; // src/dashboard/hook/UseFocusList.tsx import { createContext, useContext, useLayoutEffect, useMemo, useRef } from "react"; import { jsx } from "react/jsx-runtime"; var context = createContext(void 0); function useFocusList({ onClear }) { const focusRef = useRef(); const { reSelect, ...res } = useMemo(() => { const selects = /* @__PURE__ */ new WeakMap(); let current; let items = []; let itemsReset = true; let selectTimeout; function select(element) { if (current) current.removeAttribute("aria-selected"); if (!element) return current = void 0; element.setAttribute("aria-selected", "true"); current = element; current.scrollIntoView({ block: "nearest" }); } function navigate(direction) { if (current) { const index = items.indexOf(current); const next = items[index + direction]; if (next) return select(next); } select(items[direction === 1 ? 0 : items.length - 1]); } function onKeyDown(event) { switch (event.key) { case "ArrowUp": navigate(-1); event.preventDefault(); break; case "ArrowDown": navigate(1); event.preventDefault(); break; case "Escape": event.currentTarget.blur(); event.preventDefault(); onClear(); break; case "Enter": event.preventDefault(); selects.get(current ?? items[0])?.(); break; default: } } const focusProps = { ref: focusRef, onKeyDown, /*onFocus() { selectFirst() },*/ onBlur() { select(void 0); itemsReset = true; } }; function registerItem(onSelect, element) { let i = 0; for (const item of items) { const position = element.compareDocumentPosition(item); if (position & Node.DOCUMENT_POSITION_FOLLOWING) break; i++; } items.splice(i, 0, element); selects.set(element, onSelect); return () => { if (current === element) current = void 0; items = items.filter((item) => item !== element); }; } function Container({ children }) { return /* @__PURE__ */ jsx(context.Provider, { value: { registerItem }, children }); } function selectFirst() { if (document.activeElement !== focusRef.current && !focusRef.current?.contains(document.activeElement)) return; if (!itemsReset) return; if (!current) select(items[0]); itemsReset = false; } function reSelect2() { itemsReset = true; } return { focusProps, Container, reSelect: reSelect2 }; }, []); useLayoutEffect(reSelect); return res; } function useFocusListItem(onSelect) { const ctx = useContext(context); const itemRef = useRef(null); useLayoutEffect(() => { if (itemRef.current && ctx) return ctx.registerItem(onSelect, itemRef.current); }, []); return itemRef; } export { useFocusList, useFocusListItem };