UNPKG

@frank-auth/react

Version:

Flexible and customizable React UI components for Frank Authentication

403 lines (391 loc) 10.5 kB
'use client'; import { jsx as l, jsxs as C } from "react/jsx-runtime"; import { useTheme as T } from "../../../theme/context.js"; import { getColorVariant as x } from "../../../theme/styled.js"; import { css as i } from "@emotion/react"; import g from "@emotion/styled"; import P, { useState as V, useRef as Z, useEffect as _, useMemo as M, useCallback as E } from "react"; const ee = (e) => { const { theme: n, variant: d = "flat", color: a = "primary" } = e, o = x(n, a, 500); switch (d) { case "flat": return i` background-color: ${n.colors.background.secondary}; border: 1px solid transparent; `; case "bordered": return i` background-color: ${n.colors.background.primary}; border: 1px solid ${n.colors.border.primary}; `; case "light": return i` background-color: ${x(n, a, 50)}; border: 1px solid transparent; `; case "solid": return i` background-color: ${o}; border: 1px solid ${o}; color: ${n.colors.text.inverse}; `; default: return i``; } }, te = (e) => { const { theme: n, itemHeight: d = "md" } = e; switch (d) { case "sm": return i` min-height: ${n.spacing[8]}; padding: ${n.spacing[2]} ${n.spacing[3]}; font-size: ${n.fontSizes.sm}; `; case "md": return i` min-height: ${n.spacing[10]}; padding: ${n.spacing[3]} ${n.spacing[4]}; font-size: ${n.fontSizes.base}; `; case "lg": return i` min-height: ${n.spacing[12]}; padding: ${n.spacing[4]} ${n.spacing[6]}; font-size: ${n.fontSizes.lg}; `; default: return i``; } }, ne = (e) => { const { theme: n, isSelected: d, isFocused: a, isDisabled: o, color: c = "primary" } = e, y = x(n, c, 500), w = x(n, c, 50); if (o) return i` opacity: 0.5; cursor: not-allowed; pointer-events: none; `; let f = i` cursor: pointer; transition: all ${n.transitions.fast}; &:hover { background-color: ${n.colors.background.tertiary}; } `; return d && (f = i` ${f} background-color: ${w}; color: ${x(n, c, 700)}; &:hover { background-color: ${x(n, c, 100)}; } `), a && (f = i` ${f} outline: 2px solid ${y}; outline-offset: -2px; `), f; }, re = g.div` position: relative; border-radius: ${(e) => e.theme.borderRadius.lg}; overflow: hidden; outline: none; ${ee} ${(e) => e.maxHeight && i` max-height: ${typeof e.maxHeight == "number" ? `${e.maxHeight}px` : e.maxHeight}; overflow-y: auto; `} /* Custom scrollbar */ &::-webkit-scrollbar { width: 6px; } &::-webkit-scrollbar-track { background: ${(e) => e.theme.colors.neutral[100]}; } &::-webkit-scrollbar-thumb { background: ${(e) => e.theme.colors.neutral[300]}; border-radius: 3px; } &::-webkit-scrollbar-thumb:hover { background: ${(e) => e.theme.colors.neutral[400]}; } /* Custom CSS prop */ ${(e) => e.css} `, oe = g.div` display: flex; align-items: center; gap: ${(e) => e.theme.spacing[3]}; position: relative; user-select: none; ${te} ${ne} ${(e) => e.css} `, se = g.div` display: flex; flex-direction: column; flex: 1; min-width: 0; gap: ${(e) => e.theme.spacing[1]}; `, ie = g.div` font-weight: ${(e) => e.theme.fontWeights.medium}; color: inherit; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; `, le = g.div` font-size: ${(e) => e.theme.fontSizes.sm}; color: ${(e) => e.theme.colors.text.secondary}; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; `, ae = g.div` display: flex; align-items: center; justify-content: center; padding: ${(e) => e.theme.spacing[8]} ${(e) => e.theme.spacing[4]}; color: ${(e) => e.theme.colors.text.secondary}; font-size: ${(e) => e.theme.fontSizes.sm}; text-align: center; `, ce = g.div` display: flex; align-items: center; justify-content: center; padding: ${(e) => e.theme.spacing[6]} ${(e) => e.theme.spacing[4]}; gap: ${(e) => e.theme.spacing[2]}; color: ${(e) => e.theme.colors.text.secondary}; font-size: ${(e) => e.theme.fontSizes.sm}; `, de = g.div` height: 1px; background-color: ${(e) => e.theme.colors.border.primary}; margin: ${(e) => e.theme.spacing[1]} 0; `, fe = () => ( // biome-ignore lint/a11y/noSvgWithoutTitle: <explanation> /* @__PURE__ */ l( "svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ l("polyline", { points: "20,6 9,17 4,12" }) } ) ), he = () => ( // biome-ignore lint/a11y/noSvgWithoutTitle: <explanation> /* @__PURE__ */ l( "svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", style: { animation: "spin 1s linear infinite" }, children: /* @__PURE__ */ l("path", { d: "M21 12a9 9 0 11-6.219-8.56" }) } ) ), U = ({ item: e, isSelected: n = !1, isFocused: d = !1, isDisabled: a = !1, selectionMode: o = "single", hideSelectedIcon: c = !1, itemHeight: y = "md", color: w = "primary", className: f, css: I, onPress: k, ...L }) => { const { theme: u } = T(), m = { item: e, isSelected: n, isFocused: d, isDisabled: a || e.isDisabled, selectionMode: o, hideSelectedIcon: c, itemHeight: y, color: w, className: f, theme: u, css: I }; return /* @__PURE__ */ C( oe, { ...m, ...L, onClick: () => { m.isDisabled || k?.(); }, onKeyDown: (b) => { (b.key === "Enter" || b.key === " ") && !m.isDisabled && (b.preventDefault(), k?.()); }, tabIndex: d ? 0 : -1, role: "option", "aria-selected": n, "aria-disabled": m.isDisabled, children: [ e.startContent, /* @__PURE__ */ C(se, { theme: u, children: [ /* @__PURE__ */ l(ie, { theme: u, children: e.label }), e.description && /* @__PURE__ */ l(le, { theme: u, children: e.description }) ] }), e.endContent, !c && o !== "none" && n && /* @__PURE__ */ l(fe, {}) ] } ); }, ge = P.forwardRef( ({ items: e = [], selectedKeys: n, defaultSelectedKeys: d, disabledKeys: a = /* @__PURE__ */ new Set(), selectionMode: o = "single", selectionBehavior: c = "toggle", emptyContent: y = "No items found", isLoading: w = !1, loadingContent: f, variant: I = "flat", color: k = "primary", itemHeight: L = "md", maxHeight: u, hideSelectedIcon: m = !1, showDividers: j = !1, shouldFocusWrap: v = !0, autoFocus: b = !1, className: W, css: q, onSelectionChange: R, onAction: z, ...A }, B) => { const { theme: D } = T(), [F, G] = V(d || /* @__PURE__ */ new Set()), [$, N] = V(null), J = Z(null), K = n !== void 0, p = K ? n : F; _(() => { if (b && e.length > 0) { const t = e.find( (r) => !r.isDisabled && !a.has(r.key) ); t && N(t.key); } }, [b, e, a]); const h = M( () => e.filter((t) => !t.isDisabled && !a.has(t.key)), [e, a] ), S = E( (t) => { K || G(t), R?.(t); }, [K, R] ), H = E( (t) => { if (o === "none") { z?.(t); return; } let r; o === "single" ? c === "toggle" && p !== "all" && p.has(t) ? r = /* @__PURE__ */ new Set() : r = /* @__PURE__ */ new Set([t]) : p === "all" ? r = new Set( e.map((s) => s.key).filter((s) => s !== t) ) : (r = new Set(p), r.has(t) ? c === "toggle" && r.delete(t) : r.add(t)), S(r), z?.(t); }, [ o, c, p, e, S, z ] ), O = E( (t) => { if (h.length === 0) return; const r = $ ? h.findIndex((Y) => Y.key === $) : -1; let s = r; switch (t.key) { case "ArrowDown": t.preventDefault(), s = r + 1, s >= h.length && (s = v ? 0 : h.length - 1); break; case "ArrowUp": t.preventDefault(), s = r - 1, s < 0 && (s = v ? h.length - 1 : 0); break; case "Home": t.preventDefault(), s = 0; break; case "End": t.preventDefault(), s = h.length - 1; break; case "Enter": case " ": t.preventDefault(), $ !== null && H($); return; case "a": (t.ctrlKey || t.metaKey) && (t.preventDefault(), o === "multiple" && S("all")); return; default: return; } s !== r && h[s] && N(h[s].key); }, [ h, $, v, H, o, S ] ), Q = { variant: I, color: k, maxHeight: u, className: W, css: q }, X = (t) => p === "all" ? !0 : p.has(t); return /* @__PURE__ */ l( re, { ref: B || J, theme: D, ...Q, ...A, role: "listbox", "aria-multiselectable": o === "multiple", tabIndex: 0, onKeyDown: O, children: w ? /* @__PURE__ */ C(ce, { theme: D, children: [ /* @__PURE__ */ l(he, {}), f || "Loading...", /* @__PURE__ */ l("style", { children: "@keyframes spin { to { transform: rotate(360deg); } }" }) ] }) : e.length === 0 ? /* @__PURE__ */ l(ae, { theme: D, children: y }) : e.map((t, r) => /* @__PURE__ */ C(P.Fragment, { children: [ j && r > 0 && /* @__PURE__ */ l(de, { theme: D }), /* @__PURE__ */ l( U, { item: t, isSelected: X(t.key), isFocused: $ === t.key, isDisabled: t.isDisabled || a.has(t.key), selectionMode: o, hideSelectedIcon: m, itemHeight: L, color: k, onPress: () => H(t.key) } ) ] }, t.key)) } ); } ); ge.displayName = "Listbox"; U.displayName = "ListboxItem"; export { ge as Listbox, U as ListboxItem }; //# sourceMappingURL=listbox.js.map