asterui 0.12.60 → 0.12.62

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 (89) hide show
  1. package/dist/components/Affix.d.ts +2 -0
  2. package/dist/components/Affix.js.map +1 -1
  3. package/dist/components/Alert.d.ts +2 -0
  4. package/dist/components/Alert.js.map +1 -1
  5. package/dist/components/Avatar.d.ts +4 -0
  6. package/dist/components/Avatar.js.map +1 -1
  7. package/dist/components/Breadcrumb.js +22 -22
  8. package/dist/components/Breadcrumb.js.map +1 -1
  9. package/dist/components/Browser.d.ts +2 -0
  10. package/dist/components/Browser.js.map +1 -1
  11. package/dist/components/Chat.js +35 -26
  12. package/dist/components/Chat.js.map +1 -1
  13. package/dist/components/Code.d.ts +2 -0
  14. package/dist/components/Code.js.map +1 -1
  15. package/dist/components/Container.d.ts +2 -0
  16. package/dist/components/Container.js.map +1 -1
  17. package/dist/components/ContextMenu.js +100 -84
  18. package/dist/components/ContextMenu.js.map +1 -1
  19. package/dist/components/CopyButton.d.ts +2 -0
  20. package/dist/components/CopyButton.js +9 -8
  21. package/dist/components/CopyButton.js.map +1 -1
  22. package/dist/components/Countdown.d.ts +3 -3
  23. package/dist/components/Countdown.js +49 -47
  24. package/dist/components/Countdown.js.map +1 -1
  25. package/dist/components/Diff.d.ts +3 -3
  26. package/dist/components/Diff.js +14 -10
  27. package/dist/components/Diff.js.map +1 -1
  28. package/dist/components/Divider.d.ts +2 -0
  29. package/dist/components/Divider.js.map +1 -1
  30. package/dist/components/Dock.d.ts +4 -0
  31. package/dist/components/Dock.js +38 -25
  32. package/dist/components/Dock.js.map +1 -1
  33. package/dist/components/Dropdown.js +110 -110
  34. package/dist/components/Dropdown.js.map +1 -1
  35. package/dist/components/Fieldset.d.ts +2 -0
  36. package/dist/components/Fieldset.js.map +1 -1
  37. package/dist/components/FloatButton.d.ts +6 -0
  38. package/dist/components/FloatButton.js +122 -98
  39. package/dist/components/FloatButton.js.map +1 -1
  40. package/dist/components/Footer.d.ts +2 -0
  41. package/dist/components/Footer.js.map +1 -1
  42. package/dist/components/Grid.d.ts +4 -0
  43. package/dist/components/Grid.js.map +1 -1
  44. package/dist/components/Hero.d.ts +2 -0
  45. package/dist/components/Hero.js.map +1 -1
  46. package/dist/components/HoverGallery.d.ts +3 -3
  47. package/dist/components/HoverGallery.js +12 -10
  48. package/dist/components/HoverGallery.js.map +1 -1
  49. package/dist/components/Join.d.ts +2 -0
  50. package/dist/components/Join.js.map +1 -1
  51. package/dist/components/Kbd.d.ts +2 -0
  52. package/dist/components/Kbd.js.map +1 -1
  53. package/dist/components/Loading.d.ts +2 -0
  54. package/dist/components/Loading.js +51 -31
  55. package/dist/components/Loading.js.map +1 -1
  56. package/dist/components/Mask.d.ts +2 -2
  57. package/dist/components/Mask.js.map +1 -1
  58. package/dist/components/Navbar.d.ts +2 -0
  59. package/dist/components/Navbar.js.map +1 -1
  60. package/dist/components/Notification.js +32 -18
  61. package/dist/components/Notification.js.map +1 -1
  62. package/dist/components/Phone.d.ts +3 -2
  63. package/dist/components/Phone.js +10 -8
  64. package/dist/components/Phone.js.map +1 -1
  65. package/dist/components/Popconfirm.js +110 -92
  66. package/dist/components/Popconfirm.js.map +1 -1
  67. package/dist/components/Popover.d.ts +2 -0
  68. package/dist/components/Popover.js.map +1 -1
  69. package/dist/components/Progress.d.ts +2 -0
  70. package/dist/components/Progress.js.map +1 -1
  71. package/dist/components/Radio.d.ts +6 -3
  72. package/dist/components/Radio.js +9 -9
  73. package/dist/components/Radio.js.map +1 -1
  74. package/dist/components/Skeleton.d.ts +2 -0
  75. package/dist/components/Skeleton.js.map +1 -1
  76. package/dist/components/Space.d.ts +2 -0
  77. package/dist/components/Space.js.map +1 -1
  78. package/dist/components/Status.d.ts +3 -3
  79. package/dist/components/Status.js +27 -25
  80. package/dist/components/Status.js.map +1 -1
  81. package/dist/components/Toggle.d.ts +2 -0
  82. package/dist/components/Toggle.js.map +1 -1
  83. package/dist/components/Tooltip.d.ts +2 -0
  84. package/dist/components/Tooltip.js +38 -32
  85. package/dist/components/Tooltip.js.map +1 -1
  86. package/dist/components/Window.d.ts +3 -2
  87. package/dist/components/Window.js +9 -7
  88. package/dist/components/Window.js.map +1 -1
  89. package/package.json +5 -3
@@ -1,5 +1,5 @@
1
1
  import { jsxs as b, Fragment as V, jsx as n } from "react/jsx-runtime";
2
- import C, { useState as g, useRef as y, useCallback as M, useEffect as L, createContext as A, useContext as H } from "react";
2
+ import w, { useState as g, useRef as y, useCallback as M, useEffect as L, createContext as A, useContext as H } from "react";
3
3
  import { createPortal as O } from "react-dom";
4
4
  import { useConfig as _ } from "../providers/ConfigProvider.js";
