@brycks/core-front 0.5.0 → 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.
Files changed (56) hide show
  1. package/dist/components/data/List/List.cjs +1 -1
  2. package/dist/components/data/List/List.cjs.map +1 -1
  3. package/dist/components/data/List/List.js +68 -148
  4. package/dist/components/data/List/List.js.map +1 -1
  5. package/dist/components/data/Table/Table.cjs +1 -1
  6. package/dist/components/data/Table/Table.cjs.map +1 -1
  7. package/dist/components/data/Table/Table.js +142 -224
  8. package/dist/components/data/Table/Table.js.map +1 -1
  9. package/dist/components/data/TreeView/TreeView.cjs +1 -1
  10. package/dist/components/data/TreeView/TreeView.cjs.map +1 -1
  11. package/dist/components/data/TreeView/TreeView.js +141 -182
  12. package/dist/components/data/TreeView/TreeView.js.map +1 -1
  13. package/dist/components/feedback/Drawer/Drawer.cjs +1 -22
  14. package/dist/components/feedback/Drawer/Drawer.cjs.map +1 -1
  15. package/dist/components/feedback/Drawer/Drawer.js +84 -184
  16. package/dist/components/feedback/Drawer/Drawer.js.map +1 -1
  17. package/dist/components/feedback/Modal/Modal.cjs +1 -1
  18. package/dist/components/feedback/Modal/Modal.cjs.map +1 -1
  19. package/dist/components/feedback/Modal/Modal.js +65 -150
  20. package/dist/components/feedback/Modal/Modal.js.map +1 -1
  21. package/dist/components/feedback/Toast/Toast.cjs +1 -10
  22. package/dist/components/feedback/Toast/Toast.cjs.map +1 -1
  23. package/dist/components/feedback/Toast/Toast.js +94 -187
  24. package/dist/components/feedback/Toast/Toast.js.map +1 -1
  25. package/dist/components/form/Checkbox/Checkbox.cjs +1 -1
  26. package/dist/components/form/Checkbox/Checkbox.js +11 -11
  27. package/dist/components/form/Combobox/Combobox.cjs +1 -6
  28. package/dist/components/form/Combobox/Combobox.cjs.map +1 -1
  29. package/dist/components/form/Combobox/Combobox.js +187 -283
  30. package/dist/components/form/Combobox/Combobox.js.map +1 -1
  31. package/dist/components/form/Input/Input.cjs +1 -1
  32. package/dist/components/form/Input/Input.cjs.map +1 -1
  33. package/dist/components/form/Input/Input.js +38 -133
  34. package/dist/components/form/Input/Input.js.map +1 -1
  35. package/dist/components/form/Select/Select.cjs +1 -1
  36. package/dist/components/form/Select/Select.cjs.map +1 -1
  37. package/dist/components/form/Select/Select.js +36 -82
  38. package/dist/components/form/Select/Select.js.map +1 -1
  39. package/dist/components/form/TagInput/TagInput.cjs +1 -1
  40. package/dist/components/form/TagInput/TagInput.js +8 -8
  41. package/dist/components/form/Textarea/Textarea.cjs +1 -1
  42. package/dist/components/form/Textarea/Textarea.cjs.map +1 -1
  43. package/dist/components/form/Textarea/Textarea.js +61 -95
  44. package/dist/components/form/Textarea/Textarea.js.map +1 -1
  45. package/dist/components/navigation/ContextMenu/ContextMenu.cjs +1 -1
  46. package/dist/components/navigation/ContextMenu/ContextMenu.js +9 -9
  47. package/dist/components/navigation/Menu/Menu.cjs +1 -1
  48. package/dist/components/navigation/Menu/Menu.cjs.map +1 -1
  49. package/dist/components/navigation/Menu/Menu.js +70 -135
  50. package/dist/components/navigation/Menu/Menu.js.map +1 -1
  51. package/dist/components/navigation/Pagination/Pagination.cjs +1 -1
  52. package/dist/components/navigation/Pagination/Pagination.cjs.map +1 -1
  53. package/dist/components/navigation/Pagination/Pagination.js +87 -157
  54. package/dist/components/navigation/Pagination/Pagination.js.map +1 -1
  55. package/dist/styles.css +1 -1
  56. package/package.json +1 -1
