@wow-two-beta/ui 0.0.12 → 0.0.14

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 (110) hide show
  1. package/dist/actions/index.d.ts +1 -0
  2. package/dist/actions/index.d.ts.map +1 -1
  3. package/dist/actions/index.js +2 -2
  4. package/dist/actions/toolbar/Toolbar.d.ts +23 -0
  5. package/dist/actions/toolbar/Toolbar.d.ts.map +1 -0
  6. package/dist/actions/toolbar/index.d.ts +2 -0
  7. package/dist/actions/toolbar/index.d.ts.map +1 -0
  8. package/dist/chunk-ASXB42MH.js +1670 -0
  9. package/dist/chunk-ASXB42MH.js.map +1 -0
  10. package/dist/{chunk-K6V4KLRO.js → chunk-BQTO7XY6.js} +1299 -478
  11. package/dist/chunk-BQTO7XY6.js.map +1 -0
  12. package/dist/{chunk-52DFDWY3.js → chunk-FS6DTWWH.js} +121 -146
  13. package/dist/chunk-FS6DTWWH.js.map +1 -0
  14. package/dist/{chunk-ZTHJ5OTI.js → chunk-UGHPZ3I7.js} +212 -6
  15. package/dist/chunk-UGHPZ3I7.js.map +1 -0
  16. package/dist/{chunk-D5CHR6RX.js → chunk-ULAOIBCP.js} +113 -5
  17. package/dist/chunk-ULAOIBCP.js.map +1 -0
  18. package/dist/{chunk-YANOG5YR.js → chunk-YMSAS7M7.js} +104 -55
  19. package/dist/chunk-YMSAS7M7.js.map +1 -0
  20. package/dist/display/accordion/Accordion.d.ts +41 -0
  21. package/dist/display/accordion/Accordion.d.ts.map +1 -0
  22. package/dist/display/accordion/index.d.ts +2 -0
  23. package/dist/display/accordion/index.d.ts.map +1 -0
  24. package/dist/display/collapsible/Collapsible.d.ts +26 -0
  25. package/dist/display/collapsible/Collapsible.d.ts.map +1 -0
  26. package/dist/display/collapsible/index.d.ts +2 -0
  27. package/dist/display/collapsible/index.d.ts.map +1 -0
  28. package/dist/display/dataTable/DataTable.d.ts +34 -0
  29. package/dist/display/dataTable/DataTable.d.ts.map +1 -0
  30. package/dist/display/dataTable/index.d.ts +2 -0
  31. package/dist/display/dataTable/index.d.ts.map +1 -0
  32. package/dist/display/index.d.ts +8 -0
  33. package/dist/display/index.d.ts.map +1 -1
  34. package/dist/display/index.js +2 -3
  35. package/dist/display/list/List.d.ts +23 -0
  36. package/dist/display/list/List.d.ts.map +1 -0
  37. package/dist/display/list/List.variants.d.ts +89 -0
  38. package/dist/display/list/List.variants.d.ts.map +1 -0
  39. package/dist/display/list/index.d.ts +2 -0
  40. package/dist/display/list/index.d.ts.map +1 -0
  41. package/dist/display/table/Table.d.ts +35 -0
  42. package/dist/display/table/Table.d.ts.map +1 -0
  43. package/dist/display/table/index.d.ts +2 -0
  44. package/dist/display/table/index.d.ts.map +1 -0
  45. package/dist/display/tabs/Tabs.d.ts +31 -0
  46. package/dist/display/tabs/Tabs.d.ts.map +1 -0
  47. package/dist/display/tabs/index.d.ts +2 -0
  48. package/dist/display/tabs/index.d.ts.map +1 -0
  49. package/dist/display/timeline/Timeline.d.ts +29 -0
  50. package/dist/display/timeline/Timeline.d.ts.map +1 -0
  51. package/dist/display/timeline/index.d.ts +2 -0
  52. package/dist/display/timeline/index.d.ts.map +1 -0
  53. package/dist/display/tree/Tree.d.ts +30 -0
  54. package/dist/display/tree/Tree.d.ts.map +1 -0
  55. package/dist/display/tree/index.d.ts +2 -0
  56. package/dist/display/tree/index.d.ts.map +1 -0
  57. package/dist/forms/MonthGrid.d.ts +29 -0
  58. package/dist/forms/MonthGrid.d.ts.map +1 -0
  59. package/dist/forms/calendar/Calendar.d.ts.map +1 -1
  60. package/dist/forms/datePicker/DatePicker.d.ts.map +1 -1
  61. package/dist/forms/dateRangePicker/DateRangePicker.d.ts.map +1 -1
  62. package/dist/forms/index.d.ts +8 -0
  63. package/dist/forms/index.d.ts.map +1 -1
  64. package/dist/forms/index.js +3 -3
  65. package/dist/forms/multiSelect/MultiSelect.d.ts +4 -5
  66. package/dist/forms/multiSelect/MultiSelect.d.ts.map +1 -1
  67. package/dist/forms/rangeCalendar/RangeCalendar.d.ts.map +1 -1
  68. package/dist/forms/select/Select.d.ts +5 -9
  69. package/dist/forms/select/Select.d.ts.map +1 -1
  70. package/dist/forms/stepper/Stepper.d.ts +32 -0
  71. package/dist/forms/stepper/Stepper.d.ts.map +1 -0
  72. package/dist/forms/stepper/index.d.ts +2 -0
  73. package/dist/forms/stepper/index.d.ts.map +1 -0
  74. package/dist/forms/timePicker/TimePicker.d.ts.map +1 -1
  75. package/dist/index.js +6 -7
  76. package/dist/nav/index.d.ts +1 -0
  77. package/dist/nav/index.d.ts.map +1 -1
  78. package/dist/nav/index.js +2 -3
  79. package/dist/nav/navigationMenu/NavigationMenu.d.ts +39 -0
  80. package/dist/nav/navigationMenu/NavigationMenu.d.ts.map +1 -0
  81. package/dist/nav/navigationMenu/index.d.ts +2 -0
  82. package/dist/nav/navigationMenu/index.d.ts.map +1 -0
  83. package/dist/overlays/OverlayChrome.d.ts +34 -0
  84. package/dist/overlays/OverlayChrome.d.ts.map +1 -0
  85. package/dist/overlays/dialog/Dialog.d.ts +7 -25
  86. package/dist/overlays/dialog/Dialog.d.ts.map +1 -1
  87. package/dist/overlays/dialog/index.d.ts +1 -1
  88. package/dist/overlays/dialog/index.d.ts.map +1 -1
  89. package/dist/overlays/drawer/Drawer.d.ts +7 -21
  90. package/dist/overlays/drawer/Drawer.d.ts.map +1 -1
  91. package/dist/overlays/drawer/index.d.ts +1 -1
  92. package/dist/overlays/drawer/index.d.ts.map +1 -1
  93. package/dist/overlays/index.js +2 -3
  94. package/dist/overlays/popover/Popover.d.ts +7 -0
  95. package/dist/overlays/popover/Popover.d.ts.map +1 -1
  96. package/dist/primitives/anchoredPositioner/AnchoredPositioner.d.ts +8 -0
  97. package/dist/primitives/anchoredPositioner/AnchoredPositioner.d.ts.map +1 -1
  98. package/dist/primitives/index.js +1 -2
  99. package/dist/primitives/rovingFocusGroup/RovingFocusGroup.d.ts +1 -1
  100. package/dist/primitives/rovingFocusGroup/RovingFocusGroup.d.ts.map +1 -1
  101. package/package.json +1 -1
  102. package/dist/chunk-33IOXQYO.js +0 -47
  103. package/dist/chunk-33IOXQYO.js.map +0 -1
  104. package/dist/chunk-52DFDWY3.js.map +0 -1
  105. package/dist/chunk-D5CHR6RX.js.map +0 -1
  106. package/dist/chunk-K6V4KLRO.js.map +0 -1
  107. package/dist/chunk-VTLWHUMD.js +0 -774
  108. package/dist/chunk-VTLWHUMD.js.map +0 -1
  109. package/dist/chunk-YANOG5YR.js.map +0 -1
  110. package/dist/chunk-ZTHJ5OTI.js.map +0 -1
