@timbal-ai/timbal-react 1.4.0 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/README.md +43 -4
  3. package/dist/app.cjs +3770 -1506
  4. package/dist/app.d.cts +76 -31
  5. package/dist/app.d.ts +76 -31
  6. package/dist/app.esm.js +30 -8
  7. package/dist/{chart-artifact-C8-Py6lc.d.cts → chart-artifact-C2pZQsaP.d.ts} +247 -41
  8. package/dist/{chart-artifact-CMnDys2t.d.ts → chart-artifact-VAqgH-My.d.cts} +247 -41
  9. package/dist/{chat-ClmzWzCX.d.cts → chat-DDsp-Vzz.d.cts} +1 -1
  10. package/dist/{chat-ClmzWzCX.d.ts → chat-DDsp-Vzz.d.ts} +1 -1
  11. package/dist/chat.cjs +280 -123
  12. package/dist/chat.d.cts +3 -3
  13. package/dist/chat.d.ts +3 -3
  14. package/dist/chat.esm.js +4 -3
  15. package/dist/chunk-24B4I4XC.esm.js +232 -0
  16. package/dist/{chunk-VOWNCS3F.esm.js → chunk-6SQMTBPL.esm.js} +1669 -504
  17. package/dist/chunk-EDEKQYSU.esm.js +10 -0
  18. package/dist/{chunk-QIABF4KB.esm.js → chunk-ELEY66OH.esm.js} +2 -2
  19. package/dist/{chunk-THBA27QY.esm.js → chunk-HSL36SJ4.esm.js} +243 -124
  20. package/dist/chunk-JJOO4PR5.esm.js +391 -0
  21. package/dist/{chunk-QU7ET55D.esm.js → chunk-MBS7XHV2.esm.js} +335 -192
  22. package/dist/chunk-NO5AWNWT.esm.js +1066 -0
  23. package/dist/{chunk-VXMM2HX7.esm.js → chunk-R4RQT2XQ.esm.js} +3 -3
  24. package/dist/{chunk-OFWC4MIY.esm.js → chunk-TMP7RIA7.esm.js} +5 -3
  25. package/dist/{chunk-GQBYZRD7.esm.js → chunk-WQIQW7EM.esm.js} +40 -28
  26. package/dist/{chunk-OH23AX2V.esm.js → chunk-YYEI6XME.esm.js} +441 -957
  27. package/dist/{circular-progress-Ci8L-Hfa.d.cts → circular-progress-B9nnwzCu.d.cts} +20 -78
  28. package/dist/{circular-progress-Ci8L-Hfa.d.ts → circular-progress-B9nnwzCu.d.ts} +20 -78
  29. package/dist/index.cjs +5547 -3192
  30. package/dist/index.d.cts +10 -8
  31. package/dist/index.d.ts +10 -8
  32. package/dist/index.esm.js +76 -44
  33. package/dist/kanban-FFBeaZPS.d.cts +212 -0
  34. package/dist/kanban-FFBeaZPS.d.ts +212 -0
  35. package/dist/{layout-BTJyU8wd.d.ts → layout-CuKeSY74.d.ts} +1 -1
  36. package/dist/{layout-C2G-FcER.d.cts → layout-PzVwkJyL.d.cts} +1 -1
  37. package/dist/site.cjs +429 -0
  38. package/dist/site.d.cts +198 -0
  39. package/dist/site.d.ts +198 -0
  40. package/dist/site.esm.js +23 -0
  41. package/dist/studio.cjs +722 -363
  42. package/dist/studio.d.cts +2 -2
  43. package/dist/studio.d.ts +2 -2
  44. package/dist/studio.esm.js +8 -6
  45. package/dist/styles.css +56 -0
  46. package/dist/{timbal-v2-button-CNfdwGq4.d.cts → timbal-v2-button-DCAZNyUx.d.cts} +3 -3
  47. package/dist/{timbal-v2-button-CNfdwGq4.d.ts → timbal-v2-button-DCAZNyUx.d.ts} +3 -3
  48. package/dist/ui.cjs +1553 -708
  49. package/dist/ui.d.cts +11 -4
  50. package/dist/ui.d.ts +11 -4
  51. package/dist/ui.esm.js +45 -36
  52. package/dist/{welcome-DXqsGTwH.d.ts → welcome-B00oH5Io.d.cts} +5 -1
  53. package/dist/{welcome-BFGRoNfK.d.cts → welcome-DU-4NTjZ.d.ts} +5 -1
  54. package/package.json +9 -1
  55. package/dist/button-BoyX5pM_.d.cts +0 -18
  56. package/dist/button-BoyX5pM_.d.ts +0 -18
  57. package/dist/chunk-UCGVL7ZY.esm.js +0 -52
