@brycks/core-front 0.3.6 → 0.6.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/List/List.cjs +1 -1
- package/dist/components/data/List/List.cjs.map +1 -1
- package/dist/components/data/List/List.js +68 -148
- package/dist/components/data/List/List.js.map +1 -1
- 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 +148 -217
- package/dist/components/data/Table/Table.js.map +1 -1
- package/dist/components/data/TreeView/TreeView.cjs +1 -1
- package/dist/components/data/TreeView/TreeView.cjs.map +1 -1
- package/dist/components/data/TreeView/TreeView.js +141 -182
- package/dist/components/data/TreeView/TreeView.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/Drawer/Drawer.cjs +1 -22
- package/dist/components/feedback/Drawer/Drawer.cjs.map +1 -1
- package/dist/components/feedback/Drawer/Drawer.js +84 -184
- package/dist/components/feedback/Drawer/Drawer.js.map +1 -1
- 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 +73 -150
- 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/Toast/Toast.cjs +1 -10
- package/dist/components/feedback/Toast/Toast.cjs.map +1 -1
- package/dist/components/feedback/Toast/Toast.js +94 -187
- package/dist/components/feedback/Toast/Toast.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/Checkbox/Checkbox.cjs +1 -1
- package/dist/components/form/Checkbox/Checkbox.js +11 -11
- package/dist/components/form/Combobox/Combobox.cjs +1 -6
- package/dist/components/form/Combobox/Combobox.cjs.map +1 -1
- package/dist/components/form/Combobox/Combobox.js +190 -266
- package/dist/components/form/Combobox/Combobox.js.map +1 -1
- package/dist/components/form/Input/Input.cjs +1 -1
- package/dist/components/form/Input/Input.cjs.map +1 -1
- package/dist/components/form/Input/Input.js +38 -133
- package/dist/components/form/Input/Input.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/Select/Select.cjs +1 -1
- package/dist/components/form/Select/Select.cjs.map +1 -1
- package/dist/components/form/Select/Select.js +36 -82
- package/dist/components/form/Select/Select.js.map +1 -1
- package/dist/components/form/TagInput/TagInput.cjs +1 -1
- package/dist/components/form/TagInput/TagInput.js +8 -8
- package/dist/components/form/Textarea/Textarea.cjs +1 -1
- package/dist/components/form/Textarea/Textarea.cjs.map +1 -1
- package/dist/components/form/Textarea/Textarea.js +61 -95
- package/dist/components/form/Textarea/Textarea.js.map +1 -1
- 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/ContextMenu/ContextMenu.cjs +1 -1
- package/dist/components/navigation/ContextMenu/ContextMenu.js +9 -9
- package/dist/components/navigation/Menu/Menu.cjs +1 -1
- package/dist/components/navigation/Menu/Menu.cjs.map +1 -1
- package/dist/components/navigation/Menu/Menu.js +70 -135
- package/dist/components/navigation/Menu/Menu.js.map +1 -1
- package/dist/components/navigation/Pagination/Pagination.cjs +1 -1
- package/dist/components/navigation/Pagination/Pagination.cjs.map +1 -1
- package/dist/components/navigation/Pagination/Pagination.js +87 -157
- package/dist/components/navigation/Pagination/Pagination.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,11 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("react/jsx-runtime"),e=require("react"),
|
|
2
|
-
@keyframes brycks-toast-in {
|
|
3
|
-
from { opacity: 0; transform: translateY(-8px) scale(0.95); }
|
|
4
|
-
to { opacity: 1; transform: translateY(0) scale(1); }
|
|
5
|
-
}
|
|
6
|
-
@keyframes brycks-toast-out {
|
|
7
|
-
from { opacity: 1; transform: translateY(0) scale(1); }
|
|
8
|
-
to { opacity: 0; transform: translateY(-8px) scale(0.95); }
|
|
9
|
-
}
|
|
10
|
-
`}),t.jsxs("div",{ref:C,role:r==="error"||r==="warning"?"alert":"status","aria-live":r==="error"||r==="warning"?"assertive":"polite",className:Y.cx("brycks-toast",`brycks-toast--${r}`,v),style:z,"data-testid":a,onMouseEnter:s=>{T(!0),d?.(s)},onMouseLeave:s=>{T(!1),f?.(s)},...w,children:[t.jsx("span",{style:I,children:h||t.jsx(N,{intent:r})}),t.jsxs("div",{style:L,children:[c&&t.jsx("span",{style:P,children:c}),i&&t.jsx("span",{style:q,children:i}),m&&t.jsx("div",{style:{marginTop:8},children:m})]}),g&&t.jsx("button",{type:"button",style:R,onClick:u,"aria-label":b,onMouseEnter:s=>{s.currentTarget.style.backgroundColor="var(--brycks-background-muted)"},onMouseLeave:s=>{s.currentTarget.style.backgroundColor="transparent"},children:t.jsx($,{})})]})]})});x.displayName="Toast";const H={"top-left":{top:16,left:16},"top-center":{top:16,left:"50%",transform:"translateX(-50%)"},"top-right":{top:16,right:16},"bottom-left":{bottom:16,left:16},"bottom-center":{bottom:16,left:"50%",transform:"translateX(-50%)"},"bottom-right":{bottom:16,right:16}};let V=0;function X({children:y,position:r="top-right",maxToasts:c=5}){const[i,o]=e.useState([]),[l,u]=e.useState(!1);e.useEffect(()=>{u(!0)},[]);const g=e.useCallback(n=>{const a=`toast-${++V}`;return o(d=>{const f=[...d,{id:a,props:n}];return f.length>c?f.slice(-c):f}),a},[c]),b=e.useCallback(n=>{o(a=>a.filter(d=>d.id!==n))},[]),m=e.useCallback(()=>{o([])},[]),h={position:"fixed",zIndex:"var(--brycks-z-toast)",display:"flex",flexDirection:"column",gap:8,pointerEvents:"none",...H[r]},v={pointerEvents:"auto"};return t.jsxs(B.ToastContext.Provider,{value:{toasts:i,addToast:g,removeToast:b,removeAll:m},children:[y,l&&W.createPortal(t.jsx("div",{className:"brycks-toast-container",style:h,children:i.map(({id:n,props:a})=>t.jsx("div",{style:v,children:t.jsx(x,{...a,isOpen:!0,onClose:()=>b(n)})},n))}),document.body)]})}exports.Toast=x;exports.ToastProvider=X;
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("react/jsx-runtime"),e=require("react"),N=require("react-dom"),S=require("../../../utils/styles.cjs"),P=require("./ToastContext.cjs");function E({intent:f}){const s={info:"M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z",success:"M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z",warning:"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z",error:"M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z"};return t.jsx("svg",{width:"20",height:"20",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:t.jsx("path",{d:s[f]})})}function L(){return t.jsx("svg",{width:"16",height:"16",viewBox:"0 0 16 16",fill:"none",children:t.jsx("path",{d:"M4 4l8 8M12 4l-8 8",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round"})})}const k=e.forwardRef(function({intent:s="info",title:c,description:i,isOpen:o=!0,duration:l=5e3,onClose:u,showCloseButton:x=!0,closeLabel:h="Close toast",action:b,icon:r,className:a,style:d,testId:m,onMouseEnter:g,onMouseLeave:T,..._},M){const[w,v]=e.useState(o),[C,j]=e.useState(!1),[p,y]=e.useState(!1);return e.useEffect(()=>{if(o)v(!0),j(!1);else{j(!0);const n=setTimeout(()=>v(!1),200);return()=>clearTimeout(n)}},[o]),e.useEffect(()=>{if(!o||l===0||p)return;const n=setTimeout(()=>{u?.()},l);return()=>clearTimeout(n)},[o,l,u,p]),w?t.jsxs("div",{ref:M,role:s==="error"||s==="warning"?"alert":"status","aria-live":s==="error"||s==="warning"?"assertive":"polite",className:S.cx("brycks-toast",`brycks-toast--${s}`,C&&"brycks-toast--exiting",a),style:d,"data-testid":m,onMouseEnter:n=>{y(!0),g?.(n)},onMouseLeave:n=>{y(!1),T?.(n)},..._,children:[t.jsx("span",{className:"brycks-toast__icon",children:r||t.jsx(E,{intent:s})}),t.jsxs("div",{className:"brycks-toast__content",children:[c&&t.jsx("span",{className:"brycks-toast__title",children:c}),i&&t.jsx("span",{className:"brycks-toast__description",children:i}),b&&t.jsx("div",{className:"brycks-toast__action",children:b})]}),x&&t.jsx("button",{type:"button",className:"brycks-toast__close",onClick:u,"aria-label":h,children:t.jsx(L,{})})]}):null});k.displayName="Toast";const q={"top-left":{top:16,left:16},"top-center":{top:16,left:"50%",transform:"translateX(-50%)"},"top-right":{top:16,right:16},"bottom-left":{bottom:16,left:16},"bottom-center":{bottom:16,left:"50%",transform:"translateX(-50%)"},"bottom-right":{bottom:16,right:16}};let I=0;function z({children:f,position:s="top-right",maxToasts:c=5}){const[i,o]=e.useState([]),[l,u]=e.useState(!1);e.useEffect(()=>{u(!0)},[]);const x=e.useCallback(r=>{const a=`toast-${++I}`;return o(d=>{const m=[...d,{id:a,props:r}];return m.length>c?m.slice(-c):m}),a},[c]),h=e.useCallback(r=>{o(a=>a.filter(d=>d.id!==r))},[]),b=e.useCallback(()=>{o([])},[]);return t.jsxs(P.ToastContext.Provider,{value:{toasts:i,addToast:x,removeToast:h,removeAll:b},children:[f,l&&N.createPortal(t.jsx("div",{className:"brycks-toast-container",style:q[s],children:i.map(({id:r,props:a})=>t.jsx("div",{className:"brycks-toast-wrapper",children:t.jsx(k,{...a,isOpen:!0,onClose:()=>h(r)})},r))}),document.body)]})}exports.Toast=k;exports.ToastProvider=z;
|
|
11
2
|
//# sourceMappingURL=Toast.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Toast.cjs","sources":["../../../../src/components/feedback/Toast/Toast.tsx"],"sourcesContent":["/**\n * Toast Component\n *\n * A notification toast with auto-dismiss and action support.\n * Includes a toast container for managing multiple toasts.\n */\n\nimport {\n forwardRef,\n useState,\n useEffect,\n useCallback,\n type CSSProperties,\n type ReactNode,\n type HTMLAttributes,\n} from 'react'\nimport { createPortal } from 'react-dom'\nimport { cx } from '../../../utils/styles'\nimport { ToastContext } from './ToastContext'\nimport type { ToastItem } from './ToastContext'\n\nexport type ToastIntent = 'info' | 'success' | 'warning' | 'error'\nexport type ToastPosition = 'top-left' | 'top-center' | 'top-right' | 'bottom-left' | 'bottom-center' | 'bottom-right'\n\nexport interface ToastProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title'> {\n /** Toast intent/type */\n intent?: ToastIntent\n /** Toast title */\n title?: ReactNode\n /** Toast description */\n description?: ReactNode\n /** Whether the toast is visible */\n isOpen?: boolean\n /** Duration in ms before auto-dismiss (0 = no auto-dismiss) */\n duration?: number\n /** Callback when toast should close */\n onClose?: () => void\n /** Whether to show close button */\n showCloseButton?: boolean\n /** Accessible label of the close button */\n closeLabel?: string\n /** Action button */\n action?: ReactNode\n /** Custom icon */\n icon?: ReactNode\n /** Custom class name */\n className?: string\n /** Test ID */\n testId?: string\n}\n\nconst intentConfig: Record<ToastIntent, { bg: string; border: string; icon: string }> = {\n info: {\n bg: 'var(--brycks-info-muted)',\n border: 'var(--brycks-info-soft-hover)',\n icon: 'var(--brycks-info-default)',\n },\n success: {\n bg: 'var(--brycks-success-muted)',\n border: 'var(--brycks-success-soft-hover)',\n icon: 'var(--brycks-success-default)',\n },\n warning: {\n bg: 'var(--brycks-warning-muted)',\n border: 'var(--brycks-warning-soft-hover)',\n icon: 'var(--brycks-warning-default)',\n },\n error: {\n bg: 'var(--brycks-error-muted)',\n border: 'var(--brycks-error-soft-hover)',\n icon: 'var(--brycks-error-default)',\n },\n}\n\nfunction ToastIcon({ intent }: { intent: ToastIntent }) {\n const paths: Record<ToastIntent, string> = {\n info: 'M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z',\n success: 'M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z',\n warning: 'M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z',\n error: 'M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z',\n }\n\n return (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d={paths[intent]} />\n </svg>\n )\n}\n\nfunction CloseIcon() {\n return (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\">\n <path d=\"M4 4l8 8M12 4l-8 8\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" />\n </svg>\n )\n}\n\nexport const Toast = forwardRef<HTMLDivElement, ToastProps>(function Toast(\n {\n intent = 'info',\n title,\n description,\n isOpen = true,\n duration = 5000,\n onClose,\n showCloseButton = true,\n closeLabel = 'Close toast',\n action,\n icon,\n className,\n style,\n testId,\n onMouseEnter,\n onMouseLeave,\n ...props\n },\n ref\n) {\n const [isVisible, setIsVisible] = useState(isOpen)\n const [isExiting, setIsExiting] = useState(false)\n const [isPaused, setIsPaused] = useState(false)\n\n useEffect(() => {\n if (isOpen) {\n setIsVisible(true)\n setIsExiting(false)\n } else {\n setIsExiting(true)\n const timer = setTimeout(() => setIsVisible(false), 200)\n return () => clearTimeout(timer)\n }\n }, [isOpen])\n\n // Auto-dismiss pauses while the pointer is over the toast\n useEffect(() => {\n if (!isOpen || duration === 0 || isPaused) return\n\n const timer = setTimeout(() => {\n onClose?.()\n }, duration)\n\n return () => clearTimeout(timer)\n }, [isOpen, duration, onClose, isPaused])\n\n if (!isVisible) return null\n\n const config = intentConfig[intent]\n\n const toastStyle: CSSProperties = {\n display: 'flex',\n alignItems: 'flex-start',\n gap: 12,\n padding: '12px 16px',\n backgroundColor: config.bg,\n border: `1px solid ${config.border}`,\n borderRadius: 'var(--brycks-radius-lg)',\n boxShadow: 'var(--brycks-shadow-lg)',\n maxWidth: 400,\n animation: isExiting\n ? 'brycks-toast-out 200ms ease-in forwards'\n : 'brycks-toast-in 200ms ease-out',\n ...style,\n }\n\n const iconStyle: CSSProperties = {\n color: config.icon,\n flexShrink: 0,\n marginTop: 2,\n }\n\n const contentStyle: CSSProperties = {\n flex: 1,\n display: 'flex',\n flexDirection: 'column',\n gap: 4,\n }\n\n const titleStyle: CSSProperties = {\n fontSize: 14,\n fontWeight: 600,\n color: 'var(--brycks-foreground-default)',\n lineHeight: 1.4,\n }\n\n const descriptionStyle: CSSProperties = {\n fontSize: 13,\n color: 'var(--brycks-foreground-muted)',\n lineHeight: 1.4,\n }\n\n const closeButtonStyle: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: 24,\n height: 24,\n borderRadius: 'var(--brycks-radius-sm)',\n color: 'var(--brycks-foreground-muted)',\n transition: 'all 150ms ease-out',\n flexShrink: 0,\n marginLeft: 'auto',\n }\n\n return (\n <>\n <style>\n {`\n @keyframes brycks-toast-in {\n from { opacity: 0; transform: translateY(-8px) scale(0.95); }\n to { opacity: 1; transform: translateY(0) scale(1); }\n }\n @keyframes brycks-toast-out {\n from { opacity: 1; transform: translateY(0) scale(1); }\n to { opacity: 0; transform: translateY(-8px) scale(0.95); }\n }\n `}\n </style>\n <div\n ref={ref}\n role={intent === 'error' || intent === 'warning' ? 'alert' : 'status'}\n aria-live={intent === 'error' || intent === 'warning' ? 'assertive' : 'polite'}\n className={cx('brycks-toast', `brycks-toast--${intent}`, className)}\n style={toastStyle}\n data-testid={testId}\n onMouseEnter={(e) => {\n setIsPaused(true)\n onMouseEnter?.(e)\n }}\n onMouseLeave={(e) => {\n setIsPaused(false)\n onMouseLeave?.(e)\n }}\n {...props}\n >\n <span style={iconStyle}>\n {icon || <ToastIcon intent={intent} />}\n </span>\n <div style={contentStyle}>\n {title && <span style={titleStyle}>{title}</span>}\n {description && <span style={descriptionStyle}>{description}</span>}\n {action && <div style={{ marginTop: 8 }}>{action}</div>}\n </div>\n {showCloseButton && (\n <button\n type=\"button\"\n style={closeButtonStyle}\n onClick={onClose}\n aria-label={closeLabel}\n onMouseEnter={(e) => {\n e.currentTarget.style.backgroundColor = 'var(--brycks-background-muted)'\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.backgroundColor = 'transparent'\n }}\n >\n <CloseIcon />\n </button>\n )}\n </div>\n </>\n )\n})\n\nToast.displayName = 'Toast'\n\n// Toast Provider\nexport interface ToastProviderProps {\n children: ReactNode\n position?: ToastPosition\n maxToasts?: number\n}\n\nconst positionStyles: Record<ToastPosition, CSSProperties> = {\n 'top-left': { top: 16, left: 16 },\n 'top-center': { top: 16, left: '50%', transform: 'translateX(-50%)' },\n 'top-right': { top: 16, right: 16 },\n 'bottom-left': { bottom: 16, left: 16 },\n 'bottom-center': { bottom: 16, left: '50%', transform: 'translateX(-50%)' },\n 'bottom-right': { bottom: 16, right: 16 },\n}\n\nlet toastCounter = 0\n\nexport function ToastProvider({\n children,\n position = 'top-right',\n maxToasts = 5,\n}: ToastProviderProps) {\n const [toasts, setToasts] = useState<ToastItem[]>([])\n const [mounted, setMounted] = useState(false)\n\n useEffect(() => {\n setMounted(true)\n }, [])\n\n const addToast = useCallback(\n (props: Omit<ToastProps, 'isOpen' | 'onClose'>) => {\n const id = `toast-${++toastCounter}`\n setToasts((prev) => {\n const newToasts = [...prev, { id, props }]\n if (newToasts.length > maxToasts) {\n return newToasts.slice(-maxToasts)\n }\n return newToasts\n })\n return id\n },\n [maxToasts]\n )\n\n const removeToast = useCallback((id: string) => {\n setToasts((prev) => prev.filter((t) => t.id !== id))\n }, [])\n\n const removeAll = useCallback(() => {\n setToasts([])\n }, [])\n\n const containerStyle: CSSProperties = {\n position: 'fixed',\n zIndex: 'var(--brycks-z-toast)' as unknown as number,\n display: 'flex',\n flexDirection: 'column',\n gap: 8,\n pointerEvents: 'none',\n ...positionStyles[position],\n }\n\n const toastWrapperStyle: CSSProperties = {\n pointerEvents: 'auto',\n }\n\n return (\n <ToastContext.Provider value={{ toasts, addToast, removeToast, removeAll }}>\n {children}\n {mounted &&\n createPortal(\n <div className=\"brycks-toast-container\" style={containerStyle}>\n {toasts.map(({ id, props }) => (\n <div key={id} style={toastWrapperStyle}>\n <Toast {...props} isOpen onClose={() => removeToast(id)} />\n </div>\n ))}\n </div>,\n document.body\n )}\n </ToastContext.Provider>\n )\n}\n"],"names":["intentConfig","ToastIcon","intent","paths","jsx","CloseIcon","Toast","forwardRef","title","description","isOpen","duration","onClose","showCloseButton","closeLabel","action","icon","className","style","testId","onMouseEnter","onMouseLeave","props","ref","isVisible","setIsVisible","useState","isExiting","setIsExiting","isPaused","setIsPaused","useEffect","timer","config","toastStyle","iconStyle","contentStyle","titleStyle","descriptionStyle","closeButtonStyle","jsxs","Fragment","cx","e","positionStyles","toastCounter","ToastProvider","children","position","maxToasts","toasts","setToasts","mounted","setMounted","addToast","useCallback","id","prev","newToasts","removeToast","t","removeAll","containerStyle","toastWrapperStyle","ToastContext","createPortal"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Toast.cjs","sources":["../../../../src/components/feedback/Toast/Toast.tsx"],"sourcesContent":["/**\n * Toast Component\n *\n * A notification toast with auto-dismiss and action support.\n * Includes a toast container for managing multiple toasts.\n */\n\nimport {\n forwardRef,\n useState,\n useEffect,\n useCallback,\n type CSSProperties,\n type ReactNode,\n type HTMLAttributes,\n} from 'react'\nimport { createPortal } from 'react-dom'\nimport { cx } from '../../../utils/styles'\nimport { ToastContext } from './ToastContext'\nimport type { ToastItem } from './ToastContext'\n\nexport type ToastIntent = 'info' | 'success' | 'warning' | 'error'\nexport type ToastPosition = 'top-left' | 'top-center' | 'top-right' | 'bottom-left' | 'bottom-center' | 'bottom-right'\n\nexport interface ToastProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title'> {\n /** Toast intent/type */\n intent?: ToastIntent\n /** Toast title */\n title?: ReactNode\n /** Toast description */\n description?: ReactNode\n /** Whether the toast is visible */\n isOpen?: boolean\n /** Duration in ms before auto-dismiss (0 = no auto-dismiss) */\n duration?: number\n /** Callback when toast should close */\n onClose?: () => void\n /** Whether to show close button */\n showCloseButton?: boolean\n /** Accessible label of the close button */\n closeLabel?: string\n /** Action button */\n action?: ReactNode\n /** Custom icon */\n icon?: ReactNode\n /** Custom class name */\n className?: string\n /** Test ID */\n testId?: string\n}\n\nfunction ToastIcon({ intent }: { intent: ToastIntent }) {\n const paths: Record<ToastIntent, string> = {\n info: 'M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z',\n success: 'M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z',\n warning: 'M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z',\n error: 'M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z',\n }\n\n return (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d={paths[intent]} />\n </svg>\n )\n}\n\nfunction CloseIcon() {\n return (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\">\n <path d=\"M4 4l8 8M12 4l-8 8\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" />\n </svg>\n )\n}\n\nexport const Toast = forwardRef<HTMLDivElement, ToastProps>(function Toast(\n {\n intent = 'info',\n title,\n description,\n isOpen = true,\n duration = 5000,\n onClose,\n showCloseButton = true,\n closeLabel = 'Close toast',\n action,\n icon,\n className,\n style,\n testId,\n onMouseEnter,\n onMouseLeave,\n ...props\n },\n ref\n) {\n const [isVisible, setIsVisible] = useState(isOpen)\n const [isExiting, setIsExiting] = useState(false)\n const [isPaused, setIsPaused] = useState(false)\n\n useEffect(() => {\n if (isOpen) {\n setIsVisible(true)\n setIsExiting(false)\n } else {\n setIsExiting(true)\n const timer = setTimeout(() => setIsVisible(false), 200)\n return () => clearTimeout(timer)\n }\n }, [isOpen])\n\n // Auto-dismiss pauses while the pointer is over the toast\n useEffect(() => {\n if (!isOpen || duration === 0 || isPaused) return\n\n const timer = setTimeout(() => {\n onClose?.()\n }, duration)\n\n return () => clearTimeout(timer)\n }, [isOpen, duration, onClose, isPaused])\n\n if (!isVisible) return null\n\n return (\n <div\n ref={ref}\n role={intent === 'error' || intent === 'warning' ? 'alert' : 'status'}\n aria-live={intent === 'error' || intent === 'warning' ? 'assertive' : 'polite'}\n className={cx('brycks-toast', `brycks-toast--${intent}`, isExiting && 'brycks-toast--exiting', className)}\n style={style}\n data-testid={testId}\n onMouseEnter={(e) => {\n setIsPaused(true)\n onMouseEnter?.(e)\n }}\n onMouseLeave={(e) => {\n setIsPaused(false)\n onMouseLeave?.(e)\n }}\n {...props}\n >\n <span className=\"brycks-toast__icon\">\n {icon || <ToastIcon intent={intent} />}\n </span>\n <div className=\"brycks-toast__content\">\n {title && <span className=\"brycks-toast__title\">{title}</span>}\n {description && <span className=\"brycks-toast__description\">{description}</span>}\n {action && <div className=\"brycks-toast__action\">{action}</div>}\n </div>\n {showCloseButton && (\n <button\n type=\"button\"\n className=\"brycks-toast__close\"\n onClick={onClose}\n aria-label={closeLabel}\n >\n <CloseIcon />\n </button>\n )}\n </div>\n )\n})\n\nToast.displayName = 'Toast'\n\n// Toast Provider\nexport interface ToastProviderProps {\n children: ReactNode\n position?: ToastPosition\n maxToasts?: number\n}\n\nconst positionStyles: Record<ToastPosition, CSSProperties> = {\n 'top-left': { top: 16, left: 16 },\n 'top-center': { top: 16, left: '50%', transform: 'translateX(-50%)' },\n 'top-right': { top: 16, right: 16 },\n 'bottom-left': { bottom: 16, left: 16 },\n 'bottom-center': { bottom: 16, left: '50%', transform: 'translateX(-50%)' },\n 'bottom-right': { bottom: 16, right: 16 },\n}\n\nlet toastCounter = 0\n\nexport function ToastProvider({\n children,\n position = 'top-right',\n maxToasts = 5,\n}: ToastProviderProps) {\n const [toasts, setToasts] = useState<ToastItem[]>([])\n const [mounted, setMounted] = useState(false)\n\n useEffect(() => {\n setMounted(true)\n }, [])\n\n const addToast = useCallback(\n (props: Omit<ToastProps, 'isOpen' | 'onClose'>) => {\n const id = `toast-${++toastCounter}`\n setToasts((prev) => {\n const newToasts = [...prev, { id, props }]\n if (newToasts.length > maxToasts) {\n return newToasts.slice(-maxToasts)\n }\n return newToasts\n })\n return id\n },\n [maxToasts]\n )\n\n const removeToast = useCallback((id: string) => {\n setToasts((prev) => prev.filter((t) => t.id !== id))\n }, [])\n\n const removeAll = useCallback(() => {\n setToasts([])\n }, [])\n\n return (\n <ToastContext.Provider value={{ toasts, addToast, removeToast, removeAll }}>\n {children}\n {mounted &&\n createPortal(\n <div className=\"brycks-toast-container\" style={positionStyles[position]}>\n {toasts.map(({ id, props }) => (\n <div key={id} className=\"brycks-toast-wrapper\">\n <Toast {...props} isOpen onClose={() => removeToast(id)} />\n </div>\n ))}\n </div>,\n document.body\n )}\n </ToastContext.Provider>\n )\n}\n"],"names":["ToastIcon","intent","paths","jsx","CloseIcon","Toast","forwardRef","title","description","isOpen","duration","onClose","showCloseButton","closeLabel","action","icon","className","style","testId","onMouseEnter","onMouseLeave","props","ref","isVisible","setIsVisible","useState","isExiting","setIsExiting","isPaused","setIsPaused","useEffect","timer","jsxs","cx","e","positionStyles","toastCounter","ToastProvider","children","position","maxToasts","toasts","setToasts","mounted","setMounted","addToast","useCallback","id","prev","newToasts","removeToast","t","removeAll","ToastContext","createPortal"],"mappings":"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"}
|