@brycks/core-front 0.3.6 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/data/Table/Table.cjs +1 -1
- package/dist/components/data/Table/Table.cjs.map +1 -1
- package/dist/components/data/Table/Table.js +145 -132
- package/dist/components/data/Table/Table.js.map +1 -1
- package/dist/components/data.cjs +1 -1
- package/dist/components/data.js +23 -21
- package/dist/components/feedback/Banner/Banner.cjs +2 -0
- package/dist/components/feedback/Banner/Banner.cjs.map +1 -0
- package/dist/components/feedback/Banner/Banner.js +77 -0
- package/dist/components/feedback/Banner/Banner.js.map +1 -0
- package/dist/components/feedback/ConfirmDialog/ConfirmDialog.cjs +2 -0
- package/dist/components/feedback/ConfirmDialog/ConfirmDialog.cjs.map +1 -0
- package/dist/components/feedback/ConfirmDialog/ConfirmDialog.js +68 -0
- package/dist/components/feedback/ConfirmDialog/ConfirmDialog.js.map +1 -0
- package/dist/components/feedback/Modal/Modal.cjs +1 -1
- package/dist/components/feedback/Modal/Modal.cjs.map +1 -1
- package/dist/components/feedback/Modal/Modal.js +91 -83
- package/dist/components/feedback/Modal/Modal.js.map +1 -1
- package/dist/components/feedback/Popover/Popover.cjs +2 -2
- package/dist/components/feedback/Popover/Popover.cjs.map +1 -1
- package/dist/components/feedback/Popover/Popover.js +43 -44
- package/dist/components/feedback/Popover/Popover.js.map +1 -1
- package/dist/components/feedback.cjs +1 -1
- package/dist/components/feedback.js +17 -13
- package/dist/components/feedback.js.map +1 -1
- package/dist/components/form/Combobox/Combobox.cjs +2 -2
- package/dist/components/form/Combobox/Combobox.cjs.map +1 -1
- package/dist/components/form/Combobox/Combobox.js +166 -146
- package/dist/components/form/Combobox/Combobox.js.map +1 -1
- package/dist/components/form/SearchInput/SearchInput.cjs +2 -0
- package/dist/components/form/SearchInput/SearchInput.cjs.map +1 -0
- package/dist/components/form/SearchInput/SearchInput.js +68 -0
- package/dist/components/form/SearchInput/SearchInput.js.map +1 -0
- package/dist/components/form.cjs +1 -1
- package/dist/components/form.js +15 -13
- package/dist/components/form.js.map +1 -1
- package/dist/components/layout/Card/Card.cjs +1 -1
- package/dist/components/layout/Card/Card.cjs.map +1 -1
- package/dist/components/layout/Card/Card.js +7 -5
- package/dist/components/layout/Card/Card.js.map +1 -1
- package/dist/components/navigation/SegmentedControl/SegmentedControl.cjs +2 -0
- package/dist/components/navigation/SegmentedControl/SegmentedControl.cjs.map +1 -0
- package/dist/components/navigation/SegmentedControl/SegmentedControl.js +90 -0
- package/dist/components/navigation/SegmentedControl/SegmentedControl.js.map +1 -0
- package/dist/components/navigation.cjs +1 -1
- package/dist/components/navigation.js +25 -23
- package/dist/components/navigation.js.map +1 -1
- package/dist/components/utility/Avatar/Avatar.cjs +1 -1
- package/dist/components/utility/Avatar/Avatar.cjs.map +1 -1
- package/dist/components/utility/Avatar/Avatar.js +18 -18
- package/dist/components/utility/Avatar/Avatar.js.map +1 -1
- package/dist/components/utility/Badge/Badge.cjs +1 -1
- package/dist/components/utility/Badge/Badge.cjs.map +1 -1
- package/dist/components/utility/Badge/Badge.js +31 -23
- package/dist/components/utility/Badge/Badge.js.map +1 -1
- package/dist/components/utility/Kbd/Kbd.cjs +2 -0
- package/dist/components/utility/Kbd/Kbd.cjs.map +1 -0
- package/dist/components/utility/Kbd/Kbd.js +20 -0
- package/dist/components/utility/Kbd/Kbd.js.map +1 -0
- package/dist/components/utility/Logo/Logo.cjs +1 -1
- package/dist/components/utility/Logo/Logo.cjs.map +1 -1
- package/dist/components/utility/Logo/Logo.js +19 -19
- package/dist/components/utility/Logo/Logo.js.map +1 -1
- package/dist/components/utility.cjs +1 -1
- package/dist/components/utility.js +9 -7
- package/dist/components/utility.js.map +1 -1
- package/dist/data.d.ts +34 -1
- package/dist/feedback.d.ts +67 -2
- package/dist/form.d.ts +31 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +184 -3
- package/dist/index.js +177 -165
- package/dist/index.js.map +1 -1
- package/dist/navigation.d.ts +39 -0
- package/dist/styles.css +1 -1
- package/dist/utility.d.ts +19 -0
- package/package.json +1 -1
|
@@ -1,47 +1,46 @@
|
|
|
1
|
-
import { jsxs as
|
|
1
|
+
import { jsxs as N, Fragment as X, jsx as Y } from "react/jsx-runtime";
|
|
2
2
|
import { forwardRef as te, useState as T, useRef as g, useId as oe, useCallback as R, useEffect as E, cloneElement as re } from "react";
|
|
3
|
-
import { createPortal as
|
|
4
|
-
import { cx as
|
|
3
|
+
import { createPortal as ne } from "react-dom";
|
|
4
|
+
import { cx as se } from "../../../utils/styles.js";
|
|
5
5
|
import { useClickOutside as ce } from "../../../hooks/useClickOutside.js";
|
|
6
6
|
import { usePrefersReducedMotion as ie } from "../../../hooks/useMediaQuery.js";
|
|
7
7
|
const ae = te(function({
|
|
8
|
-
content:
|
|
8
|
+
content: F,
|
|
9
9
|
children: x,
|
|
10
10
|
placement: L = "bottom",
|
|
11
11
|
trigger: r = "click",
|
|
12
12
|
isOpen: M,
|
|
13
|
-
defaultOpen:
|
|
13
|
+
defaultOpen: K = !1,
|
|
14
14
|
onOpenChange: C,
|
|
15
15
|
offset: a = 8,
|
|
16
16
|
openDelay: P = 200,
|
|
17
17
|
closeDelay: I = 200,
|
|
18
|
-
closeOnOutsideClick:
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
...G
|
|
18
|
+
closeOnOutsideClick: W = !0,
|
|
19
|
+
className: q,
|
|
20
|
+
style: A,
|
|
21
|
+
testId: G,
|
|
22
|
+
...H
|
|
24
23
|
}, p) {
|
|
25
|
-
const [
|
|
24
|
+
const [J, Q] = T(K), [O, U] = T({ top: 0, left: 0 }), [m, z] = T(!1), h = g(null), S = g(null), l = g(null), u = g(null), j = oe(), V = ie(), o = M ?? J, n = R(
|
|
26
25
|
(e) => {
|
|
27
|
-
M === void 0 &&
|
|
26
|
+
M === void 0 && Q(e), C?.(e);
|
|
28
27
|
},
|
|
29
28
|
[M, C]
|
|
30
|
-
),
|
|
31
|
-
|
|
29
|
+
), Z = ce(() => {
|
|
30
|
+
W && r === "click" && o && n(!1);
|
|
32
31
|
}, { enabled: o && r === "click" });
|
|
33
32
|
E(() => (z(!0), () => z(!1)), []), E(() => {
|
|
34
33
|
if (!o || !h.current || !m) return;
|
|
35
34
|
const e = () => {
|
|
36
|
-
const y = h.current,
|
|
37
|
-
if (!y || !
|
|
38
|
-
const t = y.getBoundingClientRect(),
|
|
35
|
+
const y = h.current, B = S.current;
|
|
36
|
+
if (!y || !B) return;
|
|
37
|
+
const t = y.getBoundingClientRect(), s = B.getBoundingClientRect(), d = window.scrollX, f = window.scrollY;
|
|
39
38
|
let c = 0, i = 0;
|
|
40
39
|
switch (L) {
|
|
41
40
|
case "top":
|
|
42
41
|
case "top-start":
|
|
43
42
|
case "top-end":
|
|
44
|
-
c = t.top + f -
|
|
43
|
+
c = t.top + f - s.height - a;
|
|
45
44
|
break;
|
|
46
45
|
case "bottom":
|
|
47
46
|
case "bottom-start":
|
|
@@ -51,7 +50,7 @@ const ae = te(function({
|
|
|
51
50
|
case "left":
|
|
52
51
|
case "left-start":
|
|
53
52
|
case "left-end":
|
|
54
|
-
i = t.left + d -
|
|
53
|
+
i = t.left + d - s.width - a;
|
|
55
54
|
break;
|
|
56
55
|
case "right":
|
|
57
56
|
case "right-start":
|
|
@@ -62,7 +61,7 @@ const ae = te(function({
|
|
|
62
61
|
switch (L) {
|
|
63
62
|
case "top":
|
|
64
63
|
case "bottom":
|
|
65
|
-
i = t.left + d + (t.width -
|
|
64
|
+
i = t.left + d + (t.width - s.width) / 2;
|
|
66
65
|
break;
|
|
67
66
|
case "top-start":
|
|
68
67
|
case "bottom-start":
|
|
@@ -70,11 +69,11 @@ const ae = te(function({
|
|
|
70
69
|
break;
|
|
71
70
|
case "top-end":
|
|
72
71
|
case "bottom-end":
|
|
73
|
-
i = t.right + d -
|
|
72
|
+
i = t.right + d - s.width;
|
|
74
73
|
break;
|
|
75
74
|
case "left":
|
|
76
75
|
case "right":
|
|
77
|
-
c = t.top + f + (t.height -
|
|
76
|
+
c = t.top + f + (t.height - s.height) / 2;
|
|
78
77
|
break;
|
|
79
78
|
case "left-start":
|
|
80
79
|
case "right-start":
|
|
@@ -82,10 +81,10 @@ const ae = te(function({
|
|
|
82
81
|
break;
|
|
83
82
|
case "left-end":
|
|
84
83
|
case "right-end":
|
|
85
|
-
c = t.bottom + f -
|
|
84
|
+
c = t.bottom + f - s.height;
|
|
86
85
|
break;
|
|
87
86
|
}
|
|
88
|
-
|
|
87
|
+
U({ top: c, left: i });
|
|
89
88
|
};
|
|
90
89
|
return e(), window.addEventListener("resize", e), window.addEventListener("scroll", e, !0), () => {
|
|
91
90
|
window.removeEventListener("resize", e), window.removeEventListener("scroll", e, !0);
|
|
@@ -95,15 +94,15 @@ const ae = te(function({
|
|
|
95
94
|
}, []), E(() => {
|
|
96
95
|
if (!o) return;
|
|
97
96
|
const e = (y) => {
|
|
98
|
-
y.key === "Escape" && (
|
|
97
|
+
y.key === "Escape" && (n(!1), h.current?.focus());
|
|
99
98
|
};
|
|
100
99
|
return document.addEventListener("keydown", e), () => document.removeEventListener("keydown", e);
|
|
101
|
-
}, [o,
|
|
100
|
+
}, [o, n]);
|
|
102
101
|
const b = R(() => {
|
|
103
|
-
u.current && clearTimeout(u.current), r === "hover" ? l.current = setTimeout(() =>
|
|
104
|
-
}, [r, P,
|
|
105
|
-
l.current && clearTimeout(l.current), r === "hover" ? u.current = setTimeout(() =>
|
|
106
|
-
}, [r, I,
|
|
102
|
+
u.current && clearTimeout(u.current), r === "hover" ? l.current = setTimeout(() => n(!0), P) : n(!0);
|
|
103
|
+
}, [r, P, n]), v = R(() => {
|
|
104
|
+
l.current && clearTimeout(l.current), r === "hover" ? u.current = setTimeout(() => n(!1), I) : n(!1);
|
|
105
|
+
}, [r, I, n]), _ = R(() => {
|
|
107
106
|
o ? v() : b();
|
|
108
107
|
}, [o, b, v]), k = x.props, w = k.ref, $ = re(x, {
|
|
109
108
|
// Merge refs so a ref the consumer set on the trigger keeps working
|
|
@@ -115,7 +114,7 @@ const ae = te(function({
|
|
|
115
114
|
"aria-controls": o ? j : void 0,
|
|
116
115
|
...r === "click" && {
|
|
117
116
|
onClick: (e) => {
|
|
118
|
-
k.onClick?.(e),
|
|
117
|
+
k.onClick?.(e), _();
|
|
119
118
|
}
|
|
120
119
|
},
|
|
121
120
|
...r === "hover" && {
|
|
@@ -137,37 +136,37 @@ const ae = te(function({
|
|
|
137
136
|
boxShadow: "var(--brycks-shadow-lg)",
|
|
138
137
|
padding: "var(--brycks-space-3)",
|
|
139
138
|
minWidth: 120,
|
|
140
|
-
animation:
|
|
141
|
-
...
|
|
142
|
-
}, ee = o && m && /* @__PURE__ */
|
|
143
|
-
/* @__PURE__ */
|
|
139
|
+
animation: V ? "none" : "brycks-popover-in 150ms ease-out",
|
|
140
|
+
...A
|
|
141
|
+
}, ee = o && m && /* @__PURE__ */ N(X, { children: [
|
|
142
|
+
/* @__PURE__ */ Y("style", { children: `
|
|
144
143
|
@keyframes brycks-popover-in {
|
|
145
144
|
from { opacity: 0; transform: scale(0.95); }
|
|
146
145
|
to { opacity: 1; transform: scale(1); }
|
|
147
146
|
}
|
|
148
147
|
` }),
|
|
149
|
-
/* @__PURE__ */
|
|
148
|
+
/* @__PURE__ */ Y(
|
|
150
149
|
"div",
|
|
151
150
|
{
|
|
152
151
|
ref: (e) => {
|
|
153
|
-
S.current = e,
|
|
152
|
+
S.current = e, Z.current = e, typeof p == "function" ? p(e) : p && (p.current = e);
|
|
154
153
|
},
|
|
155
154
|
id: j,
|
|
156
|
-
className:
|
|
155
|
+
className: se("brycks-popover", q),
|
|
157
156
|
style: D,
|
|
158
157
|
role: "dialog",
|
|
159
158
|
"aria-modal": "false",
|
|
160
|
-
"data-testid":
|
|
159
|
+
"data-testid": G,
|
|
161
160
|
onMouseEnter: r === "hover" ? b : void 0,
|
|
162
161
|
onMouseLeave: r === "hover" ? v : void 0,
|
|
163
|
-
...
|
|
164
|
-
children:
|
|
162
|
+
...H,
|
|
163
|
+
children: F
|
|
165
164
|
}
|
|
166
165
|
)
|
|
167
166
|
] });
|
|
168
|
-
return /* @__PURE__ */
|
|
167
|
+
return /* @__PURE__ */ N(X, { children: [
|
|
169
168
|
$,
|
|
170
|
-
m &&
|
|
169
|
+
m && ne(ee, document.body)
|
|
171
170
|
] });
|
|
172
171
|
});
|
|
173
172
|
ae.displayName = "Popover";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Popover.js","sources":["../../../../src/components/feedback/Popover/Popover.tsx"],"sourcesContent":["/**\n * Popover Component\n *\n * A floating content panel that appears relative to a trigger element.\n * Supports different placements and can be triggered by click or hover.\n */\n\nimport React, {\n forwardRef,\n useState,\n useEffect,\n useRef,\n useCallback,\n cloneElement,\n useId,\n type CSSProperties,\n type ReactNode,\n type ReactElement,\n type HTMLAttributes,\n} from 'react'\nimport { createPortal } from 'react-dom'\nimport { cx } from '../../../utils/styles'\nimport { useClickOutside } from '../../../hooks/useClickOutside'\nimport { usePrefersReducedMotion } from '../../../hooks/useMediaQuery'\n\nexport type PopoverPlacement =\n | 'top'\n | 'top-start'\n | 'top-end'\n | 'bottom'\n | 'bottom-start'\n | 'bottom-end'\n | 'left'\n | 'left-start'\n | 'left-end'\n | 'right'\n | 'right-start'\n | 'right-end'\n\nexport type PopoverTrigger = 'click' | 'hover'\n\nexport interface PopoverProps extends Omit<HTMLAttributes<HTMLDivElement>, 'content'> {\n /** Popover content */\n content: ReactNode\n /** Trigger element */\n children: ReactElement\n /** Placement relative to trigger */\n placement?: PopoverPlacement\n /** How to trigger the popover */\n trigger?: PopoverTrigger\n /** Whether the popover is open (controlled) */\n isOpen?: boolean\n /** Default open state (uncontrolled) */\n defaultOpen?: boolean\n /** Callback when open state changes */\n onOpenChange?: (isOpen: boolean) => void\n /** Offset from trigger in pixels */\n offset?: number\n /** Delay before showing (hover trigger) */\n openDelay?: number\n /** Delay before hiding (hover trigger) */\n closeDelay?: number\n /** Whether to close on outside click */\n closeOnOutsideClick?: boolean\n /** Whether to show arrow */\n showArrow?: boolean\n /** Custom class name for content */\n className?: string\n /** Test ID */\n testId?: string\n}\n\nexport const Popover = forwardRef<HTMLDivElement, PopoverProps>(function Popover(\n {\n content,\n children,\n placement = 'bottom',\n trigger = 'click',\n isOpen: controlledIsOpen,\n defaultOpen = false,\n onOpenChange,\n offset = 8,\n openDelay = 200,\n closeDelay = 200,\n closeOnOutsideClick = true,\n showArrow: _showArrow = true,\n className,\n style,\n testId,\n ...props\n },\n ref\n) {\n const [internalIsOpen, setInternalIsOpen] = useState(defaultOpen)\n const [position, setPosition] = useState({ top: 0, left: 0 })\n const [mounted, setMounted] = useState(false)\n const triggerRef = useRef<HTMLElement>(null)\n const contentRef = useRef<HTMLDivElement>(null)\n const openTimeoutRef = useRef<ReturnType<typeof setTimeout>>(null)\n const closeTimeoutRef = useRef<ReturnType<typeof setTimeout>>(null)\n const popoverId = useId()\n const prefersReducedMotion = usePrefersReducedMotion()\n\n const isOpen = controlledIsOpen ?? internalIsOpen\n\n const setIsOpen = useCallback(\n (open: boolean) => {\n if (controlledIsOpen === undefined) {\n setInternalIsOpen(open)\n }\n onOpenChange?.(open)\n },\n [controlledIsOpen, onOpenChange]\n )\n\n // Click outside handler\n const clickOutsideRef = useClickOutside<HTMLDivElement>(() => {\n if (closeOnOutsideClick && trigger === 'click' && isOpen) {\n setIsOpen(false)\n }\n }, { enabled: isOpen && trigger === 'click' })\n\n useEffect(() => {\n setMounted(true)\n return () => setMounted(false)\n }, [])\n\n // Calculate position\n useEffect(() => {\n if (!isOpen || !triggerRef.current || !mounted) return\n\n const updatePosition = () => {\n const trigger = triggerRef.current\n const content = contentRef.current\n if (!trigger || !content) return\n\n const triggerRect = trigger.getBoundingClientRect()\n const contentRect = content.getBoundingClientRect()\n const scrollX = window.scrollX\n const scrollY = window.scrollY\n\n let top = 0\n let left = 0\n\n // Calculate base position\n switch (placement) {\n case 'top':\n case 'top-start':\n case 'top-end':\n top = triggerRect.top + scrollY - contentRect.height - offset\n break\n case 'bottom':\n case 'bottom-start':\n case 'bottom-end':\n top = triggerRect.bottom + scrollY + offset\n break\n case 'left':\n case 'left-start':\n case 'left-end':\n left = triggerRect.left + scrollX - contentRect.width - offset\n break\n case 'right':\n case 'right-start':\n case 'right-end':\n left = triggerRect.right + scrollX + offset\n break\n }\n\n // Calculate alignment\n switch (placement) {\n case 'top':\n case 'bottom':\n left = triggerRect.left + scrollX + (triggerRect.width - contentRect.width) / 2\n break\n case 'top-start':\n case 'bottom-start':\n left = triggerRect.left + scrollX\n break\n case 'top-end':\n case 'bottom-end':\n left = triggerRect.right + scrollX - contentRect.width\n break\n case 'left':\n case 'right':\n top = triggerRect.top + scrollY + (triggerRect.height - contentRect.height) / 2\n break\n case 'left-start':\n case 'right-start':\n top = triggerRect.top + scrollY\n break\n case 'left-end':\n case 'right-end':\n top = triggerRect.bottom + scrollY - contentRect.height\n break\n }\n\n setPosition({ top, left })\n }\n\n updatePosition()\n window.addEventListener('resize', updatePosition)\n window.addEventListener('scroll', updatePosition, true)\n\n return () => {\n window.removeEventListener('resize', updatePosition)\n window.removeEventListener('scroll', updatePosition, true)\n }\n }, [isOpen, placement, offset, mounted])\n\n // Cleanup timeouts\n useEffect(() => {\n return () => {\n if (openTimeoutRef.current) clearTimeout(openTimeoutRef.current)\n if (closeTimeoutRef.current) clearTimeout(closeTimeoutRef.current)\n }\n }, [])\n\n // Escape dismisses the popover and returns focus to the trigger (WCAG 1.4.13)\n useEffect(() => {\n if (!isOpen) return\n\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n setIsOpen(false)\n triggerRef.current?.focus()\n }\n }\n\n document.addEventListener('keydown', handleKeyDown)\n return () => document.removeEventListener('keydown', handleKeyDown)\n }, [isOpen, setIsOpen])\n\n const handleOpen = useCallback(() => {\n if (closeTimeoutRef.current) clearTimeout(closeTimeoutRef.current)\n if (trigger === 'hover') {\n openTimeoutRef.current = setTimeout(() => setIsOpen(true), openDelay)\n } else {\n setIsOpen(true)\n }\n }, [trigger, openDelay, setIsOpen])\n\n const handleClose = useCallback(() => {\n if (openTimeoutRef.current) clearTimeout(openTimeoutRef.current)\n if (trigger === 'hover') {\n closeTimeoutRef.current = setTimeout(() => setIsOpen(false), closeDelay)\n } else {\n setIsOpen(false)\n }\n }, [trigger, closeDelay, setIsOpen])\n\n const handleToggle = useCallback(() => {\n if (isOpen) {\n handleClose()\n } else {\n handleOpen()\n }\n }, [isOpen, handleOpen, handleClose])\n\n // Clone trigger with event handlers and ARIA attributes\n const childProps = children.props as Record<string, unknown>\n const childRef = childProps.ref as React.Ref<HTMLElement> | undefined\n const triggerElement = cloneElement(children as ReactElement<Record<string, unknown>>, {\n // Merge refs so a ref the consumer set on the trigger keeps working\n ref: (node: HTMLElement | null) => {\n (triggerRef as React.MutableRefObject<HTMLElement | null>).current = node\n if (typeof childRef === 'function') childRef(node)\n else if (childRef) (childRef as React.MutableRefObject<HTMLElement | null>).current = node\n },\n 'aria-expanded': isOpen,\n 'aria-haspopup': 'dialog',\n 'aria-controls': isOpen ? popoverId : undefined,\n ...(trigger === 'click' && {\n onClick: (e: React.MouseEvent) => {\n (childProps.onClick as ((e: React.MouseEvent) => void) | undefined)?.(e)\n handleToggle()\n },\n }),\n ...(trigger === 'hover' && {\n onMouseEnter: (e: React.MouseEvent) => {\n (childProps.onMouseEnter as ((e: React.MouseEvent) => void) | undefined)?.(e)\n handleOpen()\n },\n onMouseLeave: (e: React.MouseEvent) => {\n (childProps.onMouseLeave as ((e: React.MouseEvent) => void) | undefined)?.(e)\n handleClose()\n },\n }),\n })\n\n const contentStyle: CSSProperties = {\n position: 'absolute',\n top: position.top,\n left: position.left,\n zIndex: 'var(--brycks-z-popover)',\n backgroundColor: 'var(--brycks-background-elevated)',\n border: '1px solid var(--brycks-border-default)',\n borderRadius: 'var(--brycks-radius-lg)',\n boxShadow: 'var(--brycks-shadow-lg)',\n padding: 'var(--brycks-space-3)',\n minWidth: 120,\n animation: prefersReducedMotion ? 'none' : 'brycks-popover-in 150ms ease-out',\n ...style,\n }\n\n const popoverContent = isOpen && mounted && (\n <>\n <style>\n {`\n @keyframes brycks-popover-in {\n from { opacity: 0; transform: scale(0.95); }\n to { opacity: 1; transform: scale(1); }\n }\n `}\n </style>\n <div\n ref={(node) => {\n (contentRef as React.MutableRefObject<HTMLDivElement | null>).current = node;\n (clickOutsideRef as React.MutableRefObject<HTMLDivElement | null>).current = node\n if (typeof ref === 'function') ref(node)\n else if (ref) ref.current = node\n }}\n id={popoverId}\n className={cx('brycks-popover', className)}\n style={contentStyle}\n role=\"dialog\"\n aria-modal=\"false\"\n data-testid={testId}\n onMouseEnter={trigger === 'hover' ? handleOpen : undefined}\n onMouseLeave={trigger === 'hover' ? handleClose : undefined}\n {...props}\n >\n {content}\n </div>\n </>\n )\n\n return (\n <>\n {triggerElement}\n {mounted && createPortal(popoverContent, document.body)}\n </>\n )\n})\n\nPopover.displayName = 'Popover'\n"],"names":["Popover","forwardRef","content","children","placement","trigger","controlledIsOpen","defaultOpen","onOpenChange","offset","openDelay","closeDelay","closeOnOutsideClick","_showArrow","className","style","testId","props","ref","internalIsOpen","setInternalIsOpen","useState","position","setPosition","mounted","setMounted","triggerRef","useRef","contentRef","openTimeoutRef","closeTimeoutRef","popoverId","useId","prefersReducedMotion","usePrefersReducedMotion","isOpen","setIsOpen","useCallback","open","clickOutsideRef","useClickOutside","useEffect","updatePosition","triggerRect","contentRect","scrollX","scrollY","top","left","handleKeyDown","e","handleOpen","handleClose","handleToggle","childProps","childRef","triggerElement","cloneElement","node","contentStyle","popoverContent","jsxs","Fragment","jsx","cx","createPortal"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Popover.js","sources":["../../../../src/components/feedback/Popover/Popover.tsx"],"sourcesContent":["/**\n * Popover Component\n *\n * A floating content panel that appears relative to a trigger element.\n * Supports different placements and can be triggered by click or hover.\n */\n\nimport React, {\n forwardRef,\n useState,\n useEffect,\n useRef,\n useCallback,\n cloneElement,\n useId,\n type CSSProperties,\n type ReactNode,\n type ReactElement,\n type HTMLAttributes,\n} from 'react'\nimport { createPortal } from 'react-dom'\nimport { cx } from '../../../utils/styles'\nimport { useClickOutside } from '../../../hooks/useClickOutside'\nimport { usePrefersReducedMotion } from '../../../hooks/useMediaQuery'\n\nexport type PopoverPlacement =\n | 'top'\n | 'top-start'\n | 'top-end'\n | 'bottom'\n | 'bottom-start'\n | 'bottom-end'\n | 'left'\n | 'left-start'\n | 'left-end'\n | 'right'\n | 'right-start'\n | 'right-end'\n\nexport type PopoverTrigger = 'click' | 'hover'\n\nexport interface PopoverProps extends Omit<HTMLAttributes<HTMLDivElement>, 'content'> {\n /** Popover content */\n content: ReactNode\n /** Trigger element */\n children: ReactElement\n /** Placement relative to trigger */\n placement?: PopoverPlacement\n /** How to trigger the popover */\n trigger?: PopoverTrigger\n /** Whether the popover is open (controlled) */\n isOpen?: boolean\n /** Default open state (uncontrolled) */\n defaultOpen?: boolean\n /** Callback when open state changes */\n onOpenChange?: (isOpen: boolean) => void\n /** Offset from trigger in pixels */\n offset?: number\n /** Delay before showing (hover trigger) */\n openDelay?: number\n /** Delay before hiding (hover trigger) */\n closeDelay?: number\n /** Whether to close on outside click */\n closeOnOutsideClick?: boolean\n /** Custom class name for content */\n className?: string\n /** Test ID */\n testId?: string\n}\n\nexport const Popover = forwardRef<HTMLDivElement, PopoverProps>(function Popover(\n {\n content,\n children,\n placement = 'bottom',\n trigger = 'click',\n isOpen: controlledIsOpen,\n defaultOpen = false,\n onOpenChange,\n offset = 8,\n openDelay = 200,\n closeDelay = 200,\n closeOnOutsideClick = true,\n className,\n style,\n testId,\n ...props\n },\n ref\n) {\n const [internalIsOpen, setInternalIsOpen] = useState(defaultOpen)\n const [position, setPosition] = useState({ top: 0, left: 0 })\n const [mounted, setMounted] = useState(false)\n const triggerRef = useRef<HTMLElement>(null)\n const contentRef = useRef<HTMLDivElement>(null)\n const openTimeoutRef = useRef<ReturnType<typeof setTimeout>>(null)\n const closeTimeoutRef = useRef<ReturnType<typeof setTimeout>>(null)\n const popoverId = useId()\n const prefersReducedMotion = usePrefersReducedMotion()\n\n const isOpen = controlledIsOpen ?? internalIsOpen\n\n const setIsOpen = useCallback(\n (open: boolean) => {\n if (controlledIsOpen === undefined) {\n setInternalIsOpen(open)\n }\n onOpenChange?.(open)\n },\n [controlledIsOpen, onOpenChange]\n )\n\n // Click outside handler\n const clickOutsideRef = useClickOutside<HTMLDivElement>(() => {\n if (closeOnOutsideClick && trigger === 'click' && isOpen) {\n setIsOpen(false)\n }\n }, { enabled: isOpen && trigger === 'click' })\n\n useEffect(() => {\n setMounted(true)\n return () => setMounted(false)\n }, [])\n\n // Calculate position\n useEffect(() => {\n if (!isOpen || !triggerRef.current || !mounted) return\n\n const updatePosition = () => {\n const trigger = triggerRef.current\n const content = contentRef.current\n if (!trigger || !content) return\n\n const triggerRect = trigger.getBoundingClientRect()\n const contentRect = content.getBoundingClientRect()\n const scrollX = window.scrollX\n const scrollY = window.scrollY\n\n let top = 0\n let left = 0\n\n // Calculate base position\n switch (placement) {\n case 'top':\n case 'top-start':\n case 'top-end':\n top = triggerRect.top + scrollY - contentRect.height - offset\n break\n case 'bottom':\n case 'bottom-start':\n case 'bottom-end':\n top = triggerRect.bottom + scrollY + offset\n break\n case 'left':\n case 'left-start':\n case 'left-end':\n left = triggerRect.left + scrollX - contentRect.width - offset\n break\n case 'right':\n case 'right-start':\n case 'right-end':\n left = triggerRect.right + scrollX + offset\n break\n }\n\n // Calculate alignment\n switch (placement) {\n case 'top':\n case 'bottom':\n left = triggerRect.left + scrollX + (triggerRect.width - contentRect.width) / 2\n break\n case 'top-start':\n case 'bottom-start':\n left = triggerRect.left + scrollX\n break\n case 'top-end':\n case 'bottom-end':\n left = triggerRect.right + scrollX - contentRect.width\n break\n case 'left':\n case 'right':\n top = triggerRect.top + scrollY + (triggerRect.height - contentRect.height) / 2\n break\n case 'left-start':\n case 'right-start':\n top = triggerRect.top + scrollY\n break\n case 'left-end':\n case 'right-end':\n top = triggerRect.bottom + scrollY - contentRect.height\n break\n }\n\n setPosition({ top, left })\n }\n\n updatePosition()\n window.addEventListener('resize', updatePosition)\n window.addEventListener('scroll', updatePosition, true)\n\n return () => {\n window.removeEventListener('resize', updatePosition)\n window.removeEventListener('scroll', updatePosition, true)\n }\n }, [isOpen, placement, offset, mounted])\n\n // Cleanup timeouts\n useEffect(() => {\n return () => {\n if (openTimeoutRef.current) clearTimeout(openTimeoutRef.current)\n if (closeTimeoutRef.current) clearTimeout(closeTimeoutRef.current)\n }\n }, [])\n\n // Escape dismisses the popover and returns focus to the trigger (WCAG 1.4.13)\n useEffect(() => {\n if (!isOpen) return\n\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n setIsOpen(false)\n triggerRef.current?.focus()\n }\n }\n\n document.addEventListener('keydown', handleKeyDown)\n return () => document.removeEventListener('keydown', handleKeyDown)\n }, [isOpen, setIsOpen])\n\n const handleOpen = useCallback(() => {\n if (closeTimeoutRef.current) clearTimeout(closeTimeoutRef.current)\n if (trigger === 'hover') {\n openTimeoutRef.current = setTimeout(() => setIsOpen(true), openDelay)\n } else {\n setIsOpen(true)\n }\n }, [trigger, openDelay, setIsOpen])\n\n const handleClose = useCallback(() => {\n if (openTimeoutRef.current) clearTimeout(openTimeoutRef.current)\n if (trigger === 'hover') {\n closeTimeoutRef.current = setTimeout(() => setIsOpen(false), closeDelay)\n } else {\n setIsOpen(false)\n }\n }, [trigger, closeDelay, setIsOpen])\n\n const handleToggle = useCallback(() => {\n if (isOpen) {\n handleClose()\n } else {\n handleOpen()\n }\n }, [isOpen, handleOpen, handleClose])\n\n // Clone trigger with event handlers and ARIA attributes\n const childProps = children.props as Record<string, unknown>\n const childRef = childProps.ref as React.Ref<HTMLElement> | undefined\n const triggerElement = cloneElement(children as ReactElement<Record<string, unknown>>, {\n // Merge refs so a ref the consumer set on the trigger keeps working\n ref: (node: HTMLElement | null) => {\n (triggerRef as React.MutableRefObject<HTMLElement | null>).current = node\n if (typeof childRef === 'function') childRef(node)\n else if (childRef) (childRef as React.MutableRefObject<HTMLElement | null>).current = node\n },\n 'aria-expanded': isOpen,\n 'aria-haspopup': 'dialog',\n 'aria-controls': isOpen ? popoverId : undefined,\n ...(trigger === 'click' && {\n onClick: (e: React.MouseEvent) => {\n (childProps.onClick as ((e: React.MouseEvent) => void) | undefined)?.(e)\n handleToggle()\n },\n }),\n ...(trigger === 'hover' && {\n onMouseEnter: (e: React.MouseEvent) => {\n (childProps.onMouseEnter as ((e: React.MouseEvent) => void) | undefined)?.(e)\n handleOpen()\n },\n onMouseLeave: (e: React.MouseEvent) => {\n (childProps.onMouseLeave as ((e: React.MouseEvent) => void) | undefined)?.(e)\n handleClose()\n },\n }),\n })\n\n const contentStyle: CSSProperties = {\n position: 'absolute',\n top: position.top,\n left: position.left,\n zIndex: 'var(--brycks-z-popover)',\n backgroundColor: 'var(--brycks-background-elevated)',\n border: '1px solid var(--brycks-border-default)',\n borderRadius: 'var(--brycks-radius-lg)',\n boxShadow: 'var(--brycks-shadow-lg)',\n padding: 'var(--brycks-space-3)',\n minWidth: 120,\n animation: prefersReducedMotion ? 'none' : 'brycks-popover-in 150ms ease-out',\n ...style,\n }\n\n const popoverContent = isOpen && mounted && (\n <>\n <style>\n {`\n @keyframes brycks-popover-in {\n from { opacity: 0; transform: scale(0.95); }\n to { opacity: 1; transform: scale(1); }\n }\n `}\n </style>\n <div\n ref={(node) => {\n (contentRef as React.MutableRefObject<HTMLDivElement | null>).current = node;\n (clickOutsideRef as React.MutableRefObject<HTMLDivElement | null>).current = node\n if (typeof ref === 'function') ref(node)\n else if (ref) ref.current = node\n }}\n id={popoverId}\n className={cx('brycks-popover', className)}\n style={contentStyle}\n role=\"dialog\"\n aria-modal=\"false\"\n data-testid={testId}\n onMouseEnter={trigger === 'hover' ? handleOpen : undefined}\n onMouseLeave={trigger === 'hover' ? handleClose : undefined}\n {...props}\n >\n {content}\n </div>\n </>\n )\n\n return (\n <>\n {triggerElement}\n {mounted && createPortal(popoverContent, document.body)}\n </>\n )\n})\n\nPopover.displayName = 'Popover'\n"],"names":["Popover","forwardRef","content","children","placement","trigger","controlledIsOpen","defaultOpen","onOpenChange","offset","openDelay","closeDelay","closeOnOutsideClick","className","style","testId","props","ref","internalIsOpen","setInternalIsOpen","useState","position","setPosition","mounted","setMounted","triggerRef","useRef","contentRef","openTimeoutRef","closeTimeoutRef","popoverId","useId","prefersReducedMotion","usePrefersReducedMotion","isOpen","setIsOpen","useCallback","open","clickOutsideRef","useClickOutside","useEffect","updatePosition","triggerRect","contentRect","scrollX","scrollY","top","left","handleKeyDown","e","handleOpen","handleClose","handleToggle","childProps","childRef","triggerElement","cloneElement","node","contentStyle","popoverContent","jsxs","Fragment","jsx","cx","createPortal"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("./feedback/Modal/Modal.cjs"),e=require("./feedback/Alert/Alert.cjs"),t=require("./feedback/Tooltip/Tooltip.cjs"),r=require("./feedback/Toast/Toast.cjs"),
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("./feedback/Modal/Modal.cjs"),e=require("./feedback/Alert/Alert.cjs"),t=require("./feedback/Banner/Banner.cjs"),s=require("./feedback/ConfirmDialog/ConfirmDialog.cjs"),i=require("./feedback/Tooltip/Tooltip.cjs"),r=require("./feedback/Toast/Toast.cjs"),a=require("./feedback/Toast/ToastContext.cjs"),n=require("./feedback/Drawer/Drawer.cjs"),l=require("./feedback/Popover/Popover.cjs"),u=require("./feedback/Progress/Progress.cjs");exports.Modal=o.Modal;exports.Alert=e.Alert;exports.Banner=t.Banner;exports.ConfirmDialog=s.ConfirmDialog;exports.Tooltip=i.Tooltip;exports.Toast=r.Toast;exports.ToastProvider=r.ToastProvider;exports.useToast=a.useToast;exports.Drawer=n.Drawer;exports.Popover=l.Popover;exports.Progress=u.Progress;
|
|
2
2
|
//# sourceMappingURL=feedback.cjs.map
|
|
@@ -1,20 +1,24 @@
|
|
|
1
1
|
import { Modal as e } from "./feedback/Modal/Modal.js";
|
|
2
2
|
import { Alert as p } from "./feedback/Alert/Alert.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
3
|
+
import { Banner as m } from "./feedback/Banner/Banner.js";
|
|
4
|
+
import { ConfirmDialog as a } from "./feedback/ConfirmDialog/ConfirmDialog.js";
|
|
5
|
+
import { Tooltip as i } from "./feedback/Tooltip/Tooltip.js";
|
|
6
|
+
import { Toast as T, ToastProvider as n } from "./feedback/Toast/Toast.js";
|
|
7
|
+
import { useToast as d } from "./feedback/Toast/ToastContext.js";
|
|
8
|
+
import { Drawer as v } from "./feedback/Drawer/Drawer.js";
|
|
9
|
+
import { Popover as u } from "./feedback/Popover/Popover.js";
|
|
10
|
+
import { Progress as A } from "./feedback/Progress/Progress.js";
|
|
9
11
|
export {
|
|
10
12
|
p as Alert,
|
|
11
|
-
|
|
13
|
+
m as Banner,
|
|
14
|
+
a as ConfirmDialog,
|
|
15
|
+
v as Drawer,
|
|
12
16
|
e as Modal,
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
u as Popover,
|
|
18
|
+
A as Progress,
|
|
19
|
+
T as Toast,
|
|
20
|
+
n as ToastProvider,
|
|
21
|
+
i as Tooltip,
|
|
22
|
+
d as useToast
|
|
19
23
|
};
|
|
20
24
|
//# sourceMappingURL=feedback.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"feedback.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"feedback.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("react/jsx-runtime"),
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("react/jsx-runtime"),s=require("react"),ge=require("react-dom"),ye=require("../../../utils/styles.cjs"),he=require("../../../hooks/useId.cjs"),l=require("../../../design-system/tokens/motion.cjs"),i=require("../../../design-system/primitives/sizing.cjs"),z=require("../../../design-system/tokens/typography.cjs"),c=require("../../../design-system/tokens/spacing.cjs"),me={sm:{height:i.componentHeights.sm,fontSize:z.fontSizes.base-1,padding:i.componentPaddingX.sm,iconSize:i.iconSizes.sm},md:{height:i.componentHeights.md,fontSize:z.fontSizes.base,padding:i.componentPaddingX.md,iconSize:i.iconSizes.md},lg:{height:i.componentHeights.lg,fontSize:z.fontSizes.md,padding:i.componentPaddingX.lg,iconSize:i.iconSizes.lg}},ve=(w,g)=>{const p=g.toLowerCase();return w.label.toLowerCase().includes(p)||w.value.toLowerCase().includes(p)||(w.description?.toLowerCase().includes(p)??!1)};function ke(){return t.jsx("svg",{width:"16",height:"16",viewBox:"0 0 16 16",fill:"none","aria-hidden":"true",children:t.jsx("path",{d:"M4 6l4 4 4-4",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})})}function xe(){return t.jsx("svg",{width:"14",height:"14",viewBox:"0 0 14 14",fill:"none","aria-hidden":"true",children:t.jsx("path",{d:"M4 4l6 6M10 4l-6 6",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round"})})}const A=s.forwardRef(function({options:g,value:p,defaultValue:H=null,onChange:E,onInputChange:R,placeholder:N="Select or search...",size:M="md",disabled:y=!1,isInvalid:q=!1,required:Y=!1,clearable:K=!0,"aria-label":O,"aria-labelledby":V,filterFn:P=ve,emptyText:G="No options found",isLoading:D=!1,loadingText:U="Loading…",creatable:$=!1,onCreate:I,createLabel:J=m=>`Create "${m}"`,clearLabel:Q="Clear selection",listboxLabel:Z="Options",className:_,testId:ee},S){const m=he.useId("combobox-listbox"),[te,re]=s.useState(H),[a,v]=s.useState(""),[r,h]=s.useState(!1),[o,d]=s.useState(-1),[W,B]=s.useState(!1),j=s.useRef(null),C=s.useRef(null),T=s.useRef(null),u=p!==void 0?p:te,k=me[M],f=s.useMemo(()=>g.find(e=>e.value===u),[g,u]),b=s.useMemo(()=>a?g.filter(e=>P(e,a)):g,[g,a,P]);s.useEffect(()=>{!r&&f?v(f.label):!r&&!u&&v("")},[r,f,u]);const x=s.useCallback(e=>{p===void 0&&re(e),E?.(e),h(!1),d(-1),C.current?.focus()},[p,E]),ne=s.useCallback(e=>{const n=e.target.value;v(n),R?.(n),r||h(!0),d(0)},[r,R]),se=s.useCallback(e=>{e.stopPropagation(),x(null),v(""),C.current?.focus()},[x]),oe=s.useCallback(e=>{switch(e.key){case"ArrowDown":e.preventDefault(),r?d(n=>Math.min(n+1,b.length-1)):(h(!0),d(0));break;case"ArrowUp":e.preventDefault(),r&&d(n=>Math.max(n-1,0));break;case"Enter":e.preventDefault(),r&&o>=0&&b[o]?b[o].disabled||x(b[o].value):$&&a&&b.length===0&&I?.(a);break;case"Escape":e.preventDefault(),h(!1),d(-1),f&&v(f.label);break;case"Tab":r&&(h(!1),d(-1));break}},[r,o,b,x,$,a,I,f]);s.useEffect(()=>{if(!r)return;const e=n=>{j.current?.contains(n.target)||(h(!1),d(-1),f&&v(f.label))};return document.addEventListener("mousedown",e),()=>document.removeEventListener("mousedown",e)},[r,f]),s.useEffect(()=>{if(!r||o<0)return;T.current?.children[o]?.scrollIntoView({block:"nearest"})},[r,o]);const[L,ie]=s.useState({top:0,left:0,width:0});s.useEffect(()=>{if(!r||!j.current)return;const e=()=>{const n=j.current.getBoundingClientRect();ie({top:n.bottom+window.scrollY+c.spacing[1],left:n.left+window.scrollX,width:n.width})};return e(),window.addEventListener("resize",e),window.addEventListener("scroll",e,!0),()=>{window.removeEventListener("resize",e),window.removeEventListener("scroll",e,!0)}},[r]);const ae={position:"relative",display:"inline-flex",width:"100%"},le={position:"relative",display:"flex",alignItems:"center",width:"100%",height:k.height,backgroundColor:y?"var(--brycks-background-muted)":"var(--brycks-background-default)",border:`1px solid ${q?"var(--brycks-error-default)":W?"var(--brycks-primary-default)":"var(--brycks-border-default)"}`,borderRadius:"var(--brycks-radius-md)",transition:`all ${l.durations.fast}ms ${l.easings.easeOut}`,cursor:y?"not-allowed":"text",boxShadow:W?"var(--brycks-focus-ring)":void 0},ce={flex:1,height:"100%",padding:`0 ${k.padding}px`,paddingRight:c.spacing[10],fontSize:k.fontSize,color:y?"var(--brycks-foreground-disabled)":"var(--brycks-foreground-default)",backgroundColor:"transparent",border:"none",outline:"none",cursor:y?"not-allowed":"text"},de={position:"absolute",right:k.padding,display:"flex",alignItems:"center",gap:c.spacing[1],pointerEvents:"none"},ue={display:"flex",alignItems:"center",justifyContent:"center",width:c.spacing[5],height:c.spacing[5],color:"var(--brycks-foreground-muted)",cursor:"pointer",borderRadius:"var(--brycks-radius-sm)",transition:`all ${l.durations.fast}ms ${l.easings.easeOut}`,pointerEvents:"auto"},fe={display:"flex",alignItems:"center",justifyContent:"center",color:"var(--brycks-foreground-muted)",transform:r?"rotate(180deg)":"rotate(0)",transition:`transform ${l.durations.fast}ms ${l.easings.easeOut}`},pe={position:"absolute",top:L.top,left:L.left,width:L.width,maxHeight:300,overflowY:"auto",backgroundColor:"var(--brycks-background-elevated)",border:"1px solid var(--brycks-border-default)",borderRadius:"var(--brycks-radius-lg)",boxShadow:"var(--brycks-shadow-lg)",zIndex:"var(--brycks-z-dropdown)",padding:c.spacing[1],animation:`brycks-dropdown-in ${l.durations.quick}ms ${l.easings.easeOut}`},F=(e,n,be)=>({display:"flex",alignItems:"center",gap:i.componentGap.md,padding:`${c.spacing[2]}px ${i.componentPaddingX.sm}px`,fontSize:k.fontSize,color:n?"var(--brycks-foreground-disabled)":"var(--brycks-foreground-default)",backgroundColor:e?"var(--brycks-background-muted)":be?"var(--brycks-primary-muted)":"transparent",borderRadius:"var(--brycks-radius-md)",cursor:n?"not-allowed":"pointer",transition:`background-color ${l.durations.fast}ms ${l.easings.easeOut}`}),X={padding:`${c.spacing[4]}px ${c.spacing[3]}px`,fontSize:k.fontSize,color:"var(--brycks-foreground-muted)",textAlign:"center"};return t.jsxs("div",{ref:j,className:ye.cx("brycks-combobox",`brycks-combobox--${M}`,_),style:ae,"data-testid":ee,children:[t.jsxs("div",{style:le,onClick:()=>!y&&C.current?.focus(),children:[t.jsx("input",{ref:e=>{C.current=e,typeof S=="function"?S(e):S&&(S.current=e)},type:"text",role:"combobox","aria-expanded":r,"aria-haspopup":"listbox","aria-autocomplete":"list","aria-controls":r?m:void 0,"aria-activedescendant":r&&o>=0?`${m}-option-${o}`:void 0,"aria-invalid":q,"aria-required":Y,"aria-label":O,"aria-labelledby":V,value:a,placeholder:N,disabled:y,style:ce,onChange:ne,onKeyDown:oe,onFocus:()=>{B(!0),h(!0)},onBlur:()=>B(!1)}),t.jsxs("div",{style:de,children:[K&&u&&!y&&t.jsx("button",{type:"button","aria-label":Q,style:ue,onClick:se,onMouseEnter:e=>{e.currentTarget.style.backgroundColor="var(--brycks-background-muted)",e.currentTarget.style.color="var(--brycks-foreground-default)"},onMouseLeave:e=>{e.currentTarget.style.backgroundColor="transparent",e.currentTarget.style.color="var(--brycks-foreground-muted)"},children:t.jsx(xe,{})}),t.jsx("span",{style:fe,children:t.jsx(ke,{})})]})]}),r&&ge.createPortal(t.jsxs(t.Fragment,{children:[t.jsx("style",{children:`
|
|
2
2
|
@keyframes brycks-dropdown-in {
|
|
3
3
|
from { opacity: 0; transform: translateY(-4px); }
|
|
4
4
|
to { opacity: 1; transform: translateY(0); }
|
|
5
5
|
}
|
|
6
|
-
`}),t.jsx("ul",{ref:T,id:m,role:"listbox","aria-label":O||
|
|
6
|
+
`}),t.jsx("ul",{ref:T,id:m,role:"listbox","aria-label":O||Z,"aria-busy":D||void 0,style:pe,children:D?t.jsx("li",{style:X,role:"status","aria-live":"polite",children:t.jsxs("span",{style:{display:"inline-flex",alignItems:"center",justifyContent:"center",gap:c.spacing[2]},children:[t.jsxs("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",className:"brycks-animate-spin","aria-hidden":"true",children:[t.jsx("circle",{cx:"12",cy:"12",r:"10",stroke:"currentColor",strokeWidth:"2.5",strokeLinecap:"round",opacity:"0.2"}),t.jsx("path",{d:"M12 2C6.47715 2 2 6.47715 2 12",stroke:"currentColor",strokeWidth:"2.5",strokeLinecap:"round"})]}),U]})}):b.length>0?b.map((e,n)=>t.jsxs("li",{id:`${m}-option-${n}`,role:"option","aria-selected":e.value===u,"aria-disabled":e.disabled,style:F(n===o,!!e.disabled,e.value===u),onClick:()=>!e.disabled&&x(e.value),onMouseEnter:()=>d(n),children:[e.icon&&t.jsx("span",{style:{flexShrink:0},children:e.icon}),t.jsxs("div",{style:{flex:1,minWidth:0},children:[t.jsx("div",{style:{fontWeight:e.value===u?500:400},children:e.label}),e.description&&t.jsx("div",{style:{fontSize:z.fontSizes.sm,color:"var(--brycks-foreground-muted)"},children:e.description})]}),e.value===u&&t.jsx("svg",{width:"16",height:"16",viewBox:"0 0 16 16",fill:"none",style:{flexShrink:0},children:t.jsx("path",{d:"M3 8l3 3 7-7",stroke:"var(--brycks-primary-default)",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})]},e.value)):t.jsx("li",{style:X,children:$&&a?t.jsx("button",{type:"button",style:{...F(!0,!1,!1),width:"100%",border:"none",cursor:"pointer"},onClick:()=>I?.(a),children:J(a)}):G})})]}),document.body)]})});A.displayName="Combobox";exports.Combobox=A;
|
|
7
7
|
//# sourceMappingURL=Combobox.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Combobox.cjs","sources":["../../../../src/components/form/Combobox/Combobox.tsx"],"sourcesContent":["/**\n * Combobox Component\n *\n * A searchable select/autocomplete component with keyboard navigation.\n * Combines the functionality of Input with dropdown selection.\n *\n * @module components/form/Combobox\n */\n\nimport {\n forwardRef,\n useState,\n useCallback,\n useRef,\n useEffect,\n useMemo,\n type CSSProperties,\n type ReactNode,\n type KeyboardEvent,\n type ChangeEvent,\n} from 'react'\nimport { createPortal } from 'react-dom'\nimport { cx } from '../../../utils/styles'\nimport { useId } from '../../../hooks/useId'\nimport { spacing, fontSizes, durations, easings } from '../../../design-system'\nimport {\n componentHeights,\n componentPaddingX,\n componentGap,\n iconSizes,\n} from '../../../design-system/primitives'\n\nexport type ComboboxSize = 'sm' | 'md' | 'lg'\n\nexport interface ComboboxOption {\n /** Unique identifier for the option */\n value: string\n /** Display label */\n label: string\n /** Optional description */\n description?: string\n /** Optional icon */\n icon?: ReactNode\n /** Whether the option is disabled */\n disabled?: boolean\n}\n\nexport interface ComboboxProps {\n /** Available options */\n options: ComboboxOption[]\n /** Currently selected value (controlled) */\n value?: string | null\n /** Default selected value (uncontrolled) */\n defaultValue?: string | null\n /** Callback when selection changes */\n onChange?: (value: string | null) => void\n /** Callback when input value changes */\n onInputChange?: (value: string) => void\n /** Placeholder text */\n placeholder?: string\n /** Component size */\n size?: ComboboxSize\n /** Whether the combobox is disabled */\n disabled?: boolean\n /** Whether the combobox is invalid */\n isInvalid?: boolean\n /** Whether the combobox is required */\n required?: boolean\n /** Whether to allow clearing the selection */\n clearable?: boolean\n /** Label for accessibility */\n 'aria-label'?: string\n /** ID of element that labels this combobox */\n 'aria-labelledby'?: string\n /** Custom filter function */\n filterFn?: (option: ComboboxOption, inputValue: string) => boolean\n /** Text to show when no options match */\n emptyText?: string\n /** Whether to allow creating new options */\n creatable?: boolean\n /** Callback when creating new option */\n onCreate?: (inputValue: string) => void\n /** Label of the create-option button */\n createLabel?: (inputValue: string) => ReactNode\n /** Accessible label of the clear button */\n clearLabel?: string\n /** Accessible label of the options listbox (when no aria-label is given) */\n listboxLabel?: string\n /** Custom class name */\n className?: string\n /** Test ID */\n testId?: string\n}\n\nconst sizeConfig: Record<ComboboxSize, { height: number; fontSize: number; padding: number; iconSize: number }> = {\n sm: { height: componentHeights.sm, fontSize: fontSizes.base - 1, padding: componentPaddingX.sm, iconSize: iconSizes.sm },\n md: { height: componentHeights.md, fontSize: fontSizes.base, padding: componentPaddingX.md, iconSize: iconSizes.md },\n lg: { height: componentHeights.lg, fontSize: fontSizes.md, padding: componentPaddingX.lg, iconSize: iconSizes.lg },\n}\n\nconst defaultFilterFn = (option: ComboboxOption, inputValue: string): boolean => {\n const search = inputValue.toLowerCase()\n return (\n option.label.toLowerCase().includes(search) ||\n option.value.toLowerCase().includes(search) ||\n (option.description?.toLowerCase().includes(search) ?? false)\n )\n}\n\nfunction ChevronDownIcon() {\n return (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden=\"true\">\n <path d=\"M4 6l4 4 4-4\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n )\n}\n\nfunction ClearIcon() {\n return (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" aria-hidden=\"true\">\n <path d=\"M4 4l6 6M10 4l-6 6\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" />\n </svg>\n )\n}\n\nexport const Combobox = forwardRef<HTMLInputElement, ComboboxProps>(function Combobox(\n {\n options,\n value: controlledValue,\n defaultValue = null,\n onChange,\n onInputChange,\n placeholder = 'Select or search...',\n size = 'md',\n disabled = false,\n isInvalid = false,\n required = false,\n clearable = true,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledby,\n filterFn = defaultFilterFn,\n emptyText = 'No options found',\n creatable = false,\n onCreate,\n createLabel = (input) => `Create \"${input}\"`,\n clearLabel = 'Clear selection',\n listboxLabel = 'Options',\n className,\n testId,\n },\n ref\n) {\n const listboxId = useId('combobox-listbox')\n const [internalValue, setInternalValue] = useState(defaultValue)\n const [inputValue, setInputValue] = useState('')\n const [isOpen, setIsOpen] = useState(false)\n const [activeIndex, setActiveIndex] = useState(-1)\n const [isFocused, setIsFocused] = useState(false)\n\n const containerRef = useRef<HTMLDivElement>(null)\n const inputRef = useRef<HTMLInputElement>(null)\n const listRef = useRef<HTMLUListElement>(null)\n\n const value = controlledValue !== undefined ? controlledValue : internalValue\n const config = sizeConfig[size]\n\n // Get selected option\n const selectedOption = useMemo(\n () => options.find((opt) => opt.value === value),\n [options, value]\n )\n\n // Filter options based on input\n const filteredOptions = useMemo(() => {\n if (!inputValue) return options\n return options.filter((opt) => filterFn(opt, inputValue))\n }, [options, inputValue, filterFn])\n\n // Sync input with selected value\n useEffect(() => {\n if (!isOpen && selectedOption) {\n setInputValue(selectedOption.label)\n } else if (!isOpen && !value) {\n setInputValue('')\n }\n }, [isOpen, selectedOption, value])\n\n const handleSelect = useCallback(\n (optionValue: string | null) => {\n if (controlledValue === undefined) {\n setInternalValue(optionValue)\n }\n onChange?.(optionValue)\n setIsOpen(false)\n setActiveIndex(-1)\n inputRef.current?.focus()\n },\n [controlledValue, onChange]\n )\n\n const handleInputChange = useCallback(\n (e: ChangeEvent<HTMLInputElement>) => {\n const newValue = e.target.value\n setInputValue(newValue)\n onInputChange?.(newValue)\n if (!isOpen) setIsOpen(true)\n setActiveIndex(0)\n },\n [isOpen, onInputChange]\n )\n\n const handleClear = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation()\n handleSelect(null)\n setInputValue('')\n inputRef.current?.focus()\n },\n [handleSelect]\n )\n\n const handleKeyDown = useCallback(\n (e: KeyboardEvent<HTMLInputElement>) => {\n switch (e.key) {\n case 'ArrowDown':\n e.preventDefault()\n if (!isOpen) {\n setIsOpen(true)\n setActiveIndex(0)\n } else {\n setActiveIndex((prev) => Math.min(prev + 1, filteredOptions.length - 1))\n }\n break\n case 'ArrowUp':\n e.preventDefault()\n if (isOpen) {\n setActiveIndex((prev) => Math.max(prev - 1, 0))\n }\n break\n case 'Enter':\n e.preventDefault()\n if (isOpen && activeIndex >= 0 && filteredOptions[activeIndex]) {\n if (!filteredOptions[activeIndex].disabled) {\n handleSelect(filteredOptions[activeIndex].value)\n }\n } else if (creatable && inputValue && filteredOptions.length === 0) {\n onCreate?.(inputValue)\n }\n break\n case 'Escape':\n e.preventDefault()\n setIsOpen(false)\n setActiveIndex(-1)\n if (selectedOption) {\n setInputValue(selectedOption.label)\n }\n break\n case 'Tab':\n if (isOpen) {\n setIsOpen(false)\n setActiveIndex(-1)\n }\n break\n }\n },\n [isOpen, activeIndex, filteredOptions, handleSelect, creatable, inputValue, onCreate, selectedOption]\n )\n\n // Close on outside click\n useEffect(() => {\n if (!isOpen) return\n\n const handleClick = (e: MouseEvent) => {\n if (!containerRef.current?.contains(e.target as Node)) {\n setIsOpen(false)\n setActiveIndex(-1)\n if (selectedOption) {\n setInputValue(selectedOption.label)\n }\n }\n }\n\n document.addEventListener('mousedown', handleClick)\n return () => document.removeEventListener('mousedown', handleClick)\n }, [isOpen, selectedOption])\n\n // Scroll active option into view\n useEffect(() => {\n if (!isOpen || activeIndex < 0) return\n const list = listRef.current\n const activeItem = list?.children[activeIndex] as HTMLElement | undefined\n activeItem?.scrollIntoView({ block: 'nearest' })\n }, [isOpen, activeIndex])\n\n // Calculate dropdown position\n const [dropdownPosition, setDropdownPosition] = useState({ top: 0, left: 0, width: 0 })\n\n useEffect(() => {\n if (!isOpen || !containerRef.current) return\n\n const updatePosition = () => {\n const rect = containerRef.current!.getBoundingClientRect()\n setDropdownPosition({\n top: rect.bottom + window.scrollY + spacing[1],\n left: rect.left + window.scrollX,\n width: rect.width,\n })\n }\n\n updatePosition()\n window.addEventListener('resize', updatePosition)\n window.addEventListener('scroll', updatePosition, true)\n\n return () => {\n window.removeEventListener('resize', updatePosition)\n window.removeEventListener('scroll', updatePosition, true)\n }\n }, [isOpen])\n\n const containerStyle: CSSProperties = {\n position: 'relative',\n display: 'inline-flex',\n width: '100%',\n }\n\n const inputWrapperStyle: CSSProperties = {\n position: 'relative',\n display: 'flex',\n alignItems: 'center',\n width: '100%',\n height: config.height,\n backgroundColor: disabled ? 'var(--brycks-background-muted)' : 'var(--brycks-background-default)',\n border: `1px solid ${\n isInvalid\n ? 'var(--brycks-error-default)'\n : isFocused\n ? 'var(--brycks-primary-default)'\n : 'var(--brycks-border-default)'\n }`,\n borderRadius: 'var(--brycks-radius-md)',\n transition: `all ${durations.fast}ms ${easings.easeOut}`,\n cursor: disabled ? 'not-allowed' : 'text',\n boxShadow: isFocused ? 'var(--brycks-focus-ring)' : undefined,\n }\n\n const inputStyle: CSSProperties = {\n flex: 1,\n height: '100%',\n padding: `0 ${config.padding}px`,\n paddingRight: spacing[10],\n fontSize: config.fontSize,\n color: disabled ? 'var(--brycks-foreground-disabled)' : 'var(--brycks-foreground-default)',\n backgroundColor: 'transparent',\n border: 'none',\n outline: 'none',\n cursor: disabled ? 'not-allowed' : 'text',\n }\n\n const iconsStyle: CSSProperties = {\n position: 'absolute',\n right: config.padding,\n display: 'flex',\n alignItems: 'center',\n gap: spacing[1],\n pointerEvents: 'none',\n }\n\n const clearButtonStyle: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: spacing[5],\n height: spacing[5],\n color: 'var(--brycks-foreground-muted)',\n cursor: 'pointer',\n borderRadius: 'var(--brycks-radius-sm)',\n transition: `all ${durations.fast}ms ${easings.easeOut}`,\n pointerEvents: 'auto',\n }\n\n const chevronStyle: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n color: 'var(--brycks-foreground-muted)',\n transform: isOpen ? 'rotate(180deg)' : 'rotate(0)',\n transition: `transform ${durations.fast}ms ${easings.easeOut}`,\n }\n\n const dropdownStyle: CSSProperties = {\n position: 'absolute',\n top: dropdownPosition.top,\n left: dropdownPosition.left,\n width: dropdownPosition.width,\n maxHeight: 300,\n overflowY: 'auto',\n backgroundColor: 'var(--brycks-background-elevated)',\n border: '1px solid var(--brycks-border-default)',\n borderRadius: 'var(--brycks-radius-lg)',\n boxShadow: 'var(--brycks-shadow-lg)',\n zIndex: 'var(--brycks-z-dropdown)' as unknown as number,\n padding: spacing[1],\n animation: `brycks-dropdown-in ${durations.quick}ms ${easings.easeOut}`,\n }\n\n const optionStyle = (isActive: boolean, isDisabled: boolean, isSelected: boolean): CSSProperties => ({\n display: 'flex',\n alignItems: 'center',\n gap: componentGap.md,\n padding: `${spacing[2]}px ${componentPaddingX.sm}px`,\n fontSize: config.fontSize,\n color: isDisabled\n ? 'var(--brycks-foreground-disabled)'\n : 'var(--brycks-foreground-default)',\n backgroundColor: isActive\n ? 'var(--brycks-background-muted)'\n : isSelected\n ? 'var(--brycks-primary-muted)'\n : 'transparent',\n borderRadius: 'var(--brycks-radius-md)',\n cursor: isDisabled ? 'not-allowed' : 'pointer',\n transition: `background-color ${durations.fast}ms ${easings.easeOut}`,\n })\n\n const emptyStyle: CSSProperties = {\n padding: `${spacing[4]}px ${spacing[3]}px`,\n fontSize: config.fontSize,\n color: 'var(--brycks-foreground-muted)',\n textAlign: 'center',\n }\n\n return (\n <div\n ref={containerRef}\n className={cx('brycks-combobox', `brycks-combobox--${size}`, className)}\n style={containerStyle}\n data-testid={testId}\n >\n <div\n style={inputWrapperStyle}\n onClick={() => !disabled && inputRef.current?.focus()}\n >\n <input\n ref={(node) => {\n (inputRef as React.MutableRefObject<HTMLInputElement | null>).current = node\n if (typeof ref === 'function') ref(node)\n else if (ref) ref.current = node\n }}\n type=\"text\"\n role=\"combobox\"\n aria-expanded={isOpen}\n aria-haspopup=\"listbox\"\n aria-autocomplete=\"list\"\n aria-controls={isOpen ? listboxId : undefined}\n aria-activedescendant={isOpen && activeIndex >= 0 ? `${listboxId}-option-${activeIndex}` : undefined}\n aria-invalid={isInvalid}\n aria-required={required}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledby}\n value={inputValue}\n placeholder={placeholder}\n disabled={disabled}\n style={inputStyle}\n onChange={handleInputChange}\n onKeyDown={handleKeyDown}\n onFocus={() => {\n setIsFocused(true)\n setIsOpen(true)\n }}\n onBlur={() => setIsFocused(false)}\n />\n <div style={iconsStyle}>\n {clearable && value && !disabled && (\n <button\n type=\"button\"\n aria-label={clearLabel}\n style={clearButtonStyle}\n onClick={handleClear}\n onMouseEnter={(e) => {\n e.currentTarget.style.backgroundColor = 'var(--brycks-background-muted)'\n e.currentTarget.style.color = 'var(--brycks-foreground-default)'\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.backgroundColor = 'transparent'\n e.currentTarget.style.color = 'var(--brycks-foreground-muted)'\n }}\n >\n <ClearIcon />\n </button>\n )}\n <span style={chevronStyle}>\n <ChevronDownIcon />\n </span>\n </div>\n </div>\n\n {isOpen &&\n createPortal(\n <>\n <style>\n {`\n @keyframes brycks-dropdown-in {\n from { opacity: 0; transform: translateY(-4px); }\n to { opacity: 1; transform: translateY(0); }\n }\n `}\n </style>\n <ul\n ref={listRef}\n id={listboxId}\n role=\"listbox\"\n aria-label={ariaLabel || listboxLabel}\n style={dropdownStyle}\n >\n {filteredOptions.length > 0 ? (\n filteredOptions.map((option, index) => (\n <li\n key={option.value}\n id={`${listboxId}-option-${index}`}\n role=\"option\"\n aria-selected={option.value === value}\n aria-disabled={option.disabled}\n style={optionStyle(index === activeIndex, !!option.disabled, option.value === value)}\n onClick={() => !option.disabled && handleSelect(option.value)}\n onMouseEnter={() => setActiveIndex(index)}\n >\n {option.icon && <span style={{ flexShrink: 0 }}>{option.icon}</span>}\n <div style={{ flex: 1, minWidth: 0 }}>\n <div style={{ fontWeight: option.value === value ? 500 : 400 }}>{option.label}</div>\n {option.description && (\n <div style={{ fontSize: fontSizes.sm, color: 'var(--brycks-foreground-muted)' }}>\n {option.description}\n </div>\n )}\n </div>\n {option.value === value && (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" style={{ flexShrink: 0 }}>\n <path\n d=\"M3 8l3 3 7-7\"\n stroke=\"var(--brycks-primary-default)\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n )}\n </li>\n ))\n ) : (\n <li style={emptyStyle}>\n {creatable && inputValue ? (\n <button\n type=\"button\"\n style={{\n ...optionStyle(true, false, false),\n width: '100%',\n border: 'none',\n cursor: 'pointer',\n }}\n onClick={() => onCreate?.(inputValue)}\n >\n {createLabel(inputValue)}\n </button>\n ) : (\n emptyText\n )}\n </li>\n )}\n </ul>\n </>,\n document.body\n )}\n </div>\n )\n})\n\nCombobox.displayName = 'Combobox'\n"],"names":["sizeConfig","componentHeights","fontSizes","componentPaddingX","iconSizes","defaultFilterFn","option","inputValue","search","ChevronDownIcon","jsx","ClearIcon","Combobox","forwardRef","options","controlledValue","defaultValue","onChange","onInputChange","placeholder","size","disabled","isInvalid","required","clearable","ariaLabel","ariaLabelledby","filterFn","emptyText","creatable","onCreate","createLabel","input","clearLabel","listboxLabel","className","testId","ref","listboxId","useId","internalValue","setInternalValue","useState","setInputValue","isOpen","setIsOpen","activeIndex","setActiveIndex","isFocused","setIsFocused","containerRef","useRef","inputRef","listRef","value","config","selectedOption","useMemo","opt","filteredOptions","useEffect","handleSelect","useCallback","optionValue","handleInputChange","newValue","handleClear","handleKeyDown","prev","handleClick","e","dropdownPosition","setDropdownPosition","updatePosition","rect","spacing","containerStyle","inputWrapperStyle","durations","easings","inputStyle","iconsStyle","clearButtonStyle","chevronStyle","dropdownStyle","optionStyle","isActive","isDisabled","isSelected","componentGap","emptyStyle","jsxs","cx","node","createPortal","Fragment","index"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Combobox.cjs","sources":["../../../../src/components/form/Combobox/Combobox.tsx"],"sourcesContent":["/**\n * Combobox Component\n *\n * A searchable select/autocomplete component with keyboard navigation.\n * Combines the functionality of Input with dropdown selection.\n *\n * @module components/form/Combobox\n */\n\nimport {\n forwardRef,\n useState,\n useCallback,\n useRef,\n useEffect,\n useMemo,\n type CSSProperties,\n type ReactNode,\n type KeyboardEvent,\n type ChangeEvent,\n} from 'react'\nimport { createPortal } from 'react-dom'\nimport { cx } from '../../../utils/styles'\nimport { useId } from '../../../hooks/useId'\nimport { spacing, fontSizes, durations, easings } from '../../../design-system'\nimport {\n componentHeights,\n componentPaddingX,\n componentGap,\n iconSizes,\n} from '../../../design-system/primitives'\n\nexport type ComboboxSize = 'sm' | 'md' | 'lg'\n\nexport interface ComboboxOption {\n /** Unique identifier for the option */\n value: string\n /** Display label */\n label: string\n /** Optional description */\n description?: string\n /** Optional icon */\n icon?: ReactNode\n /** Whether the option is disabled */\n disabled?: boolean\n}\n\nexport interface ComboboxProps {\n /** Available options */\n options: ComboboxOption[]\n /** Currently selected value (controlled) */\n value?: string | null\n /** Default selected value (uncontrolled) */\n defaultValue?: string | null\n /** Callback when selection changes */\n onChange?: (value: string | null) => void\n /** Callback when input value changes */\n onInputChange?: (value: string) => void\n /** Placeholder text */\n placeholder?: string\n /** Component size */\n size?: ComboboxSize\n /** Whether the combobox is disabled */\n disabled?: boolean\n /** Whether the combobox is invalid */\n isInvalid?: boolean\n /** Whether the combobox is required */\n required?: boolean\n /** Whether to allow clearing the selection */\n clearable?: boolean\n /** Label for accessibility */\n 'aria-label'?: string\n /** ID of element that labels this combobox */\n 'aria-labelledby'?: string\n /** Custom filter function */\n filterFn?: (option: ComboboxOption, inputValue: string) => boolean\n /** Text to show when no options match */\n emptyText?: string\n /** Whether options are being loaded asynchronously */\n isLoading?: boolean\n /** Text to show while loading */\n loadingText?: string\n /** Whether to allow creating new options */\n creatable?: boolean\n /** Callback when creating new option */\n onCreate?: (inputValue: string) => void\n /** Label of the create-option button */\n createLabel?: (inputValue: string) => ReactNode\n /** Accessible label of the clear button */\n clearLabel?: string\n /** Accessible label of the options listbox (when no aria-label is given) */\n listboxLabel?: string\n /** Custom class name */\n className?: string\n /** Test ID */\n testId?: string\n}\n\nconst sizeConfig: Record<ComboboxSize, { height: number; fontSize: number; padding: number; iconSize: number }> = {\n sm: { height: componentHeights.sm, fontSize: fontSizes.base - 1, padding: componentPaddingX.sm, iconSize: iconSizes.sm },\n md: { height: componentHeights.md, fontSize: fontSizes.base, padding: componentPaddingX.md, iconSize: iconSizes.md },\n lg: { height: componentHeights.lg, fontSize: fontSizes.md, padding: componentPaddingX.lg, iconSize: iconSizes.lg },\n}\n\nconst defaultFilterFn = (option: ComboboxOption, inputValue: string): boolean => {\n const search = inputValue.toLowerCase()\n return (\n option.label.toLowerCase().includes(search) ||\n option.value.toLowerCase().includes(search) ||\n (option.description?.toLowerCase().includes(search) ?? false)\n )\n}\n\nfunction ChevronDownIcon() {\n return (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden=\"true\">\n <path d=\"M4 6l4 4 4-4\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n )\n}\n\nfunction ClearIcon() {\n return (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" aria-hidden=\"true\">\n <path d=\"M4 4l6 6M10 4l-6 6\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" />\n </svg>\n )\n}\n\nexport const Combobox = forwardRef<HTMLInputElement, ComboboxProps>(function Combobox(\n {\n options,\n value: controlledValue,\n defaultValue = null,\n onChange,\n onInputChange,\n placeholder = 'Select or search...',\n size = 'md',\n disabled = false,\n isInvalid = false,\n required = false,\n clearable = true,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledby,\n filterFn = defaultFilterFn,\n emptyText = 'No options found',\n isLoading = false,\n loadingText = 'Loading…',\n creatable = false,\n onCreate,\n createLabel = (input) => `Create \"${input}\"`,\n clearLabel = 'Clear selection',\n listboxLabel = 'Options',\n className,\n testId,\n },\n ref\n) {\n const listboxId = useId('combobox-listbox')\n const [internalValue, setInternalValue] = useState(defaultValue)\n const [inputValue, setInputValue] = useState('')\n const [isOpen, setIsOpen] = useState(false)\n const [activeIndex, setActiveIndex] = useState(-1)\n const [isFocused, setIsFocused] = useState(false)\n\n const containerRef = useRef<HTMLDivElement>(null)\n const inputRef = useRef<HTMLInputElement>(null)\n const listRef = useRef<HTMLUListElement>(null)\n\n const value = controlledValue !== undefined ? controlledValue : internalValue\n const config = sizeConfig[size]\n\n // Get selected option\n const selectedOption = useMemo(\n () => options.find((opt) => opt.value === value),\n [options, value]\n )\n\n // Filter options based on input\n const filteredOptions = useMemo(() => {\n if (!inputValue) return options\n return options.filter((opt) => filterFn(opt, inputValue))\n }, [options, inputValue, filterFn])\n\n // Sync input with selected value\n useEffect(() => {\n if (!isOpen && selectedOption) {\n setInputValue(selectedOption.label)\n } else if (!isOpen && !value) {\n setInputValue('')\n }\n }, [isOpen, selectedOption, value])\n\n const handleSelect = useCallback(\n (optionValue: string | null) => {\n if (controlledValue === undefined) {\n setInternalValue(optionValue)\n }\n onChange?.(optionValue)\n setIsOpen(false)\n setActiveIndex(-1)\n inputRef.current?.focus()\n },\n [controlledValue, onChange]\n )\n\n const handleInputChange = useCallback(\n (e: ChangeEvent<HTMLInputElement>) => {\n const newValue = e.target.value\n setInputValue(newValue)\n onInputChange?.(newValue)\n if (!isOpen) setIsOpen(true)\n setActiveIndex(0)\n },\n [isOpen, onInputChange]\n )\n\n const handleClear = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation()\n handleSelect(null)\n setInputValue('')\n inputRef.current?.focus()\n },\n [handleSelect]\n )\n\n const handleKeyDown = useCallback(\n (e: KeyboardEvent<HTMLInputElement>) => {\n switch (e.key) {\n case 'ArrowDown':\n e.preventDefault()\n if (!isOpen) {\n setIsOpen(true)\n setActiveIndex(0)\n } else {\n setActiveIndex((prev) => Math.min(prev + 1, filteredOptions.length - 1))\n }\n break\n case 'ArrowUp':\n e.preventDefault()\n if (isOpen) {\n setActiveIndex((prev) => Math.max(prev - 1, 0))\n }\n break\n case 'Enter':\n e.preventDefault()\n if (isOpen && activeIndex >= 0 && filteredOptions[activeIndex]) {\n if (!filteredOptions[activeIndex].disabled) {\n handleSelect(filteredOptions[activeIndex].value)\n }\n } else if (creatable && inputValue && filteredOptions.length === 0) {\n onCreate?.(inputValue)\n }\n break\n case 'Escape':\n e.preventDefault()\n setIsOpen(false)\n setActiveIndex(-1)\n if (selectedOption) {\n setInputValue(selectedOption.label)\n }\n break\n case 'Tab':\n if (isOpen) {\n setIsOpen(false)\n setActiveIndex(-1)\n }\n break\n }\n },\n [isOpen, activeIndex, filteredOptions, handleSelect, creatable, inputValue, onCreate, selectedOption]\n )\n\n // Close on outside click\n useEffect(() => {\n if (!isOpen) return\n\n const handleClick = (e: MouseEvent) => {\n if (!containerRef.current?.contains(e.target as Node)) {\n setIsOpen(false)\n setActiveIndex(-1)\n if (selectedOption) {\n setInputValue(selectedOption.label)\n }\n }\n }\n\n document.addEventListener('mousedown', handleClick)\n return () => document.removeEventListener('mousedown', handleClick)\n }, [isOpen, selectedOption])\n\n // Scroll active option into view\n useEffect(() => {\n if (!isOpen || activeIndex < 0) return\n const list = listRef.current\n const activeItem = list?.children[activeIndex] as HTMLElement | undefined\n activeItem?.scrollIntoView({ block: 'nearest' })\n }, [isOpen, activeIndex])\n\n // Calculate dropdown position\n const [dropdownPosition, setDropdownPosition] = useState({ top: 0, left: 0, width: 0 })\n\n useEffect(() => {\n if (!isOpen || !containerRef.current) return\n\n const updatePosition = () => {\n const rect = containerRef.current!.getBoundingClientRect()\n setDropdownPosition({\n top: rect.bottom + window.scrollY + spacing[1],\n left: rect.left + window.scrollX,\n width: rect.width,\n })\n }\n\n updatePosition()\n window.addEventListener('resize', updatePosition)\n window.addEventListener('scroll', updatePosition, true)\n\n return () => {\n window.removeEventListener('resize', updatePosition)\n window.removeEventListener('scroll', updatePosition, true)\n }\n }, [isOpen])\n\n const containerStyle: CSSProperties = {\n position: 'relative',\n display: 'inline-flex',\n width: '100%',\n }\n\n const inputWrapperStyle: CSSProperties = {\n position: 'relative',\n display: 'flex',\n alignItems: 'center',\n width: '100%',\n height: config.height,\n backgroundColor: disabled ? 'var(--brycks-background-muted)' : 'var(--brycks-background-default)',\n border: `1px solid ${\n isInvalid\n ? 'var(--brycks-error-default)'\n : isFocused\n ? 'var(--brycks-primary-default)'\n : 'var(--brycks-border-default)'\n }`,\n borderRadius: 'var(--brycks-radius-md)',\n transition: `all ${durations.fast}ms ${easings.easeOut}`,\n cursor: disabled ? 'not-allowed' : 'text',\n boxShadow: isFocused ? 'var(--brycks-focus-ring)' : undefined,\n }\n\n const inputStyle: CSSProperties = {\n flex: 1,\n height: '100%',\n padding: `0 ${config.padding}px`,\n paddingRight: spacing[10],\n fontSize: config.fontSize,\n color: disabled ? 'var(--brycks-foreground-disabled)' : 'var(--brycks-foreground-default)',\n backgroundColor: 'transparent',\n border: 'none',\n outline: 'none',\n cursor: disabled ? 'not-allowed' : 'text',\n }\n\n const iconsStyle: CSSProperties = {\n position: 'absolute',\n right: config.padding,\n display: 'flex',\n alignItems: 'center',\n gap: spacing[1],\n pointerEvents: 'none',\n }\n\n const clearButtonStyle: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: spacing[5],\n height: spacing[5],\n color: 'var(--brycks-foreground-muted)',\n cursor: 'pointer',\n borderRadius: 'var(--brycks-radius-sm)',\n transition: `all ${durations.fast}ms ${easings.easeOut}`,\n pointerEvents: 'auto',\n }\n\n const chevronStyle: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n color: 'var(--brycks-foreground-muted)',\n transform: isOpen ? 'rotate(180deg)' : 'rotate(0)',\n transition: `transform ${durations.fast}ms ${easings.easeOut}`,\n }\n\n const dropdownStyle: CSSProperties = {\n position: 'absolute',\n top: dropdownPosition.top,\n left: dropdownPosition.left,\n width: dropdownPosition.width,\n maxHeight: 300,\n overflowY: 'auto',\n backgroundColor: 'var(--brycks-background-elevated)',\n border: '1px solid var(--brycks-border-default)',\n borderRadius: 'var(--brycks-radius-lg)',\n boxShadow: 'var(--brycks-shadow-lg)',\n zIndex: 'var(--brycks-z-dropdown)' as unknown as number,\n padding: spacing[1],\n animation: `brycks-dropdown-in ${durations.quick}ms ${easings.easeOut}`,\n }\n\n const optionStyle = (isActive: boolean, isDisabled: boolean, isSelected: boolean): CSSProperties => ({\n display: 'flex',\n alignItems: 'center',\n gap: componentGap.md,\n padding: `${spacing[2]}px ${componentPaddingX.sm}px`,\n fontSize: config.fontSize,\n color: isDisabled\n ? 'var(--brycks-foreground-disabled)'\n : 'var(--brycks-foreground-default)',\n backgroundColor: isActive\n ? 'var(--brycks-background-muted)'\n : isSelected\n ? 'var(--brycks-primary-muted)'\n : 'transparent',\n borderRadius: 'var(--brycks-radius-md)',\n cursor: isDisabled ? 'not-allowed' : 'pointer',\n transition: `background-color ${durations.fast}ms ${easings.easeOut}`,\n })\n\n const emptyStyle: CSSProperties = {\n padding: `${spacing[4]}px ${spacing[3]}px`,\n fontSize: config.fontSize,\n color: 'var(--brycks-foreground-muted)',\n textAlign: 'center',\n }\n\n return (\n <div\n ref={containerRef}\n className={cx('brycks-combobox', `brycks-combobox--${size}`, className)}\n style={containerStyle}\n data-testid={testId}\n >\n <div\n style={inputWrapperStyle}\n onClick={() => !disabled && inputRef.current?.focus()}\n >\n <input\n ref={(node) => {\n (inputRef as React.MutableRefObject<HTMLInputElement | null>).current = node\n if (typeof ref === 'function') ref(node)\n else if (ref) ref.current = node\n }}\n type=\"text\"\n role=\"combobox\"\n aria-expanded={isOpen}\n aria-haspopup=\"listbox\"\n aria-autocomplete=\"list\"\n aria-controls={isOpen ? listboxId : undefined}\n aria-activedescendant={isOpen && activeIndex >= 0 ? `${listboxId}-option-${activeIndex}` : undefined}\n aria-invalid={isInvalid}\n aria-required={required}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledby}\n value={inputValue}\n placeholder={placeholder}\n disabled={disabled}\n style={inputStyle}\n onChange={handleInputChange}\n onKeyDown={handleKeyDown}\n onFocus={() => {\n setIsFocused(true)\n setIsOpen(true)\n }}\n onBlur={() => setIsFocused(false)}\n />\n <div style={iconsStyle}>\n {clearable && value && !disabled && (\n <button\n type=\"button\"\n aria-label={clearLabel}\n style={clearButtonStyle}\n onClick={handleClear}\n onMouseEnter={(e) => {\n e.currentTarget.style.backgroundColor = 'var(--brycks-background-muted)'\n e.currentTarget.style.color = 'var(--brycks-foreground-default)'\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.backgroundColor = 'transparent'\n e.currentTarget.style.color = 'var(--brycks-foreground-muted)'\n }}\n >\n <ClearIcon />\n </button>\n )}\n <span style={chevronStyle}>\n <ChevronDownIcon />\n </span>\n </div>\n </div>\n\n {isOpen &&\n createPortal(\n <>\n <style>\n {`\n @keyframes brycks-dropdown-in {\n from { opacity: 0; transform: translateY(-4px); }\n to { opacity: 1; transform: translateY(0); }\n }\n `}\n </style>\n <ul\n ref={listRef}\n id={listboxId}\n role=\"listbox\"\n aria-label={ariaLabel || listboxLabel}\n aria-busy={isLoading || undefined}\n style={dropdownStyle}\n >\n {isLoading ? (\n <li style={emptyStyle} role=\"status\" aria-live=\"polite\">\n <span style={{ display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: spacing[2] }}>\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n className=\"brycks-animate-spin\"\n aria-hidden=\"true\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" strokeWidth=\"2.5\" strokeLinecap=\"round\" opacity=\"0.2\" />\n <path d=\"M12 2C6.47715 2 2 6.47715 2 12\" stroke=\"currentColor\" strokeWidth=\"2.5\" strokeLinecap=\"round\" />\n </svg>\n {loadingText}\n </span>\n </li>\n ) : filteredOptions.length > 0 ? (\n filteredOptions.map((option, index) => (\n <li\n key={option.value}\n id={`${listboxId}-option-${index}`}\n role=\"option\"\n aria-selected={option.value === value}\n aria-disabled={option.disabled}\n style={optionStyle(index === activeIndex, !!option.disabled, option.value === value)}\n onClick={() => !option.disabled && handleSelect(option.value)}\n onMouseEnter={() => setActiveIndex(index)}\n >\n {option.icon && <span style={{ flexShrink: 0 }}>{option.icon}</span>}\n <div style={{ flex: 1, minWidth: 0 }}>\n <div style={{ fontWeight: option.value === value ? 500 : 400 }}>{option.label}</div>\n {option.description && (\n <div style={{ fontSize: fontSizes.sm, color: 'var(--brycks-foreground-muted)' }}>\n {option.description}\n </div>\n )}\n </div>\n {option.value === value && (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" style={{ flexShrink: 0 }}>\n <path\n d=\"M3 8l3 3 7-7\"\n stroke=\"var(--brycks-primary-default)\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n )}\n </li>\n ))\n ) : (\n <li style={emptyStyle}>\n {creatable && inputValue ? (\n <button\n type=\"button\"\n style={{\n ...optionStyle(true, false, false),\n width: '100%',\n border: 'none',\n cursor: 'pointer',\n }}\n onClick={() => onCreate?.(inputValue)}\n >\n {createLabel(inputValue)}\n </button>\n ) : (\n emptyText\n )}\n </li>\n )}\n </ul>\n </>,\n document.body\n )}\n </div>\n )\n})\n\nCombobox.displayName = 'Combobox'\n"],"names":["sizeConfig","componentHeights","fontSizes","componentPaddingX","iconSizes","defaultFilterFn","option","inputValue","search","ChevronDownIcon","jsx","ClearIcon","Combobox","forwardRef","options","controlledValue","defaultValue","onChange","onInputChange","placeholder","size","disabled","isInvalid","required","clearable","ariaLabel","ariaLabelledby","filterFn","emptyText","isLoading","loadingText","creatable","onCreate","createLabel","input","clearLabel","listboxLabel","className","testId","ref","listboxId","useId","internalValue","setInternalValue","useState","setInputValue","isOpen","setIsOpen","activeIndex","setActiveIndex","isFocused","setIsFocused","containerRef","useRef","inputRef","listRef","value","config","selectedOption","useMemo","opt","filteredOptions","useEffect","handleSelect","useCallback","optionValue","handleInputChange","newValue","handleClear","handleKeyDown","prev","handleClick","e","dropdownPosition","setDropdownPosition","updatePosition","rect","spacing","containerStyle","inputWrapperStyle","durations","easings","inputStyle","iconsStyle","clearButtonStyle","chevronStyle","dropdownStyle","optionStyle","isActive","isDisabled","isSelected","componentGap","emptyStyle","jsxs","cx","node","createPortal","Fragment","index"],"mappings":"gdAkGMA,GAA4G,CAChH,GAAI,CAAE,OAAQC,EAAAA,iBAAiB,GAAI,SAAUC,EAAAA,UAAU,KAAO,EAAG,QAASC,EAAAA,kBAAkB,GAAI,SAAUC,EAAAA,UAAU,EAAA,EACpH,GAAI,CAAE,OAAQH,EAAAA,iBAAiB,GAAI,SAAUC,EAAAA,UAAU,KAAM,QAASC,EAAAA,kBAAkB,GAAI,SAAUC,EAAAA,UAAU,EAAA,EAChH,GAAI,CAAE,OAAQH,mBAAiB,GAAI,SAAUC,EAAAA,UAAU,GAAI,QAASC,EAAAA,kBAAkB,GAAI,SAAUC,EAAAA,UAAU,EAAA,CAChH,EAEMC,GAAkB,CAACC,EAAwBC,IAAgC,CAC/E,MAAMC,EAASD,EAAW,YAAA,EAC1B,OACED,EAAO,MAAM,YAAA,EAAc,SAASE,CAAM,GAC1CF,EAAO,MAAM,YAAA,EAAc,SAASE,CAAM,IACzCF,EAAO,aAAa,cAAc,SAASE,CAAM,GAAK,GAE3D,EAEA,SAASC,IAAkB,CACzB,OACEC,EAAAA,IAAC,MAAA,CAAI,MAAM,KAAK,OAAO,KAAK,QAAQ,YAAY,KAAK,OAAO,cAAY,OACtE,eAAC,OAAA,CAAK,EAAE,eAAe,OAAO,eAAe,YAAY,MAAM,cAAc,QAAQ,eAAe,OAAA,CAAQ,CAAA,CAC9G,CAEJ,CAEA,SAASC,IAAY,CACnB,OACED,MAAC,OAAI,MAAM,KAAK,OAAO,KAAK,QAAQ,YAAY,KAAK,OAAO,cAAY,OACtE,SAAAA,EAAAA,IAAC,OAAA,CAAK,EAAE,qBAAqB,OAAO,eAAe,YAAY,MAAM,cAAc,OAAA,CAAQ,CAAA,CAC7F,CAEJ,CAEO,MAAME,EAAWC,EAAAA,WAA4C,SAClE,CACE,QAAAC,EACA,MAAOC,EACP,aAAAC,EAAe,KACf,SAAAC,EACA,cAAAC,EACA,YAAAC,EAAc,sBACd,KAAAC,EAAO,KACP,SAAAC,EAAW,GACX,UAAAC,EAAY,GACZ,SAAAC,EAAW,GACX,UAAAC,EAAY,GACZ,aAAcC,EACd,kBAAmBC,EACnB,SAAAC,EAAWtB,GACX,UAAAuB,EAAY,mBACZ,UAAAC,EAAY,GACZ,YAAAC,EAAc,WACd,UAAAC,EAAY,GACZ,SAAAC,EACA,YAAAC,EAAeC,GAAU,WAAWA,CAAK,IACzC,WAAAC,EAAa,kBACb,aAAAC,EAAe,UACf,UAAAC,EACA,OAAAC,EACF,EACAC,EACA,CACA,MAAMC,EAAYC,GAAAA,MAAM,kBAAkB,EACpC,CAACC,GAAeC,EAAgB,EAAIC,EAAAA,SAAS5B,CAAY,EACzD,CAACT,EAAYsC,CAAa,EAAID,EAAAA,SAAS,EAAE,EACzC,CAACE,EAAQC,CAAS,EAAIH,EAAAA,SAAS,EAAK,EACpC,CAACI,EAAaC,CAAc,EAAIL,EAAAA,SAAS,EAAE,EAC3C,CAACM,EAAWC,CAAY,EAAIP,EAAAA,SAAS,EAAK,EAE1CQ,EAAeC,EAAAA,OAAuB,IAAI,EAC1CC,EAAWD,EAAAA,OAAyB,IAAI,EACxCE,EAAUF,EAAAA,OAAyB,IAAI,EAEvCG,EAAQzC,IAAoB,OAAYA,EAAkB2B,GAC1De,EAASzD,GAAWoB,CAAI,EAGxBsC,EAAiBC,EAAAA,QACrB,IAAM7C,EAAQ,KAAM8C,GAAQA,EAAI,QAAUJ,CAAK,EAC/C,CAAC1C,EAAS0C,CAAK,CAAA,EAIXK,EAAkBF,EAAAA,QAAQ,IACzBpD,EACEO,EAAQ,OAAQ8C,GAAQjC,EAASiC,EAAKrD,CAAU,CAAC,EADhCO,EAEvB,CAACA,EAASP,EAAYoB,CAAQ,CAAC,EAGlCmC,EAAAA,UAAU,IAAM,CACV,CAAChB,GAAUY,EACbb,EAAca,EAAe,KAAK,EACzB,CAACZ,GAAU,CAACU,GACrBX,EAAc,EAAE,CAEpB,EAAG,CAACC,EAAQY,EAAgBF,CAAK,CAAC,EAElC,MAAMO,EAAeC,EAAAA,YAClBC,GAA+B,CAC1BlD,IAAoB,QACtB4B,GAAiBsB,CAAW,EAE9BhD,IAAWgD,CAAW,EACtBlB,EAAU,EAAK,EACfE,EAAe,EAAE,EACjBK,EAAS,SAAS,MAAA,CACpB,EACA,CAACvC,EAAiBE,CAAQ,CAAA,EAGtBiD,GAAoBF,EAAAA,YACvB,GAAqC,CACpC,MAAMG,EAAW,EAAE,OAAO,MAC1BtB,EAAcsB,CAAQ,EACtBjD,IAAgBiD,CAAQ,EACnBrB,GAAQC,EAAU,EAAI,EAC3BE,EAAe,CAAC,CAClB,EACA,CAACH,EAAQ5B,CAAa,CAAA,EAGlBkD,GAAcJ,EAAAA,YACjB,GAAwB,CACvB,EAAE,gBAAA,EACFD,EAAa,IAAI,EACjBlB,EAAc,EAAE,EAChBS,EAAS,SAAS,MAAA,CACpB,EACA,CAACS,CAAY,CAAA,EAGTM,GAAgBL,EAAAA,YACnB,GAAuC,CACtC,OAAQ,EAAE,IAAA,CACR,IAAK,YACH,EAAE,eAAA,EACGlB,EAIHG,EAAgBqB,GAAS,KAAK,IAAIA,EAAO,EAAGT,EAAgB,OAAS,CAAC,CAAC,GAHvEd,EAAU,EAAI,EACdE,EAAe,CAAC,GAIlB,MACF,IAAK,UACH,EAAE,eAAA,EACEH,GACFG,EAAgBqB,GAAS,KAAK,IAAIA,EAAO,EAAG,CAAC,CAAC,EAEhD,MACF,IAAK,QACH,EAAE,eAAA,EACExB,GAAUE,GAAe,GAAKa,EAAgBb,CAAW,EACtDa,EAAgBb,CAAW,EAAE,UAChCe,EAAaF,EAAgBb,CAAW,EAAE,KAAK,EAExCjB,GAAaxB,GAAcsD,EAAgB,SAAW,GAC/D7B,IAAWzB,CAAU,EAEvB,MACF,IAAK,SACH,EAAE,eAAA,EACFwC,EAAU,EAAK,EACfE,EAAe,EAAE,EACbS,GACFb,EAAca,EAAe,KAAK,EAEpC,MACF,IAAK,MACCZ,IACFC,EAAU,EAAK,EACfE,EAAe,EAAE,GAEnB,KAAA,CAEN,EACA,CAACH,EAAQE,EAAaa,EAAiBE,EAAchC,EAAWxB,EAAYyB,EAAU0B,CAAc,CAAA,EAItGI,EAAAA,UAAU,IAAM,CACd,GAAI,CAAChB,EAAQ,OAEb,MAAMyB,EAAeC,GAAkB,CAChCpB,EAAa,SAAS,SAASoB,EAAE,MAAc,IAClDzB,EAAU,EAAK,EACfE,EAAe,EAAE,EACbS,GACFb,EAAca,EAAe,KAAK,EAGxC,EAEA,gBAAS,iBAAiB,YAAaa,CAAW,EAC3C,IAAM,SAAS,oBAAoB,YAAaA,CAAW,CACpE,EAAG,CAACzB,EAAQY,CAAc,CAAC,EAG3BI,EAAAA,UAAU,IAAM,CACd,GAAI,CAAChB,GAAUE,EAAc,EAAG,OACnBO,EAAQ,SACI,SAASP,CAAW,GACjC,eAAe,CAAE,MAAO,SAAA,CAAW,CACjD,EAAG,CAACF,EAAQE,CAAW,CAAC,EAGxB,KAAM,CAACyB,EAAkBC,EAAmB,EAAI9B,EAAAA,SAAS,CAAE,IAAK,EAAG,KAAM,EAAG,MAAO,CAAA,CAAG,EAEtFkB,EAAAA,UAAU,IAAM,CACd,GAAI,CAAChB,GAAU,CAACM,EAAa,QAAS,OAEtC,MAAMuB,EAAiB,IAAM,CAC3B,MAAMC,EAAOxB,EAAa,QAAS,sBAAA,EACnCsB,GAAoB,CAClB,IAAKE,EAAK,OAAS,OAAO,QAAUC,EAAAA,QAAQ,CAAC,EAC7C,KAAMD,EAAK,KAAO,OAAO,QACzB,MAAOA,EAAK,KAAA,CACb,CACH,EAEA,OAAAD,EAAA,EACA,OAAO,iBAAiB,SAAUA,CAAc,EAChD,OAAO,iBAAiB,SAAUA,EAAgB,EAAI,EAE/C,IAAM,CACX,OAAO,oBAAoB,SAAUA,CAAc,EACnD,OAAO,oBAAoB,SAAUA,EAAgB,EAAI,CAC3D,CACF,EAAG,CAAC7B,CAAM,CAAC,EAEX,MAAMgC,GAAgC,CACpC,SAAU,WACV,QAAS,cACT,MAAO,MAAA,EAGHC,GAAmC,CACvC,SAAU,WACV,QAAS,OACT,WAAY,SACZ,MAAO,OACP,OAAQtB,EAAO,OACf,gBAAiBpC,EAAW,iCAAmC,mCAC/D,OAAQ,aACNC,EACI,8BACA4B,EACA,gCACA,8BACN,GACA,aAAc,0BACd,WAAY,OAAO8B,EAAAA,UAAU,IAAI,MAAMC,EAAAA,QAAQ,OAAO,GACtD,OAAQ5D,EAAW,cAAgB,OACnC,UAAW6B,EAAY,2BAA6B,MAAA,EAGhDgC,GAA4B,CAChC,KAAM,EACN,OAAQ,OACR,QAAS,KAAKzB,EAAO,OAAO,KAC5B,aAAcoB,EAAAA,QAAQ,EAAE,EACxB,SAAUpB,EAAO,SACjB,MAAOpC,EAAW,oCAAsC,mCACxD,gBAAiB,cACjB,OAAQ,OACR,QAAS,OACT,OAAQA,EAAW,cAAgB,MAAA,EAG/B8D,GAA4B,CAChC,SAAU,WACV,MAAO1B,EAAO,QACd,QAAS,OACT,WAAY,SACZ,IAAKoB,EAAAA,QAAQ,CAAC,EACd,cAAe,MAAA,EAGXO,GAAkC,CACtC,QAAS,OACT,WAAY,SACZ,eAAgB,SAChB,MAAOP,EAAAA,QAAQ,CAAC,EAChB,OAAQA,EAAAA,QAAQ,CAAC,EACjB,MAAO,iCACP,OAAQ,UACR,aAAc,0BACd,WAAY,OAAOG,EAAAA,UAAU,IAAI,MAAMC,EAAAA,QAAQ,OAAO,GACtD,cAAe,MAAA,EAGXI,GAA8B,CAClC,QAAS,OACT,WAAY,SACZ,eAAgB,SAChB,MAAO,iCACP,UAAWvC,EAAS,iBAAmB,YACvC,WAAY,aAAakC,EAAAA,UAAU,IAAI,MAAMC,EAAAA,QAAQ,OAAO,EAAA,EAGxDK,GAA+B,CACnC,SAAU,WACV,IAAKb,EAAiB,IACtB,KAAMA,EAAiB,KACvB,MAAOA,EAAiB,MACxB,UAAW,IACX,UAAW,OACX,gBAAiB,oCACjB,OAAQ,yCACR,aAAc,0BACd,UAAW,0BACX,OAAQ,2BACR,QAASI,EAAAA,QAAQ,CAAC,EAClB,UAAW,sBAAsBG,EAAAA,UAAU,KAAK,MAAMC,EAAAA,QAAQ,OAAO,EAAA,EAGjEM,EAAc,CAACC,EAAmBC,EAAqBC,MAAwC,CACnG,QAAS,OACT,WAAY,SACZ,IAAKC,EAAAA,aAAa,GAClB,QAAS,GAAGd,EAAAA,QAAQ,CAAC,CAAC,MAAM1E,EAAAA,kBAAkB,EAAE,KAChD,SAAUsD,EAAO,SACjB,MAAOgC,EACH,oCACA,mCACJ,gBAAiBD,EACb,iCACAE,GACA,8BACA,cACJ,aAAc,0BACd,OAAQD,EAAa,cAAgB,UACrC,WAAY,oBAAoBT,EAAAA,UAAU,IAAI,MAAMC,EAAAA,QAAQ,OAAO,EAAA,GAG/DW,EAA4B,CAChC,QAAS,GAAGf,EAAAA,QAAQ,CAAC,CAAC,MAAMA,EAAAA,QAAQ,CAAC,CAAC,KACtC,SAAUpB,EAAO,SACjB,MAAO,iCACP,UAAW,QAAA,EAGb,OACEoC,EAAAA,KAAC,MAAA,CACC,IAAKzC,EACL,UAAW0C,GAAAA,GAAG,kBAAmB,oBAAoB1E,CAAI,GAAIiB,CAAS,EACtE,MAAOyC,GACP,cAAaxC,GAEb,SAAA,CAAAuD,EAAAA,KAAC,MAAA,CACC,MAAOd,GACP,QAAS,IAAM,CAAC1D,GAAYiC,EAAS,SAAS,MAAA,EAE9C,SAAA,CAAA5C,EAAAA,IAAC,QAAA,CACC,IAAMqF,GAAS,CACZzC,EAA6D,QAAUyC,EACpE,OAAOxD,GAAQ,WAAYA,EAAIwD,CAAI,EAC9BxD,MAAS,QAAUwD,EAC9B,EACA,KAAK,OACL,KAAK,WACL,gBAAejD,EACf,gBAAc,UACd,oBAAkB,OAClB,gBAAeA,EAASN,EAAY,OACpC,wBAAuBM,GAAUE,GAAe,EAAI,GAAGR,CAAS,WAAWQ,CAAW,GAAK,OAC3F,eAAc1B,EACd,gBAAeC,EACf,aAAYE,EACZ,kBAAiBC,EACjB,MAAOnB,EACP,YAAAY,EACA,SAAAE,EACA,MAAO6D,GACP,SAAUhB,GACV,UAAWG,GACX,QAAS,IAAM,CACblB,EAAa,EAAI,EACjBJ,EAAU,EAAI,CAChB,EACA,OAAQ,IAAMI,EAAa,EAAK,CAAA,CAAA,EAElC0C,EAAAA,KAAC,MAAA,CAAI,MAAOV,GACT,SAAA,CAAA3D,GAAagC,GAAS,CAACnC,GACtBX,EAAAA,IAAC,SAAA,CACC,KAAK,SACL,aAAYyB,EACZ,MAAOiD,GACP,QAAShB,GACT,aAAe,GAAM,CACnB,EAAE,cAAc,MAAM,gBAAkB,iCACxC,EAAE,cAAc,MAAM,MAAQ,kCAChC,EACA,aAAe,GAAM,CACnB,EAAE,cAAc,MAAM,gBAAkB,cACxC,EAAE,cAAc,MAAM,MAAQ,gCAChC,EAEA,eAACzD,GAAA,CAAA,CAAU,CAAA,CAAA,QAGd,OAAA,CAAK,MAAO0E,GACX,SAAA3E,EAAAA,IAACD,KAAgB,CAAA,CACnB,CAAA,CAAA,CACF,CAAA,CAAA,CAAA,EAGDqC,GACCkD,GAAAA,aACEH,OAAAI,EAAAA,SAAA,CACE,SAAA,CAAAvF,MAAC,QAAA,CACE,SAAA;AAAA;AAAA;AAAA;AAAA;AAAA,gBAMH,EACAA,EAAAA,IAAC,KAAA,CACC,IAAK6C,EACL,GAAIf,EACJ,KAAK,UACL,aAAYf,GAAaW,EACzB,YAAWP,GAAa,OACxB,MAAOyD,GAEN,SAAAzD,QACE,KAAA,CAAG,MAAO+D,EAAY,KAAK,SAAS,YAAU,SAC7C,SAAAC,EAAAA,KAAC,OAAA,CAAK,MAAO,CAAE,QAAS,cAAe,WAAY,SAAU,eAAgB,SAAU,IAAKhB,EAAAA,QAAQ,CAAC,CAAA,EACnG,SAAA,CAAAgB,EAAAA,KAAC,MAAA,CACC,MAAM,KACN,OAAO,KACP,QAAQ,YACR,KAAK,OACL,UAAU,sBACV,cAAY,OAEZ,SAAA,CAAAnF,EAAAA,IAAC,SAAA,CAAO,GAAG,KAAK,GAAG,KAAK,EAAE,KAAK,OAAO,eAAe,YAAY,MAAM,cAAc,QAAQ,QAAQ,MAAM,EAC3GA,EAAAA,IAAC,QAAK,EAAE,iCAAiC,OAAO,eAAe,YAAY,MAAM,cAAc,OAAA,CAAQ,CAAA,CAAA,CAAA,EAExGoB,CAAA,CAAA,CACH,CAAA,CACF,EACE+B,EAAgB,OAAS,EAC3BA,EAAgB,IAAI,CAACvD,EAAQ4F,IAC3BL,EAAAA,KAAC,KAAA,CAEC,GAAI,GAAGrD,CAAS,WAAW0D,CAAK,GAChC,KAAK,SACL,gBAAe5F,EAAO,QAAUkD,EAChC,gBAAelD,EAAO,SACtB,MAAOiF,EAAYW,IAAUlD,EAAa,CAAC,CAAC1C,EAAO,SAAUA,EAAO,QAAUkD,CAAK,EACnF,QAAS,IAAM,CAAClD,EAAO,UAAYyD,EAAazD,EAAO,KAAK,EAC5D,aAAc,IAAM2C,EAAeiD,CAAK,EAEvC,SAAA,CAAA5F,EAAO,YAAS,OAAA,CAAK,MAAO,CAAE,WAAY,CAAA,EAAM,SAAAA,EAAO,IAAA,CAAK,EAC7DuF,OAAC,OAAI,MAAO,CAAE,KAAM,EAAG,SAAU,GAC/B,SAAA,CAAAnF,EAAAA,IAAC,MAAA,CAAI,MAAO,CAAE,WAAYJ,EAAO,QAAUkD,EAAQ,IAAM,GAAA,EAAQ,SAAAlD,EAAO,KAAA,CAAM,EAC7EA,EAAO,aACNI,EAAAA,IAAC,MAAA,CAAI,MAAO,CAAE,SAAUR,EAAAA,UAAU,GAAI,MAAO,gCAAA,EAC1C,WAAO,WAAA,CACV,CAAA,EAEJ,EACCI,EAAO,QAAUkD,GAChB9C,EAAAA,IAAC,MAAA,CAAI,MAAM,KAAK,OAAO,KAAK,QAAQ,YAAY,KAAK,OAAO,MAAO,CAAE,WAAY,GAC/E,SAAAA,EAAAA,IAAC,OAAA,CACC,EAAE,eACF,OAAO,gCACP,YAAY,IACZ,cAAc,QACd,eAAe,OAAA,CAAA,CACjB,CACF,CAAA,CAAA,EA3BGJ,EAAO,KAAA,CA8Bf,EAEDI,EAAAA,IAAC,MAAG,MAAOkF,EACR,YAAarF,EACZG,EAAAA,IAAC,SAAA,CACC,KAAK,SACL,MAAO,CACL,GAAG6E,EAAY,GAAM,GAAO,EAAK,EACjC,MAAO,OACP,OAAQ,OACR,OAAQ,SAAA,EAEV,QAAS,IAAMvD,IAAWzB,CAAU,EAEnC,WAAYA,CAAU,CAAA,CAAA,EAGzBqB,CAAA,CAEJ,CAAA,CAAA,CAEJ,EACF,EACA,SAAS,IAAA,CACX,CAAA,CAAA,CAGR,CAAC,EAEDhB,EAAS,YAAc"}
|