@@ -1,20 +1,9 @@
1
- import { jsx as t, jsxs as v } from "react/jsx-runtime";
2
- import { forwardRef as X, useRef as i, useEffect as u, useCallback as Y, useMemo as L, memo as Z } from "react";
3
- import { createPortal as _ } from "react-dom";
4
- import { cx as O } from "../../../utils/styles.js";
5
- import { useId as T } from "../../../hooks/useId.js";
6
- import { iconButtonSizes as N } from "../../../design-system/primitives/layout.js";
7
- import { spacing as o } from "../../../design-system/tokens/spacing.js";
8
- import { fontSizes as j } from "../../../design-system/tokens/typography.js";
9
- import { componentGap as ee } from "../../../design-system/primitives/sizing.js";
10
- const te = {
11
- sm: "400px",
12
- md: "500px",
13
- lg: "640px",
14
- xl: "800px",
15
- "2xl": "1200px",
16
- full: "calc(100vw - 48px)"
17
- }, re = Z(function() {
1
+ import { jsx as t, jsxs as b } from "react/jsx-runtime";
2
+ import { forwardRef as H, useRef as d, useEffect as i, useCallback as P, memo as S } from "react";
3
+ import { createPortal as W } from "react-dom";
4
+ import { cx as $ } from "../../../utils/styles.js";
5
+ import { useId as I } from "../../../hooks/useId.js";
6
+ const z = S(function() {
18
7
  return /* @__PURE__ */ t("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ t(
19
8
  "path",
20
9
  {
@@ -24,181 +13,107 @@ const te = {
24
13
  strokeLinecap: "round"
25
14
  }
26
15
  ) });
27
- }), oe = X(function({
16
+ }), B = H(function({
28
17
  isOpen: r,
29
18
  onClose: n,
30
- size: l = "md",
19
+ size: M = "md",
31
20
  title: c,
32
- description: m,
33
- closeOnOverlayClick: p = !0,
34
- closeOnEscape: k = !0,
35
- showCloseButton: x = !0,
36
- closeLabel: D = "Close modal",
37
- footer: g,
38
- className: $,
39
- style: h,
40
- testId: z,
41
- children: W,
42
- ...B
43
- }, d) {
44
- const f = i(null), w = T("modal-title"), S = T("modal-description"), y = i(null), s = i(!1);
45
- u(() => {
46
- r && !s.current ? (y.current = document.activeElement, s.current = !0) : !r && s.current && (document.activeElement instanceof HTMLElement && document.activeElement.blur(), y.current?.focus(), y.current = null, s.current = !1);
21
+ description: s,
22
+ closeOnOverlayClick: y = !0,
23
+ closeOnEscape: v = !0,
24
+ showCloseButton: h = !0,
25
+ closeLabel: R = "Close modal",
26
+ footer: k,
27
+ className: C,
28
+ style: D,
29
+ testId: K,
30
+ children: T,
31
+ ...j
32
+ }, l) {
33
+ const u = d(null), E = I("modal-title"), p = I("modal-description"), m = d(null), a = d(!1);
34
+ i(() => {
35
+ r && !a.current ? (m.current = document.activeElement, a.current = !0) : !r && a.current && (document.activeElement instanceof HTMLElement && document.activeElement.blur(), m.current?.focus(), m.current = null, a.current = !1);
47
36
  }, [r]);
48
- const E = i(n);
49
- u(() => {
50
- E.current = n;
51
- }, [n]), u(() => {
37
+ const N = d(n);
38
+ i(() => {
39
+ N.current = n;
40
+ }, [n]), i(() => {
52
41
  if (!r) return;
53
- const e = f.current;
42
+ const e = u.current;
54
43
  e && e.focus();
55
- }, [r]), u(() => {
44
+ }, [r]), i(() => {
56
45
  if (!r) return;
57
- const e = f.current, C = (a) => {
58
- if (a.key === "Escape" && k) {
59
- E.current();
46
+ const e = u.current, x = (o) => {
47
+ if (o.key === "Escape" && v) {
48
+ N.current();
60
49
  return;
61
50
  }
62
- if (a.key === "Tab" && e) {
63
- const b = e.querySelectorAll(
51
+ if (o.key === "Tab" && e) {
52
+ const f = e.querySelectorAll(
64
53
  'button:not([disabled]), [href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [contenteditable="true"], [tabindex]:not([tabindex="-1"])'
65
- ), I = b[0], M = b[b.length - 1];
66
- a.shiftKey && document.activeElement === I ? (a.preventDefault(), M?.focus()) : !a.shiftKey && document.activeElement === M && (a.preventDefault(), I?.focus());
54
+ ), w = f[0], g = f[f.length - 1];
55
+ o.shiftKey && document.activeElement === w ? (o.preventDefault(), g?.focus()) : !o.shiftKey && document.activeElement === g && (o.preventDefault(), w?.focus());
67
56
  }
68
57
  };
69
- return document.addEventListener("keydown", C), document.body.style.overflow = "hidden", () => {
70
- document.removeEventListener("keydown", C), document.body.style.overflow = "";
58
+ return document.addEventListener("keydown", x), document.body.style.overflow = "hidden", () => {
59
+ document.removeEventListener("keydown", x), document.body.style.overflow = "";
71
60
  };
72
- }, [r, k]);
73
- const H = Y(
61
+ }, [r, v]);
62
+ const A = P(
74
63
  (e) => {
75
- e.target === e.currentTarget && p && n();
64
+ e.target === e.currentTarget && y && n();
76
65
  },
77
- [p, n]
78
- ), K = L(() => ({
79
- position: "fixed",
80
- inset: 0,
81
- zIndex: "var(--brycks-z-modal)",
82
- display: "flex",
83
- alignItems: "center",
84
- justifyContent: "center",
85
- padding: o[6],
86
- backgroundColor: "var(--brycks-background-overlay)",
87
- animation: "brycks-fade-in var(--brycks-duration-normal) var(--brycks-ease-out)"
88
- }), []), A = L(() => ({
89
- position: "relative",
90
- width: "100%",
91
- maxWidth: te[l],
92
- maxHeight: l === "full" ? "calc(100vh - 48px)" : "85vh",
93
- backgroundColor: "var(--brycks-background-elevated)",
94
- borderRadius: "var(--brycks-radius-xl)",
95
- boxShadow: "var(--brycks-shadow-2xl)",
96
- display: "flex",
97
- flexDirection: "column",
98
- overflow: "hidden",
99
- animation: "brycks-scale-in var(--brycks-duration-normal) var(--brycks-ease-out)",
100
- outline: "none",
101
- ...h
102
- }), [l, h]);
66
+ [y, n]
67
+ );
103
68
  if (!r) return null;
104
- const q = {
105
- display: "flex",
106
- alignItems: "flex-start",
107
- justifyContent: "space-between",
108
- padding: `${o[5]}px ${o[6]}px`,
109
- borderBottom: "1px solid var(--brycks-border-muted)"
110
- }, G = {
111
- display: "flex",
112
- flexDirection: "column",
113
- gap: o[1]
114
- }, P = {
115
- fontSize: j.lg,
116
- fontWeight: 600,
117
- color: "var(--brycks-foreground-default)",
118
- margin: 0,
119
- lineHeight: 1.3
120
- }, F = {
121
- fontSize: j.base,
122
- color: "var(--brycks-foreground-muted)",
123
- margin: 0
124
- }, J = {
125
- display: "flex",
126
- alignItems: "center",
127
- justifyContent: "center",
128
- width: N.sm,
129
- height: N.sm,
130
- borderRadius: "var(--brycks-radius-md)",
131
- color: "var(--brycks-foreground-muted)",
132
- transition: "all var(--brycks-duration-fast) var(--brycks-ease-out)",
133
- marginLeft: ee.xl,
134
- flexShrink: 0
135
- }, Q = {
136
- flex: 1,
137
- overflow: "auto",
138
- padding: o[6]
139
- }, U = {
140
- display: "flex",
141
- alignItems: "center",
142
- justifyContent: "flex-end",
143
- gap: o[2],
144
- padding: `${o[4]}px ${o[6]}px`,
145
- borderTop: "1px solid var(--brycks-border-muted)"
146
- }, V = /* @__PURE__ */ t(
69
+ const q = /* @__PURE__ */ t(
147
70
  "div",
148
71
  {
149
72
  className: "brycks-modal-overlay",
150
- style: K,
151
- onClick: H,
152
- children: /* @__PURE__ */ v(
73
+ onClick: A,
74
+ children: /* @__PURE__ */ b(
153
75
  "div",
154
76
  {
155
77
  ref: (e) => {
156
- f.current = e, typeof d == "function" ? d(e) : d && (d.current = e);
78
+ u.current = e, typeof l == "function" ? l(e) : l && (l.current = e);
157
79
  },
158
80
  role: "dialog",
159
81
  "aria-modal": "true",
160
- "aria-labelledby": c ? w : void 0,
161
- "aria-describedby": m ? S : void 0,
162
- className: O("brycks-modal", `brycks-modal--${l}`, $),
163
- style: A,
82
+ "aria-labelledby": c ? E : void 0,
83
+ "aria-describedby": s ? p : void 0,
84
+ className: $("brycks-modal", `brycks-modal--${M}`, C),
85
+ style: D,
164
86
  tabIndex: -1,
165
- "data-testid": z,
166
- ...B,
87
+ "data-testid": K,
88
+ ...j,
167
89
  children: [
168
- (c || x) && /* @__PURE__ */ v("div", { className: "brycks-modal-header", style: q, children: [
169
- /* @__PURE__ */ v("div", { style: G, children: [
170
- c && /* @__PURE__ */ t("h2", { id: w, style: P, children: c }),
171
- m && /* @__PURE__ */ t("p", { id: S, style: F, children: m })
90
+ (c || h) && /* @__PURE__ */ b("div", { className: "brycks-modal-header", children: [
91
+ /* @__PURE__ */ b("div", { className: "brycks-modal-title-container", children: [
92
+ c && /* @__PURE__ */ t("h2", { id: E, className: "brycks-modal-title", children: c }),
93
+ s && /* @__PURE__ */ t("p", { id: p, className: "brycks-modal-description", children: s })
172
94
  ] }),
173
- x && /* @__PURE__ */ t(
95
+ h && /* @__PURE__ */ t(
174
96
  "button",
175
97
  {
176
98
  type: "button",
177
99
  className: "brycks-modal-close",
178
- style: J,
179
100
  onClick: n,
180
- "aria-label": D,
181
- onMouseEnter: (e) => {
182
- e.currentTarget.style.backgroundColor = "var(--brycks-background-muted)", e.currentTarget.style.color = "var(--brycks-foreground-default)";
183
- },
184
- onMouseLeave: (e) => {
185
- e.currentTarget.style.backgroundColor = "transparent", e.currentTarget.style.color = "var(--brycks-foreground-muted)";
186
- },
187
- children: /* @__PURE__ */ t(re, {})
101
+ "aria-label": R,
102
+ children: /* @__PURE__ */ t(z, {})
188
103
  }
189
104
  )
190
105
  ] }),
191
- /* @__PURE__ */ t("div", { className: "brycks-modal-content", style: Q, children: W }),
192
- g && /* @__PURE__ */ t("div", { className: "brycks-modal-footer", style: U, children: g })
106
+ /* @__PURE__ */ t("div", { className: "brycks-modal-content", children: T }),
107
+ k && /* @__PURE__ */ t("div", { className: "brycks-modal-footer", children: k })
193
108
  ]
194
109
  }
195
110
  )
196
111
  }
197
112
  );
198
- return _(V, document.body);
113
+ return W(q, document.body);
199
114
  });
200
- oe.displayName = "Modal";
115
+ B.displayName = "Modal";
201
116
  export {
202
- oe as Modal
117
+ B as Modal
203
118
  };
204
119
  //# sourceMappingURL=Modal.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Modal.js","sources":["../../../../src/components/feedback/Modal/Modal.tsx"],"sourcesContent":["/**\r\n * Modal Component\r\n *\r\n * Accessible modal dialog with smooth Apple-inspired animations.\r\n * Supports focus trapping and keyboard navigation.\r\n */\r\n\r\nimport {\r\n forwardRef,\r\n useEffect,\r\n useRef,\r\n useCallback,\r\n useMemo,\r\n memo,\r\n type CSSProperties,\r\n type ReactNode,\r\n type HTMLAttributes,\r\n} from 'react'\r\nimport { createPortal } from 'react-dom'\r\nimport { cx } from '../../../utils/styles'\r\nimport { useId } from '../../../hooks/useId'\r\nimport { spacing, fontSizes } from '../../../design-system'\r\nimport { componentGap, iconButtonSizes } from '../../../design-system/primitives'\r\n\r\nexport type ModalSize = 'sm' | 'md' | 'lg' | 'xl' | '2xl' | 'full'\r\n\r\nexport interface ModalProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title'> {\r\n /** Whether the modal is open */\r\n isOpen: boolean\r\n /** Callback when modal should close */\r\n onClose: () => void\r\n /** Modal size */\r\n size?: ModalSize\r\n /** Modal title */\r\n title?: ReactNode\r\n /** Modal description */\r\n description?: ReactNode\r\n /** Whether to close on overlay click */\r\n closeOnOverlayClick?: boolean\r\n /** Whether to close on escape key */\r\n closeOnEscape?: boolean\r\n /** Whether to show close button */\r\n showCloseButton?: boolean\r\n /** Accessible label of the close button */\r\n closeLabel?: string\r\n /** Footer content (e.g. action buttons), pinned below the scrollable body */\r\n footer?: ReactNode\r\n /** Custom class name */\r\n className?: string\r\n /** Test ID */\r\n testId?: string\r\n /** Modal content */\r\n children?: ReactNode\r\n}\r\n\r\nconst sizeWidths: Record<ModalSize, string> = {\r\n sm: '400px',\r\n md: '500px',\r\n lg: '640px',\r\n xl: '800px',\r\n '2xl': '1200px',\r\n full: 'calc(100vw - 48px)',\r\n}\r\n\r\n/** Close icon - memoized to prevent re-renders */\r\nconst CloseIcon = memo(function CloseIcon() {\r\n return (\r\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden=\"true\">\r\n <path\r\n d=\"M4 4L12 12M12 4L4 12\"\r\n stroke=\"currentColor\"\r\n strokeWidth=\"1.5\"\r\n strokeLinecap=\"round\"\r\n />\r\n </svg>\r\n )\r\n})\r\n\r\nexport const Modal = forwardRef<HTMLDivElement, ModalProps>(function Modal(\r\n {\r\n isOpen,\r\n onClose,\r\n size = 'md',\r\n title,\r\n description,\r\n closeOnOverlayClick = true,\r\n closeOnEscape = true,\r\n showCloseButton = true,\r\n closeLabel = 'Close modal',\r\n footer,\r\n className,\r\n style,\r\n testId,\r\n children,\r\n ...props\r\n },\r\n ref\r\n) {\r\n const modalRef = useRef<HTMLDivElement>(null)\r\n const titleId = useId('modal-title')\r\n const descriptionId = useId('modal-description')\r\n const previousActiveElement = useRef<HTMLElement | null>(null)\r\n const wasOpen = useRef(false)\r\n\r\n // Track previous open state to handle focus restoration before unmount\r\n useEffect(() => {\r\n // Modal just opened\r\n if (isOpen && !wasOpen.current) {\r\n previousActiveElement.current = document.activeElement as HTMLElement\r\n wasOpen.current = true\r\n }\r\n // Modal is about to close - restore focus BEFORE unmount\r\n else if (!isOpen && wasOpen.current) {\r\n // Blur any focused element inside modal to prevent aria-hidden warning\r\n if (document.activeElement instanceof HTMLElement) {\r\n document.activeElement.blur()\r\n }\r\n // Restore focus to previous element\r\n previousActiveElement.current?.focus()\r\n previousActiveElement.current = null\r\n wasOpen.current = false\r\n }\r\n }, [isOpen])\r\n\r\n // Store onClose in a ref to avoid re-running effects when it changes\r\n const onCloseRef = useRef(onClose)\r\n useEffect(() => {\r\n onCloseRef.current = onClose\r\n }, [onClose])\r\n\r\n // Focus modal when it opens (only once)\r\n useEffect(() => {\r\n if (!isOpen) return\r\n\r\n const modal = modalRef.current\r\n if (modal) {\r\n modal.focus()\r\n }\r\n }, [isOpen])\r\n\r\n // Keyboard handling and body scroll lock\r\n useEffect(() => {\r\n if (!isOpen) return\r\n\r\n const modal = modalRef.current\r\n\r\n const handleKeyDown = (e: KeyboardEvent) => {\r\n if (e.key === 'Escape' && closeOnEscape) {\r\n onCloseRef.current()\r\n return\r\n }\r\n\r\n if (e.key === 'Tab' && modal) {\r\n const focusableElements = modal.querySelectorAll<HTMLElement>(\r\n 'button:not([disabled]), [href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [contenteditable=\"true\"], [tabindex]:not([tabindex=\"-1\"])'\r\n )\r\n const firstElement = focusableElements[0]\r\n const lastElement = focusableElements[focusableElements.length - 1]\r\n\r\n if (e.shiftKey && document.activeElement === firstElement) {\r\n e.preventDefault()\r\n lastElement?.focus()\r\n } else if (!e.shiftKey && document.activeElement === lastElement) {\r\n e.preventDefault()\r\n firstElement?.focus()\r\n }\r\n }\r\n }\r\n\r\n document.addEventListener('keydown', handleKeyDown)\r\n document.body.style.overflow = 'hidden'\r\n\r\n return () => {\r\n document.removeEventListener('keydown', handleKeyDown)\r\n document.body.style.overflow = ''\r\n }\r\n }, [isOpen, closeOnEscape])\r\n\r\n const handleOverlayClick = useCallback(\r\n (e: React.MouseEvent) => {\r\n if (e.target === e.currentTarget && closeOnOverlayClick) {\r\n onClose()\r\n }\r\n },\r\n [closeOnOverlayClick, onClose]\r\n )\r\n\r\n // Memoize styles to prevent object recreation on every render\r\n const overlayStyle = useMemo<CSSProperties>(() => ({\r\n position: 'fixed',\r\n inset: 0,\r\n zIndex: 'var(--brycks-z-modal)',\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n padding: spacing[6],\r\n backgroundColor: 'var(--brycks-background-overlay)',\r\n animation: 'brycks-fade-in var(--brycks-duration-normal) var(--brycks-ease-out)',\r\n }), [])\r\n\r\n const modalStyle = useMemo<CSSProperties>(() => ({\r\n position: 'relative',\r\n width: '100%',\r\n maxWidth: sizeWidths[size],\r\n maxHeight: size === 'full' ? 'calc(100vh - 48px)' : '85vh',\r\n backgroundColor: 'var(--brycks-background-elevated)',\r\n borderRadius: 'var(--brycks-radius-xl)',\r\n boxShadow: 'var(--brycks-shadow-2xl)',\r\n display: 'flex',\r\n flexDirection: 'column',\r\n overflow: 'hidden',\r\n animation: 'brycks-scale-in var(--brycks-duration-normal) var(--brycks-ease-out)',\r\n outline: 'none',\r\n ...style,\r\n }), [size, style])\r\n\r\n if (!isOpen) return null\r\n\r\n const headerStyle: CSSProperties = {\r\n display: 'flex',\r\n alignItems: 'flex-start',\r\n justifyContent: 'space-between',\r\n padding: `${spacing[5]}px ${spacing[6]}px`,\r\n borderBottom: '1px solid var(--brycks-border-muted)',\r\n }\r\n\r\n const titleContainerStyle: CSSProperties = {\r\n display: 'flex',\r\n flexDirection: 'column',\r\n gap: spacing[1],\r\n }\r\n\r\n const titleStyle: CSSProperties = {\r\n fontSize: fontSizes.lg,\r\n fontWeight: 600,\r\n color: 'var(--brycks-foreground-default)',\r\n margin: 0,\r\n lineHeight: 1.3,\r\n }\r\n\r\n const descriptionStyle: CSSProperties = {\r\n fontSize: fontSizes.base,\r\n color: 'var(--brycks-foreground-muted)',\r\n margin: 0,\r\n }\r\n\r\n const closeButtonStyle: CSSProperties = {\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n width: iconButtonSizes.sm,\r\n height: iconButtonSizes.sm,\r\n borderRadius: 'var(--brycks-radius-md)',\r\n color: 'var(--brycks-foreground-muted)',\r\n transition: 'all var(--brycks-duration-fast) var(--brycks-ease-out)',\r\n marginLeft: componentGap.xl,\r\n flexShrink: 0,\r\n }\r\n\r\n const contentStyle: CSSProperties = {\r\n flex: 1,\r\n overflow: 'auto',\r\n padding: spacing[6],\r\n }\r\n\r\n const footerStyle: CSSProperties = {\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'flex-end',\r\n gap: spacing[2],\r\n padding: `${spacing[4]}px ${spacing[6]}px`,\r\n borderTop: '1px solid var(--brycks-border-muted)',\r\n }\r\n\r\n const modalContent = (\r\n <div\r\n className=\"brycks-modal-overlay\"\r\n style={overlayStyle}\r\n onClick={handleOverlayClick}\r\n >\r\n <div\r\n ref={(node) => {\r\n (modalRef as React.MutableRefObject<HTMLDivElement | null>).current = node\r\n if (typeof ref === 'function') ref(node)\r\n else if (ref) (ref as React.MutableRefObject<HTMLDivElement | null>).current = node\r\n }}\r\n role=\"dialog\"\r\n aria-modal=\"true\"\r\n aria-labelledby={title ? titleId : undefined}\r\n aria-describedby={description ? descriptionId : undefined}\r\n className={cx('brycks-modal', `brycks-modal--${size}`, className)}\r\n style={modalStyle}\r\n tabIndex={-1}\r\n data-testid={testId}\r\n {...props}\r\n >\r\n {(title || showCloseButton) && (\r\n <div className=\"brycks-modal-header\" style={headerStyle}>\r\n <div style={titleContainerStyle}>\r\n {title && (\r\n <h2 id={titleId} style={titleStyle}>\r\n {title}\r\n </h2>\r\n )}\r\n {description && (\r\n <p id={descriptionId} style={descriptionStyle}>\r\n {description}\r\n </p>\r\n )}\r\n </div>\r\n {showCloseButton && (\r\n <button\r\n type=\"button\"\r\n className=\"brycks-modal-close\"\r\n style={closeButtonStyle}\r\n onClick={onClose}\r\n aria-label={closeLabel}\r\n onMouseEnter={(e) => {\r\n e.currentTarget.style.backgroundColor = 'var(--brycks-background-muted)'\r\n e.currentTarget.style.color = 'var(--brycks-foreground-default)'\r\n }}\r\n onMouseLeave={(e) => {\r\n e.currentTarget.style.backgroundColor = 'transparent'\r\n e.currentTarget.style.color = 'var(--brycks-foreground-muted)'\r\n }}\r\n >\r\n <CloseIcon />\r\n </button>\r\n )}\r\n </div>\r\n )}\r\n\r\n <div className=\"brycks-modal-content\" style={contentStyle}>\r\n {children}\r\n </div>\r\n\r\n {footer && (\r\n <div className=\"brycks-modal-footer\" style={footerStyle}>\r\n {footer}\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n )\r\n\r\n return createPortal(modalContent, document.body)\r\n})\r\n\r\nModal.displayName = 'Modal'\r\n"],"names":["sizeWidths","CloseIcon","memo","jsx","Modal","forwardRef","isOpen","onClose","size","title","description","closeOnOverlayClick","closeOnEscape","showCloseButton","closeLabel","footer","className","style","testId","children","props","ref","modalRef","useRef","titleId","useId","descriptionId","previousActiveElement","wasOpen","useEffect","onCloseRef","modal","handleKeyDown","e","focusableElements","firstElement","lastElement","handleOverlayClick","useCallback","overlayStyle","useMemo","spacing","modalStyle","headerStyle","titleContainerStyle","titleStyle","fontSizes","descriptionStyle","closeButtonStyle","iconButtonSizes","componentGap","contentStyle","footerStyle","modalContent","jsxs","node","cx","createPortal"],"mappings":"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"}
1
+ {"version":3,"file":"Modal.js","sources":["../../../../src/components/feedback/Modal/Modal.tsx"],"sourcesContent":["/**\r\n * Modal Component\r\n *\r\n * Accessible modal dialog with smooth Apple-inspired animations.\r\n * Supports focus trapping and keyboard navigation.\r\n */\r\n\r\nimport {\r\n forwardRef,\r\n useEffect,\r\n useRef,\r\n useCallback,\r\n memo,\r\n type ReactNode,\r\n type HTMLAttributes,\r\n} from 'react'\r\nimport { createPortal } from 'react-dom'\r\nimport { cx } from '../../../utils/styles'\r\nimport { useId } from '../../../hooks/useId'\r\n\r\nexport type ModalSize = 'sm' | 'md' | 'lg' | 'xl' | '2xl' | 'full'\r\n\r\nexport interface ModalProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title'> {\r\n /** Whether the modal is open */\r\n isOpen: boolean\r\n /** Callback when modal should close */\r\n onClose: () => void\r\n /** Modal size */\r\n size?: ModalSize\r\n /** Modal title */\r\n title?: ReactNode\r\n /** Modal description */\r\n description?: ReactNode\r\n /** Whether to close on overlay click */\r\n closeOnOverlayClick?: boolean\r\n /** Whether to close on escape key */\r\n closeOnEscape?: boolean\r\n /** Whether to show close button */\r\n showCloseButton?: boolean\r\n /** Accessible label of the close button */\r\n closeLabel?: string\r\n /** Footer content (e.g. action buttons), pinned below the scrollable body */\r\n footer?: ReactNode\r\n /** Custom class name */\r\n className?: string\r\n /** Test ID */\r\n testId?: string\r\n /** Modal content */\r\n children?: ReactNode\r\n}\r\n\r\n/** Close icon - memoized to prevent re-renders */\r\nconst CloseIcon = memo(function CloseIcon() {\r\n return (\r\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden=\"true\">\r\n <path\r\n d=\"M4 4L12 12M12 4L4 12\"\r\n stroke=\"currentColor\"\r\n strokeWidth=\"1.5\"\r\n strokeLinecap=\"round\"\r\n />\r\n </svg>\r\n )\r\n})\r\n\r\nexport const Modal = forwardRef<HTMLDivElement, ModalProps>(function Modal(\r\n {\r\n isOpen,\r\n onClose,\r\n size = 'md',\r\n title,\r\n description,\r\n closeOnOverlayClick = true,\r\n closeOnEscape = true,\r\n showCloseButton = true,\r\n closeLabel = 'Close modal',\r\n footer,\r\n className,\r\n style,\r\n testId,\r\n children,\r\n ...props\r\n },\r\n ref\r\n) {\r\n const modalRef = useRef<HTMLDivElement>(null)\r\n const titleId = useId('modal-title')\r\n const descriptionId = useId('modal-description')\r\n const previousActiveElement = useRef<HTMLElement | null>(null)\r\n const wasOpen = useRef(false)\r\n\r\n // Track previous open state to handle focus restoration before unmount\r\n useEffect(() => {\r\n // Modal just opened\r\n if (isOpen && !wasOpen.current) {\r\n previousActiveElement.current = document.activeElement as HTMLElement\r\n wasOpen.current = true\r\n }\r\n // Modal is about to close - restore focus BEFORE unmount\r\n else if (!isOpen && wasOpen.current) {\r\n // Blur any focused element inside modal to prevent aria-hidden warning\r\n if (document.activeElement instanceof HTMLElement) {\r\n document.activeElement.blur()\r\n }\r\n // Restore focus to previous element\r\n previousActiveElement.current?.focus()\r\n previousActiveElement.current = null\r\n wasOpen.current = false\r\n }\r\n }, [isOpen])\r\n\r\n // Store onClose in a ref to avoid re-running effects when it changes\r\n const onCloseRef = useRef(onClose)\r\n useEffect(() => {\r\n onCloseRef.current = onClose\r\n }, [onClose])\r\n\r\n // Focus modal when it opens (only once)\r\n useEffect(() => {\r\n if (!isOpen) return\r\n\r\n const modal = modalRef.current\r\n if (modal) {\r\n modal.focus()\r\n }\r\n }, [isOpen])\r\n\r\n // Keyboard handling and body scroll lock\r\n useEffect(() => {\r\n if (!isOpen) return\r\n\r\n const modal = modalRef.current\r\n\r\n const handleKeyDown = (e: KeyboardEvent) => {\r\n if (e.key === 'Escape' && closeOnEscape) {\r\n onCloseRef.current()\r\n return\r\n }\r\n\r\n if (e.key === 'Tab' && modal) {\r\n const focusableElements = modal.querySelectorAll<HTMLElement>(\r\n 'button:not([disabled]), [href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [contenteditable=\"true\"], [tabindex]:not([tabindex=\"-1\"])'\r\n )\r\n const firstElement = focusableElements[0]\r\n const lastElement = focusableElements[focusableElements.length - 1]\r\n\r\n if (e.shiftKey && document.activeElement === firstElement) {\r\n e.preventDefault()\r\n lastElement?.focus()\r\n } else if (!e.shiftKey && document.activeElement === lastElement) {\r\n e.preventDefault()\r\n firstElement?.focus()\r\n }\r\n }\r\n }\r\n\r\n document.addEventListener('keydown', handleKeyDown)\r\n document.body.style.overflow = 'hidden'\r\n\r\n return () => {\r\n document.removeEventListener('keydown', handleKeyDown)\r\n document.body.style.overflow = ''\r\n }\r\n }, [isOpen, closeOnEscape])\r\n\r\n const handleOverlayClick = useCallback(\r\n (e: React.MouseEvent) => {\r\n if (e.target === e.currentTarget && closeOnOverlayClick) {\r\n onClose()\r\n }\r\n },\r\n [closeOnOverlayClick, onClose]\r\n )\r\n\r\n if (!isOpen) return null\r\n\r\n const modalContent = (\r\n <div\r\n className=\"brycks-modal-overlay\"\r\n onClick={handleOverlayClick}\r\n >\r\n <div\r\n ref={(node) => {\r\n (modalRef as React.MutableRefObject<HTMLDivElement | null>).current = node\r\n if (typeof ref === 'function') ref(node)\r\n else if (ref) (ref as React.MutableRefObject<HTMLDivElement | null>).current = node\r\n }}\r\n role=\"dialog\"\r\n aria-modal=\"true\"\r\n aria-labelledby={title ? titleId : undefined}\r\n aria-describedby={description ? descriptionId : undefined}\r\n className={cx('brycks-modal', `brycks-modal--${size}`, className)}\r\n style={style}\r\n tabIndex={-1}\r\n data-testid={testId}\r\n {...props}\r\n >\r\n {(title || showCloseButton) && (\r\n <div className=\"brycks-modal-header\">\r\n <div className=\"brycks-modal-title-container\">\r\n {title && (\r\n <h2 id={titleId} className=\"brycks-modal-title\">\r\n {title}\r\n </h2>\r\n )}\r\n {description && (\r\n <p id={descriptionId} className=\"brycks-modal-description\">\r\n {description}\r\n </p>\r\n )}\r\n </div>\r\n {showCloseButton && (\r\n <button\r\n type=\"button\"\r\n className=\"brycks-modal-close\"\r\n onClick={onClose}\r\n aria-label={closeLabel}\r\n >\r\n <CloseIcon />\r\n </button>\r\n )}\r\n </div>\r\n )}\r\n\r\n <div className=\"brycks-modal-content\">\r\n {children}\r\n </div>\r\n\r\n {footer && (\r\n <div className=\"brycks-modal-footer\">\r\n {footer}\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n )\r\n\r\n return createPortal(modalContent, document.body)\r\n})\r\n\r\nModal.displayName = 'Modal'\r\n"],"names":["CloseIcon","memo","jsx","Modal","forwardRef","isOpen","onClose","size","title","description","closeOnOverlayClick","closeOnEscape","showCloseButton","closeLabel","footer","className","style","testId","children","props","ref","modalRef","useRef","titleId","useId","descriptionId","previousActiveElement","wasOpen","useEffect","onCloseRef","modal","handleKeyDown","e","focusableElements","firstElement","lastElement","handleOverlayClick","useCallback","modalContent","jsxs","node","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"),W=require("react-dom"),Y=require("../../../utils/styles.cjs"),B=require("./ToastContext.cjs"),D={info:{bg:"var(--brycks-info-muted)",border:"var(--brycks-info-soft-hover)",icon:"var(--brycks-info-default)"},success:{bg:"var(--brycks-success-muted)",border:"var(--brycks-success-soft-hover)",icon:"var(--brycks-success-default)"},warning:{bg:"var(--brycks-warning-muted)",border:"var(--brycks-warning-soft-hover)",icon:"var(--brycks-warning-default)"},error:{bg:"var(--brycks-error-muted)",border:"var(--brycks-error-soft-hover)",icon:"var(--brycks-error-default)"}};function N({intent:y}){const r={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:r[y]})})}function $(){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 x=e.forwardRef(function({intent:r="info",title:c,description:i,isOpen:o=!0,duration:l=5e3,onClose:u,showCloseButton:g=!0,closeLabel:b="Close toast",action:m,icon:h,className:v,style:n,testId:a,onMouseEnter:d,onMouseLeave:f,...w},C){const[M,p]=e.useState(o),[E,j]=e.useState(!1),[S,T]=e.useState(!1);if(e.useEffect(()=>{if(o)p(!0),j(!1);else{j(!0);const s=setTimeout(()=>p(!1),200);return()=>clearTimeout(s)}},[o]),e.useEffect(()=>{if(!o||l===0||S)return;const s=setTimeout(()=>{u?.()},l);return()=>clearTimeout(s)},[o,l,u,S]),!M)return null;const k=D[r],z={display:"flex",alignItems:"flex-start",gap:12,padding:"12px 16px",backgroundColor:k.bg,border:`1px solid ${k.border}`,borderRadius:"var(--brycks-radius-lg)",boxShadow:"var(--brycks-shadow-lg)",maxWidth:400,animation:E?"brycks-toast-out 200ms ease-in forwards":"brycks-toast-in 200ms ease-out",...n},I={color:k.icon,flexShrink:0,marginTop:2},L={flex:1,display:"flex",flexDirection:"column",gap:4},P={fontSize:14,fontWeight:600,color:"var(--brycks-foreground-default)",lineHeight:1.4},q={fontSize:13,color:"var(--brycks-foreground-muted)",lineHeight:1.4},R={display:"flex",alignItems:"center",justifyContent:"center",width:24,height:24,borderRadius:"var(--brycks-radius-sm)",color:"var(--brycks-foreground-muted)",transition:"all 150ms ease-out",flexShrink:0,marginLeft:"auto"};return t.jsxs(t.Fragment,{children:[t.jsx("style",{children:`
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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"}