UNPKG

@konstructio/ui

Version:

A set of reusable and customizable React components built for konstruct.io

104 lines (103 loc) 2.57 kB
import { useRef as m, useEffect as c, useCallback as b } from "react"; import { useDropdownContext as L } from "../contexts/dropdown.hook.js"; const p = ({ ulRef: f, inputRef: t, disabled: w, internalValue: u, onBlur: g }) => { const r = m(null), a = m(null), { value: i, setSearchTerm: v, setCanFilter: d, toggleOpen: n } = L(); c(() => { const e = new AbortController(), o = (l) => { l.key === "Escape" && n(!1); }, s = (l) => { r.current?.contains(l.target) || n(!1); }; return document.addEventListener("keydown", o, { signal: e.signal }), document.addEventListener("mousedown", s, { signal: e.signal }), document.addEventListener( "visibilitychange", () => { document.hidden && n(!1); }, { signal: e.signal } ), a.current?.addEventListener( "focusin", (l) => { !w && l.target?.matches(":focus-visible") && n(!0); }, { signal: e.signal } ), () => { e.abort(); }; }, [n, r]), c(() => { const e = new AbortController(); return a.current?.addEventListener( "keydown", (o) => { if (o.key === "ArrowDown") { const s = f.current?.querySelector("li"); s && s.focus(); } }, { signal: e.signal } ), () => { e.abort(); }; }, [a, f]), c(() => { const e = new AbortController(); return t?.current?.addEventListener( "focusin", () => { v(u?.value ?? ""), d(!1); }, { signal: e.signal } ), t?.current?.addEventListener( "focusout", () => { d(!0); }, { signal: e.signal } ), a.current?.addEventListener( "focus", () => { d(!1); }, { signal: e.signal } ), r.current?.addEventListener( "focusout", (o) => { r.current?.contains(o.relatedTarget) || n(!1); }, { signal: e.signal } ), () => { e.abort(); }; }, [i]), c(() => { t?.current && (t.current.value = i && u?.value || ""); }, [u, i]), c(() => { const e = new AbortController(); return r.current?.addEventListener("focusout", (o) => { const s = o.relatedTarget; (!s || !r.current?.contains(s)) && (t?.current?.value || g?.()); }), () => { e.abort(); }; }, [n, r, v, g, i]); const E = b(() => { n(!0), requestAnimationFrame(() => t?.current?.focus()); }, [t, n]); return { wrapperRef: r, wrapperInputRef: a, handleOpen: E }; }; export { p as useDropdown };