5
5
  const k = "menu", S = "divider", $ = A(null), F = () => {
@@ -9,63 +9,70 @@ const k = "menu", S = "divider", $ = A(null), F = () => {
9
9
  return e;
10
10
  }, R = ({
11
11
  children: e,
12
- icon: l,
13
- disabled: s = !1,
14
- danger: h = !1,
12
+ icon: a,
13
+ disabled: o = !1,
14
+ danger: d = !1,
15
15
  className: m = "",
16
- _key: i
16
+ _key: c
17
17
  }) => {
18
- const { onSelect: u, onClose: c } = F();
19
- return /* @__PURE__ */ n("li", { className: m, children: /* @__PURE__ */ b(
18
+ const { onSelect: u, onClose: s } = F();
19
+ return /* @__PURE__ */ n("li", { className: m, role: "none", children: /* @__PURE__ */ b(
20
20
  "button",
21
21
  {
22
22
  onClick: () => {
23
- s || !i || (u(i), c());
23
+ o || !c || (u(c), s());
24
24
  },
25
- disabled: s,
25
+ disabled: o,
26
+ role: "menuitem",
27
+ "aria-disabled": o,
26
28
  className: `
27
29
  flex items-center gap-2 w-full px-4 py-2 text-left text-sm
28
- ${s ? "opacity-50 cursor-not-allowed" : "hover:bg-base-200"}
29
- ${h ? "text-error hover:bg-error/10" : ""}
30
+ ${o ? "opacity-50 cursor-not-allowed" : "hover:bg-base-200"}
31
+ ${d ? "text-error hover:bg-error/10" : ""}
30
32
  `,
31
33
  children: [
32
- l && /* @__PURE__ */ n("span", { className: "w-4 h-4", children: l }),
34
+ a && /* @__PURE__ */ n("span", { className: "w-4 h-4", "aria-hidden": "true", children: a }),
33
35
  /* @__PURE__ */ n("span", { className: "flex-1", children: e })
34
36
  ]
35
37
  }
36
38
  ) });
37
- }, X = ({ className: e = "" }) => /* @__PURE__ */ n("li", { className: `${S} my-1 ${e}` }), D = ({
39
+ }, X = ({ className: e = "" }) => /* @__PURE__ */ n("li", { className: `${S} my-1 ${e}`, role: "separator" }), D = ({
38
40
  label: e,
39
- icon: l,
40
- disabled: s = !1,
41
- children: h,
41
+ icon: a,
42
+ disabled: o = !1,
43
+ children: d,
42
44
  className: m = "",
43
- _key: i
45
+ _key: c
44
46
  }) => {
45
- const [u, c] = g(!1), r = y(null), f = () => {
46
- s || (r.current && clearTimeout(r.current), c(!0));
47
- }, a = () => {
48
- r.current = setTimeout(() => c(!1), 100);
47
+ const [u, s] = g(!1), l = y(null), p = () => {
48
+ o || (l.current && clearTimeout(l.current), s(!0));
49
+ }, i = () => {
50
+ l.current = setTimeout(() => s(!1), 100);
49
51
  };
50
52
  return /* @__PURE__ */ b(
51
53
  "li",
52
54
  {
53
- onMouseEnter: f,
54
- onMouseLeave: a,
55
+ onMouseEnter: p,
56
+ onMouseLeave: i,
55
57
  className: `relative ${m}`,
58
+ role: "none",
56
59
  children: [
57
60
  /* @__PURE__ */ b(
58
61
  "button",
59
62
  {
60
- disabled: s,
63
+ disabled: o,
64
+ role: "menuitem",
65
+ "aria-haspopup": "menu",
66
+ "aria-expanded": u,
67
+ "aria-disabled": o,
61
68
  className: `
62
69
  flex items-center gap-2 w-full px-4 py-2 text-left text-sm
63
- ${s ? "opacity-50 cursor-not-allowed" : "hover:bg-base-200"}
70
+ ${o ? "opacity-50 cursor-not-allowed" : "hover:bg-base-200"}
64
71
  `,
65
72
  children: [
66
- l && /* @__PURE__ */ n("span", { className: "w-4 h-4", children: l }),
73
+ a && /* @__PURE__ */ n("span", { className: "w-4 h-4", "aria-hidden": "true", children: a }),
67
74
  /* @__PURE__ */ n("span", { className: "flex-1", children: e }),
68
- /* @__PURE__ */ n("svg", { className: "w-4 h-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ n("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M9 5l7 7-7 7" }) })
75
+ /* @__PURE__ */ n("svg", { className: "w-4 h-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", "aria-hidden": "true", children: /* @__PURE__ */ n("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M9 5l7 7-7 7" }) })
69
76
  ]
70
77
  }
71
78
  ),
@@ -73,56 +80,63 @@ const k = "menu", S = "divider", $ = A(null), F = () => {
73
80
  "ul",
74
81
  {
75
82
  className: `${k} bg-base-100 rounded-box shadow-lg border border-base-300 absolute left-full top-0 min-w-[160px] z-50 p-1`,
76
- onMouseEnter: f,
77
- onMouseLeave: a,
78
- children: h
83
+ onMouseEnter: p,
84
+ onMouseLeave: i,
85
+ role: "menu",
86
+ children: d
79
87
  }
80
88
  )
81
89
  ]
82
90
  }
83
91
  );
84
- }, j = ({ item: e, onSelect: l, onClose: s }) => {
85
- const [h, m] = g(!1), i = y(null);
92
+ }, j = ({ item: e, onSelect: a, onClose: o }) => {
93
+ const [d, m] = g(!1), c = y(null);
86
94
  if (e.divider)
87
- return /* @__PURE__ */ n("li", { className: `${S} my-1` });
95
+ return /* @__PURE__ */ n("li", { className: `${S} my-1`, role: "separator" });
88
96
  const u = () => {
89
- e.disabled || e.children && e.children.length > 0 || (l(e.key), s());
90
- }, c = e.children && e.children.length > 0, r = () => {
91
- c && (i.current && clearTimeout(i.current), m(!0));
92
- }, f = () => {
93
- c && (i.current = setTimeout(() => m(!1), 100));
97
+ e.disabled || e.children && e.children.length > 0 || (a(e.key), o());
98
+ }, s = e.children && e.children.length > 0, l = () => {
99
+ s && (c.current && clearTimeout(c.current), m(!0));
100
+ }, p = () => {
101
+ s && (c.current = setTimeout(() => m(!1), 100));
94
102
  };
95
103
  return /* @__PURE__ */ b(
96
104
  "li",
97
105
  {
98
- onMouseEnter: r,
99
- onMouseLeave: f,
106
+ onMouseEnter: l,
107
+ onMouseLeave: p,
100
108
  className: "relative",
109
+ role: "none",
101
110
  children: [
102
111
  /* @__PURE__ */ b(
103
112
  "button",
104
113
  {
105
114
  onClick: u,
106
115
  disabled: e.disabled,
116
+ role: "menuitem",
117
+ "aria-haspopup": s ? "menu" : void 0,
118
+ "aria-expanded": s ? d : void 0,
119
+ "aria-disabled": e.disabled,
107
120
  className: `
108
121
  flex items-center gap-2 w-full px-4 py-2 text-left text-sm
109
122
  ${e.disabled ? "opacity-50 cursor-not-allowed" : "hover:bg-base-200"}
110
123
  ${e.danger ? "text-error hover:bg-error/10" : ""}
111
124
  `,
112
125
  children: [
113
- e.icon && /* @__PURE__ */ n("span", { className: "w-4 h-4", children: e.icon }),
126
+ e.icon && /* @__PURE__ */ n("span", { className: "w-4 h-4", "aria-hidden": "true", children: e.icon }),
114
127
  /* @__PURE__ */ n("span", { className: "flex-1", children: e.label }),
115
- c && /* @__PURE__ */ n("svg", { className: "w-4 h-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ n("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M9 5l7 7-7 7" }) })
128
+ s && /* @__PURE__ */ n("svg", { className: "w-4 h-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", "aria-hidden": "true", children: /* @__PURE__ */ n("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M9 5l7 7-7 7" }) })
116
129
  ]
117
130
  }
118
131
  ),
119
- c && h && /* @__PURE__ */ n(
132
+ s && d && /* @__PURE__ */ n(
120
133
  "ul",
121
134
  {
122
135
  className: `${k} bg-base-100 rounded-box shadow-lg border border-base-300 absolute left-full top-0 min-w-[160px] z-50 p-1`,
123
- onMouseEnter: r,
124
- onMouseLeave: f,
125
- children: e.children.map((a) => /* @__PURE__ */ n(j, { item: a, onSelect: l, onClose: s }, a.key))
136
+ onMouseEnter: l,
137
+ onMouseLeave: p,
138
+ role: "menu",
139
+ children: e.children.map((i) => /* @__PURE__ */ n(j, { item: i, onSelect: a, onClose: o }, i.key))
126
140
  }
127
141
  )
128
142
  ]
@@ -130,56 +144,56 @@ const k = "menu", S = "divider", $ = A(null), F = () => {
130
144
  );
131
145
  }, Y = ({
132
146
  children: e,
133
- items: l,
134
- onSelect: s,
135
- disabled: h = !1,
147
+ items: a,
148
+ onSelect: o,
149
+ disabled: d = !1,
136
150
  className: m = ""
137
151
  }) => {
138
- const { getPopupContainer: i } = _(), [u, c] = g(!1), [r, f] = g({ x: 0, y: 0 }), a = y(null), P = y(null), W = M(
139
- (o) => {
140
- if (h) return;
141
- o.preventDefault(), o.stopPropagation();
142
- let t = o.clientX, d = o.clientY;
143
- f({ x: t, y: d }), c(!0);
152
+ const { getPopupContainer: c } = _(), [u, s] = g(!1), [l, p] = g({ x: 0, y: 0 }), i = y(null), P = y(null), W = M(
153
+ (r) => {
154
+ if (d) return;
155
+ r.preventDefault(), r.stopPropagation();
156
+ let t = r.clientX, h = r.clientY;
157
+ p({ x: t, y: h }), s(!0);
144
158
  },
145
- [h]
146
- ), p = M(() => {
147
- c(!1);
159
+ [d]
160
+ ), f = M(() => {
161
+ s(!1);
148
162
  }, []), N = M(
149
- (o) => {
150
- s?.(o);
163
+ (r) => {
164
+ o?.(r);
151
165
  },
152
- [s]
166
+ [o]
153
167
  );
154
168
  L(() => {
155
- if (u && a.current) {
156
- const t = a.current.getBoundingClientRect(), d = window.innerWidth, x = window.innerHeight;
157
- let { x: v, y: w } = r;
158
- v + t.width > d && (v = d - t.width - 8), w + t.height > x && (w = x - t.height - 8), (v !== r.x || w !== r.y) && f({ x: v, y: w });
169
+ if (u && i.current) {
170
+ const t = i.current.getBoundingClientRect(), h = window.innerWidth, x = window.innerHeight;
171
+ let { x: v, y: C } = l;
172
+ v + t.width > h && (v = h - t.width - 8), C + t.height > x && (C = x - t.height - 8), (v !== l.x || C !== l.y) && p({ x: v, y: C });
159
173
  }
160
- }, [u, r]), L(() => {
174
+ }, [u, l]), L(() => {
161
175
  if (!u) return;
162
- const o = (x) => {
163
- a.current && !a.current.contains(x.target) && p();
176
+ const r = (x) => {
177
+ i.current && !i.current.contains(x.target) && f();
164
178
  }, t = (x) => {
165
- x.key === "Escape" && p();
166
- }, d = () => {
167
- p();
179
+ x.key === "Escape" && f();
180
+ }, h = () => {
181
+ f();
168
182
  };
169
- return document.addEventListener("mousedown", o), document.addEventListener("keydown", t), document.addEventListener("scroll", d, !0), () => {
170
- document.removeEventListener("mousedown", o), document.removeEventListener("keydown", t), document.removeEventListener("scroll", d, !0);
183
+ return document.addEventListener("mousedown", r), document.addEventListener("keydown", t), document.addEventListener("scroll", h, !0), () => {
184
+ document.removeEventListener("mousedown", r), document.removeEventListener("keydown", t), document.removeEventListener("scroll", h, !0);
171
185
  };
172
- }, [u, p]);
173
- const T = (o) => C.Children.map(o, (t) => {
174
- if (C.isValidElement(t)) {
175
- const d = t.key != null ? String(t.key) : void 0;
186
+ }, [u, f]);
187
+ const T = (r) => w.Children.map(r, (t) => {
188
+ if (w.isValidElement(t)) {
189
+ const h = t.key != null ? String(t.key) : void 0;
176
190
  if (t.type === R || t.type === D)
177
- return C.cloneElement(t, { _key: d });
191
+ return w.cloneElement(t, { _key: h });
178
192
  }
179
193
  return t;
180
- }), E = C.Children.toArray(e), z = E[0], B = T(E.slice(1)), I = l && l.length > 0, K = {
194
+ }), E = w.Children.toArray(e), z = E[0], B = T(E.slice(1)), I = a && a.length > 0, K = {
181
195
  onSelect: N,
182
- onClose: p
196
+ onClose: f
183
197
  };
184
198
  return /* @__PURE__ */ b(V, { children: [
185
199
  /* @__PURE__ */ n("div", { ref: P, onContextMenu: W, className: "inline-block", children: z }),
@@ -187,13 +201,15 @@ const k = "menu", S = "divider", $ = A(null), F = () => {
187
201
  /* @__PURE__ */ n($.Provider, { value: K, children: /* @__PURE__ */ n(
188
202
  "ul",
189
203
  {
190
- ref: a,
204
+ ref: i,
191
205
  className: `${k} bg-base-100 rounded-box shadow-lg border border-base-300 min-w-[160px] p-1 fixed z-[9999] ${m}`,
192
- style: { left: r.x, top: r.y },
193
- children: I ? l.map((o) => /* @__PURE__ */ n(j, { item: o, onSelect: N, onClose: p }, o.key)) : B
206
+ style: { left: l.x, top: l.y },
207
+ role: "menu",
208
+ "aria-label": "Context menu",
209
+ children: I ? a.map((r) => /* @__PURE__ */ n(j, { item: r, onSelect: N, onClose: f }, r.key)) : B
194
210
  }
195
211
  ) }),
196
- i ? i(document.body) : document.body
212
+ c ? c(document.body) : document.body
197
213
  )
198
214
  ] });
199
215
  }, U = Object.assign(Y, {
@@ -1 +1 @@
1
- {"version":3,"file":"ContextMenu.js","sources":["../../src/components/ContextMenu.tsx"],"sourcesContent":["import React, { useState, useRef, useEffect, useCallback, createContext, useContext } from 'react'\nimport { createPortal } from 'react-dom'\nimport { useConfig } from '../providers/ConfigProvider'\n\n// DaisyUI classes\nconst dMenu = 'menu'\nconst dDivider = 'divider'\n\nexport interface ContextMenuItem {\n key: string\n label: React.ReactNode\n icon?: React.ReactNode\n disabled?: boolean\n danger?: boolean\n divider?: boolean\n children?: ContextMenuItem[]\n}\n\nexport interface ContextMenuProps {\n /** Element that triggers the context menu on right-click */\n children: React.ReactNode\n /** Menu items (data-driven pattern) */\n items?: ContextMenuItem[]\n /** Callback when an item is selected */\n onSelect?: (key: string) => void\n /** Whether the context menu is disabled */\n disabled?: boolean\n /** Additional CSS classes for the menu */\n className?: string\n}\n\nexport interface ContextMenuItemProps {\n /** Item content */\n children: React.ReactNode\n /** Icon to display before label */\n icon?: React.ReactNode\n /** Whether the item is disabled */\n disabled?: boolean\n /** Show as danger/destructive action */\n danger?: boolean\n /** Additional CSS classes */\n className?: string\n /** @internal */\n _key?: string\n}\n\nexport interface ContextMenuDividerProps {\n /** Additional CSS classes */\n className?: string\n}\n\nexport interface ContextMenuSubMenuProps {\n /** Submenu label */\n label: React.ReactNode\n /** Icon to display before label */\n icon?: React.ReactNode\n /** Whether the submenu is disabled */\n disabled?: boolean\n /** Submenu items */\n children: React.ReactNode\n /** Additional CSS classes */\n className?: string\n /** @internal */\n _key?: string\n}\n\ninterface ContextMenuContextValue {\n onSelect: (key: string) => void\n onClose: () => void\n}\n\ninterface MenuPosition {\n x: number\n y: number\n}\n\nconst ContextMenuContext = createContext<ContextMenuContextValue | null>(null)\n\nconst useContextMenuContext = () => {\n const context = useContext(ContextMenuContext)\n if (!context) {\n throw new Error('ContextMenu compound components must be used within a ContextMenu')\n }\n return context\n}\n\n// Compound pattern components\nconst ContextMenuItemComponent: React.FC<ContextMenuItemProps> = ({\n children,\n icon,\n disabled = false,\n danger = false,\n className = '',\n _key,\n}) => {\n const { onSelect, onClose } = useContextMenuContext()\n\n const handleClick = () => {\n if (disabled || !_key) return\n onSelect(_key)\n onClose()\n }\n\n return (\n <li className={className}>\n <button\n onClick={handleClick}\n disabled={disabled}\n className={`\n flex items-center gap-2 w-full px-4 py-2 text-left text-sm\n ${disabled ? 'opacity-50 cursor-not-allowed' : 'hover:bg-base-200'}\n ${danger ? 'text-error hover:bg-error/10' : ''}\n `}\n >\n {icon && <span className=\"w-4 h-4\">{icon}</span>}\n <span className=\"flex-1\">{children}</span>\n </button>\n </li>\n )\n}\n\nconst ContextMenuDividerComponent: React.FC<ContextMenuDividerProps> = ({ className = '' }) => {\n return <li className={`${dDivider} my-1 ${className}`}></li>\n}\n\nconst ContextMenuSubMenuComponent: React.FC<ContextMenuSubMenuProps> = ({\n label,\n icon,\n disabled = false,\n children,\n className = '',\n _key: _unusedKey,\n}) => {\n const [showSubmenu, setShowSubmenu] = useState(false)\n const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null)\n\n const handleMouseEnter = () => {\n if (disabled) return\n if (timeoutRef.current) clearTimeout(timeoutRef.current)\n setShowSubmenu(true)\n }\n\n const handleMouseLeave = () => {\n timeoutRef.current = setTimeout(() => setShowSubmenu(false), 100)\n }\n\n return (\n <li\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n className={`relative ${className}`}\n >\n <button\n disabled={disabled}\n className={`\n flex items-center gap-2 w-full px-4 py-2 text-left text-sm\n ${disabled ? 'opacity-50 cursor-not-allowed' : 'hover:bg-base-200'}\n `}\n >\n {icon && <span className=\"w-4 h-4\">{icon}</span>}\n <span className=\"flex-1\">{label}</span>\n <svg className=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M9 5l7 7-7 7\" />\n </svg>\n </button>\n {showSubmenu && (\n <ul\n className={`${dMenu} bg-base-100 rounded-box shadow-lg border border-base-300 absolute left-full top-0 min-w-[160px] z-50 p-1`}\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n >\n {children}\n </ul>\n )}\n </li>\n )\n}\n\n// Data-driven pattern internal component\nconst MenuItem: React.FC<{\n item: ContextMenuItem\n onSelect: (key: string) => void\n onClose: () => void\n}> = ({ item, onSelect, onClose }) => {\n const [showSubmenu, setShowSubmenu] = useState(false)\n const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null)\n\n if (item.divider) {\n return <li className={`${dDivider} my-1`}></li>\n }\n\n const handleClick = () => {\n if (item.disabled) return\n if (item.children && item.children.length > 0) return\n onSelect(item.key)\n onClose()\n }\n\n const hasSubmenu = item.children && item.children.length > 0\n\n const handleMouseEnter = () => {\n if (!hasSubmenu) return\n if (timeoutRef.current) clearTimeout(timeoutRef.current)\n setShowSubmenu(true)\n }\n\n const handleMouseLeave = () => {\n if (!hasSubmenu) return\n timeoutRef.current = setTimeout(() => setShowSubmenu(false), 100)\n }\n\n return (\n <li\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n className=\"relative\"\n >\n <button\n onClick={handleClick}\n disabled={item.disabled}\n className={`\n flex items-center gap-2 w-full px-4 py-2 text-left text-sm\n ${item.disabled ? 'opacity-50 cursor-not-allowed' : 'hover:bg-base-200'}\n ${item.danger ? 'text-error hover:bg-error/10' : ''}\n `}\n >\n {item.icon && <span className=\"w-4 h-4\">{item.icon}</span>}\n <span className=\"flex-1\">{item.label}</span>\n {hasSubmenu && (\n <svg className=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M9 5l7 7-7 7\" />\n </svg>\n )}\n </button>\n {hasSubmenu && showSubmenu && (\n <ul\n className={`${dMenu} bg-base-100 rounded-box shadow-lg border border-base-300 absolute left-full top-0 min-w-[160px] z-50 p-1`}\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n >\n {item.children!.map((child) => (\n <MenuItem key={child.key} item={child} onSelect={onSelect} onClose={onClose} />\n ))}\n </ul>\n )}\n </li>\n )\n}\n\nconst ContextMenuRoot: React.FC<ContextMenuProps> = ({\n children,\n items,\n onSelect,\n disabled = false,\n className = '',\n}) => {\n const { getPopupContainer } = useConfig()\n const [visible, setVisible] = useState(false)\n const [position, setPosition] = useState<MenuPosition>({ x: 0, y: 0 })\n const menuRef = useRef<HTMLUListElement>(null)\n const triggerRef = useRef<HTMLDivElement>(null)\n\n const handleContextMenu = useCallback(\n (e: React.MouseEvent) => {\n if (disabled) return\n e.preventDefault()\n e.stopPropagation()\n\n // Calculate position, ensuring menu stays within viewport\n let x = e.clientX\n let y = e.clientY\n\n // We'll adjust after render when we know menu dimensions\n setPosition({ x, y })\n setVisible(true)\n },\n [disabled]\n )\n\n const handleClose = useCallback(() => {\n setVisible(false)\n }, [])\n\n const handleSelect = useCallback(\n (key: string) => {\n onSelect?.(key)\n },\n [onSelect]\n )\n\n // Adjust position after menu renders to keep it in viewport\n useEffect(() => {\n if (visible && menuRef.current) {\n const menu = menuRef.current\n const rect = menu.getBoundingClientRect()\n const viewportWidth = window.innerWidth\n const viewportHeight = window.innerHeight\n\n let { x, y } = position\n\n if (x + rect.width > viewportWidth) {\n x = viewportWidth - rect.width - 8\n }\n if (y + rect.height > viewportHeight) {\n y = viewportHeight - rect.height - 8\n }\n\n if (x !== position.x || y !== position.y) {\n setPosition({ x, y })\n }\n }\n }, [visible, position])\n\n // Close on click outside or escape\n useEffect(() => {\n if (!visible) return\n\n const handleClickOutside = (e: MouseEvent) => {\n if (menuRef.current && !menuRef.current.contains(e.target as Node)) {\n handleClose()\n }\n }\n\n const handleEscape = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n handleClose()\n }\n }\n\n const handleScroll = () => {\n handleClose()\n }\n\n document.addEventListener('mousedown', handleClickOutside)\n document.addEventListener('keydown', handleEscape)\n document.addEventListener('scroll', handleScroll, true)\n\n return () => {\n document.removeEventListener('mousedown', handleClickOutside)\n document.removeEventListener('keydown', handleEscape)\n document.removeEventListener('scroll', handleScroll, true)\n }\n }, [visible, handleClose])\n\n // Clone children to extract keys\n const cloneChildrenWithKeys = (children: React.ReactNode): React.ReactNode => {\n return React.Children.map(children, (child) => {\n if (React.isValidElement(child)) {\n const childKey = child.key != null ? String(child.key) : undefined\n if (child.type === ContextMenuItemComponent || child.type === ContextMenuSubMenuComponent) {\n return React.cloneElement(child as React.ReactElement<any>, { _key: childKey })\n }\n }\n return child\n })\n }\n\n // Determine if using data-driven or compound pattern\n // Find menu content children (not the trigger element)\n const childArray = React.Children.toArray(children)\n const triggerChild = childArray[0]\n const menuChildren = cloneChildrenWithKeys(childArray.slice(1))\n const useDataDriven = items && items.length > 0\n\n const contextValue: ContextMenuContextValue = {\n onSelect: handleSelect,\n onClose: handleClose,\n }\n\n return (\n <>\n <div ref={triggerRef} onContextMenu={handleContextMenu} className=\"inline-block\">\n {triggerChild}\n </div>\n {visible &&\n createPortal(\n <ContextMenuContext.Provider value={contextValue}>\n <ul\n ref={menuRef}\n className={`${dMenu} bg-base-100 rounded-box shadow-lg border border-base-300 min-w-[160px] p-1 fixed z-[9999] ${className}`}\n style={{ left: position.x, top: position.y }}\n >\n {useDataDriven\n ? items!.map((item) => (\n <MenuItem key={item.key} item={item} onSelect={handleSelect} onClose={handleClose} />\n ))\n : menuChildren}\n </ul>\n </ContextMenuContext.Provider>,\n getPopupContainer ? getPopupContainer(document.body) : document.body\n )}\n </>\n )\n}\n\n// Assign compound components\nexport const ContextMenu = Object.assign(ContextMenuRoot, {\n Item: ContextMenuItemComponent,\n Divider: ContextMenuDividerComponent,\n SubMenu: ContextMenuSubMenuComponent,\n})\n"],"names":["dMenu","dDivider","ContextMenuContext","createContext","useContextMenuContext","context","useContext","ContextMenuItemComponent","children","icon","disabled","danger","className","_key","onSelect","onClose","jsx","jsxs","ContextMenuDividerComponent","ContextMenuSubMenuComponent","label","_unusedKey","showSubmenu","setShowSubmenu","useState","timeoutRef","useRef","handleMouseEnter","handleMouseLeave","MenuItem","item","handleClick","hasSubmenu","child","ContextMenuRoot","items","getPopupContainer","useConfig","visible","setVisible","position","setPosition","menuRef","triggerRef","handleContextMenu","useCallback","e","x","y","handleClose","handleSelect","key","useEffect","rect","viewportWidth","viewportHeight","handleClickOutside","handleEscape","handleScroll","cloneChildrenWithKeys","React","childKey","childArray","triggerChild","menuChildren","useDataDriven","contextValue","Fragment","createPortal","ContextMenu"],"mappings":"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"}
1
+ {"version":3,"file":"ContextMenu.js","sources":["../../src/components/ContextMenu.tsx"],"sourcesContent":["import React, { useState, useRef, useEffect, useCallback, createContext, useContext } from 'react'\nimport { createPortal } from 'react-dom'\nimport { useConfig } from '../providers/ConfigProvider'\n\n// DaisyUI classes\nconst dMenu = 'menu'\nconst dDivider = 'divider'\n\nexport interface ContextMenuItem {\n key: string\n label: React.ReactNode\n icon?: React.ReactNode\n disabled?: boolean\n danger?: boolean\n divider?: boolean\n children?: ContextMenuItem[]\n}\n\nexport interface ContextMenuProps {\n /** Element that triggers the context menu on right-click */\n children: React.ReactNode\n /** Menu items (data-driven pattern) */\n items?: ContextMenuItem[]\n /** Callback when an item is selected */\n onSelect?: (key: string) => void\n /** Whether the context menu is disabled */\n disabled?: boolean\n /** Additional CSS classes for the menu */\n className?: string\n}\n\nexport interface ContextMenuItemProps {\n /** Item content */\n children: React.ReactNode\n /** Icon to display before label */\n icon?: React.ReactNode\n /** Whether the item is disabled */\n disabled?: boolean\n /** Show as danger/destructive action */\n danger?: boolean\n /** Additional CSS classes */\n className?: string\n /** @internal */\n _key?: string\n}\n\nexport interface ContextMenuDividerProps {\n /** Additional CSS classes */\n className?: string\n}\n\nexport interface ContextMenuSubMenuProps {\n /** Submenu label */\n label: React.ReactNode\n /** Icon to display before label */\n icon?: React.ReactNode\n /** Whether the submenu is disabled */\n disabled?: boolean\n /** Submenu items */\n children: React.ReactNode\n /** Additional CSS classes */\n className?: string\n /** @internal */\n _key?: string\n}\n\ninterface ContextMenuContextValue {\n onSelect: (key: string) => void\n onClose: () => void\n}\n\ninterface MenuPosition {\n x: number\n y: number\n}\n\nconst ContextMenuContext = createContext<ContextMenuContextValue | null>(null)\n\nconst useContextMenuContext = () => {\n const context = useContext(ContextMenuContext)\n if (!context) {\n throw new Error('ContextMenu compound components must be used within a ContextMenu')\n }\n return context\n}\n\n// Compound pattern components\nconst ContextMenuItemComponent: React.FC<ContextMenuItemProps> = ({\n children,\n icon,\n disabled = false,\n danger = false,\n className = '',\n _key,\n}) => {\n const { onSelect, onClose } = useContextMenuContext()\n\n const handleClick = () => {\n if (disabled || !_key) return\n onSelect(_key)\n onClose()\n }\n\n return (\n <li className={className} role=\"none\">\n <button\n onClick={handleClick}\n disabled={disabled}\n role=\"menuitem\"\n aria-disabled={disabled}\n className={`\n flex items-center gap-2 w-full px-4 py-2 text-left text-sm\n ${disabled ? 'opacity-50 cursor-not-allowed' : 'hover:bg-base-200'}\n ${danger ? 'text-error hover:bg-error/10' : ''}\n `}\n >\n {icon && <span className=\"w-4 h-4\" aria-hidden=\"true\">{icon}</span>}\n <span className=\"flex-1\">{children}</span>\n </button>\n </li>\n )\n}\n\nconst ContextMenuDividerComponent: React.FC<ContextMenuDividerProps> = ({ className = '' }) => {\n return <li className={`${dDivider} my-1 ${className}`} role=\"separator\"></li>\n}\n\nconst ContextMenuSubMenuComponent: React.FC<ContextMenuSubMenuProps> = ({\n label,\n icon,\n disabled = false,\n children,\n className = '',\n _key: _unusedKey,\n}) => {\n const [showSubmenu, setShowSubmenu] = useState(false)\n const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null)\n\n const handleMouseEnter = () => {\n if (disabled) return\n if (timeoutRef.current) clearTimeout(timeoutRef.current)\n setShowSubmenu(true)\n }\n\n const handleMouseLeave = () => {\n timeoutRef.current = setTimeout(() => setShowSubmenu(false), 100)\n }\n\n return (\n <li\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n className={`relative ${className}`}\n role=\"none\"\n >\n <button\n disabled={disabled}\n role=\"menuitem\"\n aria-haspopup=\"menu\"\n aria-expanded={showSubmenu}\n aria-disabled={disabled}\n className={`\n flex items-center gap-2 w-full px-4 py-2 text-left text-sm\n ${disabled ? 'opacity-50 cursor-not-allowed' : 'hover:bg-base-200'}\n `}\n >\n {icon && <span className=\"w-4 h-4\" aria-hidden=\"true\">{icon}</span>}\n <span className=\"flex-1\">{label}</span>\n <svg className=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" aria-hidden=\"true\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M9 5l7 7-7 7\" />\n </svg>\n </button>\n {showSubmenu && (\n <ul\n className={`${dMenu} bg-base-100 rounded-box shadow-lg border border-base-300 absolute left-full top-0 min-w-[160px] z-50 p-1`}\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n role=\"menu\"\n >\n {children}\n </ul>\n )}\n </li>\n )\n}\n\n// Data-driven pattern internal component\nconst MenuItem: React.FC<{\n item: ContextMenuItem\n onSelect: (key: string) => void\n onClose: () => void\n}> = ({ item, onSelect, onClose }) => {\n const [showSubmenu, setShowSubmenu] = useState(false)\n const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null)\n\n if (item.divider) {\n return <li className={`${dDivider} my-1`} role=\"separator\"></li>\n }\n\n const handleClick = () => {\n if (item.disabled) return\n if (item.children && item.children.length > 0) return\n onSelect(item.key)\n onClose()\n }\n\n const hasSubmenu = item.children && item.children.length > 0\n\n const handleMouseEnter = () => {\n if (!hasSubmenu) return\n if (timeoutRef.current) clearTimeout(timeoutRef.current)\n setShowSubmenu(true)\n }\n\n const handleMouseLeave = () => {\n if (!hasSubmenu) return\n timeoutRef.current = setTimeout(() => setShowSubmenu(false), 100)\n }\n\n return (\n <li\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n className=\"relative\"\n role=\"none\"\n >\n <button\n onClick={handleClick}\n disabled={item.disabled}\n role=\"menuitem\"\n aria-haspopup={hasSubmenu ? 'menu' : undefined}\n aria-expanded={hasSubmenu ? showSubmenu : undefined}\n aria-disabled={item.disabled}\n className={`\n flex items-center gap-2 w-full px-4 py-2 text-left text-sm\n ${item.disabled ? 'opacity-50 cursor-not-allowed' : 'hover:bg-base-200'}\n ${item.danger ? 'text-error hover:bg-error/10' : ''}\n `}\n >\n {item.icon && <span className=\"w-4 h-4\" aria-hidden=\"true\">{item.icon}</span>}\n <span className=\"flex-1\">{item.label}</span>\n {hasSubmenu && (\n <svg className=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" aria-hidden=\"true\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M9 5l7 7-7 7\" />\n </svg>\n )}\n </button>\n {hasSubmenu && showSubmenu && (\n <ul\n className={`${dMenu} bg-base-100 rounded-box shadow-lg border border-base-300 absolute left-full top-0 min-w-[160px] z-50 p-1`}\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n role=\"menu\"\n >\n {item.children!.map((child) => (\n <MenuItem key={child.key} item={child} onSelect={onSelect} onClose={onClose} />\n ))}\n </ul>\n )}\n </li>\n )\n}\n\nconst ContextMenuRoot: React.FC<ContextMenuProps> = ({\n children,\n items,\n onSelect,\n disabled = false,\n className = '',\n}) => {\n const { getPopupContainer } = useConfig()\n const [visible, setVisible] = useState(false)\n const [position, setPosition] = useState<MenuPosition>({ x: 0, y: 0 })\n const menuRef = useRef<HTMLUListElement>(null)\n const triggerRef = useRef<HTMLDivElement>(null)\n\n const handleContextMenu = useCallback(\n (e: React.MouseEvent) => {\n if (disabled) return\n e.preventDefault()\n e.stopPropagation()\n\n // Calculate position, ensuring menu stays within viewport\n let x = e.clientX\n let y = e.clientY\n\n // We'll adjust after render when we know menu dimensions\n setPosition({ x, y })\n setVisible(true)\n },\n [disabled]\n )\n\n const handleClose = useCallback(() => {\n setVisible(false)\n }, [])\n\n const handleSelect = useCallback(\n (key: string) => {\n onSelect?.(key)\n },\n [onSelect]\n )\n\n // Adjust position after menu renders to keep it in viewport\n useEffect(() => {\n if (visible && menuRef.current) {\n const menu = menuRef.current\n const rect = menu.getBoundingClientRect()\n const viewportWidth = window.innerWidth\n const viewportHeight = window.innerHeight\n\n let { x, y } = position\n\n if (x + rect.width > viewportWidth) {\n x = viewportWidth - rect.width - 8\n }\n if (y + rect.height > viewportHeight) {\n y = viewportHeight - rect.height - 8\n }\n\n if (x !== position.x || y !== position.y) {\n setPosition({ x, y })\n }\n }\n }, [visible, position])\n\n // Close on click outside or escape\n useEffect(() => {\n if (!visible) return\n\n const handleClickOutside = (e: MouseEvent) => {\n if (menuRef.current && !menuRef.current.contains(e.target as Node)) {\n handleClose()\n }\n }\n\n const handleEscape = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n handleClose()\n }\n }\n\n const handleScroll = () => {\n handleClose()\n }\n\n document.addEventListener('mousedown', handleClickOutside)\n document.addEventListener('keydown', handleEscape)\n document.addEventListener('scroll', handleScroll, true)\n\n return () => {\n document.removeEventListener('mousedown', handleClickOutside)\n document.removeEventListener('keydown', handleEscape)\n document.removeEventListener('scroll', handleScroll, true)\n }\n }, [visible, handleClose])\n\n // Clone children to extract keys\n const cloneChildrenWithKeys = (children: React.ReactNode): React.ReactNode => {\n return React.Children.map(children, (child) => {\n if (React.isValidElement(child)) {\n const childKey = child.key != null ? String(child.key) : undefined\n if (child.type === ContextMenuItemComponent || child.type === ContextMenuSubMenuComponent) {\n return React.cloneElement(child as React.ReactElement<any>, { _key: childKey })\n }\n }\n return child\n })\n }\n\n // Determine if using data-driven or compound pattern\n // Find menu content children (not the trigger element)\n const childArray = React.Children.toArray(children)\n const triggerChild = childArray[0]\n const menuChildren = cloneChildrenWithKeys(childArray.slice(1))\n const useDataDriven = items && items.length > 0\n\n const contextValue: ContextMenuContextValue = {\n onSelect: handleSelect,\n onClose: handleClose,\n }\n\n return (\n <>\n <div ref={triggerRef} onContextMenu={handleContextMenu} className=\"inline-block\">\n {triggerChild}\n </div>\n {visible &&\n createPortal(\n <ContextMenuContext.Provider value={contextValue}>\n <ul\n ref={menuRef}\n className={`${dMenu} bg-base-100 rounded-box shadow-lg border border-base-300 min-w-[160px] p-1 fixed z-[9999] ${className}`}\n style={{ left: position.x, top: position.y }}\n role=\"menu\"\n aria-label=\"Context menu\"\n >\n {useDataDriven\n ? items!.map((item) => (\n <MenuItem key={item.key} item={item} onSelect={handleSelect} onClose={handleClose} />\n ))\n : menuChildren}\n </ul>\n </ContextMenuContext.Provider>,\n getPopupContainer ? getPopupContainer(document.body) : document.body\n )}\n </>\n )\n}\n\n// Assign compound components\nexport const ContextMenu = Object.assign(ContextMenuRoot, {\n Item: ContextMenuItemComponent,\n Divider: ContextMenuDividerComponent,\n SubMenu: ContextMenuSubMenuComponent,\n})\n"],"names":["dMenu","dDivider","ContextMenuContext","createContext","useContextMenuContext","context","useContext","ContextMenuItemComponent","children","icon","disabled","danger","className","_key","onSelect","onClose","jsx","jsxs","ContextMenuDividerComponent","ContextMenuSubMenuComponent","label","_unusedKey","showSubmenu","setShowSubmenu","useState","timeoutRef","useRef","handleMouseEnter","handleMouseLeave","MenuItem","item","handleClick","hasSubmenu","child","ContextMenuRoot","items","getPopupContainer","useConfig","visible","setVisible","position","setPosition","menuRef","triggerRef","handleContextMenu","useCallback","e","x","y","handleClose","handleSelect","key","useEffect","rect","viewportWidth","viewportHeight","handleClickOutside","handleEscape","handleScroll","cloneChildrenWithKeys","React","childKey","childArray","triggerChild","menuChildren","useDataDriven","contextValue","Fragment","createPortal","ContextMenu"],"mappings":"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"}
@@ -33,5 +33,7 @@ export interface CopyButtonProps extends Omit<React.ButtonHTMLAttributes<HTMLBut
33
33
  tooltipText?: string;
34
34
  /** Tooltip text for copied state */
35
35
  copiedTooltipText?: string;
36
+ /** Test ID for testing */
37
+ 'data-testid'?: string;
36
38
  }
37
39
  export declare const CopyButton: React.FC<CopyButtonProps>;
@@ -44,7 +44,7 @@ const H = "btn", M = "btn-primary", O = "btn-secondary", V = "btn-accent", J = "
44
44
  variant: r,
45
45
  size: g,
46
46
  shape: a,
47
- position: o,
47
+ position: s,
48
48
  icon: y,
49
49
  copiedIcon: k,
50
50
  children: v,
@@ -59,7 +59,7 @@ const H = "btn", M = "btn-primary", O = "btn-secondary", V = "btn-accent", J = "
59
59
  onClick: I,
60
60
  ...L
61
61
  }) => {
62
- const { componentSize: N } = G(), b = g ?? N ?? "md", { copy: j, copied: s } = D(C), q = async (e) => {
62
+ const { componentSize: N } = G(), b = g ?? N ?? "md", { copy: j, copied: o } = D(C), q = async (e) => {
63
63
  if (I?.(e), u) return;
64
64
  await j(n) ? z?.() : S?.(new Error("Failed to copy to clipboard"));
65
65
  }, W = {
@@ -90,12 +90,12 @@ const H = "btn", M = "btn-primary", O = "btn-secondary", V = "btn-accent", J = "
90
90
  }, A = [
91
91
  H,
92
92
  c && W[c],
93
- s && h,
93
+ o && h,
94
94
  r && E[r],
95
95
  P[b],
96
96
  a && X[a],
97
97
  // Only add position classes if not using tooltip (tooltip wrapper gets them instead)
98
- !i && o && f[o],
98
+ !i && s && f[s],
99
99
  x
100
100
  ].filter(Boolean).join(" "), m = /* @__PURE__ */ t(
101
101
  "button",
@@ -104,14 +104,15 @@ const H = "btn", M = "btn-primary", O = "btn-secondary", V = "btn-accent", J = "
104
104
  className: A,
105
105
  onClick: q,
106
106
  disabled: u,
107
- "aria-label": s ? d : l,
107
+ "aria-label": o ? d : l,
108
+ "data-state": o ? "copied" : "idle",
108
109
  ...L,
109
- children: /* @__PURE__ */ t(F, { size: b, children: s ? w ?? (k ?? /* @__PURE__ */ t(at, {})) : v ?? (y ?? /* @__PURE__ */ t(rt, {})) })
110
+ children: /* @__PURE__ */ t(F, { size: b, children: o ? w ?? (k ?? /* @__PURE__ */ t(at, {})) : v ?? (y ?? /* @__PURE__ */ t(rt, {})) })
110
111
  }
111
112
  );
112
113
  if (i) {
113
- const e = [ct, o && f[o]].filter(Boolean).join(" ");
114
- return /* @__PURE__ */ t("div", { className: e, "data-tip": s ? d : l, children: m });
114
+ const e = [ct, s && f[s]].filter(Boolean).join(" ");
115
+ return /* @__PURE__ */ t("div", { className: e, "data-tip": o ? d : l, children: m });
115
116
  }
116
117
  return m;
117
118
  };
@@ -1 +1 @@
1
- {"version":3,"file":"CopyButton.js","sources":["../../src/components/CopyButton.tsx"],"sourcesContent":["import React from 'react'\nimport { useClipboard } from '../hooks/useClipboard'\nimport { SizeProvider, useSize } from '../contexts/SizeContext'\nimport { useConfig } from '../providers/ConfigProvider'\n\n// DaisyUI classes\nconst dBtn = 'btn'\nconst dBtnPrimary = 'btn-primary'\nconst dBtnSecondary = 'btn-secondary'\nconst dBtnAccent = 'btn-accent'\nconst dBtnInfo = 'btn-info'\nconst dBtnSuccess = 'btn-success'\nconst dBtnWarning = 'btn-warning'\nconst dBtnError = 'btn-error'\nconst dBtnNeutral = 'btn-neutral'\nconst dBtnOutline = 'btn-outline'\nconst dBtnDash = 'btn-dash'\nconst dBtnSoft = 'btn-soft'\nconst dBtnGhost = 'btn-ghost'\nconst dBtnLink = 'btn-link'\nconst dBtnXs = 'btn-xs'\nconst dBtnSm = 'btn-sm'\nconst dBtnLg = 'btn-lg'\nconst dBtnXl = 'btn-xl'\nconst dBtnSquare = 'btn-square'\nconst dBtnCircle = 'btn-circle'\nconst dTooltip = 'tooltip'\n\nconst iconSizeClasses = {\n xs: 'w-3.5 h-3.5',\n sm: 'w-3.5 h-3.5',\n md: 'w-4 h-4',\n lg: 'w-5 h-5',\n xl: 'w-6 h-6',\n}\n\nexport type CopyButtonPosition = 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left'\n\nexport interface CopyButtonProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'children' | 'onError'> {\n /** Text to copy to clipboard */\n text: string\n /** Duration in ms to show copied state */\n timeout?: number\n /** Button color */\n color?: 'primary' | 'secondary' | 'accent' | 'info' | 'success' | 'warning' | 'error' | 'neutral'\n /** Button style variant */\n variant?: 'solid' | 'outline' | 'dash' | 'soft' | 'ghost' | 'link'\n /** Button size */\n size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl'\n /** Button shape */\n shape?: 'square' | 'circle'\n /** Absolute position within parent (parent must have position: relative) */\n position?: CopyButtonPosition\n /** Custom icon for default state */\n icon?: React.ReactNode\n /** Custom icon for copied state */\n copiedIcon?: React.ReactNode\n /** Custom content for default state (overrides icon) */\n children?: React.ReactNode\n /** Custom content for copied state */\n copiedChildren?: React.ReactNode\n /** Callback when copy succeeds */\n onCopy?: () => void\n /** Callback when copy fails */\n onError?: (error: Error) => void\n /** Show tooltip with copy status */\n showTooltip?: boolean\n /** Tooltip text for default state */\n tooltipText?: string\n /** Tooltip text for copied state */\n copiedTooltipText?: string\n}\n\nconst CopyIcon: React.FC = () => {\n const size = useSize() ?? 'md'\n return (\n <svg\n className={iconSizeClasses[size]}\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth=\"2\" d=\"M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z\" />\n </svg>\n )\n}\n\nconst CheckIcon: React.FC = () => {\n const size = useSize() ?? 'md'\n return (\n <svg\n className={iconSizeClasses[size]}\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth=\"2\" d=\"m4.5 12.75 6 6 9-13.5\" />\n </svg>\n )\n}\n\nconst positionClasses: Record<CopyButtonPosition, string> = {\n 'top-right': 'absolute top-2 right-2',\n 'top-left': 'absolute top-2 left-2',\n 'bottom-right': 'absolute bottom-2 right-2',\n 'bottom-left': 'absolute bottom-2 left-2',\n}\n\nexport const CopyButton: React.FC<CopyButtonProps> = ({\n text,\n timeout = 2000,\n color,\n variant,\n size,\n shape,\n position,\n icon,\n copiedIcon,\n children,\n copiedChildren,\n onCopy,\n onError,\n showTooltip = false,\n tooltipText = 'Copy',\n copiedTooltipText = 'Copied!',\n className = '',\n disabled,\n onClick,\n ...rest\n}) => {\n const { componentSize } = useConfig()\n const effectiveSize = size ?? componentSize ?? 'md'\n const { copy, copied } = useClipboard(timeout)\n\n const handleClick = async (e: React.MouseEvent<HTMLButtonElement>) => {\n onClick?.(e)\n if (disabled) return\n\n const success = await copy(text)\n if (success) {\n onCopy?.()\n } else {\n onError?.(new Error('Failed to copy to clipboard'))\n }\n }\n\n const colorClasses = {\n primary: dBtnPrimary,\n secondary: dBtnSecondary,\n accent: dBtnAccent,\n info: dBtnInfo,\n success: dBtnSuccess,\n warning: dBtnWarning,\n error: dBtnError,\n neutral: dBtnNeutral,\n }\n\n const variantClasses = {\n solid: '',\n outline: dBtnOutline,\n dash: dBtnDash,\n soft: dBtnSoft,\n ghost: dBtnGhost,\n link: dBtnLink,\n }\n\n const sizeClasses = {\n xs: dBtnXs,\n sm: dBtnSm,\n md: '',\n lg: dBtnLg,\n xl: dBtnXl,\n }\n\n const shapeClasses = {\n square: dBtnSquare,\n circle: dBtnCircle,\n }\n\n const classes = [\n dBtn,\n color && colorClasses[color],\n copied && dBtnSuccess,\n variant && variantClasses[variant],\n sizeClasses[effectiveSize],\n shape && shapeClasses[shape],\n // Only add position classes if not using tooltip (tooltip wrapper gets them instead)\n !showTooltip && position && positionClasses[position],\n className,\n ]\n .filter(Boolean)\n .join(' ')\n\n const defaultIcon = icon ?? <CopyIcon />\n const successIcon = copiedIcon ?? <CheckIcon />\n\n const content = copied\n ? (copiedChildren ?? successIcon)\n : (children ?? defaultIcon)\n\n const button = (\n <button\n type=\"button\"\n className={classes}\n onClick={handleClick}\n disabled={disabled}\n aria-label={copied ? copiedTooltipText : tooltipText}\n {...rest}\n >\n <SizeProvider size={effectiveSize}>\n {content}\n </SizeProvider>\n </button>\n )\n\n if (showTooltip) {\n const tooltipClasses = [dTooltip, position && positionClasses[position]].filter(Boolean).join(' ')\n return (\n <div className={tooltipClasses} data-tip={copied ? copiedTooltipText : tooltipText}>\n {button}\n </div>\n )\n }\n\n return button\n}\n\nCopyButton.displayName = 'CopyButton'\n"],"names":["dBtn","dBtnPrimary","dBtnSecondary","dBtnAccent","dBtnInfo","dBtnSuccess","dBtnWarning","dBtnError","dBtnNeutral","dBtnOutline","dBtnDash","dBtnSoft","dBtnGhost","dBtnLink","dBtnXs","dBtnSm","dBtnLg","dBtnXl","dBtnSquare","dBtnCircle","dTooltip","iconSizeClasses","CopyIcon","size","useSize","jsx","CheckIcon","positionClasses","CopyButton","text","timeout","color","variant","shape","position","icon","copiedIcon","children","copiedChildren","onCopy","onError","showTooltip","tooltipText","copiedTooltipText","className","disabled","onClick","rest","componentSize","useConfig","effectiveSize","copy","copied","useClipboard","handleClick","colorClasses","variantClasses","sizeClasses","shapeClasses","classes","button","SizeProvider","tooltipClasses"],"mappings":"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"}
1
+ {"version":3,"file":"CopyButton.js","sources":["../../src/components/CopyButton.tsx"],"sourcesContent":["import React from 'react'\nimport { useClipboard } from '../hooks/useClipboard'\nimport { SizeProvider, useSize } from '../contexts/SizeContext'\nimport { useConfig } from '../providers/ConfigProvider'\n\n// DaisyUI classes\nconst dBtn = 'btn'\nconst dBtnPrimary = 'btn-primary'\nconst dBtnSecondary = 'btn-secondary'\nconst dBtnAccent = 'btn-accent'\nconst dBtnInfo = 'btn-info'\nconst dBtnSuccess = 'btn-success'\nconst dBtnWarning = 'btn-warning'\nconst dBtnError = 'btn-error'\nconst dBtnNeutral = 'btn-neutral'\nconst dBtnOutline = 'btn-outline'\nconst dBtnDash = 'btn-dash'\nconst dBtnSoft = 'btn-soft'\nconst dBtnGhost = 'btn-ghost'\nconst dBtnLink = 'btn-link'\nconst dBtnXs = 'btn-xs'\nconst dBtnSm = 'btn-sm'\nconst dBtnLg = 'btn-lg'\nconst dBtnXl = 'btn-xl'\nconst dBtnSquare = 'btn-square'\nconst dBtnCircle = 'btn-circle'\nconst dTooltip = 'tooltip'\n\nconst iconSizeClasses = {\n xs: 'w-3.5 h-3.5',\n sm: 'w-3.5 h-3.5',\n md: 'w-4 h-4',\n lg: 'w-5 h-5',\n xl: 'w-6 h-6',\n}\n\nexport type CopyButtonPosition = 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left'\n\nexport interface CopyButtonProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'children' | 'onError'> {\n /** Text to copy to clipboard */\n text: string\n /** Duration in ms to show copied state */\n timeout?: number\n /** Button color */\n color?: 'primary' | 'secondary' | 'accent' | 'info' | 'success' | 'warning' | 'error' | 'neutral'\n /** Button style variant */\n variant?: 'solid' | 'outline' | 'dash' | 'soft' | 'ghost' | 'link'\n /** Button size */\n size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl'\n /** Button shape */\n shape?: 'square' | 'circle'\n /** Absolute position within parent (parent must have position: relative) */\n position?: CopyButtonPosition\n /** Custom icon for default state */\n icon?: React.ReactNode\n /** Custom icon for copied state */\n copiedIcon?: React.ReactNode\n /** Custom content for default state (overrides icon) */\n children?: React.ReactNode\n /** Custom content for copied state */\n copiedChildren?: React.ReactNode\n /** Callback when copy succeeds */\n onCopy?: () => void\n /** Callback when copy fails */\n onError?: (error: Error) => void\n /** Show tooltip with copy status */\n showTooltip?: boolean\n /** Tooltip text for default state */\n tooltipText?: string\n /** Tooltip text for copied state */\n copiedTooltipText?: string\n /** Test ID for testing */\n 'data-testid'?: string\n}\n\nconst CopyIcon: React.FC = () => {\n const size = useSize() ?? 'md'\n return (\n <svg\n className={iconSizeClasses[size]}\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth=\"2\" d=\"M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z\" />\n </svg>\n )\n}\n\nconst CheckIcon: React.FC = () => {\n const size = useSize() ?? 'md'\n return (\n <svg\n className={iconSizeClasses[size]}\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth=\"2\" d=\"m4.5 12.75 6 6 9-13.5\" />\n </svg>\n )\n}\n\nconst positionClasses: Record<CopyButtonPosition, string> = {\n 'top-right': 'absolute top-2 right-2',\n 'top-left': 'absolute top-2 left-2',\n 'bottom-right': 'absolute bottom-2 right-2',\n 'bottom-left': 'absolute bottom-2 left-2',\n}\n\nexport const CopyButton: React.FC<CopyButtonProps> = ({\n text,\n timeout = 2000,\n color,\n variant,\n size,\n shape,\n position,\n icon,\n copiedIcon,\n children,\n copiedChildren,\n onCopy,\n onError,\n showTooltip = false,\n tooltipText = 'Copy',\n copiedTooltipText = 'Copied!',\n className = '',\n disabled,\n onClick,\n ...rest\n}) => {\n const { componentSize } = useConfig()\n const effectiveSize = size ?? componentSize ?? 'md'\n const { copy, copied } = useClipboard(timeout)\n\n const handleClick = async (e: React.MouseEvent<HTMLButtonElement>) => {\n onClick?.(e)\n if (disabled) return\n\n const success = await copy(text)\n if (success) {\n onCopy?.()\n } else {\n onError?.(new Error('Failed to copy to clipboard'))\n }\n }\n\n const colorClasses = {\n primary: dBtnPrimary,\n secondary: dBtnSecondary,\n accent: dBtnAccent,\n info: dBtnInfo,\n success: dBtnSuccess,\n warning: dBtnWarning,\n error: dBtnError,\n neutral: dBtnNeutral,\n }\n\n const variantClasses = {\n solid: '',\n outline: dBtnOutline,\n dash: dBtnDash,\n soft: dBtnSoft,\n ghost: dBtnGhost,\n link: dBtnLink,\n }\n\n const sizeClasses = {\n xs: dBtnXs,\n sm: dBtnSm,\n md: '',\n lg: dBtnLg,\n xl: dBtnXl,\n }\n\n const shapeClasses = {\n square: dBtnSquare,\n circle: dBtnCircle,\n }\n\n const classes = [\n dBtn,\n color && colorClasses[color],\n copied && dBtnSuccess,\n variant && variantClasses[variant],\n sizeClasses[effectiveSize],\n shape && shapeClasses[shape],\n // Only add position classes if not using tooltip (tooltip wrapper gets them instead)\n !showTooltip && position && positionClasses[position],\n className,\n ]\n .filter(Boolean)\n .join(' ')\n\n const defaultIcon = icon ?? <CopyIcon />\n const successIcon = copiedIcon ?? <CheckIcon />\n\n const content = copied\n ? (copiedChildren ?? successIcon)\n : (children ?? defaultIcon)\n\n const button = (\n <button\n type=\"button\"\n className={classes}\n onClick={handleClick}\n disabled={disabled}\n aria-label={copied ? copiedTooltipText : tooltipText}\n data-state={copied ? 'copied' : 'idle'}\n {...rest}\n >\n <SizeProvider size={effectiveSize}>\n {content}\n </SizeProvider>\n </button>\n )\n\n if (showTooltip) {\n const tooltipClasses = [dTooltip, position && positionClasses[position]].filter(Boolean).join(' ')\n return (\n <div className={tooltipClasses} data-tip={copied ? copiedTooltipText : tooltipText}>\n {button}\n </div>\n )\n }\n\n return button\n}\n\nCopyButton.displayName = 'CopyButton'\n"],"names":["dBtn","dBtnPrimary","dBtnSecondary","dBtnAccent","dBtnInfo","dBtnSuccess","dBtnWarning","dBtnError","dBtnNeutral","dBtnOutline","dBtnDash","dBtnSoft","dBtnGhost","dBtnLink","dBtnXs","dBtnSm","dBtnLg","dBtnXl","dBtnSquare","dBtnCircle","dTooltip","iconSizeClasses","CopyIcon","size","useSize","jsx","CheckIcon","positionClasses","CopyButton","text","timeout","color","variant","shape","position","icon","copiedIcon","children","copiedChildren","onCopy","onError","showTooltip","tooltipText","copiedTooltipText","className","disabled","onClick","rest","componentSize","useConfig","effectiveSize","copy","copied","useClipboard","handleClick","colorClasses","variantClasses","sizeClasses","shapeClasses","classes","button","SizeProvider","tooltipClasses"],"mappings":";;;;AAMA,MAAMA,IAAO,OACPC,IAAc,eACdC,IAAgB,iBAChBC,IAAa,cACbC,IAAW,YACXC,IAAc,eACdC,IAAc,eACdC,IAAY,aACZC,IAAc,eACdC,IAAc,eACdC,IAAW,YACXC,IAAW,YACXC,IAAY,aACZC,IAAW,YACXC,IAAS,UACTC,KAAS,UACTC,KAAS,UACTC,KAAS,UACTC,KAAa,cACbC,KAAa,cACbC,KAAW,WAEXC,IAAkB;AAAA,EACtB,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AACN,GAyCMC,KAAqB,MAAM;AAC/B,QAAMC,IAAOC,OAAa;AAC1B,SACE,gBAAAC;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAWJ,EAAgBE,CAAI;AAAA,MAC/B,MAAK;AAAA,MACL,SAAQ;AAAA,MACR,QAAO;AAAA,MAEP,UAAA,gBAAAE,EAAC,UAAK,eAAc,SAAQ,gBAAe,SAAQ,aAAY,KAAI,GAAE,wHAAA,CAAwH;AAAA,IAAA;AAAA,EAAA;AAGnM,GAEMC,KAAsB,MAAM;AAChC,QAAMH,IAAOC,OAAa;AAC1B,SACE,gBAAAC;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAWJ,EAAgBE,CAAI;AAAA,MAC/B,MAAK;AAAA,MACL,SAAQ;AAAA,MACR,QAAO;AAAA,MAEP,UAAA,gBAAAE,EAAC,UAAK,eAAc,SAAQ,gBAAe,SAAQ,aAAY,KAAI,GAAE,wBAAA,CAAwB;AAAA,IAAA;AAAA,EAAA;AAGnG,GAEME,IAAsD;AAAA,EAC1D,aAAa;AAAA,EACb,YAAY;AAAA,EACZ,gBAAgB;AAAA,EAChB,eAAe;AACjB,GAEaC,KAAwC,CAAC;AAAA,EACpD,MAAAC;AAAA,EACA,SAAAC,IAAU;AAAA,EACV,OAAAC;AAAA,EACA,SAAAC;AAAA,EACA,MAAAT;AAAA,EACA,OAAAU;AAAA,EACA,UAAAC;AAAA,EACA,MAAAC;AAAA,EACA,YAAAC;AAAA,EACA,UAAAC;AAAA,EACA,gBAAAC;AAAA,EACA,QAAAC;AAAA,EACA,SAAAC;AAAA,EACA,aAAAC,IAAc;AAAA,EACd,aAAAC,IAAc;AAAA,EACd,mBAAAC,IAAoB;AAAA,EACpB,WAAAC,IAAY;AAAA,EACZ,UAAAC;AAAA,EACA,SAAAC;AAAA,EACA,GAAGC;AACL,MAAM;AACJ,QAAM,EAAE,eAAAC,EAAA,IAAkBC,EAAA,GACpBC,IAAgB3B,KAAQyB,KAAiB,MACzC,EAAE,MAAAG,GAAM,QAAAC,MAAWC,EAAavB,CAAO,GAEvCwB,IAAc,OAAO,MAA2C;AAEpE,QADAR,IAAU,CAAC,GACPD,EAAU;AAGd,IADgB,MAAMM,EAAKtB,CAAI,IAE7BU,IAAA,IAEAC,IAAU,IAAI,MAAM,6BAA6B,CAAC;AAAA,EAEtD,GAEMe,IAAe;AAAA,IACnB,SAAStD;AAAA,IACT,WAAWC;AAAA,IACX,QAAQC;AAAA,IACR,MAAMC;AAAA,IACN,SAASC;AAAA,IACT,SAASC;AAAA,IACT,OAAOC;AAAA,IACP,SAASC;AAAA,EAAA,GAGLgD,IAAiB;AAAA,IACrB,OAAO;AAAA,IACP,SAAS/C;AAAA,IACT,MAAMC;AAAA,IACN,MAAMC;AAAA,IACN,OAAOC;AAAA,IACP,MAAMC;AAAA,EAAA,GAGF4C,IAAc;AAAA,IAClB,IAAI3C;AAAA,IACJ,IAAIC;AAAA,IACJ,IAAI;AAAA,IACJ,IAAIC;AAAA,IACJ,IAAIC;AAAA,EAAA,GAGAyC,IAAe;AAAA,IACnB,QAAQxC;AAAA,IACR,QAAQC;AAAA,EAAA,GAGJwC,IAAU;AAAA,IACd3D;AAAA,IACA+B,KAASwB,EAAaxB,CAAK;AAAA,IAC3BqB,KAAU/C;AAAA,IACV2B,KAAWwB,EAAexB,CAAO;AAAA,IACjCyB,EAAYP,CAAa;AAAA,IACzBjB,KAASyB,EAAazB,CAAK;AAAA;AAAA,IAE3B,CAACQ,KAAeP,KAAYP,EAAgBO,CAAQ;AAAA,IACpDU;AAAA,EAAA,EAEC,OAAO,OAAO,EACd,KAAK,GAAG,GASLgB,IACJ,gBAAAnC;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,MAAK;AAAA,MACL,WAAWkC;AAAA,MACX,SAASL;AAAA,MACT,UAAAT;AAAA,MACA,cAAYO,IAAST,IAAoBD;AAAA,MACzC,cAAYU,IAAS,WAAW;AAAA,MAC/B,GAAGL;AAAA,MAEJ,UAAA,gBAAAtB,EAACoC,GAAA,EAAa,MAAMX,GACjB,UAfSE,IACXd,MAHeF,KAAc,gBAAAX,EAACC,IAAA,CAAA,CAAU,KAIxCW,MALeF,KAAQ,gBAAAV,EAACH,IAAA,CAAA,CAAS,GAkB/B,CACH;AAAA,IAAA;AAAA,EAAA;AAIJ,MAAImB,GAAa;AACf,UAAMqB,IAAiB,CAAC1C,IAAUc,KAAYP,EAAgBO,CAAQ,CAAC,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG;AACjG,WACE,gBAAAT,EAAC,SAAI,WAAWqC,GAAgB,YAAUV,IAAST,IAAoBD,GACpE,UAAAkB,EAAA,CACH;AAAA,EAEJ;AAEA,SAAOA;AACT;AAEAhC,GAAW,cAAc;"}
@@ -1,5 +1,5 @@
1
1
  import { default as React } from 'react';
2
- export interface CountdownProps {
2
+ export interface CountdownProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange'> {
3
3
  /** Target timestamp in milliseconds or Date object */
4
4
  value: number | Date;
5
5
  /** Format string: 'D' days, 'H' hours, 'M' minutes, 'S' seconds */
@@ -8,8 +8,6 @@ export interface CountdownProps {
8
8
  onFinish?: () => void;
9
9
  /** Callback on each tick with remaining time */
10
10
  onChange?: (value: number) => void;
11
- /** Additional CSS classes */
12
- className?: string;
13
11
  /** Size variant */
14
12
  size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
15
13
  /** Show labels under each unit */
@@ -23,5 +21,7 @@ export interface CountdownProps {
23
21
  };
24
22
  /** Show box style around each unit */
25
23
  boxed?: boolean;
24
+ /** Test ID for testing */
25
+ 'data-testid'?: string;
26
26
  }
27
27
  export declare const Countdown: React.FC<CountdownProps>;