UNPKG

@anoki/fse-ui

Version:

FSE UI components library

626 lines (625 loc) • 22.1 kB
import * as r from "react"; import { composeEventHandlers as M } from "./index.es470.js"; import { createCollection as Xe } from "./index.es482.js"; import { useComposedRefs as k, composeRefs as He } from "./index.es471.js"; import { createContextScope as We } from "./index.es472.js"; import { useDirection as ze } from "./index.es483.js"; import { DismissableLayer as Ze } from "./index.es484.js"; import { useFocusGuards as $e } from "./index.es485.js"; import { FocusScope as qe } from "./index.es486.js"; import { createPopperScope as pe, Root as Je, Anchor as Qe, Content as et, Arrow as tt } from "./index.es487.js"; import { Portal as nt } from "./index.es488.js"; import { Presence as H } from "./index.es489.js"; import { Primitive as N, dispatchDiscreteCustomEvent as ot } from "./index.es474.js"; import { createRovingFocusGroupScope as ve, Item as rt, Root as ct } from "./index.es490.js"; import { createSlot as st } from "./index.es481.js"; import { useCallbackRef as Me } from "./index.es480.js"; import { hideOthers as at } from "./index.es491.js"; import ut from "./index.es492.js"; import { j as u } from "./index.es244.js"; var Q = ["Enter", " "], it = ["ArrowDown", "PageUp", "Home"], he = ["ArrowUp", "PageDown", "End"], lt = [...it, ...he], dt = { ltr: [...Q, "ArrowRight"], rtl: [...Q, "ArrowLeft"] }, ft = { ltr: ["ArrowLeft"], rtl: ["ArrowRight"] }, F = "Menu", [D, mt, pt] = Xe(F), [w, tn] = We(F, [ pt, pe, ve ]), W = pe(), Ce = ve(), [vt, S] = w(F), [Mt, L] = w(F), xe = (e) => { const { __scopeMenu: n, open: t = !1, children: o, dir: a, onOpenChange: c, modal: l = !0 } = e, m = W(n), [p, v] = r.useState(null), f = r.useRef(!1), s = Me(c), d = ze(a); return r.useEffect(() => { const C = () => { f.current = !0, document.addEventListener("pointerdown", h, { capture: !0, once: !0 }), document.addEventListener("pointermove", h, { capture: !0, once: !0 }); }, h = () => f.current = !1; return document.addEventListener("keydown", C, { capture: !0 }), () => { document.removeEventListener("keydown", C, { capture: !0 }), document.removeEventListener("pointerdown", h, { capture: !0 }), document.removeEventListener("pointermove", h, { capture: !0 }); }; }, []), /* @__PURE__ */ u.jsx(Je, { ...m, children: /* @__PURE__ */ u.jsx( vt, { scope: n, open: t, onOpenChange: s, content: p, onContentChange: v, children: /* @__PURE__ */ u.jsx( Mt, { scope: n, onClose: r.useCallback(() => s(!1), [s]), isUsingKeyboardRef: f, dir: d, modal: l, children: o } ) } ) }); }; xe.displayName = F; var ht = "MenuAnchor", ee = r.forwardRef( (e, n) => { const { __scopeMenu: t, ...o } = e, a = W(t); return /* @__PURE__ */ u.jsx(Qe, { ...a, ...o, ref: n }); } ); ee.displayName = ht; var te = "MenuPortal", [Ct, _e] = w(te, { forceMount: void 0 }), ge = (e) => { const { __scopeMenu: n, forceMount: t, children: o, container: a } = e, c = S(te, n); return /* @__PURE__ */ u.jsx(Ct, { scope: n, forceMount: t, children: /* @__PURE__ */ u.jsx(H, { present: t || c.open, children: /* @__PURE__ */ u.jsx(nt, { asChild: !0, container: a, children: o }) }) }); }; ge.displayName = te; var _ = "MenuContent", [xt, ne] = w(_), Re = r.forwardRef( (e, n) => { const t = _e(_, e.__scopeMenu), { forceMount: o = t.forceMount, ...a } = e, c = S(_, e.__scopeMenu), l = L(_, e.__scopeMenu); return /* @__PURE__ */ u.jsx(D.Provider, { scope: e.__scopeMenu, children: /* @__PURE__ */ u.jsx(H, { present: o || c.open, children: /* @__PURE__ */ u.jsx(D.Slot, { scope: e.__scopeMenu, children: l.modal ? /* @__PURE__ */ u.jsx(_t, { ...a, ref: n }) : /* @__PURE__ */ u.jsx(gt, { ...a, ref: n }) }) }) }); } ), _t = r.forwardRef( (e, n) => { const t = S(_, e.__scopeMenu), o = r.useRef(null), a = k(n, o); return r.useEffect(() => { const c = o.current; if (c) return at(c); }, []), /* @__PURE__ */ u.jsx( oe, { ...e, ref: a, trapFocus: t.open, disableOutsidePointerEvents: t.open, disableOutsideScroll: !0, onFocusOutside: M( e.onFocusOutside, (c) => c.preventDefault(), { checkForDefaultPrevented: !1 } ), onDismiss: () => t.onOpenChange(!1) } ); } ), gt = r.forwardRef((e, n) => { const t = S(_, e.__scopeMenu); return /* @__PURE__ */ u.jsx( oe, { ...e, ref: n, trapFocus: !1, disableOutsidePointerEvents: !1, disableOutsideScroll: !1, onDismiss: () => t.onOpenChange(!1) } ); }), Rt = st("MenuContent.ScrollLock"), oe = r.forwardRef( (e, n) => { const { __scopeMenu: t, loop: o = !1, trapFocus: a, onOpenAutoFocus: c, onCloseAutoFocus: l, disableOutsidePointerEvents: m, onEntryFocus: p, onEscapeKeyDown: v, onPointerDownOutside: f, onFocusOutside: s, onInteractOutside: d, onDismiss: C, disableOutsideScroll: h, ...E } = e, I = S(_, t), T = L(_, t), K = W(t), G = Ce(t), ae = mt(t), [Ke, ue] = r.useState(null), U = r.useRef(null), Ge = k(n, U, I.onContentChange), B = r.useRef(0), V = r.useRef(""), Ue = r.useRef(0), Z = r.useRef(null), ie = r.useRef("right"), $ = r.useRef(0), Be = h ? ut : r.Fragment, Ve = h ? { as: Rt, allowPinchZoom: !0 } : void 0, Ye = (i) => { var b, de; const x = V.current + i, g = ae().filter((R) => !R.disabled), P = document.activeElement, q = (b = g.find((R) => R.ref.current === P)) == null ? void 0 : b.textValue, J = g.map((R) => R.textValue), le = jt(J, x, q), A = (de = g.find((R) => R.textValue === le)) == null ? void 0 : de.ref.current; (function R(fe) { V.current = fe, window.clearTimeout(B.current), fe !== "" && (B.current = window.setTimeout(() => R(""), 1e3)); })(x), A && setTimeout(() => A.focus()); }; r.useEffect(() => () => window.clearTimeout(B.current), []), $e(); const y = r.useCallback((i) => { var g, P; return ie.current === ((g = Z.current) == null ? void 0 : g.side) && Nt(i, (P = Z.current) == null ? void 0 : P.area); }, []); return /* @__PURE__ */ u.jsx( xt, { scope: t, searchRef: V, onItemEnter: r.useCallback( (i) => { y(i) && i.preventDefault(); }, [y] ), onItemLeave: r.useCallback( (i) => { var x; y(i) || ((x = U.current) == null || x.focus(), ue(null)); }, [y] ), onTriggerLeave: r.useCallback( (i) => { y(i) && i.preventDefault(); }, [y] ), pointerGraceTimerRef: Ue, onPointerGraceIntentChange: r.useCallback((i) => { Z.current = i; }, []), children: /* @__PURE__ */ u.jsx(Be, { ...Ve, children: /* @__PURE__ */ u.jsx( qe, { asChild: !0, trapped: a, onMountAutoFocus: M(c, (i) => { var x; i.preventDefault(), (x = U.current) == null || x.focus({ preventScroll: !0 }); }), onUnmountAutoFocus: l, children: /* @__PURE__ */ u.jsx( Ze, { asChild: !0, disableOutsidePointerEvents: m, onEscapeKeyDown: v, onPointerDownOutside: f, onFocusOutside: s, onInteractOutside: d, onDismiss: C, children: /* @__PURE__ */ u.jsx( ct, { asChild: !0, ...G, dir: T.dir, orientation: "vertical", loop: o, currentTabStopId: Ke, onCurrentTabStopIdChange: ue, onEntryFocus: M(p, (i) => { T.isUsingKeyboardRef.current || i.preventDefault(); }), preventScrollOnEntryFocus: !0, children: /* @__PURE__ */ u.jsx( et, { role: "menu", "aria-orientation": "vertical", "data-state": Le(I.open), "data-radix-menu-content": "", dir: T.dir, ...K, ...E, ref: Ge, style: { outline: "none", ...E.style }, onKeyDown: M(E.onKeyDown, (i) => { const g = i.target.closest("[data-radix-menu-content]") === i.currentTarget, P = i.ctrlKey || i.altKey || i.metaKey, q = i.key.length === 1; g && (i.key === "Tab" && i.preventDefault(), !P && q && Ye(i.key)); const J = U.current; if (i.target !== J || !lt.includes(i.key)) return; i.preventDefault(); const A = ae().filter((b) => !b.disabled).map((b) => b.ref.current); he.includes(i.key) && A.reverse(), Ot(A); }), onBlur: M(e.onBlur, (i) => { i.currentTarget.contains(i.target) || (window.clearTimeout(B.current), V.current = ""); }), onPointerMove: M( e.onPointerMove, j((i) => { const x = i.target, g = $.current !== i.clientX; if (i.currentTarget.contains(x) && g) { const P = i.clientX > $.current ? "right" : "left"; ie.current = P, $.current = i.clientX; } }) ) } ) } ) } ) } ) }) } ); } ); Re.displayName = _; var Pt = "MenuGroup", re = r.forwardRef( (e, n) => { const { __scopeMenu: t, ...o } = e; return /* @__PURE__ */ u.jsx(N.div, { role: "group", ...o, ref: n }); } ); re.displayName = Pt; var Et = "MenuLabel", Pe = r.forwardRef( (e, n) => { const { __scopeMenu: t, ...o } = e; return /* @__PURE__ */ u.jsx(N.div, { ...o, ref: n }); } ); Pe.displayName = Et; var Y = "MenuItem", me = "menu.itemSelect", z = r.forwardRef( (e, n) => { const { disabled: t = !1, onSelect: o, ...a } = e, c = r.useRef(null), l = L(Y, e.__scopeMenu), m = ne(Y, e.__scopeMenu), p = k(n, c), v = r.useRef(!1), f = () => { const s = c.current; if (!t && s) { const d = new CustomEvent(me, { bubbles: !0, cancelable: !0 }); s.addEventListener(me, (C) => o == null ? void 0 : o(C), { once: !0 }), ot(s, d), d.defaultPrevented ? v.current = !1 : l.onClose(); } }; return /* @__PURE__ */ u.jsx( Ee, { ...a, ref: p, disabled: t, onClick: M(e.onClick, f), onPointerDown: (s) => { var d; (d = e.onPointerDown) == null || d.call(e, s), v.current = !0; }, onPointerUp: M(e.onPointerUp, (s) => { var d; v.current || (d = s.currentTarget) == null || d.click(); }), onKeyDown: M(e.onKeyDown, (s) => { const d = m.searchRef.current !== ""; t || d && s.key === " " || Q.includes(s.key) && (s.currentTarget.click(), s.preventDefault()); }) } ); } ); z.displayName = Y; var Ee = r.forwardRef( (e, n) => { const { __scopeMenu: t, disabled: o = !1, textValue: a, ...c } = e, l = ne(Y, t), m = Ce(t), p = r.useRef(null), v = k(n, p), [f, s] = r.useState(!1), [d, C] = r.useState(""); return r.useEffect(() => { const h = p.current; h && C((h.textContent ?? "").trim()); }, [c.children]), /* @__PURE__ */ u.jsx( D.ItemSlot, { scope: t, disabled: o, textValue: a ?? d, children: /* @__PURE__ */ u.jsx(rt, { asChild: !0, ...m, focusable: !o, children: /* @__PURE__ */ u.jsx( N.div, { role: "menuitem", "data-highlighted": f ? "" : void 0, "aria-disabled": o || void 0, "data-disabled": o ? "" : void 0, ...c, ref: v, onPointerMove: M( e.onPointerMove, j((h) => { o ? l.onItemLeave(h) : (l.onItemEnter(h), h.defaultPrevented || h.currentTarget.focus({ preventScroll: !0 })); }) ), onPointerLeave: M( e.onPointerLeave, j((h) => l.onItemLeave(h)) ), onFocus: M(e.onFocus, () => s(!0)), onBlur: M(e.onBlur, () => s(!1)) } ) }) } ); } ), wt = "MenuCheckboxItem", we = r.forwardRef( (e, n) => { const { checked: t = !1, onCheckedChange: o, ...a } = e; return /* @__PURE__ */ u.jsx(Te, { scope: e.__scopeMenu, checked: t, children: /* @__PURE__ */ u.jsx( z, { role: "menuitemcheckbox", "aria-checked": X(t) ? "mixed" : t, ...a, ref: n, "data-state": se(t), onSelect: M( a.onSelect, () => o == null ? void 0 : o(X(t) ? !0 : !t), { checkForDefaultPrevented: !1 } ) } ) }); } ); we.displayName = wt; var Se = "MenuRadioGroup", [St, It] = w( Se, { value: void 0, onValueChange: () => { } } ), Ie = r.forwardRef( (e, n) => { const { value: t, onValueChange: o, ...a } = e, c = Me(o); return /* @__PURE__ */ u.jsx(St, { scope: e.__scopeMenu, value: t, onValueChange: c, children: /* @__PURE__ */ u.jsx(re, { ...a, ref: n }) }); } ); Ie.displayName = Se; var ye = "MenuRadioItem", be = r.forwardRef( (e, n) => { const { value: t, ...o } = e, a = It(ye, e.__scopeMenu), c = t === a.value; return /* @__PURE__ */ u.jsx(Te, { scope: e.__scopeMenu, checked: c, children: /* @__PURE__ */ u.jsx( z, { role: "menuitemradio", "aria-checked": c, ...o, ref: n, "data-state": se(c), onSelect: M( o.onSelect, () => { var l; return (l = a.onValueChange) == null ? void 0 : l.call(a, t); }, { checkForDefaultPrevented: !1 } ) } ) }); } ); be.displayName = ye; var ce = "MenuItemIndicator", [Te, yt] = w( ce, { checked: !1 } ), Ae = r.forwardRef( (e, n) => { const { __scopeMenu: t, forceMount: o, ...a } = e, c = yt(ce, t); return /* @__PURE__ */ u.jsx( H, { present: o || X(c.checked) || c.checked === !0, children: /* @__PURE__ */ u.jsx( N.span, { ...a, ref: n, "data-state": se(c.checked) } ) } ); } ); Ae.displayName = ce; var bt = "MenuSeparator", Oe = r.forwardRef( (e, n) => { const { __scopeMenu: t, ...o } = e; return /* @__PURE__ */ u.jsx( N.div, { role: "separator", "aria-orientation": "horizontal", ...o, ref: n } ); } ); Oe.displayName = bt; var Tt = "MenuArrow", De = r.forwardRef( (e, n) => { const { __scopeMenu: t, ...o } = e, a = W(t); return /* @__PURE__ */ u.jsx(tt, { ...a, ...o, ref: n }); } ); De.displayName = Tt; var At = "MenuSub", [nn, je] = w(At), O = "MenuSubTrigger", ke = r.forwardRef( (e, n) => { const t = S(O, e.__scopeMenu), o = L(O, e.__scopeMenu), a = je(O, e.__scopeMenu), c = ne(O, e.__scopeMenu), l = r.useRef(null), { pointerGraceTimerRef: m, onPointerGraceIntentChange: p } = c, v = { __scopeMenu: e.__scopeMenu }, f = r.useCallback(() => { l.current && window.clearTimeout(l.current), l.current = null; }, []); return r.useEffect(() => f, [f]), r.useEffect(() => { const s = m.current; return () => { window.clearTimeout(s), p(null); }; }, [m, p]), /* @__PURE__ */ u.jsx(ee, { asChild: !0, ...v, children: /* @__PURE__ */ u.jsx( Ee, { id: a.triggerId, "aria-haspopup": "menu", "aria-expanded": t.open, "aria-controls": a.contentId, "data-state": Le(t.open), ...e, ref: He(n, a.onTriggerChange), onClick: (s) => { var d; (d = e.onClick) == null || d.call(e, s), !(e.disabled || s.defaultPrevented) && (s.currentTarget.focus(), t.open || t.onOpenChange(!0)); }, onPointerMove: M( e.onPointerMove, j((s) => { c.onItemEnter(s), !s.defaultPrevented && !e.disabled && !t.open && !l.current && (c.onPointerGraceIntentChange(null), l.current = window.setTimeout(() => { t.onOpenChange(!0), f(); }, 100)); }) ), onPointerLeave: M( e.onPointerLeave, j((s) => { var C, h; f(); const d = (C = t.content) == null ? void 0 : C.getBoundingClientRect(); if (d) { const E = (h = t.content) == null ? void 0 : h.dataset.side, I = E === "right", T = I ? -5 : 5, K = d[I ? "left" : "right"], G = d[I ? "right" : "left"]; c.onPointerGraceIntentChange({ area: [ // Apply a bleed on clientX to ensure that our exit point is // consistently within polygon bounds { x: s.clientX + T, y: s.clientY }, { x: K, y: d.top }, { x: G, y: d.top }, { x: G, y: d.bottom }, { x: K, y: d.bottom } ], side: E }), window.clearTimeout(m.current), m.current = window.setTimeout( () => c.onPointerGraceIntentChange(null), 300 ); } else { if (c.onTriggerLeave(s), s.defaultPrevented) return; c.onPointerGraceIntentChange(null); } }) ), onKeyDown: M(e.onKeyDown, (s) => { var C; const d = c.searchRef.current !== ""; e.disabled || d && s.key === " " || dt[o.dir].includes(s.key) && (t.onOpenChange(!0), (C = t.content) == null || C.focus(), s.preventDefault()); }) } ) }); } ); ke.displayName = O; var Ne = "MenuSubContent", Fe = r.forwardRef( (e, n) => { const t = _e(_, e.__scopeMenu), { forceMount: o = t.forceMount, ...a } = e, c = S(_, e.__scopeMenu), l = L(_, e.__scopeMenu), m = je(Ne, e.__scopeMenu), p = r.useRef(null), v = k(n, p); return /* @__PURE__ */ u.jsx(D.Provider, { scope: e.__scopeMenu, children: /* @__PURE__ */ u.jsx(H, { present: o || c.open, children: /* @__PURE__ */ u.jsx(D.Slot, { scope: e.__scopeMenu, children: /* @__PURE__ */ u.jsx( oe, { id: m.contentId, "aria-labelledby": m.triggerId, ...a, ref: v, align: "start", side: l.dir === "rtl" ? "left" : "right", disableOutsidePointerEvents: !1, disableOutsideScroll: !1, trapFocus: !1, onOpenAutoFocus: (f) => { var s; l.isUsingKeyboardRef.current && ((s = p.current) == null || s.focus()), f.preventDefault(); }, onCloseAutoFocus: (f) => f.preventDefault(), onFocusOutside: M(e.onFocusOutside, (f) => { f.target !== m.trigger && c.onOpenChange(!1); }), onEscapeKeyDown: M(e.onEscapeKeyDown, (f) => { l.onClose(), f.preventDefault(); }), onKeyDown: M(e.onKeyDown, (f) => { var C; const s = f.currentTarget.contains(f.target), d = ft[l.dir].includes(f.key); s && d && (c.onOpenChange(!1), (C = m.trigger) == null || C.focus(), f.preventDefault()); }) } ) }) }) }); } ); Fe.displayName = Ne; function Le(e) { return e ? "open" : "closed"; } function X(e) { return e === "indeterminate"; } function se(e) { return X(e) ? "indeterminate" : e ? "checked" : "unchecked"; } function Ot(e) { const n = document.activeElement; for (const t of e) if (t === n || (t.focus(), document.activeElement !== n)) return; } function Dt(e, n) { return e.map((t, o) => e[(n + o) % e.length]); } function jt(e, n, t) { const a = n.length > 1 && Array.from(n).every((v) => v === n[0]) ? n[0] : n, c = t ? e.indexOf(t) : -1; let l = Dt(e, Math.max(c, 0)); a.length === 1 && (l = l.filter((v) => v !== t)); const p = l.find( (v) => v.toLowerCase().startsWith(a.toLowerCase()) ); return p !== t ? p : void 0; } function kt(e, n) { const { x: t, y: o } = e; let a = !1; for (let c = 0, l = n.length - 1; c < n.length; l = c++) { const m = n[c].x, p = n[c].y, v = n[l].x, f = n[l].y; p > o != f > o && t < (v - m) * (o - p) / (f - p) + m && (a = !a); } return a; } function Nt(e, n) { if (!n) return !1; const t = { x: e.clientX, y: e.clientY }; return kt(t, n); } function j(e) { return (n) => n.pointerType === "mouse" ? e(n) : void 0; } var on = xe, rn = ee, cn = ge, sn = Re, an = re, un = Pe, ln = z, dn = we, fn = Ie, mn = be, pn = Ae, vn = Oe, Mn = De, hn = ke, Cn = Fe; export { rn as Anchor, Mn as Arrow, dn as CheckboxItem, sn as Content, an as Group, ln as Item, pn as ItemIndicator, un as Label, xe as Menu, ee as MenuAnchor, De as MenuArrow, we as MenuCheckboxItem, Re as MenuContent, re as MenuGroup, z as MenuItem, Ae as MenuItemIndicator, Pe as MenuLabel, ge as MenuPortal, Ie as MenuRadioGroup, be as MenuRadioItem, Oe as MenuSeparator, Fe as MenuSubContent, ke as MenuSubTrigger, cn as Portal, fn as RadioGroup, mn as RadioItem, on as Root, vn as Separator, Cn as SubContent, hn as SubTrigger, tn as createMenuScope }; //# sourceMappingURL=index.es475.js.map