@@ -0,0 +1,1066 @@
1
+ import {
2
+ controlClass,
3
+ overlayItemClass,
4
+ overlayListPanelClass,
5
+ overlaySurfaceClass
6
+ } from "./chunk-MBS7XHV2.esm.js";
7
+ import {
8
+ cn
9
+ } from "./chunk-EDEKQYSU.esm.js";
10
+
11
+ // src/ui/copy-button.tsx
12
+ import * as React from "react";
13
+ import { CheckIcon, CopyIcon } from "lucide-react";
14
+ import { jsx, jsxs } from "react/jsx-runtime";
15
+ function CopyButton({
16
+ value,
17
+ timeout = 1500,
18
+ onCopied,
19
+ className,
20
+ children,
21
+ onClick,
22
+ ...props
23
+ }) {
24
+ const [copied, setCopied] = React.useState(false);
25
+ const timer = React.useRef(void 0);
26
+ React.useEffect(() => () => clearTimeout(timer.current), []);
27
+ const handleClick = async (event) => {
28
+ onClick?.(event);
29
+ if (event.defaultPrevented) return;
30
+ try {
31
+ await navigator.clipboard.writeText(value);
32
+ setCopied(true);
33
+ onCopied?.(value);
34
+ clearTimeout(timer.current);
35
+ timer.current = setTimeout(() => setCopied(false), timeout);
36
+ } catch {
37
+ }
38
+ };
39
+ const Icon = copied ? CheckIcon : CopyIcon;
40
+ return /* @__PURE__ */ jsxs(
41
+ "button",
42
+ {
43
+ type: "button",
44
+ "data-slot": "copy-button",
45
+ "data-copied": copied || void 0,
46
+ "aria-label": copied ? "Copied" : "Copy",
47
+ onClick: handleClick,
48
+ className: cn(
49
+ "inline-flex items-center justify-center gap-1.5 rounded-md text-sm font-medium text-muted-foreground transition-colors",
50
+ "hover:bg-accent hover:text-foreground data-[copied=true]:text-emerald-600 dark:data-[copied=true]:text-emerald-400",
51
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-foreground/15",
52
+ children ? "h-7 px-1.5" : "size-7",
53
+ className
54
+ ),
55
+ ...props,
56
+ children: [
57
+ /* @__PURE__ */ jsx(Icon, { className: "size-4 shrink-0", "aria-hidden": true }),
58
+ children
59
+ ]
60
+ }
61
+ );
62
+ }
63
+
64
+ // src/ui/checkbox.tsx
65
+ import { Checkbox as CheckboxPrimitive } from "radix-ui";
66
+ import { CheckIcon as CheckIcon2 } from "lucide-react";
67
+ import { jsx as jsx2 } from "react/jsx-runtime";
68
+ function Checkbox({
69
+ className,
70
+ ...props
71
+ }) {
72
+ return /* @__PURE__ */ jsx2(
73
+ CheckboxPrimitive.Root,
74
+ {
75
+ "data-slot": "checkbox",
76
+ className: cn(
77
+ "peer size-4 shrink-0 rounded-[4px] border border-border bg-gradient-to-b from-elevated-from to-elevated-to shadow-card outline-none transition-[box-shadow,background-color,border-color]",
78
+ "focus-visible:ring-2 focus-visible:ring-foreground/10 disabled:cursor-not-allowed disabled:opacity-50",
79
+ "data-[state=checked]:border-foreground/15 data-[state=checked]:from-primary-fill-from data-[state=checked]:to-primary-fill-to data-[state=checked]:text-primary-foreground",
80
+ className
81
+ ),
82
+ ...props,
83
+ children: /* @__PURE__ */ jsx2(
84
+ CheckboxPrimitive.Indicator,
85
+ {
86
+ "data-slot": "checkbox-indicator",
87
+ className: "flex items-center justify-center text-current animate-checkbox-pop",
88
+ children: /* @__PURE__ */ jsx2(CheckIcon2, { className: "size-2.5 stroke-[3.5px]" })
89
+ }
90
+ )
91
+ }
92
+ );
93
+ }
94
+
95
+ // src/ui/select.tsx
96
+ import { Select as SelectPrimitive } from "radix-ui";
97
+ import { CheckIcon as CheckIcon3, ChevronDownIcon, ChevronUpIcon } from "lucide-react";
98
+ import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
99
+ function Select({
100
+ ...props
101
+ }) {
102
+ return /* @__PURE__ */ jsx3(SelectPrimitive.Root, { "data-slot": "select", ...props });
103
+ }
104
+ function SelectGroup({
105
+ ...props
106
+ }) {
107
+ return /* @__PURE__ */ jsx3(SelectPrimitive.Group, { "data-slot": "select-group", ...props });
108
+ }
109
+ function SelectValue({
110
+ ...props
111
+ }) {
112
+ return /* @__PURE__ */ jsx3(SelectPrimitive.Value, { "data-slot": "select-value", ...props });
113
+ }
114
+ function SelectTrigger({
115
+ className,
116
+ size = "default",
117
+ children,
118
+ ...props
119
+ }) {
120
+ return /* @__PURE__ */ jsxs2(
121
+ SelectPrimitive.Trigger,
122
+ {
123
+ "data-slot": "select-trigger",
124
+ "data-size": size,
125
+ className: cn(
126
+ controlClass({ size }),
127
+ "flex w-fit items-center justify-between gap-2 whitespace-nowrap *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground",
128
+ className
129
+ ),
130
+ ...props,
131
+ children: [
132
+ children,
133
+ /* @__PURE__ */ jsx3(SelectPrimitive.Icon, { asChild: true, children: /* @__PURE__ */ jsx3(ChevronDownIcon, { className: "size-4 opacity-50" }) })
134
+ ]
135
+ }
136
+ );
137
+ }
138
+ function SelectContent({
139
+ className,
140
+ children,
141
+ position = "popper",
142
+ ...props
143
+ }) {
144
+ return /* @__PURE__ */ jsx3(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsxs2(
145
+ SelectPrimitive.Content,
146
+ {
147
+ "data-slot": "select-content",
148
+ className: cn(
149
+ overlayListPanelClass,
150
+ "relative max-h-[var(--radix-select-content-available-height)] min-w-[8rem] origin-[var(--radix-select-content-transform-origin)] overflow-x-hidden overflow-y-auto",
151
+ position === "popper" && "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
152
+ className
153
+ ),
154
+ position,
155
+ ...props,
156
+ children: [
157
+ /* @__PURE__ */ jsx3(SelectScrollUpButton, {}),
158
+ /* @__PURE__ */ jsx3(
159
+ SelectPrimitive.Viewport,
160
+ {
161
+ className: cn(
162
+ "p-1",
163
+ position === "popper" && "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)] scroll-my-1"
164
+ ),
165
+ children
166
+ }
167
+ ),
168
+ /* @__PURE__ */ jsx3(SelectScrollDownButton, {})
169
+ ]
170
+ }
171
+ ) });
172
+ }
173
+ function SelectLabel({
174
+ className,
175
+ ...props
176
+ }) {
177
+ return /* @__PURE__ */ jsx3(
178
+ SelectPrimitive.Label,
179
+ {
180
+ "data-slot": "select-label",
181
+ className: cn("px-2 py-1.5 text-xs font-medium text-muted-foreground", className),
182
+ ...props
183
+ }
184
+ );
185
+ }
186
+ function SelectItem({
187
+ className,
188
+ children,
189
+ ...props
190
+ }) {
191
+ return /* @__PURE__ */ jsxs2(
192
+ SelectPrimitive.Item,
193
+ {
194
+ "data-slot": "select-item",
195
+ className: cn(
196
+ overlayItemClass,
197
+ "w-full py-1 pr-8 pl-2 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2",
198
+ className
199
+ ),
200
+ ...props,
201
+ children: [
202
+ /* @__PURE__ */ jsx3("span", { className: "absolute right-2 flex size-3.5 items-center justify-center", children: /* @__PURE__ */ jsx3(SelectPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx3(CheckIcon3, { className: "size-4" }) }) }),
203
+ /* @__PURE__ */ jsx3(SelectPrimitive.ItemText, { children })
204
+ ]
205
+ }
206
+ );
207
+ }
208
+ function SelectSeparator({
209
+ className,
210
+ ...props
211
+ }) {
212
+ return /* @__PURE__ */ jsx3(
213
+ SelectPrimitive.Separator,
214
+ {
215
+ "data-slot": "select-separator",
216
+ className: cn("-mx-1 my-1 h-px bg-border", className),
217
+ ...props
218
+ }
219
+ );
220
+ }
221
+ function SelectScrollUpButton({
222
+ className,
223
+ ...props
224
+ }) {
225
+ return /* @__PURE__ */ jsx3(
226
+ SelectPrimitive.ScrollUpButton,
227
+ {
228
+ "data-slot": "select-scroll-up-button",
229
+ className: cn("flex cursor-default items-center justify-center py-1", className),
230
+ ...props,
231
+ children: /* @__PURE__ */ jsx3(ChevronUpIcon, { className: "size-4" })
232
+ }
233
+ );
234
+ }
235
+ function SelectScrollDownButton({
236
+ className,
237
+ ...props
238
+ }) {
239
+ return /* @__PURE__ */ jsx3(
240
+ SelectPrimitive.ScrollDownButton,
241
+ {
242
+ "data-slot": "select-scroll-down-button",
243
+ className: cn("flex cursor-default items-center justify-center py-1", className),
244
+ ...props,
245
+ children: /* @__PURE__ */ jsx3(ChevronDownIcon, { className: "size-4" })
246
+ }
247
+ );
248
+ }
249
+
250
+ // src/ui/popover.tsx
251
+ import { Popover as PopoverPrimitive } from "radix-ui";
252
+ import { jsx as jsx4 } from "react/jsx-runtime";
253
+ function Popover({
254
+ ...props
255
+ }) {
256
+ return /* @__PURE__ */ jsx4(PopoverPrimitive.Root, { "data-slot": "popover", ...props });
257
+ }
258
+ function PopoverTrigger({
259
+ ...props
260
+ }) {
261
+ return /* @__PURE__ */ jsx4(PopoverPrimitive.Trigger, { "data-slot": "popover-trigger", ...props });
262
+ }
263
+ function PopoverAnchor({
264
+ ...props
265
+ }) {
266
+ return /* @__PURE__ */ jsx4(PopoverPrimitive.Anchor, { "data-slot": "popover-anchor", ...props });
267
+ }
268
+ function PopoverContent({
269
+ className,
270
+ align = "center",
271
+ sideOffset = 4,
272
+ variant = "default",
273
+ ...props
274
+ }) {
275
+ return /* @__PURE__ */ jsx4(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx4(
276
+ PopoverPrimitive.Content,
277
+ {
278
+ "data-slot": "popover-content",
279
+ "data-variant": variant,
280
+ align,
281
+ sideOffset,
282
+ className: cn(
283
+ variant === "list" ? cn(
284
+ overlayListPanelClass,
285
+ "min-w-[8rem] origin-[var(--radix-popover-content-transform-origin)]"
286
+ ) : cn(
287
+ overlaySurfaceClass,
288
+ "w-72 origin-[var(--radix-popover-content-transform-origin)] rounded-xl p-3 outline-hidden"
289
+ ),
290
+ className
291
+ ),
292
+ ...props
293
+ }
294
+ ) });
295
+ }
296
+
297
+ // src/ui/skeleton.tsx
298
+ import { jsx as jsx5 } from "react/jsx-runtime";
299
+ function Skeleton({ className, ...props }) {
300
+ return /* @__PURE__ */ jsx5(
301
+ "div",
302
+ {
303
+ "data-slot": "skeleton",
304
+ className: cn("animate-pulse rounded-lg bg-muted", className),
305
+ ...props
306
+ }
307
+ );
308
+ }
309
+
310
+ // src/ui/untitled-button.tsx
311
+ import { cva } from "class-variance-authority";
312
+ import { Slot } from "radix-ui";
313
+ import { jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
314
+ var SOLID_SKEUOMORPHIC_SHADOW = "shadow-skeuomorphic-solid";
315
+ var BORDERED_SKEUOMORPHIC_SHADOW = "shadow-skeuomorphic-bordered";
316
+ var untitledButtonVariants = cva(
317
+ cn(
318
+ "relative inline-flex shrink-0 cursor-pointer select-none items-center justify-center whitespace-nowrap font-medium",
319
+ "transition-all duration-300 ease-in-out outline-none border",
320
+ "focus-visible:ring-4 focus-visible:ring-primary/20 focus-visible:ring-offset-0",
321
+ "disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50",
322
+ "[&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-5",
323
+ // Overflow hidden can clip out-of-bounds shadow, so we use precise overflow management and rounded-[inherit] on pseudo overlays
324
+ "after:absolute after:inset-0 after:rounded-[inherit] after:pointer-events-none after:transition-opacity after:duration-300 after:ease-in-out after:opacity-0"
325
+ ),
326
+ {
327
+ variants: {
328
+ color: {
329
+ primary: cn(
330
+ // Exact Premium Untitled UI primary BLACK / dark charcoal: gradient + borders
331
+ "bg-gradient-to-b from-[#344054] to-[#0F1117] text-white border-[#1A1E29]",
332
+ "hover:border-[#181C26]",
333
+ "active:border-[#0A0D14]",
334
+ SOLID_SKEUOMORPHIC_SHADOW,
335
+ // Hover/active overlays for beautiful animation (the gradient is static, the overlay opacity is transitioned)
336
+ "after:bg-white/[0.08] hover:after:opacity-100 active:after:bg-black/[0.12]",
337
+ // Premium Dark Mode inversion: Primary becomes white, popping out elegantly
338
+ "dark:bg-gradient-to-b dark:from-white dark:to-[#F9FAFB] dark:text-[#10121C] dark:border-white",
339
+ "dark:hover:border-[#D0D5DD] dark:hover:text-[#10121C]",
340
+ "dark:shadow-skeuomorphic-bordered",
341
+ "dark:after:bg-black/[0.04] dark:active:after:bg-black/[0.08]"
342
+ ),
343
+ secondary: cn(
344
+ // Exact Untitled UI secondary: premium white/gray gradient + borders
345
+ "bg-gradient-to-b from-white to-[#F9FAFB] text-[#344054] border-[#D0D5DD]",
346
+ "hover:text-[#1D2939] hover:border-[#D0D5DD]",
347
+ BORDERED_SKEUOMORPHIC_SHADOW,
348
+ // Hover/active overlays for white/gray gradient
349
+ "after:bg-black/[0.03] hover:after:opacity-100 active:after:bg-black/[0.08]",
350
+ // Premium Dark Mode inversion: Secondary becomes dark charcoal/gray, merging into the background
351
+ "dark:bg-gradient-to-b dark:from-[#1F242F] dark:to-[#10121C] dark:text-[#D1D5DB] dark:border-[#344054]",
352
+ "dark:hover:border-[#475467] dark:hover:text-white",
353
+ "dark:shadow-skeuomorphic-solid",
354
+ "dark:after:bg-white/[0.06] dark:active:after:bg-black/[0.15]"
355
+ ),
356
+ tertiary: cn(
357
+ "bg-transparent text-[#475467] border-transparent",
358
+ "hover:bg-[#F9FAFB] hover:text-[#344054]",
359
+ "active:bg-[#F2F4F7] active:text-[#1D2939]",
360
+ "after:hidden",
361
+ // No overlay needed for transparent surfaces
362
+ // Dark Mode
363
+ "dark:text-[#9CA3AF] dark:hover:bg-[#1F242F] dark:hover:text-white dark:active:bg-[#11131A]"
364
+ ),
365
+ link: cn(
366
+ "h-auto! bg-transparent p-0! border-transparent text-[#1F242F] hover:text-[#10121C]",
367
+ "hover:underline",
368
+ "after:hidden",
369
+ // Dark Mode
370
+ "dark:text-[#9CA3AF] dark:hover:text-white"
371
+ ),
372
+ "primary-destructive": cn(
373
+ // Exact Untitled UI primary destructive: premium red gradient + borders (vibrant and subtle, not too dark)
374
+ "bg-gradient-to-b from-[#D92D20] to-[#B42318] text-white border-[#B42318]",
375
+ "hover:border-[#9E1B12]",
376
+ "active:border-[#84140D]",
377
+ SOLID_SKEUOMORPHIC_SHADOW,
378
+ // Destructive red hover/active overlays
379
+ "after:bg-white/[0.12] hover:after:opacity-100 active:after:bg-black/[0.15]"
380
+ ),
381
+ "secondary-destructive": cn(
382
+ // Exact Untitled UI secondary destructive: soft red bordered
383
+ "bg-gradient-to-b from-white to-[#F9FAFB] text-[#B42318] border-[#FDA29B]",
384
+ "hover:text-[#9E1B12] hover:border-[#FDA29B]",
385
+ BORDERED_SKEUOMORPHIC_SHADOW,
386
+ // Hover overlay
387
+ "after:bg-red-500/[0.04] hover:after:opacity-100 active:after:bg-red-950/[0.08]",
388
+ // Dark Mode Secondary Destructive: Charcoal fill with red borders and label
389
+ "dark:bg-gradient-to-b dark:from-[#1F242F] dark:to-[#10121C] dark:text-[#F87171] dark:border-[#9E1B12]/50",
390
+ "dark:hover:border-[#F87171]/40",
391
+ "dark:shadow-skeuomorphic-solid",
392
+ "dark:after:bg-white/[0.06] dark:active:after:bg-black/[0.15]"
393
+ )
394
+ },
395
+ size: {
396
+ sm: "h-8 gap-1 rounded-md px-2.5 text-xs",
397
+ md: "h-9 gap-1.5 rounded-lg px-3 text-sm",
398
+ lg: "h-10 gap-1.5 rounded-lg px-3.5 text-sm",
399
+ xl: "h-11 gap-2 rounded-lg px-4 text-base"
400
+ }
401
+ },
402
+ defaultVariants: {
403
+ color: "primary",
404
+ size: "md"
405
+ }
406
+ }
407
+ );
408
+ function UntitledButton({
409
+ className,
410
+ color,
411
+ size,
412
+ iconLeading,
413
+ iconTrailing,
414
+ isLoading = false,
415
+ asChild = false,
416
+ disabled,
417
+ type = "button",
418
+ children,
419
+ ...props
420
+ }) {
421
+ const isDisabled = disabled || isLoading;
422
+ const classes = cn(untitledButtonVariants({ color, size }), className);
423
+ if (asChild) {
424
+ return /* @__PURE__ */ jsx6(
425
+ Slot.Root,
426
+ {
427
+ className: classes,
428
+ "aria-disabled": isDisabled ? true : void 0,
429
+ "data-slot": "untitled-button",
430
+ ...props,
431
+ children
432
+ }
433
+ );
434
+ }
435
+ return /* @__PURE__ */ jsxs3(
436
+ "button",
437
+ {
438
+ type,
439
+ disabled: isDisabled,
440
+ "data-slot": "untitled-button",
441
+ className: classes,
442
+ ...props,
443
+ children: [
444
+ isLoading ? /* @__PURE__ */ jsx6(
445
+ "span",
446
+ {
447
+ "aria-hidden": true,
448
+ className: "size-4 animate-spin rounded-full border-2 border-current border-t-transparent"
449
+ }
450
+ ) : iconLeading,
451
+ children,
452
+ !isLoading ? iconTrailing : null
453
+ ]
454
+ }
455
+ );
456
+ }
457
+
458
+ // src/ui/banner.tsx
459
+ import { XIcon } from "lucide-react";
460
+ import { jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
461
+ var bannerSoftClass = {
462
+ default: "border-border/50 bg-muted/30 text-foreground/90 dark:bg-muted/15",
463
+ primary: "border-primary/15 bg-primary/5 text-primary-800 dark:text-primary-200 [&_[data-banner-icon]]:text-primary",
464
+ success: "border-emerald-500/15 bg-emerald-500/5 text-emerald-800 dark:text-emerald-300 [&_[data-banner-icon]]:text-emerald-600 dark:[&_[data-banner-icon]]:text-emerald-400",
465
+ warn: "border-amber-500/15 bg-amber-500/5 text-amber-800 dark:text-amber-300 [&_[data-banner-icon]]:text-amber-600 dark:[&_[data-banner-icon]]:text-amber-400",
466
+ danger: "border-destructive/15 bg-destructive/5 text-destructive dark:text-red-300 [&_[data-banner-icon]]:text-destructive"
467
+ };
468
+ var bannerSolidClass = {
469
+ default: "border-transparent bg-foreground text-background shadow-sm",
470
+ primary: "border-transparent bg-gradient-to-r from-primary to-primary/95 text-primary-foreground shadow-sm shadow-primary/5",
471
+ success: "border-transparent bg-gradient-to-r from-emerald-600 to-emerald-500 text-white shadow-sm shadow-emerald-500/5 dark:from-emerald-500 dark:to-emerald-400",
472
+ warn: "border-transparent bg-gradient-to-r from-amber-500 to-amber-400 text-white shadow-sm shadow-amber-500/5 dark:from-amber-500 dark:to-amber-400",
473
+ danger: "border-transparent bg-gradient-to-r from-destructive to-destructive/95 text-destructive-foreground shadow-sm shadow-destructive/5"
474
+ };
475
+ var bannerOutlineClass = {
476
+ default: "border-border/80 bg-background/50 text-foreground/90 backdrop-blur-sm shadow-sm",
477
+ primary: "border-primary/30 bg-primary/[0.02] text-foreground [&_[data-banner-icon]]:text-primary shadow-sm",
478
+ success: "border-emerald-500/30 bg-emerald-500/[0.02] text-foreground [&_[data-banner-icon]]:text-emerald-600 dark:[&_[data-banner-icon]]:text-emerald-400 shadow-sm",
479
+ warn: "border-amber-500/30 bg-amber-500/[0.02] text-foreground [&_[data-banner-icon]]:text-amber-600 dark:[&_[data-banner-icon]]:text-amber-400 shadow-sm",
480
+ danger: "border-destructive/30 bg-destructive/[0.02] text-foreground [&_[data-banner-icon]]:text-destructive shadow-sm"
481
+ };
482
+ var bannerVariantClass = {
483
+ soft: bannerSoftClass,
484
+ solid: bannerSolidClass,
485
+ outline: bannerOutlineClass
486
+ };
487
+ var bannerSizeClass = {
488
+ sm: "gap-2.5 px-3.5 py-2 text-xs",
489
+ default: "gap-3 px-4 py-3 text-sm"
490
+ };
491
+ function Banner({
492
+ tone = "default",
493
+ variant = "soft",
494
+ size = "default",
495
+ icon,
496
+ title,
497
+ actions,
498
+ onDismiss,
499
+ className,
500
+ children,
501
+ ...props
502
+ }) {
503
+ const isSolid = variant === "solid";
504
+ const isSingleLine = !title;
505
+ return /* @__PURE__ */ jsxs4(
506
+ "div",
507
+ {
508
+ "data-slot": "banner",
509
+ "data-variant": variant,
510
+ role: "status",
511
+ className: cn(
512
+ "flex w-full rounded-xl border transition-all duration-200",
513
+ isSingleLine ? "items-center" : "items-start",
514
+ bannerSizeClass[size],
515
+ bannerVariantClass[variant][tone],
516
+ className
517
+ ),
518
+ ...props,
519
+ children: [
520
+ icon ? /* @__PURE__ */ jsx7(
521
+ "span",
522
+ {
523
+ "data-banner-icon": true,
524
+ className: cn(
525
+ "shrink-0 [&_svg]:size-4",
526
+ isSingleLine ? "self-center" : "mt-0.5"
527
+ ),
528
+ children: icon
529
+ }
530
+ ) : null,
531
+ /* @__PURE__ */ jsxs4("div", { className: "min-w-0 flex-1", children: [
532
+ title ? /* @__PURE__ */ jsx7("p", { className: "font-medium tracking-tight", children: title }) : null,
533
+ children ? /* @__PURE__ */ jsx7(
534
+ "div",
535
+ {
536
+ className: cn(
537
+ isSolid ? "opacity-90" : "text-muted-foreground",
538
+ title && "mt-0.5"
539
+ ),
540
+ children
541
+ }
542
+ ) : null
543
+ ] }),
544
+ actions ? /* @__PURE__ */ jsx7("div", { className: "flex shrink-0 items-center gap-2", children: actions }) : null,
545
+ onDismiss ? /* @__PURE__ */ jsx7(
546
+ "button",
547
+ {
548
+ type: "button",
549
+ "aria-label": "Dismiss",
550
+ onClick: onDismiss,
551
+ className: cn(
552
+ "-mr-1 inline-flex size-7 shrink-0 items-center justify-center rounded-md transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-foreground/15",
553
+ isSingleLine ? "self-center" : "-mt-0.5",
554
+ isSolid ? "opacity-80 hover:bg-background/15 hover:opacity-100" : "text-muted-foreground hover:bg-foreground/10 hover:text-foreground"
555
+ ),
556
+ children: /* @__PURE__ */ jsx7(XIcon, { className: "size-4", "aria-hidden": true })
557
+ }
558
+ ) : null
559
+ ]
560
+ }
561
+ );
562
+ }
563
+
564
+ // src/ui/timeline.tsx
565
+ import { jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
566
+ var timelineRowGap = {
567
+ sm: "pb-4",
568
+ default: "pb-6"
569
+ };
570
+ var toneStyles = {
571
+ default: {
572
+ border: "border-neutral-300 dark:border-neutral-700",
573
+ dot: "bg-neutral-400 dark:bg-neutral-500",
574
+ icon: "text-neutral-500 dark:text-neutral-400"
575
+ },
576
+ primary: {
577
+ border: "border-primary/50 dark:border-primary/40",
578
+ dot: "bg-primary",
579
+ icon: "text-primary"
580
+ },
581
+ success: {
582
+ border: "border-emerald-500/40 dark:border-emerald-500/30",
583
+ dot: "bg-emerald-500",
584
+ icon: "text-emerald-500"
585
+ },
586
+ warn: {
587
+ border: "border-amber-500/40 dark:border-amber-500/30",
588
+ dot: "bg-amber-500",
589
+ icon: "text-amber-500"
590
+ },
591
+ danger: {
592
+ border: "border-destructive/40 dark:border-destructive/30",
593
+ dot: "bg-destructive",
594
+ icon: "text-destructive"
595
+ }
596
+ };
597
+ function Timeline({ items, size = "default", className, ...props }) {
598
+ return /* @__PURE__ */ jsx8("ol", { "data-slot": "timeline", className: cn("flex flex-col", className), ...props, children: items.map((item, index) => {
599
+ const last = index === items.length - 1;
600
+ const tone = item.tone ?? "default";
601
+ const styles = toneStyles[tone];
602
+ return /* @__PURE__ */ jsxs5(
603
+ "li",
604
+ {
605
+ className: cn("relative flex gap-3.5 last:pb-0", timelineRowGap[size]),
606
+ children: [
607
+ !last ? /* @__PURE__ */ jsx8(
608
+ "span",
609
+ {
610
+ "aria-hidden": true,
611
+ className: cn(
612
+ "absolute left-2.5 bottom-0 w-[1.5px] -translate-x-1/2 bg-neutral-200 dark:bg-neutral-800",
613
+ item.icon ? "top-6" : "top-3"
614
+ )
615
+ }
616
+ ) : null,
617
+ /* @__PURE__ */ jsx8("div", { className: "relative flex w-5 shrink-0 justify-center pt-0.5", children: /* @__PURE__ */ jsx8(
618
+ "span",
619
+ {
620
+ className: cn(
621
+ "relative z-10 flex shrink-0 items-center justify-center rounded-full border-[1.5px] bg-background transition-colors",
622
+ styles.border,
623
+ item.icon ? "size-6" : "size-4"
624
+ ),
625
+ children: item.icon ? /* @__PURE__ */ jsx8("div", { className: cn("text-xs", styles.icon), children: item.icon }) : /* @__PURE__ */ jsx8(
626
+ "span",
627
+ {
628
+ className: cn(
629
+ "size-1.5 rounded-full",
630
+ styles.dot
631
+ )
632
+ }
633
+ )
634
+ }
635
+ ) }),
636
+ /* @__PURE__ */ jsxs5("div", { className: "min-w-0 flex-1 pb-0.5", children: [
637
+ /* @__PURE__ */ jsxs5("div", { className: "flex items-start justify-between gap-2", children: [
638
+ /* @__PURE__ */ jsx8("p", { className: "text-sm font-normal text-foreground", children: item.title }),
639
+ item.meta ? /* @__PURE__ */ jsx8("span", { className: "shrink-0 text-xs text-muted-foreground tabular-nums", children: item.meta }) : null
640
+ ] }),
641
+ item.description ? /* @__PURE__ */ jsx8("p", { className: "mt-0.5 text-[13px] leading-relaxed text-muted-foreground", children: item.description }) : null
642
+ ] })
643
+ ]
644
+ },
645
+ item.id
646
+ );
647
+ }) });
648
+ }
649
+
650
+ // src/ui/kanban.tsx
651
+ import * as React2 from "react";
652
+ import {
653
+ DndContext,
654
+ DragOverlay,
655
+ KeyboardSensor,
656
+ PointerSensor,
657
+ closestCorners,
658
+ useDroppable,
659
+ useSensor,
660
+ useSensors
661
+ } from "@dnd-kit/core";
662
+ import {
663
+ SortableContext,
664
+ arrayMove,
665
+ sortableKeyboardCoordinates,
666
+ useSortable,
667
+ verticalListSortingStrategy
668
+ } from "@dnd-kit/sortable";
669
+ import { CSS } from "@dnd-kit/utilities";
670
+ import { GripVerticalIcon } from "lucide-react";
671
+ import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
672
+ var columnTitleToneClass = {
673
+ default: "text-foreground",
674
+ primary: "text-blue-600 dark:text-blue-400",
675
+ success: "text-emerald-600 dark:text-emerald-400",
676
+ warn: "text-amber-600 dark:text-amber-400",
677
+ danger: "text-rose-600 dark:text-rose-400"
678
+ };
679
+ var cardVariantClass = {
680
+ default: "border border-border/70 bg-card shadow-sm hover:border-border hover:shadow-md",
681
+ outline: "border border-border bg-card hover:border-foreground/25",
682
+ muted: "border border-transparent bg-muted/60 hover:bg-muted"
683
+ };
684
+ var cardToneClass = {
685
+ default: "bg-card shadow-sm hover:shadow-md",
686
+ primary: "bg-card shadow-sm hover:shadow-md",
687
+ success: "bg-card shadow-sm hover:shadow-md",
688
+ warn: "bg-card shadow-sm hover:shadow-md",
689
+ danger: "bg-card shadow-sm hover:shadow-md"
690
+ };
691
+ function cardSurfaceClass(variant, tone) {
692
+ return variant === "tonal" ? cardToneClass[tone] : cardVariantClass[variant];
693
+ }
694
+ var densityColumnClass = {
695
+ default: "w-72 gap-2.5",
696
+ compact: "w-64 gap-2"
697
+ };
698
+ var densityListClass = {
699
+ default: "gap-2.5",
700
+ compact: "gap-2"
701
+ };
702
+ var densityCardClass = {
703
+ default: "rounded-lg p-2",
704
+ compact: "rounded-lg p-1.5"
705
+ };
706
+ function defaultGetCardId(card) {
707
+ return card.id;
708
+ }
709
+ function SortableCard({
710
+ card,
711
+ cardId,
712
+ column,
713
+ density,
714
+ variant,
715
+ disabled,
716
+ dragHandle,
717
+ className,
718
+ renderCard
719
+ }) {
720
+ const {
721
+ attributes,
722
+ listeners,
723
+ setNodeRef,
724
+ transform,
725
+ transition,
726
+ isDragging
727
+ } = useSortable({ id: cardId, disabled });
728
+ const style = {
729
+ transform: CSS.Translate.toString(transform),
730
+ transition
731
+ };
732
+ const dragHandleProps = disabled ? void 0 : { ...attributes, ...listeners };
733
+ return /* @__PURE__ */ jsxs6(
734
+ "div",
735
+ {
736
+ ref: setNodeRef,
737
+ style,
738
+ "data-slot": "kanban-card",
739
+ "data-dragging": isDragging ? "" : void 0,
740
+ className: cn(
741
+ "group/kanban-card relative text-sm text-foreground transition",
742
+ densityCardClass[density],
743
+ cardSurfaceClass(variant, column.tone ?? "default"),
744
+ isDragging && "opacity-40",
745
+ className
746
+ ),
747
+ children: [
748
+ !disabled && dragHandle === "auto" ? /* @__PURE__ */ jsx9(
749
+ "button",
750
+ {
751
+ type: "button",
752
+ "aria-label": "Drag card",
753
+ className: "absolute right-1.5 top-1.5 z-10 grid size-6 cursor-grab touch-none place-items-center rounded-md text-muted-foreground/40 opacity-0 transition hover:bg-foreground/5 hover:text-foreground focus-visible:opacity-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-foreground/15 group-hover/kanban-card:opacity-100 active:cursor-grabbing",
754
+ ...attributes,
755
+ ...listeners,
756
+ children: /* @__PURE__ */ jsx9(GripVerticalIcon, { className: "size-4", "aria-hidden": true })
757
+ }
758
+ ) : null,
759
+ renderCard(card, { column, isDragging, isOverlay: false, dragHandleProps })
760
+ ]
761
+ }
762
+ );
763
+ }
764
+ function KanbanColumnView({
765
+ column,
766
+ cardIds,
767
+ density,
768
+ cardVariant,
769
+ disabled,
770
+ dragHandle,
771
+ emptyColumnLabel,
772
+ className,
773
+ cardClassName,
774
+ getCardId,
775
+ renderColumnHeader,
776
+ renderCard
777
+ }) {
778
+ const tone = column.tone ?? "default";
779
+ const { setNodeRef, isOver } = useDroppable({ id: column.id, disabled });
780
+ return /* @__PURE__ */ jsxs6(
781
+ "div",
782
+ {
783
+ "data-slot": "kanban-column",
784
+ className: cn(
785
+ "flex shrink-0 flex-col",
786
+ densityColumnClass[density],
787
+ className
788
+ ),
789
+ children: [
790
+ renderColumnHeader ? renderColumnHeader(column) : /* @__PURE__ */ jsxs6("div", { className: "flex flex-col gap-0.5 px-1 pb-0.5", children: [
791
+ /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-2", children: [
792
+ /* @__PURE__ */ jsx9(
793
+ "h3",
794
+ {
795
+ className: cn(
796
+ "min-w-0 flex-1 truncate text-xs font-medium",
797
+ columnTitleToneClass[tone]
798
+ ),
799
+ children: column.title
800
+ }
801
+ ),
802
+ /* @__PURE__ */ jsx9("span", { className: "shrink-0 text-xs font-normal tabular-nums text-muted-foreground/60", children: column.cards.length }),
803
+ column.action ? /* @__PURE__ */ jsx9("div", { className: "shrink-0", children: column.action }) : null
804
+ ] }),
805
+ column.description ? /* @__PURE__ */ jsx9("p", { className: "truncate text-xs text-muted-foreground", children: column.description }) : null
806
+ ] }),
807
+ /* @__PURE__ */ jsx9(SortableContext, { items: cardIds, strategy: verticalListSortingStrategy, children: /* @__PURE__ */ jsx9(
808
+ "div",
809
+ {
810
+ ref: setNodeRef,
811
+ "data-slot": "kanban-column-body",
812
+ className: cn(
813
+ "flex min-h-16 flex-1 flex-col rounded-xl transition-colors",
814
+ densityListClass[density],
815
+ isOver && "bg-muted/50"
816
+ ),
817
+ children: column.cards.length === 0 ? /* @__PURE__ */ jsx9("div", { className: "flex flex-1 items-center justify-center rounded-xl border border-dashed border-border/60 px-2 py-8 text-center text-xs text-muted-foreground/70", children: emptyColumnLabel ?? "Drop here" }) : column.cards.map((card) => {
818
+ const id = getCardId(card);
819
+ return /* @__PURE__ */ jsx9(
820
+ SortableCard,
821
+ {
822
+ card,
823
+ cardId: id,
824
+ column,
825
+ density,
826
+ variant: cardVariant,
827
+ disabled,
828
+ dragHandle,
829
+ className: cardClassName,
830
+ renderCard
831
+ },
832
+ id
833
+ );
834
+ })
835
+ }
836
+ ) }),
837
+ column.footer ? /* @__PURE__ */ jsx9("div", { className: "px-0.5 pt-0.5", children: column.footer }) : null
838
+ ]
839
+ }
840
+ );
841
+ }
842
+ function cloneColumns(columns) {
843
+ return columns.map((col) => ({ ...col, cards: [...col.cards] }));
844
+ }
845
+ function locateCard(columns, getCardId, cardId) {
846
+ for (const col of columns) {
847
+ const index = col.cards.findIndex((c) => getCardId(c) === cardId);
848
+ if (index !== -1) return { columnId: col.id, index };
849
+ }
850
+ return null;
851
+ }
852
+ function Kanban({
853
+ columns: columnsProp,
854
+ defaultColumns,
855
+ onColumnsChange,
856
+ onMove,
857
+ renderCard,
858
+ renderColumnHeader,
859
+ getCardId = defaultGetCardId,
860
+ emptyColumnLabel,
861
+ density = "default",
862
+ cardVariant = "default",
863
+ dragHandle = "auto",
864
+ disabled = false,
865
+ className,
866
+ columnClassName,
867
+ cardClassName,
868
+ ...rest
869
+ }) {
870
+ const ariaLabel = rest["aria-label"] ?? "Kanban board";
871
+ const isControlled = columnsProp !== void 0;
872
+ const [internal, setInternal] = React2.useState(
873
+ () => cloneColumns(defaultColumns ?? columnsProp ?? [])
874
+ );
875
+ const [activeId, setActiveId] = React2.useState(null);
876
+ const dragOriginRef = React2.useRef(null);
877
+ React2.useEffect(() => {
878
+ if (isControlled && activeId === null) {
879
+ setInternal(cloneColumns(columnsProp));
880
+ }
881
+ }, [columnsProp, isControlled, activeId]);
882
+ const columns = internal;
883
+ const columnIds = React2.useMemo(
884
+ () => new Set(columns.map((c) => c.id)),
885
+ [columns]
886
+ );
887
+ const sensors = useSensors(
888
+ useSensor(PointerSensor, { activationConstraint: { distance: 6 } }),
889
+ useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates })
890
+ );
891
+ const activeCard = React2.useMemo(() => {
892
+ if (!activeId) return null;
893
+ for (const col of columns) {
894
+ const card = col.cards.find((c) => getCardId(c) === activeId);
895
+ if (card) return { card, column: col };
896
+ }
897
+ return null;
898
+ }, [activeId, columns, getCardId]);
899
+ const resolveTargetColumnId = (overId) => {
900
+ if (columnIds.has(overId)) return overId;
901
+ const loc = locateCard(columns, getCardId, overId);
902
+ return loc?.columnId;
903
+ };
904
+ const handleDragStart = (event) => {
905
+ const id = String(event.active.id);
906
+ setActiveId(id);
907
+ dragOriginRef.current = locateCard(columns, getCardId, id);
908
+ };
909
+ const handleDragOver = (event) => {
910
+ const { active, over } = event;
911
+ if (!over) return;
912
+ const activeCardId = String(active.id);
913
+ const overId = String(over.id);
914
+ const from = locateCard(columns, getCardId, activeCardId);
915
+ const toColumnId = resolveTargetColumnId(overId);
916
+ if (!from || !toColumnId || from.columnId === toColumnId) return;
917
+ setInternal((prev) => {
918
+ const next = cloneColumns(prev);
919
+ const fromCol = next.find((c) => c.id === from.columnId);
920
+ const toCol = next.find((c) => c.id === toColumnId);
921
+ if (!fromCol || !toCol) return prev;
922
+ const movingIndex = fromCol.cards.findIndex(
923
+ (c) => getCardId(c) === activeCardId
924
+ );
925
+ if (movingIndex === -1) return prev;
926
+ const [moving] = fromCol.cards.splice(movingIndex, 1);
927
+ const overIsCard = !columnIds.has(overId);
928
+ const overIndex = overIsCard ? toCol.cards.findIndex((c) => getCardId(c) === overId) : toCol.cards.length;
929
+ const insertAt = overIndex === -1 ? toCol.cards.length : overIndex;
930
+ toCol.cards.splice(insertAt, 0, moving);
931
+ return next;
932
+ });
933
+ };
934
+ const finishDrag = (event) => {
935
+ const { active, over } = event;
936
+ const origin = dragOriginRef.current;
937
+ const movedCard = activeCard?.card;
938
+ dragOriginRef.current = null;
939
+ setActiveId(null);
940
+ if (!over || !origin) return;
941
+ const activeCardId = String(active.id);
942
+ const overId = String(over.id);
943
+ let next = columns;
944
+ const current = locateCard(columns, getCardId, activeCardId);
945
+ const toColumnId = resolveTargetColumnId(overId) ?? current?.columnId;
946
+ if (current && toColumnId && current.columnId === toColumnId) {
947
+ const col = columns.find((c) => c.id === toColumnId);
948
+ if (col) {
949
+ const oldIndex = col.cards.findIndex((c) => getCardId(c) === activeCardId);
950
+ const overIsCard = !columnIds.has(overId);
951
+ const overIndex = overIsCard ? col.cards.findIndex((c) => getCardId(c) === overId) : col.cards.length - 1;
952
+ const newIndex = overIndex === -1 ? col.cards.length - 1 : overIndex;
953
+ if (oldIndex !== -1 && newIndex !== -1 && oldIndex !== newIndex) {
954
+ next = columns.map(
955
+ (c) => c.id === toColumnId ? { ...c, cards: arrayMove(c.cards, oldIndex, newIndex) } : c
956
+ );
957
+ }
958
+ }
959
+ }
960
+ if (next !== columns) setInternal(next);
961
+ const finalLoc = locateCard(next, getCardId, activeCardId);
962
+ const moved = finalLoc && (finalLoc.columnId !== origin.columnId || finalLoc.index !== origin.index);
963
+ if (moved) {
964
+ if (movedCard) {
965
+ onMove?.({
966
+ card: movedCard,
967
+ cardId: activeCardId,
968
+ from: origin,
969
+ to: finalLoc,
970
+ columns: next
971
+ });
972
+ }
973
+ onColumnsChange?.(next);
974
+ }
975
+ };
976
+ return /* @__PURE__ */ jsxs6(
977
+ DndContext,
978
+ {
979
+ sensors,
980
+ collisionDetection: closestCorners,
981
+ onDragStart: handleDragStart,
982
+ onDragOver: handleDragOver,
983
+ onDragEnd: finishDrag,
984
+ onDragCancel: () => {
985
+ dragOriginRef.current = null;
986
+ setActiveId(null);
987
+ if (isControlled) setInternal(cloneColumns(columnsProp));
988
+ },
989
+ children: [
990
+ /* @__PURE__ */ jsx9(
991
+ "div",
992
+ {
993
+ "data-slot": "kanban",
994
+ role: "list",
995
+ "aria-label": ariaLabel,
996
+ className: cn(
997
+ "flex w-full items-start overflow-x-auto p-1.5 pb-6 -m-1.5",
998
+ density === "compact" ? "gap-3" : "gap-4",
999
+ className
1000
+ ),
1001
+ children: columns.map((column) => /* @__PURE__ */ jsx9(
1002
+ KanbanColumnView,
1003
+ {
1004
+ column,
1005
+ cardIds: column.cards.map(getCardId),
1006
+ density,
1007
+ cardVariant,
1008
+ disabled,
1009
+ dragHandle,
1010
+ emptyColumnLabel,
1011
+ className: columnClassName,
1012
+ cardClassName,
1013
+ getCardId,
1014
+ renderColumnHeader,
1015
+ renderCard
1016
+ },
1017
+ column.id
1018
+ ))
1019
+ }
1020
+ ),
1021
+ /* @__PURE__ */ jsx9(DragOverlay, { children: activeCard ? /* @__PURE__ */ jsx9(
1022
+ "div",
1023
+ {
1024
+ "data-slot": "kanban-card-overlay",
1025
+ className: cn(
1026
+ "text-sm text-foreground shadow-xl ring-1 ring-black/5",
1027
+ densityCardClass[density],
1028
+ cardSurfaceClass(cardVariant, activeCard.column.tone ?? "default"),
1029
+ "rotate-2 cursor-grabbing"
1030
+ ),
1031
+ children: renderCard(activeCard.card, {
1032
+ column: activeCard.column,
1033
+ isDragging: true,
1034
+ isOverlay: true
1035
+ })
1036
+ }
1037
+ ) : null })
1038
+ ]
1039
+ }
1040
+ );
1041
+ }
1042
+
1043
+ export {
1044
+ CopyButton,
1045
+ Checkbox,
1046
+ Select,
1047
+ SelectGroup,
1048
+ SelectValue,
1049
+ SelectTrigger,
1050
+ SelectContent,
1051
+ SelectLabel,
1052
+ SelectItem,
1053
+ SelectSeparator,
1054
+ SelectScrollUpButton,
1055
+ SelectScrollDownButton,
1056
+ Popover,
1057
+ PopoverTrigger,
1058
+ PopoverAnchor,
1059
+ PopoverContent,
1060
+ Skeleton,
1061
+ untitledButtonVariants,
1062
+ UntitledButton,
1063
+ Banner,
1064
+ Timeline,
1065
+ Kanban
1066
+ };