@@ -0,0 +1,1670 @@
1
+ import { useClipboard, useControlled } from './chunk-4P2TFUVW.js';
2
+ import { Slot, RovingFocusGroup, useRovingFocusItem, Portal, AnchoredPositioner } from './chunk-YMSAS7M7.js';
3
+ import { tv, dataAttr } from './chunk-BMBIZLO4.js';
4
+ import { Icon } from './chunk-TDX22OWF.js';
5
+ import { composeRefs } from './chunk-DN7WBRIV.js';
6
+ import { cn } from './chunk-KZ4VFY2T.js';
7
+ import { forwardRef, useState, Children, isValidElement, Fragment as Fragment$1, createContext, useId, useMemo, useCallback, useContext, useRef, cloneElement } from 'react';
8
+ import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
9
+ import { X, TrendingUp, TrendingDown, Check, Copy, ChevronDown, ChevronRight, ArrowUp, ArrowDown, ArrowUpDown } from 'lucide-react';
10
+
11
+ // src/display/heading/Heading.variants.ts
12
+ var headingVariants = tv({
13
+ base: "font-semibold tracking-tight text-foreground",
14
+ variants: {
15
+ size: {
16
+ xs: "text-sm",
17
+ sm: "text-base",
18
+ md: "text-lg",
19
+ lg: "text-xl",
20
+ xl: "text-2xl",
21
+ "2xl": "text-3xl",
22
+ "3xl": "text-4xl",
23
+ "4xl": "text-5xl"
24
+ },
25
+ weight: {
26
+ normal: "font-normal",
27
+ medium: "font-medium",
28
+ semibold: "font-semibold",
29
+ bold: "font-bold"
30
+ },
31
+ align: {
32
+ left: "text-left",
33
+ center: "text-center",
34
+ right: "text-right"
35
+ }
36
+ },
37
+ defaultVariants: {
38
+ size: "lg",
39
+ weight: "semibold"
40
+ }
41
+ });
42
+ var Heading = forwardRef(
43
+ ({ level = 2, className, size, weight, align, ...props }, ref) => {
44
+ const Tag2 = `h${level}`;
45
+ return /* @__PURE__ */ jsx(
46
+ Tag2,
47
+ {
48
+ ref,
49
+ className: cn(headingVariants({ size, weight, align }), className),
50
+ ...props
51
+ }
52
+ );
53
+ }
54
+ );
55
+ Heading.displayName = "Heading";
56
+
57
+ // src/display/text/Text.variants.ts
58
+ var textVariants = tv({
59
+ base: "",
60
+ variants: {
61
+ size: {
62
+ xs: "text-xs",
63
+ sm: "text-sm",
64
+ md: "text-base",
65
+ lg: "text-lg",
66
+ xl: "text-xl"
67
+ },
68
+ weight: {
69
+ normal: "font-normal",
70
+ medium: "font-medium",
71
+ semibold: "font-semibold",
72
+ bold: "font-bold"
73
+ },
74
+ color: {
75
+ default: "text-foreground",
76
+ muted: "text-muted-foreground",
77
+ subtle: "text-subtle-foreground",
78
+ brand: "text-primary",
79
+ success: "text-success",
80
+ warning: "text-warning",
81
+ danger: "text-destructive"
82
+ },
83
+ align: {
84
+ left: "text-left",
85
+ center: "text-center",
86
+ right: "text-right",
87
+ justify: "text-justify"
88
+ },
89
+ truncate: {
90
+ true: "truncate"
91
+ }
92
+ },
93
+ defaultVariants: {
94
+ size: "md",
95
+ weight: "normal",
96
+ color: "default"
97
+ }
98
+ });
99
+ var Text = forwardRef(
100
+ ({ as: Component = "p", className, size, weight, color, align, truncate, ...props }, ref) => /* @__PURE__ */ jsx(
101
+ Component,
102
+ {
103
+ ref,
104
+ className: cn(textVariants({ size, weight, color, align, truncate }), className),
105
+ ...props
106
+ }
107
+ )
108
+ );
109
+ Text.displayName = "Text";
110
+
111
+ // src/display/code/Code.variants.ts
112
+ var codeVariants = tv({
113
+ base: "font-mono text-sm",
114
+ variants: {
115
+ variant: {
116
+ inline: "rounded-sm bg-muted px-1 py-0.5 text-foreground",
117
+ block: "block w-full overflow-x-auto rounded-md bg-muted p-4 text-foreground"
118
+ }
119
+ },
120
+ defaultVariants: {
121
+ variant: "inline"
122
+ }
123
+ });
124
+ var Code = forwardRef(
125
+ ({ className, variant, ...props }, ref) => /* @__PURE__ */ jsx("code", { ref, className: cn(codeVariants({ variant }), className), ...props })
126
+ );
127
+ Code.displayName = "Code";
128
+ var Kbd = forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
129
+ "kbd",
130
+ {
131
+ ref,
132
+ className: cn(
133
+ "inline-flex h-5 min-w-5 items-center justify-center rounded-sm border border-border",
134
+ "bg-muted px-1.5 font-mono text-xs text-muted-foreground shadow-[inset_0_-1px_0_0_rgb(0_0_0/0.05)]",
135
+ className
136
+ ),
137
+ ...props
138
+ }
139
+ ));
140
+ Kbd.displayName = "Kbd";
141
+ var Image = forwardRef(
142
+ ({ fallback, onError, alt = "", className, ...props }, ref) => {
143
+ const [errored, setErrored] = useState(false);
144
+ if (errored && fallback !== void 0) return /* @__PURE__ */ jsx(Fragment, { children: fallback });
145
+ return /* @__PURE__ */ jsx(
146
+ "img",
147
+ {
148
+ ref,
149
+ alt,
150
+ className: cn("block max-w-full", className),
151
+ onError: (e) => {
152
+ setErrored(true);
153
+ onError?.(e);
154
+ },
155
+ ...props
156
+ }
157
+ );
158
+ }
159
+ );
160
+ Image.displayName = "Image";
161
+
162
+ // src/display/avatar/Avatar.variants.ts
163
+ var avatarVariants = tv({
164
+ base: "inline-flex shrink-0 select-none items-center justify-center overflow-hidden rounded-full bg-muted text-muted-foreground font-medium",
165
+ variants: {
166
+ size: {
167
+ xs: "h-6 w-6 text-xs",
168
+ sm: "h-8 w-8 text-sm",
169
+ md: "h-10 w-10 text-base",
170
+ lg: "h-12 w-12 text-lg",
171
+ xl: "h-16 w-16 text-xl",
172
+ "2xl": "h-20 w-20 text-2xl"
173
+ },
174
+ shape: {
175
+ circle: "rounded-full",
176
+ square: "rounded-md"
177
+ }
178
+ },
179
+ defaultVariants: {
180
+ size: "md",
181
+ shape: "circle"
182
+ }
183
+ });
184
+ function getInitials(name) {
185
+ const parts = name.trim().split(/\s+/);
186
+ if (parts.length === 0) return "";
187
+ const first = parts[0]?.[0] ?? "";
188
+ const last = parts.length > 1 ? parts[parts.length - 1]?.[0] ?? "" : "";
189
+ return (first + last).toUpperCase();
190
+ }
191
+ var Avatar = forwardRef(
192
+ ({ src, name = "", fallback, alt, className, size, shape, ...props }, ref) => {
193
+ const [errored, setErrored] = useState(false);
194
+ const showImage = src && !errored;
195
+ return /* @__PURE__ */ jsx(
196
+ "span",
197
+ {
198
+ ref,
199
+ className: cn(avatarVariants({ size, shape }), className),
200
+ ...props,
201
+ children: showImage ? /* @__PURE__ */ jsx(
202
+ "img",
203
+ {
204
+ src,
205
+ alt: alt ?? name,
206
+ className: "h-full w-full object-cover",
207
+ onError: () => setErrored(true)
208
+ }
209
+ ) : fallback ?? getInitials(name)
210
+ }
211
+ );
212
+ }
213
+ );
214
+ Avatar.displayName = "Avatar";
215
+
216
+ // src/display/badge/Badge.variants.ts
217
+ var badgeVariants = tv({
218
+ base: "inline-flex items-center rounded-full font-medium",
219
+ variants: {
220
+ variant: {
221
+ neutral: "bg-muted text-foreground",
222
+ brand: "bg-primary-soft text-primary-soft-foreground",
223
+ success: "bg-success-soft text-success-soft-foreground",
224
+ warning: "bg-warning-soft text-warning-soft-foreground",
225
+ danger: "bg-destructive-soft text-destructive-soft-foreground",
226
+ info: "bg-info-soft text-info-soft-foreground",
227
+ outline: "border border-border text-foreground"
228
+ },
229
+ size: {
230
+ sm: "h-5 px-2 text-xs",
231
+ md: "h-6 px-2.5 text-xs",
232
+ lg: "h-7 px-3 text-sm"
233
+ }
234
+ },
235
+ defaultVariants: {
236
+ variant: "neutral",
237
+ size: "md"
238
+ }
239
+ });
240
+ var Badge = forwardRef(
241
+ ({ className, variant, size, ...props }, ref) => /* @__PURE__ */ jsx("span", { ref, className: cn(badgeVariants({ variant, size }), className), ...props })
242
+ );
243
+ Badge.displayName = "Badge";
244
+
245
+ // src/display/tag/Tag.variants.ts
246
+ var tagVariants = tv({
247
+ base: "inline-flex items-center gap-1 rounded-md border border-border bg-card px-2 py-0.5 text-xs font-medium text-card-foreground",
248
+ variants: {
249
+ variant: {
250
+ neutral: "",
251
+ brand: "border-transparent bg-primary-soft text-primary-soft-foreground",
252
+ success: "border-transparent bg-success-soft text-success-soft-foreground",
253
+ warning: "border-transparent bg-warning-soft text-warning-soft-foreground",
254
+ danger: "border-transparent bg-destructive-soft text-destructive-soft-foreground",
255
+ info: "border-transparent bg-info-soft text-info-soft-foreground"
256
+ }
257
+ },
258
+ defaultVariants: {
259
+ variant: "neutral"
260
+ }
261
+ });
262
+ var Tag = forwardRef(
263
+ ({ children, onClose, closeLabel = "Remove", variant, className, ...props }, ref) => /* @__PURE__ */ jsxs("span", { ref, className: cn(tagVariants({ variant }), className), ...props, children: [
264
+ children,
265
+ onClose && /* @__PURE__ */ jsx(
266
+ "button",
267
+ {
268
+ type: "button",
269
+ "aria-label": closeLabel,
270
+ onClick: onClose,
271
+ className: "-mr-1 inline-flex h-4 w-4 items-center justify-center rounded-sm text-muted-foreground hover:bg-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
272
+ children: /* @__PURE__ */ jsx(Icon, { icon: X, size: 12 })
273
+ }
274
+ )
275
+ ] })
276
+ );
277
+ Tag.displayName = "Tag";
278
+ var Separator = forwardRef(
279
+ ({ orientation = "horizontal", decorative = true, className, ...props }, ref) => /* @__PURE__ */ jsx(
280
+ "div",
281
+ {
282
+ ref,
283
+ role: decorative ? "none" : "separator",
284
+ "aria-orientation": decorative ? void 0 : orientation,
285
+ className: cn(
286
+ "bg-border",
287
+ orientation === "horizontal" ? "h-px w-full" : "w-px self-stretch",
288
+ className
289
+ ),
290
+ ...props
291
+ }
292
+ )
293
+ );
294
+ Separator.displayName = "Separator";
295
+ var Mark = forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
296
+ "mark",
297
+ {
298
+ ref,
299
+ className: cn("rounded-sm bg-warning-soft px-0.5 text-warning-soft-foreground", className),
300
+ ...props
301
+ }
302
+ ));
303
+ Mark.displayName = "Mark";
304
+ var Quote = forwardRef(
305
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsx(
306
+ "blockquote",
307
+ {
308
+ ref,
309
+ className: cn(
310
+ "border-l-4 border-border pl-4 italic text-muted-foreground",
311
+ className
312
+ ),
313
+ ...props
314
+ }
315
+ )
316
+ );
317
+ Quote.displayName = "Quote";
318
+ var PADDING = {
319
+ none: "",
320
+ sm: "p-3",
321
+ md: "p-4",
322
+ lg: "p-6"
323
+ };
324
+ var CardRoot = forwardRef(
325
+ ({ className, padding = "none", ...props }, ref) => /* @__PURE__ */ jsx(
326
+ "div",
327
+ {
328
+ ref,
329
+ className: cn(
330
+ "rounded-lg border border-border bg-card text-card-foreground shadow-xs",
331
+ PADDING[padding],
332
+ className
333
+ ),
334
+ ...props
335
+ }
336
+ )
337
+ );
338
+ CardRoot.displayName = "Card";
339
+ var CardHeader = forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("flex flex-col gap-1 p-4 pb-2", className), ...props }));
340
+ CardHeader.displayName = "Card.Header";
341
+ var CardTitle = forwardRef(
342
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsx("h3", { ref, className: cn("text-lg font-semibold tracking-tight", className), ...props })
343
+ );
344
+ CardTitle.displayName = "Card.Title";
345
+ var CardDescription = forwardRef(
346
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsx("p", { ref, className: cn("text-sm text-muted-foreground", className), ...props })
347
+ );
348
+ CardDescription.displayName = "Card.Description";
349
+ var CardBody = forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("p-4 pt-2", className), ...props }));
350
+ CardBody.displayName = "Card.Body";
351
+ var CardFooter = forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("flex items-center gap-2 border-t border-border p-4", className), ...props }));
352
+ CardFooter.displayName = "Card.Footer";
353
+ var Card = Object.assign(CardRoot, {
354
+ Header: CardHeader,
355
+ Title: CardTitle,
356
+ Description: CardDescription,
357
+ Body: CardBody,
358
+ Footer: CardFooter
359
+ });
360
+ var AvatarGroup = forwardRef(
361
+ ({ max, size = "md", overlap = "-ml-2", className, children, ...props }, ref) => {
362
+ const all = Children.toArray(children).filter(isValidElement);
363
+ const visible = max ? all.slice(0, max) : all;
364
+ const overflow = max ? Math.max(0, all.length - max) : 0;
365
+ return /* @__PURE__ */ jsxs(
366
+ "div",
367
+ {
368
+ ref,
369
+ className: cn("inline-flex items-center", className),
370
+ ...props,
371
+ children: [
372
+ visible.map((child, i) => /* @__PURE__ */ jsx(
373
+ "div",
374
+ {
375
+ className: cn("ring-2 ring-background rounded-full", i > 0 && overlap),
376
+ children: /* @__PURE__ */ jsx(Avatar, { ...child.props, size })
377
+ },
378
+ i
379
+ )),
380
+ overflow > 0 && /* @__PURE__ */ jsx(
381
+ Avatar,
382
+ {
383
+ size,
384
+ name: `+${overflow}`,
385
+ className: cn(overlap, "ring-2 ring-background")
386
+ }
387
+ )
388
+ ]
389
+ }
390
+ );
391
+ }
392
+ );
393
+ AvatarGroup.displayName = "AvatarGroup";
394
+ function Tooltip({
395
+ content,
396
+ children,
397
+ placement = "top",
398
+ openDelay = 700,
399
+ closeDelay = 0,
400
+ open: controlledOpen,
401
+ disabled
402
+ }) {
403
+ const [uncontrolledOpen, setUncontrolledOpen] = useState(false);
404
+ const open = controlledOpen ?? uncontrolledOpen;
405
+ const [anchor, setAnchor] = useState(null);
406
+ const openTimer = useRef(null);
407
+ const closeTimer = useRef(null);
408
+ const clear = () => {
409
+ if (openTimer.current) clearTimeout(openTimer.current);
410
+ if (closeTimer.current) clearTimeout(closeTimer.current);
411
+ openTimer.current = null;
412
+ closeTimer.current = null;
413
+ };
414
+ const show = () => {
415
+ clear();
416
+ openTimer.current = setTimeout(() => setUncontrolledOpen(true), openDelay);
417
+ };
418
+ const hide = () => {
419
+ clear();
420
+ closeTimer.current = setTimeout(() => setUncontrolledOpen(false), closeDelay);
421
+ };
422
+ if (!isValidElement(children)) return children;
423
+ const trigger = children;
424
+ const cloned = cloneElement(trigger, {
425
+ ref: composeRefs(setAnchor, trigger.ref),
426
+ onPointerEnter: (e) => {
427
+ trigger.props.onPointerEnter?.(e);
428
+ show();
429
+ },
430
+ onPointerLeave: (e) => {
431
+ trigger.props.onPointerLeave?.(e);
432
+ hide();
433
+ },
434
+ onFocus: (e) => {
435
+ trigger.props.onFocus?.(e);
436
+ show();
437
+ },
438
+ onBlur: (e) => {
439
+ trigger.props.onBlur?.(e);
440
+ hide();
441
+ }
442
+ });
443
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
444
+ cloned,
445
+ !disabled && open && content && /* @__PURE__ */ jsx(Portal, { children: /* @__PURE__ */ jsx(AnchoredPositioner, { anchor, placement, offset: 6, children: /* @__PURE__ */ jsx(
446
+ "div",
447
+ {
448
+ role: "tooltip",
449
+ className: cn(
450
+ "z-tooltip rounded-md bg-inverse px-2.5 py-1.5 text-xs text-inverse-foreground shadow-md",
451
+ "animate-in fade-in-0 zoom-in-95"
452
+ ),
453
+ children: content
454
+ }
455
+ ) }) })
456
+ ] });
457
+ }
458
+ var SIZE = {
459
+ sm: { wrap: "gap-2 py-6", iconBox: "h-10 w-10" },
460
+ md: { wrap: "gap-3 py-10", iconBox: "h-14 w-14" },
461
+ lg: { wrap: "gap-4 py-16", iconBox: "h-20 w-20" }
462
+ };
463
+ var EmptyState = forwardRef(
464
+ ({ icon, title, description, actions, size = "md", className, ...props }, ref) => {
465
+ const sz = SIZE[size];
466
+ return /* @__PURE__ */ jsxs(
467
+ "div",
468
+ {
469
+ ref,
470
+ className: cn("flex flex-col items-center text-center", sz.wrap, className),
471
+ ...props,
472
+ children: [
473
+ icon && /* @__PURE__ */ jsx(
474
+ "div",
475
+ {
476
+ className: cn(
477
+ "flex items-center justify-center rounded-full bg-muted text-muted-foreground",
478
+ sz.iconBox
479
+ ),
480
+ children: icon
481
+ }
482
+ ),
483
+ /* @__PURE__ */ jsx(Heading, { level: 3, size: size === "sm" ? "md" : size === "lg" ? "xl" : "lg", children: title }),
484
+ description && /* @__PURE__ */ jsx(Text, { color: "muted", size: size === "lg" ? "md" : "sm", children: description }),
485
+ actions && /* @__PURE__ */ jsx("div", { className: "mt-2 flex items-center gap-2", children: actions })
486
+ ]
487
+ }
488
+ );
489
+ }
490
+ );
491
+ EmptyState.displayName = "EmptyState";
492
+ var VALUE_SIZE = {
493
+ sm: "2xl",
494
+ md: "3xl",
495
+ lg: "4xl"
496
+ };
497
+ var Stat = forwardRef(
498
+ ({ label, value, trend, helper, size = "md", className, ...props }, ref) => {
499
+ const trendUp = trend ? trend.value >= 0 : false;
500
+ return /* @__PURE__ */ jsxs("div", { ref, className: cn("flex flex-col gap-1", className), ...props, children: [
501
+ /* @__PURE__ */ jsx(Text, { size: "sm", color: "muted", children: label }),
502
+ /* @__PURE__ */ jsx(Heading, { level: 3, size: VALUE_SIZE[size], weight: "bold", children: value }),
503
+ (trend || helper) && /* @__PURE__ */ jsxs("div", { className: "mt-1 flex items-center gap-2", children: [
504
+ trend && /* @__PURE__ */ jsxs(
505
+ "span",
506
+ {
507
+ className: cn(
508
+ "inline-flex items-center gap-0.5 text-xs font-medium",
509
+ trendUp ? "text-success" : "text-destructive"
510
+ ),
511
+ children: [
512
+ /* @__PURE__ */ jsx(Icon, { icon: trendUp ? TrendingUp : TrendingDown, size: 12 }),
513
+ trend.value > 0 ? "+" : "",
514
+ trend.value,
515
+ "%",
516
+ trend.label && /* @__PURE__ */ jsxs("span", { className: "text-muted-foreground", children: [
517
+ " ",
518
+ trend.label
519
+ ] })
520
+ ]
521
+ }
522
+ ),
523
+ helper && !trend && /* @__PURE__ */ jsx(Text, { size: "xs", color: "muted", children: helper })
524
+ ] })
525
+ ] });
526
+ }
527
+ );
528
+ Stat.displayName = "Stat";
529
+ var Snippet = forwardRef(
530
+ ({ text, variant = "inline", className, ...props }, ref) => {
531
+ const { copied, copy } = useClipboard();
532
+ return /* @__PURE__ */ jsxs(
533
+ "div",
534
+ {
535
+ ref,
536
+ className: cn(
537
+ "group relative inline-flex w-full items-start",
538
+ variant === "inline" ? "gap-2" : "flex-col gap-0",
539
+ className
540
+ ),
541
+ ...props,
542
+ children: [
543
+ /* @__PURE__ */ jsx(Code, { variant, className: "flex-1 pr-10", children: text }),
544
+ /* @__PURE__ */ jsx(
545
+ "button",
546
+ {
547
+ type: "button",
548
+ "aria-label": copied ? "Copied" : "Copy",
549
+ onClick: () => void copy(text),
550
+ className: cn(
551
+ "absolute right-2 grid h-7 w-7 place-items-center rounded text-muted-foreground transition-colors hover:bg-background hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
552
+ variant === "inline" ? "top-1/2 -translate-y-1/2" : "top-2"
553
+ ),
554
+ children: /* @__PURE__ */ jsx(Icon, { icon: copied ? Check : Copy, size: 14 })
555
+ }
556
+ )
557
+ ]
558
+ }
559
+ );
560
+ }
561
+ );
562
+ Snippet.displayName = "Snippet";
563
+ var TONE = {
564
+ destructive: "bg-destructive",
565
+ success: "bg-success",
566
+ warning: "bg-warning",
567
+ info: "bg-info",
568
+ primary: "bg-primary",
569
+ neutral: "bg-muted-foreground"
570
+ };
571
+ var SIZE2 = {
572
+ xs: "h-1.5 w-1.5",
573
+ sm: "h-2 w-2",
574
+ md: "h-2.5 w-2.5"
575
+ };
576
+ var POS = {
577
+ "top-right": "absolute -top-0.5 -right-0.5",
578
+ "top-left": "absolute -top-0.5 -left-0.5",
579
+ "bottom-right": "absolute -bottom-0.5 -right-0.5",
580
+ "bottom-left": "absolute -bottom-0.5 -left-0.5"
581
+ };
582
+ var NotificationDot = forwardRef(
583
+ ({ tone = "destructive", size = "sm", pulse, position, className, ...props }, ref) => /* @__PURE__ */ jsx(
584
+ "span",
585
+ {
586
+ ref,
587
+ "aria-hidden": "true",
588
+ className: cn(
589
+ "inline-flex rounded-full ring-2 ring-background",
590
+ TONE[tone],
591
+ SIZE2[size],
592
+ position && POS[position],
593
+ pulse && 'after:absolute after:inset-0 after:animate-ping after:rounded-full after:opacity-75 after:content-[""] ' + TONE[tone],
594
+ className
595
+ ),
596
+ ...props
597
+ }
598
+ )
599
+ );
600
+ NotificationDot.displayName = "NotificationDot";
601
+ var CountBadge = forwardRef(
602
+ ({ value, max = 99, hideZero = true, variant = "danger", className, ...props }, ref) => {
603
+ if (value === 0 && hideZero) return null;
604
+ const display = value > max ? `${max}+` : `${value}`;
605
+ return /* @__PURE__ */ jsx(
606
+ Badge,
607
+ {
608
+ ref,
609
+ variant,
610
+ size: "sm",
611
+ className: cn("min-w-5 justify-center px-1.5", className),
612
+ ...props,
613
+ children: display
614
+ }
615
+ );
616
+ }
617
+ );
618
+ CountBadge.displayName = "CountBadge";
619
+ var TONE2 = {
620
+ success: "bg-success",
621
+ warning: "bg-warning",
622
+ destructive: "bg-destructive",
623
+ info: "bg-info",
624
+ neutral: "bg-muted-foreground"
625
+ };
626
+ var Status = forwardRef(
627
+ ({ tone = "success", pulse, className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
628
+ "span",
629
+ {
630
+ ref,
631
+ className: cn("inline-flex items-center gap-2 text-sm text-foreground", className),
632
+ ...props,
633
+ children: [
634
+ /* @__PURE__ */ jsxs("span", { className: "relative inline-flex", children: [
635
+ /* @__PURE__ */ jsx("span", { className: cn("inline-block h-2 w-2 rounded-full", TONE2[tone]) }),
636
+ pulse && /* @__PURE__ */ jsx(
637
+ "span",
638
+ {
639
+ className: cn(
640
+ "absolute inset-0 inline-block rounded-full opacity-75 animate-ping",
641
+ TONE2[tone]
642
+ )
643
+ }
644
+ )
645
+ ] }),
646
+ children
647
+ ]
648
+ }
649
+ )
650
+ );
651
+ Status.displayName = "Status";
652
+ var KeyboardShortcut = forwardRef(
653
+ ({ keys, separator = "+", className, ...props }, ref) => /* @__PURE__ */ jsx(
654
+ "span",
655
+ {
656
+ ref,
657
+ className: cn("inline-flex items-center gap-1 text-muted-foreground", className),
658
+ ...props,
659
+ children: keys.map((key, i) => /* @__PURE__ */ jsxs(Fragment$1, { children: [
660
+ i > 0 && /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: separator }),
661
+ /* @__PURE__ */ jsx(Kbd, { children: key })
662
+ ] }, i))
663
+ }
664
+ )
665
+ );
666
+ KeyboardShortcut.displayName = "KeyboardShortcut";
667
+ var ROW_GAP = {
668
+ sm: "gap-y-1",
669
+ md: "gap-y-2",
670
+ lg: "gap-y-3"
671
+ };
672
+ var DescriptionList = forwardRef(
673
+ ({ items, layout = "inline", density = "md", className, ...props }, ref) => /* @__PURE__ */ jsx(
674
+ "dl",
675
+ {
676
+ ref,
677
+ className: cn(
678
+ "text-sm",
679
+ layout === "inline" ? "grid grid-cols-[max-content_1fr] gap-x-4" : "flex flex-col gap-1",
680
+ ROW_GAP[density],
681
+ className
682
+ ),
683
+ ...props,
684
+ children: items.map((item, i) => /* @__PURE__ */ jsxs("div", { className: cn("contents", layout === "stacked" && "flex flex-col gap-0.5"), children: [
685
+ /* @__PURE__ */ jsx("dt", { className: "text-muted-foreground", children: item.label }),
686
+ /* @__PURE__ */ jsx("dd", { className: "text-foreground", children: item.value })
687
+ ] }, i))
688
+ }
689
+ )
690
+ );
691
+ DescriptionList.displayName = "DescriptionList";
692
+ var InfoRow = forwardRef(
693
+ ({ label, value, icon, layout = "inline", className, ...props }, ref) => /* @__PURE__ */ jsxs(
694
+ "div",
695
+ {
696
+ ref,
697
+ className: cn(
698
+ "flex text-sm",
699
+ layout === "inline" ? "items-center justify-between gap-3" : "flex-col gap-0.5",
700
+ className
701
+ ),
702
+ ...props,
703
+ children: [
704
+ /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1.5 text-muted-foreground", children: [
705
+ icon,
706
+ label
707
+ ] }),
708
+ /* @__PURE__ */ jsx("span", { className: "text-foreground", children: value })
709
+ ]
710
+ }
711
+ )
712
+ );
713
+ InfoRow.displayName = "InfoRow";
714
+ var POS2 = {
715
+ "top-right": "top-0 right-0 -translate-y-1/2 translate-x-1/2",
716
+ "top-left": "top-0 left-0 -translate-y-1/2 -translate-x-1/2",
717
+ "bottom-right": "bottom-0 right-0 translate-y-1/2 translate-x-1/2",
718
+ "bottom-left": "bottom-0 left-0 translate-y-1/2 -translate-x-1/2"
719
+ };
720
+ var BadgeOverlay = forwardRef(
721
+ ({ children, badge, position = "top-right", hidden, className, ...props }, ref) => /* @__PURE__ */ jsxs("div", { ref, className: cn("relative inline-flex", className), ...props, children: [
722
+ children,
723
+ !hidden && /* @__PURE__ */ jsx("span", { className: cn("absolute z-10", POS2[position]), children: badge })
724
+ ] })
725
+ );
726
+ BadgeOverlay.displayName = "BadgeOverlay";
727
+ var SectionHeader = forwardRef(
728
+ ({ title, description, actions, level = 2, size = "lg", bordered = true, className, ...props }, ref) => /* @__PURE__ */ jsxs(
729
+ "header",
730
+ {
731
+ ref,
732
+ className: cn(
733
+ "flex items-start justify-between gap-4 pb-3",
734
+ bordered && "border-b border-border",
735
+ className
736
+ ),
737
+ ...props,
738
+ children: [
739
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-col gap-1", children: [
740
+ /* @__PURE__ */ jsx(Heading, { level, size, children: title }),
741
+ description && /* @__PURE__ */ jsx(Text, { size: "sm", color: "muted", children: description })
742
+ ] }),
743
+ actions && /* @__PURE__ */ jsx("div", { className: "flex shrink-0 items-center gap-2", children: actions })
744
+ ]
745
+ }
746
+ )
747
+ );
748
+ SectionHeader.displayName = "SectionHeader";
749
+ function escape(re) {
750
+ return re.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
751
+ }
752
+ var Highlight = forwardRef(
753
+ ({ children, query, wholeWord, className, ...props }, ref) => {
754
+ const queries = (Array.isArray(query) ? query : [query]).filter(Boolean);
755
+ if (queries.length === 0) return /* @__PURE__ */ jsx("span", { ref, className: cn(className), ...props, children });
756
+ const pattern = queries.map(escape).join("|");
757
+ const regex = new RegExp(wholeWord ? `\\b(${pattern})\\b` : `(${pattern})`, "gi");
758
+ const parts = children.split(regex);
759
+ const nodes = [];
760
+ parts.forEach((part, i) => {
761
+ if (queries.some((q) => part.toLowerCase() === q.toLowerCase())) {
762
+ nodes.push(/* @__PURE__ */ jsx(Mark, { children: part }, i));
763
+ } else if (part) {
764
+ nodes.push(/* @__PURE__ */ jsx(Fragment$1, { children: part }, i));
765
+ }
766
+ });
767
+ return /* @__PURE__ */ jsx("span", { ref, className: cn(className), ...props, children: nodes });
768
+ }
769
+ );
770
+ Highlight.displayName = "Highlight";
771
+ var CollapsibleContext = createContext(null);
772
+ function useCollapsibleContext() {
773
+ const ctx = useContext(CollapsibleContext);
774
+ if (!ctx) throw new Error("Collapsible.* must be used inside <Collapsible>");
775
+ return ctx;
776
+ }
777
+ var Collapsible = forwardRef(function Collapsible2({ open: openProp, defaultOpen = false, onOpenChange, disabled = false, className, children, ...rest }, ref) {
778
+ const [open, setOpen] = useControlled({
779
+ controlled: openProp,
780
+ default: defaultOpen,
781
+ onChange: onOpenChange
782
+ });
783
+ const contentId = useId();
784
+ const triggerId = useId();
785
+ const ctx = useMemo(
786
+ () => ({ open, setOpen, contentId, triggerId, disabled }),
787
+ [open, setOpen, contentId, triggerId, disabled]
788
+ );
789
+ return /* @__PURE__ */ jsx(CollapsibleContext.Provider, { value: ctx, children: /* @__PURE__ */ jsx(
790
+ "div",
791
+ {
792
+ ref,
793
+ "data-state": open ? "open" : "closed",
794
+ "data-disabled": dataAttr(disabled),
795
+ className,
796
+ ...rest,
797
+ children
798
+ }
799
+ ) });
800
+ });
801
+ var CollapsibleTrigger = forwardRef(
802
+ function CollapsibleTrigger2({ asChild, onClick, children, ...rest }, ref) {
803
+ const ctx = useCollapsibleContext();
804
+ const Component = asChild ? Slot : "button";
805
+ return /* @__PURE__ */ jsx(
806
+ Component,
807
+ {
808
+ ref,
809
+ id: ctx.triggerId,
810
+ type: "button",
811
+ "aria-expanded": ctx.open,
812
+ "aria-controls": ctx.contentId,
813
+ "data-state": ctx.open ? "open" : "closed",
814
+ "data-disabled": dataAttr(ctx.disabled),
815
+ disabled: ctx.disabled,
816
+ onClick: (e) => {
817
+ onClick?.(e);
818
+ if (e.defaultPrevented || ctx.disabled) return;
819
+ ctx.setOpen(!ctx.open);
820
+ },
821
+ ...rest,
822
+ children
823
+ }
824
+ );
825
+ }
826
+ );
827
+ var CollapsibleContent = forwardRef(
828
+ function CollapsibleContent2({ forceMount, className, children, ...rest }, ref) {
829
+ const ctx = useCollapsibleContext();
830
+ if (!ctx.open && !forceMount) return null;
831
+ return /* @__PURE__ */ jsx(
832
+ "div",
833
+ {
834
+ ref,
835
+ id: ctx.contentId,
836
+ role: "region",
837
+ "aria-labelledby": ctx.triggerId,
838
+ "data-state": ctx.open ? "open" : "closed",
839
+ hidden: !ctx.open,
840
+ className: cn(
841
+ "overflow-hidden data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
842
+ className
843
+ ),
844
+ ...rest,
845
+ children
846
+ }
847
+ );
848
+ }
849
+ );
850
+ Collapsible.Trigger = CollapsibleTrigger;
851
+ Collapsible.Content = CollapsibleContent;
852
+ var AccordionContext = createContext(null);
853
+ function useAccordionContext() {
854
+ const ctx = useContext(AccordionContext);
855
+ if (!ctx) throw new Error("Accordion.* must be used inside <Accordion>");
856
+ return ctx;
857
+ }
858
+ var AccordionItemContext = createContext(null);
859
+ function useAccordionItemContext() {
860
+ const ctx = useContext(AccordionItemContext);
861
+ if (!ctx) throw new Error("Accordion.Trigger / Content must be used inside <Accordion.Item>");
862
+ return ctx;
863
+ }
864
+ var Accordion = forwardRef(function Accordion2(props, ref) {
865
+ const {
866
+ type = "single",
867
+ value,
868
+ defaultValue,
869
+ onValueChange,
870
+ collapsible = false,
871
+ disabled = false,
872
+ className,
873
+ children,
874
+ ...rest
875
+ } = props;
876
+ const initial = defaultValue ?? (type === "multiple" ? [] : "");
877
+ const [current, setCurrent] = useControlled({
878
+ controlled: value,
879
+ default: initial,
880
+ onChange: onValueChange
881
+ });
882
+ const isOpen = useCallback(
883
+ (val) => Array.isArray(current) ? current.includes(val) : current === val,
884
+ [current]
885
+ );
886
+ const toggle = useCallback(
887
+ (val) => {
888
+ if (type === "multiple") {
889
+ const arr = Array.isArray(current) ? current : [];
890
+ setCurrent(arr.includes(val) ? arr.filter((v) => v !== val) : [...arr, val]);
891
+ } else {
892
+ if (current === val) {
893
+ if (collapsible) setCurrent("");
894
+ } else {
895
+ setCurrent(val);
896
+ }
897
+ }
898
+ },
899
+ [collapsible, current, setCurrent, type]
900
+ );
901
+ const ctx = useMemo(
902
+ () => ({ isOpen, toggle, disabled }),
903
+ [isOpen, toggle, disabled]
904
+ );
905
+ return /* @__PURE__ */ jsx(AccordionContext.Provider, { value: ctx, children: /* @__PURE__ */ jsx(
906
+ RovingFocusGroup,
907
+ {
908
+ ref,
909
+ orientation: "vertical",
910
+ loop: true,
911
+ className: cn("flex flex-col", className),
912
+ ...rest,
913
+ children
914
+ }
915
+ ) });
916
+ });
917
+ var AccordionItem = forwardRef(
918
+ function AccordionItem2({ value, disabled = false, className, children, ...rest }, ref) {
919
+ const accordion = useAccordionContext();
920
+ const open = accordion.isOpen(value);
921
+ const contentId = useId();
922
+ const triggerId = useId();
923
+ const itemDisabled = disabled || accordion.disabled;
924
+ const itemCtx = useMemo(
925
+ () => ({ value, open, contentId, triggerId, disabled: itemDisabled }),
926
+ [value, open, contentId, triggerId, itemDisabled]
927
+ );
928
+ return /* @__PURE__ */ jsx(AccordionItemContext.Provider, { value: itemCtx, children: /* @__PURE__ */ jsx(
929
+ "div",
930
+ {
931
+ ref,
932
+ "data-state": open ? "open" : "closed",
933
+ "data-disabled": dataAttr(itemDisabled),
934
+ className: cn("border-b border-border", className),
935
+ ...rest,
936
+ children
937
+ }
938
+ ) });
939
+ }
940
+ );
941
+ var AccordionTrigger = forwardRef(
942
+ function AccordionTrigger2({ className, onClick, children, ...rest }, ref) {
943
+ const accordion = useAccordionContext();
944
+ const item = useAccordionItemContext();
945
+ const roving = useRovingFocusItem();
946
+ return /* @__PURE__ */ jsx("h3", { className: "flex", children: /* @__PURE__ */ jsxs(
947
+ "button",
948
+ {
949
+ ref: (node) => {
950
+ roving.ref(node);
951
+ if (typeof ref === "function") ref(node);
952
+ else if (ref) ref.current = node;
953
+ },
954
+ id: item.triggerId,
955
+ type: "button",
956
+ "aria-expanded": item.open,
957
+ "aria-controls": item.contentId,
958
+ "data-state": item.open ? "open" : "closed",
959
+ "data-disabled": dataAttr(item.disabled),
960
+ disabled: item.disabled,
961
+ tabIndex: roving.tabIndex,
962
+ onFocus: roving.onFocus,
963
+ onKeyDown: roving.onKeyDown,
964
+ onClick: (e) => {
965
+ onClick?.(e);
966
+ if (e.defaultPrevented || item.disabled) return;
967
+ accordion.toggle(item.value);
968
+ },
969
+ className: cn(
970
+ "flex w-full items-center justify-between gap-2 px-3 py-3 text-left text-sm font-medium text-foreground transition-colors hover:bg-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
971
+ className
972
+ ),
973
+ ...rest,
974
+ children: [
975
+ /* @__PURE__ */ jsx("span", { className: "flex-1", children }),
976
+ /* @__PURE__ */ jsx(
977
+ ChevronDown,
978
+ {
979
+ className: cn(
980
+ "h-4 w-4 shrink-0 text-muted-foreground transition-transform",
981
+ item.open && "rotate-180"
982
+ )
983
+ }
984
+ )
985
+ ]
986
+ }
987
+ ) });
988
+ }
989
+ );
990
+ var AccordionContent = forwardRef(
991
+ function AccordionContent2({ className, children, ...rest }, ref) {
992
+ const item = useAccordionItemContext();
993
+ if (!item.open) return null;
994
+ return /* @__PURE__ */ jsx(
995
+ "div",
996
+ {
997
+ ref,
998
+ id: item.contentId,
999
+ role: "region",
1000
+ "aria-labelledby": item.triggerId,
1001
+ "data-state": "open",
1002
+ className: cn("overflow-hidden px-3 pb-3 text-sm text-foreground", className),
1003
+ ...rest,
1004
+ children
1005
+ }
1006
+ );
1007
+ }
1008
+ );
1009
+ Accordion.Item = AccordionItem;
1010
+ Accordion.Trigger = AccordionTrigger;
1011
+ Accordion.Content = AccordionContent;
1012
+ var TabsContext = createContext(null);
1013
+ function useTabsContext() {
1014
+ const ctx = useContext(TabsContext);
1015
+ if (!ctx) throw new Error("Tabs.* must be used inside <Tabs>");
1016
+ return ctx;
1017
+ }
1018
+ var Tabs = forwardRef(function Tabs2({
1019
+ value,
1020
+ defaultValue,
1021
+ onValueChange,
1022
+ orientation = "horizontal",
1023
+ activationMode = "automatic",
1024
+ className,
1025
+ children,
1026
+ ...rest
1027
+ }, ref) {
1028
+ const [active, setActive] = useControlled({
1029
+ controlled: value,
1030
+ default: defaultValue ?? "",
1031
+ onChange: onValueChange
1032
+ });
1033
+ const baseId = useId();
1034
+ const ctx = useMemo(
1035
+ () => ({ value: active, setValue: setActive, orientation, activationMode, baseId }),
1036
+ [active, setActive, orientation, activationMode, baseId]
1037
+ );
1038
+ return /* @__PURE__ */ jsx(TabsContext.Provider, { value: ctx, children: /* @__PURE__ */ jsx(
1039
+ "div",
1040
+ {
1041
+ ref,
1042
+ "data-orientation": orientation,
1043
+ className: cn(
1044
+ orientation === "vertical" ? "flex gap-2" : "flex flex-col gap-2",
1045
+ className
1046
+ ),
1047
+ ...rest,
1048
+ children
1049
+ }
1050
+ ) });
1051
+ });
1052
+ var TabsList = forwardRef(function TabsList2({ className, children, ...rest }, ref) {
1053
+ const ctx = useTabsContext();
1054
+ return /* @__PURE__ */ jsx(
1055
+ RovingFocusGroup,
1056
+ {
1057
+ ref,
1058
+ orientation: ctx.orientation,
1059
+ loop: true,
1060
+ role: "tablist",
1061
+ "aria-orientation": ctx.orientation,
1062
+ "data-orientation": ctx.orientation,
1063
+ className: cn(
1064
+ "inline-flex border-border",
1065
+ ctx.orientation === "vertical" ? "flex-col border-r" : "flex-row border-b",
1066
+ className
1067
+ ),
1068
+ ...rest,
1069
+ children
1070
+ }
1071
+ );
1072
+ });
1073
+ var TabsTab = forwardRef(function TabsTab2({ value, disabled = false, className, onClick, onFocus, children, ...rest }, ref) {
1074
+ const ctx = useTabsContext();
1075
+ const roving = useRovingFocusItem();
1076
+ const selected = ctx.value === value;
1077
+ const tabId = `${ctx.baseId}-tab-${value}`;
1078
+ const panelId = `${ctx.baseId}-panel-${value}`;
1079
+ return /* @__PURE__ */ jsx(
1080
+ "button",
1081
+ {
1082
+ ref: (node) => {
1083
+ roving.ref(node);
1084
+ if (typeof ref === "function") ref(node);
1085
+ else if (ref) ref.current = node;
1086
+ },
1087
+ id: tabId,
1088
+ role: "tab",
1089
+ type: "button",
1090
+ "aria-selected": selected,
1091
+ "aria-controls": panelId,
1092
+ "data-state": selected ? "active" : "inactive",
1093
+ "data-disabled": dataAttr(disabled),
1094
+ tabIndex: roving.tabIndex,
1095
+ disabled,
1096
+ onClick: (e) => {
1097
+ onClick?.(e);
1098
+ if (e.defaultPrevented || disabled) return;
1099
+ ctx.setValue(value);
1100
+ },
1101
+ onFocus: (e) => {
1102
+ onFocus?.(e);
1103
+ roving.onFocus();
1104
+ if (ctx.activationMode === "automatic" && !disabled) {
1105
+ ctx.setValue(value);
1106
+ }
1107
+ },
1108
+ onKeyDown: roving.onKeyDown,
1109
+ className: cn(
1110
+ "inline-flex items-center justify-center gap-2 px-4 py-2 text-sm font-medium text-muted-foreground transition-colors",
1111
+ "hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
1112
+ "data-[state=active]:text-foreground data-[state=active]:border-primary",
1113
+ ctx.orientation === "vertical" ? "border-r-2 border-transparent data-[state=active]:border-primary" : "border-b-2 border-transparent data-[state=active]:border-primary",
1114
+ "data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
1115
+ className
1116
+ ),
1117
+ ...rest,
1118
+ children
1119
+ }
1120
+ );
1121
+ });
1122
+ var TabsPanel = forwardRef(function TabsPanel2({ value, className, children, ...rest }, ref) {
1123
+ const ctx = useTabsContext();
1124
+ if (ctx.value !== value) return null;
1125
+ const tabId = `${ctx.baseId}-tab-${value}`;
1126
+ const panelId = `${ctx.baseId}-panel-${value}`;
1127
+ return /* @__PURE__ */ jsx(
1128
+ "div",
1129
+ {
1130
+ ref,
1131
+ id: panelId,
1132
+ role: "tabpanel",
1133
+ "aria-labelledby": tabId,
1134
+ tabIndex: 0,
1135
+ className: cn(
1136
+ "flex-1 outline-none focus-visible:ring-2 focus-visible:ring-ring",
1137
+ className
1138
+ ),
1139
+ ...rest,
1140
+ children
1141
+ }
1142
+ );
1143
+ });
1144
+ Tabs.List = TabsList;
1145
+ Tabs.Tab = TabsTab;
1146
+ Tabs.Panel = TabsPanel;
1147
+
1148
+ // src/display/list/List.variants.ts
1149
+ var listVariants = tv({
1150
+ base: "list-outside",
1151
+ variants: {
1152
+ marker: {
1153
+ none: "list-none pl-0",
1154
+ disc: "list-disc pl-5",
1155
+ decimal: "list-decimal pl-5",
1156
+ check: "list-none pl-0"
1157
+ },
1158
+ spacing: {
1159
+ tight: "[&>li]:py-0.5",
1160
+ normal: "[&>li]:py-1",
1161
+ loose: "[&>li]:py-2"
1162
+ }
1163
+ },
1164
+ defaultVariants: {
1165
+ marker: "none",
1166
+ spacing: "normal"
1167
+ }
1168
+ });
1169
+ var listItemVariants = tv({
1170
+ base: "flex items-start gap-3 text-sm text-foreground"
1171
+ });
1172
+ var List = forwardRef(function List2({ ordered, marker, spacing, className, children, ...rest }, ref) {
1173
+ const Component = ordered ? "ol" : "ul";
1174
+ return /* @__PURE__ */ jsx(
1175
+ Component,
1176
+ {
1177
+ ref,
1178
+ className: cn(listVariants({ marker, spacing }), className),
1179
+ ...rest,
1180
+ children
1181
+ }
1182
+ );
1183
+ });
1184
+ var ListItem = forwardRef(function ListItem2({ leading, trailing, showCheckMarker, className, children, ...rest }, ref) {
1185
+ return /* @__PURE__ */ jsxs("li", { ref, className: cn(listItemVariants(), className), ...rest, children: [
1186
+ showCheckMarker && /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "mt-0.5 shrink-0 text-primary", children: /* @__PURE__ */ jsx(Check, { className: "h-4 w-4" }) }),
1187
+ leading && /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "mt-0.5 shrink-0 text-muted-foreground", children: leading }),
1188
+ /* @__PURE__ */ jsx("span", { className: "flex-1", children }),
1189
+ trailing && /* @__PURE__ */ jsx("span", { className: "shrink-0 text-muted-foreground", children: trailing })
1190
+ ] });
1191
+ });
1192
+ List.Item = ListItem;
1193
+ var TimelineContext = createContext(null);
1194
+ var Timeline = forwardRef(function Timeline2({ align = "left", className, children, ...rest }, ref) {
1195
+ const total = Children.toArray(children).filter(isValidElement).length;
1196
+ return /* @__PURE__ */ jsx(TimelineContext.Provider, { value: { align, total }, children: /* @__PURE__ */ jsx(
1197
+ "ol",
1198
+ {
1199
+ ref,
1200
+ className: cn(
1201
+ "flex list-none flex-col",
1202
+ align === "right" && "items-end",
1203
+ className
1204
+ ),
1205
+ ...rest,
1206
+ children: Children.map(children, (child, idx) => {
1207
+ if (!isValidElement(child)) return child;
1208
+ return idx === total - 1 ? (
1209
+ // mark the last item so the connector line is suppressed
1210
+ { ...child, props: { ...child.props, "data-last": "" } }
1211
+ ) : child;
1212
+ })
1213
+ }
1214
+ ) });
1215
+ });
1216
+ var STATUS_BG = {
1217
+ default: "bg-muted text-muted-foreground border-border",
1218
+ primary: "bg-primary text-primary-foreground border-primary",
1219
+ success: "bg-success text-success-foreground border-success",
1220
+ warning: "bg-warning text-warning-foreground border-warning",
1221
+ destructive: "bg-destructive text-destructive-foreground border-destructive",
1222
+ info: "bg-info text-info-foreground border-info"
1223
+ };
1224
+ var TimelineItem = forwardRef(function TimelineItem2({ status = "default", icon, className, children, ...rest }, ref) {
1225
+ const ctx = useContext(TimelineContext);
1226
+ const isLast = rest["data-last"] !== void 0;
1227
+ return /* @__PURE__ */ jsxs(
1228
+ "li",
1229
+ {
1230
+ ref,
1231
+ "data-status": status,
1232
+ className: cn("relative flex gap-3 pb-6 last:pb-0", className),
1233
+ ...rest,
1234
+ children: [
1235
+ /* @__PURE__ */ jsxs("div", { className: "relative flex flex-col items-center", children: [
1236
+ /* @__PURE__ */ jsx(
1237
+ "span",
1238
+ {
1239
+ "aria-hidden": "true",
1240
+ className: cn(
1241
+ "relative z-10 grid h-7 w-7 place-items-center rounded-full border-2",
1242
+ STATUS_BG[status]
1243
+ ),
1244
+ children: icon ?? /* @__PURE__ */ jsx("span", { className: "h-1.5 w-1.5 rounded-full bg-current" })
1245
+ }
1246
+ ),
1247
+ !isLast && /* @__PURE__ */ jsx(
1248
+ "span",
1249
+ {
1250
+ "aria-hidden": "true",
1251
+ className: cn(
1252
+ "absolute left-1/2 top-7 h-full w-px -translate-x-1/2 bg-border"
1253
+ )
1254
+ }
1255
+ )
1256
+ ] }),
1257
+ /* @__PURE__ */ jsx("div", { className: cn("flex-1 pt-0.5", ctx?.align === "right" && "order-first text-right"), children })
1258
+ ]
1259
+ }
1260
+ );
1261
+ });
1262
+ function TimelineTitle({ className, children, ...rest }) {
1263
+ return /* @__PURE__ */ jsx("h4", { className: cn("text-sm font-medium text-foreground", className), ...rest, children });
1264
+ }
1265
+ function TimelineDescription({
1266
+ className,
1267
+ children,
1268
+ ...rest
1269
+ }) {
1270
+ return /* @__PURE__ */ jsx("p", { className: cn("text-xs text-muted-foreground", className), ...rest, children });
1271
+ }
1272
+ Timeline.Item = TimelineItem;
1273
+ Timeline.Title = TimelineTitle;
1274
+ Timeline.Description = TimelineDescription;
1275
+ var TreeContext = createContext(null);
1276
+ function useTreeContext() {
1277
+ const ctx = useContext(TreeContext);
1278
+ if (!ctx) throw new Error("Tree.* must be used inside <Tree>");
1279
+ return ctx;
1280
+ }
1281
+ var TreeLevelContext = createContext({ level: 1 });
1282
+ function useTreeLevel() {
1283
+ return useContext(TreeLevelContext).level;
1284
+ }
1285
+ var Tree = forwardRef(function Tree2({
1286
+ selectedValue,
1287
+ defaultSelectedValue,
1288
+ onSelectionChange,
1289
+ expanded,
1290
+ defaultExpanded,
1291
+ onExpandedChange,
1292
+ className,
1293
+ children,
1294
+ ...rest
1295
+ }, ref) {
1296
+ const [selected, setSelected] = useControlled({
1297
+ controlled: selectedValue,
1298
+ default: defaultSelectedValue ?? null,
1299
+ onChange: onSelectionChange
1300
+ });
1301
+ const [expandedList, setExpandedList] = useControlled({
1302
+ controlled: expanded,
1303
+ default: defaultExpanded ?? [],
1304
+ onChange: onExpandedChange
1305
+ });
1306
+ const expandedSet = useMemo(() => new Set(expandedList), [expandedList]);
1307
+ const toggleExpanded = useCallback(
1308
+ (value) => {
1309
+ const next = new Set(expandedSet);
1310
+ if (next.has(value)) next.delete(value);
1311
+ else next.add(value);
1312
+ setExpandedList(Array.from(next));
1313
+ },
1314
+ [expandedSet, setExpandedList]
1315
+ );
1316
+ const ctx = useMemo(
1317
+ () => ({
1318
+ selectedValue: selected,
1319
+ setSelectedValue: setSelected,
1320
+ expanded: expandedSet,
1321
+ toggleExpanded
1322
+ }),
1323
+ [selected, setSelected, expandedSet, toggleExpanded]
1324
+ );
1325
+ return /* @__PURE__ */ jsx(TreeContext.Provider, { value: ctx, children: /* @__PURE__ */ jsx(
1326
+ RovingFocusGroup,
1327
+ {
1328
+ ref,
1329
+ orientation: "vertical",
1330
+ loop: true,
1331
+ role: "tree",
1332
+ className: cn("flex flex-col text-sm", className),
1333
+ ...rest,
1334
+ children
1335
+ }
1336
+ ) });
1337
+ });
1338
+ function NodeRow({
1339
+ level,
1340
+ selected,
1341
+ expanded,
1342
+ hasChildren,
1343
+ disabled,
1344
+ onActivate,
1345
+ label
1346
+ }) {
1347
+ const roving = useRovingFocusItem();
1348
+ const handleKeyDown = useCallback(
1349
+ (e) => {
1350
+ roving.onKeyDown(e);
1351
+ if (e.defaultPrevented || disabled) return;
1352
+ if (e.key === "Enter" || e.key === " ") {
1353
+ e.preventDefault();
1354
+ onActivate();
1355
+ }
1356
+ },
1357
+ [roving, disabled, onActivate]
1358
+ );
1359
+ return /* @__PURE__ */ jsxs(
1360
+ "div",
1361
+ {
1362
+ ref: roving.ref,
1363
+ role: "treeitem",
1364
+ "aria-level": level,
1365
+ "aria-selected": selected || void 0,
1366
+ "aria-expanded": hasChildren ? expanded : void 0,
1367
+ "aria-disabled": disabled || void 0,
1368
+ "data-selected": dataAttr(selected),
1369
+ "data-disabled": dataAttr(disabled),
1370
+ tabIndex: roving.tabIndex,
1371
+ onFocus: roving.onFocus,
1372
+ onKeyDown: handleKeyDown,
1373
+ onClick: () => {
1374
+ if (!disabled) onActivate();
1375
+ },
1376
+ style: { paddingLeft: `${(level - 1) * 16}px` },
1377
+ className: cn(
1378
+ "flex cursor-pointer items-center gap-1 rounded-sm px-2 py-1 transition-colors",
1379
+ "hover:bg-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
1380
+ selected && "bg-primary-soft text-primary-soft-foreground",
1381
+ disabled && "pointer-events-none opacity-50"
1382
+ ),
1383
+ children: [
1384
+ hasChildren ? /* @__PURE__ */ jsx(
1385
+ ChevronRight,
1386
+ {
1387
+ className: cn(
1388
+ "h-4 w-4 shrink-0 text-muted-foreground transition-transform",
1389
+ expanded && "rotate-90"
1390
+ )
1391
+ }
1392
+ ) : /* @__PURE__ */ jsx("span", { className: "w-4 shrink-0" }),
1393
+ /* @__PURE__ */ jsx("span", { className: "flex-1 truncate", children: label })
1394
+ ]
1395
+ }
1396
+ );
1397
+ }
1398
+ var TreeGroup = forwardRef(function TreeGroup2({ value, label, disabled = false, className, children, ...rest }, ref) {
1399
+ const ctx = useTreeContext();
1400
+ const level = useTreeLevel();
1401
+ const expanded = ctx.expanded.has(value);
1402
+ return /* @__PURE__ */ jsxs(
1403
+ "li",
1404
+ {
1405
+ ref,
1406
+ role: "presentation",
1407
+ "data-state": expanded ? "open" : "closed",
1408
+ className: cn("list-none", className),
1409
+ ...rest,
1410
+ children: [
1411
+ /* @__PURE__ */ jsx(
1412
+ NodeRow,
1413
+ {
1414
+ level,
1415
+ selected: false,
1416
+ expanded,
1417
+ hasChildren: true,
1418
+ disabled,
1419
+ onActivate: () => ctx.toggleExpanded(value),
1420
+ label
1421
+ }
1422
+ ),
1423
+ expanded && /* @__PURE__ */ jsx(TreeLevelContext.Provider, { value: { level: level + 1 }, children: /* @__PURE__ */ jsx("ul", { role: "group", className: "flex flex-col", children }) })
1424
+ ]
1425
+ }
1426
+ );
1427
+ });
1428
+ var TreeItem = forwardRef(function TreeItem2({ value, disabled = false, className, children, ...rest }, ref) {
1429
+ const ctx = useTreeContext();
1430
+ const level = useTreeLevel();
1431
+ const selected = ctx.selectedValue === value;
1432
+ return /* @__PURE__ */ jsx("li", { ref, role: "presentation", className: cn("list-none", className), ...rest, children: /* @__PURE__ */ jsx(
1433
+ NodeRow,
1434
+ {
1435
+ level,
1436
+ selected,
1437
+ hasChildren: false,
1438
+ disabled,
1439
+ onActivate: () => ctx.setSelectedValue(value),
1440
+ label: children
1441
+ }
1442
+ ) });
1443
+ });
1444
+ Tree.Group = TreeGroup;
1445
+ Tree.Item = TreeItem;
1446
+ var TableContext = createContext({
1447
+ striped: false,
1448
+ hoverable: false,
1449
+ density: "cozy"
1450
+ });
1451
+ var DENSITY_CELL = {
1452
+ compact: "px-2 py-1.5 text-sm",
1453
+ cozy: "px-3 py-2 text-sm",
1454
+ comfortable: "px-4 py-3 text-sm"
1455
+ };
1456
+ var Table = forwardRef(function Table2({ striped = false, hoverable = false, density = "cozy", bare = false, className, children, ...rest }, ref) {
1457
+ const ctx = { striped, hoverable, density };
1458
+ const tableEl = /* @__PURE__ */ jsx(
1459
+ "table",
1460
+ {
1461
+ ref,
1462
+ className: cn("w-full caption-bottom border-collapse text-left", className),
1463
+ ...rest,
1464
+ children
1465
+ }
1466
+ );
1467
+ return /* @__PURE__ */ jsx(TableContext.Provider, { value: ctx, children: bare ? tableEl : /* @__PURE__ */ jsx("div", { className: "relative w-full overflow-x-auto rounded-md border border-border", children: tableEl }) });
1468
+ });
1469
+ var TableHead = forwardRef(
1470
+ function TableHead2({ className, ...rest }, ref) {
1471
+ return /* @__PURE__ */ jsx(
1472
+ "thead",
1473
+ {
1474
+ ref,
1475
+ className: cn("border-b border-border bg-muted/50 text-xs font-semibold uppercase tracking-wide text-muted-foreground", className),
1476
+ ...rest
1477
+ }
1478
+ );
1479
+ }
1480
+ );
1481
+ var TableBody = forwardRef(
1482
+ function TableBody2({ className, ...rest }, ref) {
1483
+ const ctx = useContext(TableContext);
1484
+ return /* @__PURE__ */ jsx(
1485
+ "tbody",
1486
+ {
1487
+ ref,
1488
+ className: cn(
1489
+ ctx.striped && "[&>tr:nth-child(even)]:bg-muted/30",
1490
+ ctx.hoverable && "[&>tr:hover]:bg-muted",
1491
+ className
1492
+ ),
1493
+ ...rest
1494
+ }
1495
+ );
1496
+ }
1497
+ );
1498
+ var TableFooter = forwardRef(
1499
+ function TableFooter2({ className, ...rest }, ref) {
1500
+ return /* @__PURE__ */ jsx(
1501
+ "tfoot",
1502
+ {
1503
+ ref,
1504
+ className: cn("border-t border-border bg-muted/50 font-medium", className),
1505
+ ...rest
1506
+ }
1507
+ );
1508
+ }
1509
+ );
1510
+ var TableRow = forwardRef(
1511
+ function TableRow2({ className, ...rest }, ref) {
1512
+ return /* @__PURE__ */ jsx(
1513
+ "tr",
1514
+ {
1515
+ ref,
1516
+ className: cn("border-b border-border last:border-0 transition-colors data-[selected]:bg-primary-soft", className),
1517
+ ...rest
1518
+ }
1519
+ );
1520
+ }
1521
+ );
1522
+ var TableHeaderCell = forwardRef(
1523
+ function TableHeaderCell2({ className, ...rest }, ref) {
1524
+ const ctx = useContext(TableContext);
1525
+ return /* @__PURE__ */ jsx(
1526
+ "th",
1527
+ {
1528
+ ref,
1529
+ scope: "col",
1530
+ className: cn(DENSITY_CELL[ctx.density], "font-semibold text-foreground", className),
1531
+ ...rest
1532
+ }
1533
+ );
1534
+ }
1535
+ );
1536
+ var TableCell = forwardRef(function TableCell2({ className, ...rest }, ref) {
1537
+ const ctx = useContext(TableContext);
1538
+ return /* @__PURE__ */ jsx(
1539
+ "td",
1540
+ {
1541
+ ref,
1542
+ className: cn(DENSITY_CELL[ctx.density], "align-middle", className),
1543
+ ...rest
1544
+ }
1545
+ );
1546
+ });
1547
+ var TableCaption = forwardRef(function TableCaption2({ className, ...rest }, ref) {
1548
+ return /* @__PURE__ */ jsx(
1549
+ "caption",
1550
+ {
1551
+ ref,
1552
+ className: cn("mt-2 text-sm text-muted-foreground", className),
1553
+ ...rest
1554
+ }
1555
+ );
1556
+ });
1557
+ Table.Head = TableHead;
1558
+ Table.Body = TableBody;
1559
+ Table.Footer = TableFooter;
1560
+ Table.Row = TableRow;
1561
+ Table.HeaderCell = TableHeaderCell;
1562
+ Table.Cell = TableCell;
1563
+ Table.Caption = TableCaption;
1564
+ function defaultCompare(a, b) {
1565
+ if (a === b) return 0;
1566
+ if (a === null || a === void 0) return 1;
1567
+ if (b === null || b === void 0) return -1;
1568
+ if (typeof a === "number" && typeof b === "number") return a - b;
1569
+ if (a instanceof Date && b instanceof Date) return a.getTime() - b.getTime();
1570
+ return String(a).localeCompare(String(b));
1571
+ }
1572
+ function DataTable({
1573
+ columns,
1574
+ data,
1575
+ rowKey,
1576
+ onRowClick,
1577
+ sortBy,
1578
+ defaultSortBy,
1579
+ onSortChange,
1580
+ striped,
1581
+ hoverable = !!onRowClick,
1582
+ density,
1583
+ bare,
1584
+ emptyContent = "No results.",
1585
+ className,
1586
+ "aria-label": ariaLabel
1587
+ }) {
1588
+ const [sort, setSort] = useControlled({
1589
+ controlled: sortBy,
1590
+ default: defaultSortBy ?? null,
1591
+ onChange: onSortChange
1592
+ });
1593
+ const sortedData = useMemo(() => {
1594
+ if (!sort) return data;
1595
+ const col = columns.find((c) => c.key === sort.columnKey);
1596
+ if (!col?.accessor) return data;
1597
+ const accessor = col.accessor;
1598
+ const sorted = [...data].sort((a, b) => {
1599
+ const r = defaultCompare(accessor(a), accessor(b));
1600
+ return sort.direction === "asc" ? r : -r;
1601
+ });
1602
+ return sorted;
1603
+ }, [data, columns, sort]);
1604
+ const cycleSort = (columnKey) => {
1605
+ if (!sort || sort.columnKey !== columnKey) {
1606
+ setSort({ columnKey, direction: "asc" });
1607
+ } else if (sort.direction === "asc") {
1608
+ setSort({ columnKey, direction: "desc" });
1609
+ } else {
1610
+ setSort(null);
1611
+ }
1612
+ };
1613
+ const alignClass = (a) => a === "right" ? "text-right" : a === "center" ? "text-center" : "text-left";
1614
+ return /* @__PURE__ */ jsxs(
1615
+ Table,
1616
+ {
1617
+ striped,
1618
+ hoverable,
1619
+ density,
1620
+ bare,
1621
+ className,
1622
+ "aria-label": ariaLabel,
1623
+ children: [
1624
+ /* @__PURE__ */ jsx(TableHead, { children: /* @__PURE__ */ jsx(TableRow, { children: columns.map((col) => {
1625
+ const isSorted = sort?.columnKey === col.key;
1626
+ const ariaSort = isSorted ? sort?.direction === "asc" ? "ascending" : "descending" : col.sortable ? "none" : void 0;
1627
+ return /* @__PURE__ */ jsx(
1628
+ TableHeaderCell,
1629
+ {
1630
+ "aria-sort": ariaSort,
1631
+ style: col.width ? { width: col.width } : void 0,
1632
+ className: alignClass(col.align),
1633
+ children: col.sortable ? /* @__PURE__ */ jsxs(
1634
+ "button",
1635
+ {
1636
+ type: "button",
1637
+ onClick: () => cycleSort(col.key),
1638
+ className: cn(
1639
+ "inline-flex items-center gap-1 rounded-sm transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
1640
+ ),
1641
+ children: [
1642
+ /* @__PURE__ */ jsx("span", { children: col.header }),
1643
+ isSorted ? sort?.direction === "asc" ? /* @__PURE__ */ jsx(ArrowUp, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ jsx(ArrowDown, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ jsx(ArrowUpDown, { className: "h-3.5 w-3.5 opacity-50" })
1644
+ ]
1645
+ }
1646
+ ) : col.header
1647
+ },
1648
+ col.key
1649
+ );
1650
+ }) }) }),
1651
+ /* @__PURE__ */ jsx(TableBody, { children: sortedData.length === 0 ? /* @__PURE__ */ jsx(TableRow, { children: /* @__PURE__ */ jsx(TableCell, { colSpan: columns.length, className: "py-8 text-center text-muted-foreground", children: emptyContent }) }) : sortedData.map((row, rowIndex) => {
1652
+ const key = rowKey ? rowKey(row, rowIndex) : rowIndex;
1653
+ return /* @__PURE__ */ jsx(
1654
+ TableRow,
1655
+ {
1656
+ onClick: onRowClick ? () => onRowClick(row, rowIndex) : void 0,
1657
+ className: cn(onRowClick && "cursor-pointer"),
1658
+ children: columns.map((col) => /* @__PURE__ */ jsx(TableCell, { className: alignClass(col.align), children: col.cell ? col.cell(row, rowIndex) : col.accessor ? col.accessor(row) : null }, col.key))
1659
+ },
1660
+ key
1661
+ );
1662
+ }) })
1663
+ ]
1664
+ }
1665
+ );
1666
+ }
1667
+
1668
+ export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, Avatar, AvatarGroup, Badge, BadgeOverlay, Card, Code, Collapsible, CollapsibleContent, CollapsibleTrigger, CountBadge, DataTable, DescriptionList, EmptyState, Heading, Highlight, Image, InfoRow, Kbd, KeyboardShortcut, List, ListItem, Mark, NotificationDot, Quote, SectionHeader, Separator, Snippet, Stat, Status, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeaderCell, TableRow, Tabs, TabsList, TabsPanel, TabsTab, Tag, Text, Timeline, TimelineDescription, TimelineItem, TimelineTitle, Tooltip, Tree, TreeGroup, TreeItem, avatarVariants, badgeVariants, codeVariants, headingVariants, tagVariants, textVariants };
1669
+ //# sourceMappingURL=chunk-ASXB42MH.js.map
1670
+ //# sourceMappingURL=chunk-ASXB42MH.js.map