@timbal-ai/timbal-react 1.1.0 → 1.3.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 (43) hide show
  1. package/CHANGELOG.md +28 -1
  2. package/LICENSE +201 -0
  3. package/README.md +20 -11
  4. package/dist/app.cjs +1675 -1218
  5. package/dist/app.d.cts +22 -6
  6. package/dist/app.d.ts +22 -6
  7. package/dist/app.esm.js +26 -8
  8. package/dist/{chart-artifact-BZp7nmaf.d.ts → chart-artifact-Q5QgMtbj.d.ts} +107 -28
  9. package/dist/{chart-artifact-CX-rh9nq.d.cts → chart-artifact-WDEW9dHT.d.cts} +107 -28
  10. package/dist/{chat-DCms8pJ_.d.cts → chat-ClmzWzCX.d.cts} +2 -0
  11. package/dist/{chat-DCms8pJ_.d.ts → chat-ClmzWzCX.d.ts} +2 -0
  12. package/dist/chat.cjs +868 -511
  13. package/dist/chat.d.cts +1 -1
  14. package/dist/chat.d.ts +1 -1
  15. package/dist/chat.esm.js +3 -3
  16. package/dist/{chunk-YXZ22OJN.esm.js → chunk-GQBYZRD7.esm.js} +670 -402
  17. package/dist/{chunk-XCM3V6RK.esm.js → chunk-OFWC4MIY.esm.js} +2 -2
  18. package/dist/{chunk-6HWMJNZT.esm.js → chunk-OH23AX2V.esm.js} +757 -56
  19. package/dist/{chunk-4AKJ6FKE.esm.js → chunk-QU7ET55D.esm.js} +120 -23
  20. package/dist/{chunk-FRZOEYBO.esm.js → chunk-THBA27QY.esm.js} +4 -4
  21. package/dist/{chunk-JEAUF54A.esm.js → chunk-UCGVL7ZY.esm.js} +1 -1
  22. package/dist/{chunk-P3KDAYX6.esm.js → chunk-VXMM2HX7.esm.js} +1 -1
  23. package/dist/{chunk-TK2AGIME.esm.js → chunk-YCXN67SD.esm.js} +565 -480
  24. package/dist/{pill-segmented-tabs-Ba5q0feL.d.cts → circular-progress-Ci8L-Hfa.d.cts} +230 -6
  25. package/dist/{pill-segmented-tabs-Ba5q0feL.d.ts → circular-progress-Ci8L-Hfa.d.ts} +230 -6
  26. package/dist/index.cjs +2850 -1689
  27. package/dist/index.d.cts +5 -5
  28. package/dist/index.d.ts +5 -5
  29. package/dist/index.esm.js +41 -11
  30. package/dist/studio.cjs +1089 -732
  31. package/dist/studio.d.cts +2 -2
  32. package/dist/studio.d.ts +2 -2
  33. package/dist/studio.esm.js +5 -5
  34. package/dist/styles.css +14 -16
  35. package/dist/ui.cjs +880 -71
  36. package/dist/ui.d.cts +1 -1
  37. package/dist/ui.d.ts +1 -1
  38. package/dist/ui.esm.js +28 -4
  39. package/dist/{welcome-CRqOPKMp.d.cts → welcome-BFGRoNfK.d.cts} +1 -1
  40. package/dist/{welcome-DlHUa3OL.d.ts → welcome-DXqsGTwH.d.ts} +1 -1
  41. package/package.json +1 -1
  42. package/vite/local-dev.d.ts +5 -1
  43. package/vite/local-dev.mjs +17 -13
package/dist/ui.cjs CHANGED
@@ -30,6 +30,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/ui.ts
31
31
  var ui_exports = {};
32
32
  __export(ui_exports, {
33
+ AVATAR_PRIMARY_FALLBACK_CLASS: () => AVATAR_PRIMARY_FALLBACK_CLASS,
33
34
  Accordion: () => Accordion,
34
35
  AccordionContent: () => AccordionContent,
35
36
  AccordionItem: () => AccordionItem,
@@ -51,8 +52,10 @@ __export(ui_exports, {
51
52
  AspectRatio: () => AspectRatio,
52
53
  Avatar: () => Avatar,
53
54
  AvatarFallback: () => AvatarFallback,
55
+ AvatarGroup: () => AvatarGroup,
54
56
  AvatarImage: () => AvatarImage,
55
57
  Badge: () => Badge,
58
+ Banner: () => Banner,
56
59
  Breadcrumb: () => Breadcrumb,
57
60
  BreadcrumbEllipsis: () => BreadcrumbEllipsis,
58
61
  BreadcrumbItem: () => BreadcrumbItem,
@@ -77,6 +80,7 @@ __export(ui_exports, {
77
80
  ChartTooltip: () => ChartTooltip,
78
81
  ChartTooltipContent: () => ChartTooltipContent,
79
82
  Checkbox: () => Checkbox,
83
+ CircularProgress: () => CircularProgress,
80
84
  Collapsible: () => Collapsible,
81
85
  CollapsibleContent: () => CollapsibleContent,
82
86
  CollapsibleTrigger: () => CollapsibleTrigger,
@@ -115,6 +119,7 @@ __export(ui_exports, {
115
119
  ContextMenuSubContent: () => ContextMenuSubContent,
116
120
  ContextMenuSubTrigger: () => ContextMenuSubTrigger,
117
121
  ContextMenuTrigger: () => ContextMenuTrigger,
122
+ CopyButton: () => CopyButton,
118
123
  DatePicker: () => DatePicker,
119
124
  DatePickerButton: () => DatePickerButton,
120
125
  DatePickerCalendar: () => DatePickerCalendar,
@@ -190,6 +195,7 @@ __export(ui_exports, {
190
195
  NavigationMenuList: () => NavigationMenuList,
191
196
  NavigationMenuTrigger: () => NavigationMenuTrigger,
192
197
  NavigationMenuViewport: () => NavigationMenuViewport,
198
+ NumberField: () => NumberField,
193
199
  Pagination: () => Pagination,
194
200
  PaginationContent: () => PaginationContent,
195
201
  PaginationEllipsis: () => PaginationEllipsis,
@@ -205,6 +211,7 @@ __export(ui_exports, {
205
211
  Progress: () => Progress,
206
212
  RadioGroup: () => RadioGroup,
207
213
  RadioGroupItem: () => RadioGroupItem,
214
+ Rating: () => Rating,
208
215
  ScrollArea: () => ScrollArea,
209
216
  ScrollBar: () => ScrollBar,
210
217
  Select: () => Select,
@@ -229,7 +236,9 @@ __export(ui_exports, {
229
236
  Shimmer: () => Shimmer,
230
237
  Skeleton: () => Skeleton,
231
238
  Slider: () => Slider,
239
+ Snippet: () => Snippet,
232
240
  Spinner: () => Spinner,
241
+ Stepper: () => Stepper,
233
242
  Switch: () => Switch,
234
243
  Table: () => Table,
235
244
  TableBody: () => TableBody,
@@ -239,8 +248,10 @@ __export(ui_exports, {
239
248
  TableHead: () => TableHead,
240
249
  TableHeader: () => TableHeader,
241
250
  TableRow: () => TableRow,
251
+ TagInput: () => TagInput,
242
252
  Textarea: () => Textarea,
243
253
  TimbalV2Button: () => TimbalV2Button,
254
+ Timeline: () => Timeline,
244
255
  Toast: () => Toast,
245
256
  ToastAction: () => ToastAction,
246
257
  ToastClose: () => ToastClose,
@@ -263,6 +274,7 @@ __export(ui_exports, {
263
274
  TooltipProvider: () => TooltipProvider,
264
275
  TooltipTrigger: () => TooltipTrigger,
265
276
  alertVariants: () => alertVariants,
277
+ avatarChartVariantClass: () => avatarChartVariantClass,
266
278
  badgeVariants: () => badgeVariants,
267
279
  controlClass: () => controlClass,
268
280
  controlSurfaceClass: () => controlSurfaceClass,
@@ -375,6 +387,33 @@ var TIMBAL_V2_SHADOW = {
375
387
  ghost: "",
376
388
  link: ""
377
389
  };
390
+ var TIMBAL_V2_PRIMARY_SURFACE = cn(
391
+ TIMBAL_V2_PRIMARY_GRADIENT,
392
+ TIMBAL_V2_SHADOW.primary,
393
+ TIMBAL_V2_BORDER.primary
394
+ );
395
+ var TIMBAL_V2_PRIMARY_PILL_ROOT = cn(
396
+ "relative box-border inline-flex items-center justify-center overflow-hidden rounded-full border-0 bg-transparent p-0 font-normal shadow-none transition duration-200 ease-in-out",
397
+ TIMBAL_V2_SHADOW.primary,
398
+ TIMBAL_V2_BORDER.primary
399
+ );
400
+ var TIMBAL_V2_PRIMARY_PILL_FILL_LAYER = cn(
401
+ "pointer-events-none absolute inset-0 transition duration-200 ease-in-out",
402
+ "bg-gradient-to-b from-primary-fill-from to-primary-fill-to",
403
+ "group-hover/avatar:from-primary-fill-hover-from group-hover/avatar:to-primary-fill-hover-to",
404
+ "group-active/avatar:from-primary-fill-active-from group-active/avatar:to-primary-fill-active-to"
405
+ );
406
+ var TIMBAL_V2_SECONDARY_PILL_ROOT = cn(
407
+ "relative box-border inline-flex items-center justify-center overflow-hidden rounded-full bg-transparent p-0 font-normal shadow-none transition duration-200 ease-in-out",
408
+ TIMBAL_V2_SHADOW.secondary,
409
+ TIMBAL_V2_BORDER.secondary
410
+ );
411
+ var TIMBAL_V2_SECONDARY_PILL_FILL_LAYER = cn(
412
+ "pointer-events-none absolute inset-0 transition duration-200 ease-in-out",
413
+ TIMBAL_V2_ELEVATED_GRADIENT,
414
+ "group-hover/avatar:from-secondary-fill-hover-from group-hover/avatar:to-secondary-fill-hover-to",
415
+ "group-active/avatar:from-secondary-fill-active-from group-active/avatar:to-secondary-fill-active-to"
416
+ );
378
417
  var TIMBAL_V2_SWITCH_TRACK_OFF = cn(
379
418
  TIMBAL_V2_ELEVATED_GRADIENT,
380
419
  "border border-border shadow-card"
@@ -452,12 +491,12 @@ var TimbalV2Button = React.forwardRef(function TimbalV2Button2({
452
491
  ...props
453
492
  }, ref) {
454
493
  const isDisabled = disabled || isLoading;
455
- const sizeClass = isIconOnly ? TIMBAL_V2_SIZE_ICON[size] : TIMBAL_V2_SIZE_HEIGHT[size];
494
+ const sizeClass2 = isIconOnly ? TIMBAL_V2_SIZE_ICON[size] : TIMBAL_V2_SIZE_HEIGHT[size];
456
495
  const radiusClass = "rounded-full";
457
496
  const sharedRootClass = cn(
458
497
  "relative box-border inline-flex items-center justify-center gap-2 whitespace-nowrap border-0 text-sm font-normal shadow-none transition duration-200 ease-in-out",
459
498
  "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/60 focus-visible:ring-offset-1 focus-visible:ring-offset-background",
460
- sizeClass,
499
+ sizeClass2,
461
500
  radiusClass,
462
501
  TIMBAL_V2_BORDER[variant],
463
502
  TIMBAL_V2_SHADOW[variant],
@@ -643,25 +682,74 @@ function TooltipContent({
643
682
  }
644
683
 
645
684
  // src/ui/avatar.tsx
685
+ var React2 = __toESM(require("react"), 1);
646
686
  var import_radix_ui3 = require("radix-ui");
647
687
  var import_jsx_runtime4 = require("react/jsx-runtime");
688
+ var AVATAR_PRIMARY_FALLBACK_CLASS = cn(
689
+ TIMBAL_V2_SECONDARY_PILL_ROOT,
690
+ TIMBAL_V2_LABEL.secondary,
691
+ "font-medium"
692
+ );
693
+ var AVATAR_SECONDARY_FILL_STYLE = {
694
+ backgroundImage: "linear-gradient(to bottom, var(--elevated-from), var(--elevated-to))"
695
+ };
696
+ var AvatarChromeContext = React2.createContext(
697
+ null
698
+ );
699
+ function useAvatarChrome() {
700
+ return React2.useContext(AvatarChromeContext);
701
+ }
702
+ function isBrandedVariant(variant) {
703
+ return variant === "secondary" || variant === "primary" || variant === "chart";
704
+ }
705
+ function avatarChartVariantClass(_seed) {
706
+ return AVATAR_PRIMARY_FALLBACK_CLASS;
707
+ }
708
+ var AVATAR_SIZE_CLASS = {
709
+ default: "size-8",
710
+ sm: "size-6",
711
+ lg: "size-10"
712
+ };
648
713
  function Avatar({
649
714
  className,
650
715
  size = "default",
716
+ variant: rootVariant,
717
+ children,
651
718
  ...props
652
719
  }) {
653
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
720
+ const [chrome, setChrome] = React2.useState(rootVariant ?? "muted");
721
+ React2.useLayoutEffect(() => {
722
+ if (rootVariant !== void 0) {
723
+ setChrome(rootVariant);
724
+ }
725
+ }, [rootVariant]);
726
+ const branded = isBrandedVariant(chrome);
727
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(AvatarChromeContext.Provider, { value: { chrome, setChrome }, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
654
728
  import_radix_ui3.Avatar.Root,
655
729
  {
656
730
  "data-slot": "avatar",
657
731
  "data-size": size,
732
+ "data-variant": branded ? "secondary" : chrome,
658
733
  className: cn(
659
- "group/avatar relative flex size-8 shrink-0 overflow-hidden rounded-full select-none data-[size=lg]:size-10 data-[size=sm]:size-6",
734
+ "group/avatar relative shrink-0 select-none",
735
+ AVATAR_SIZE_CLASS[size],
736
+ branded ? TIMBAL_V2_SECONDARY_PILL_ROOT : "flex overflow-hidden rounded-full",
660
737
  className
661
738
  ),
662
- ...props
739
+ ...props,
740
+ children: [
741
+ branded ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
742
+ "span",
743
+ {
744
+ "aria-hidden": true,
745
+ className: TIMBAL_V2_SECONDARY_PILL_FILL_LAYER,
746
+ style: AVATAR_SECONDARY_FILL_STYLE
747
+ }
748
+ ) : null,
749
+ children
750
+ ]
663
751
  }
664
- );
752
+ ) });
665
753
  }
666
754
  function AvatarImage({
667
755
  className,
@@ -671,24 +759,44 @@ function AvatarImage({
671
759
  import_radix_ui3.Avatar.Image,
672
760
  {
673
761
  "data-slot": "avatar-image",
674
- className: cn("aspect-square size-full", className),
762
+ className: cn(
763
+ "relative z-10 aspect-square size-full rounded-full object-cover",
764
+ className
765
+ ),
675
766
  ...props
676
767
  }
677
768
  );
678
769
  }
679
770
  function AvatarFallback({
680
771
  className,
772
+ variant = "muted",
773
+ seed: _seed,
774
+ children,
775
+ style,
681
776
  ...props
682
777
  }) {
778
+ const chromeCtx = useAvatarChrome();
779
+ React2.useLayoutEffect(() => {
780
+ chromeCtx?.setChrome(variant);
781
+ }, [chromeCtx, variant]);
782
+ const branded = isBrandedVariant(variant);
683
783
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
684
784
  import_radix_ui3.Avatar.Fallback,
685
785
  {
686
786
  "data-slot": "avatar-fallback",
787
+ "data-variant": branded ? "secondary" : variant,
687
788
  className: cn(
688
- "bg-muted text-muted-foreground flex size-full items-center justify-center rounded-full text-sm group-data-[size=sm]/avatar:text-xs",
789
+ "relative z-10 flex size-full items-center justify-center rounded-full",
790
+ branded ? cn(
791
+ "bg-transparent font-medium",
792
+ TIMBAL_V2_LABEL.secondary,
793
+ "text-sm group-data-[size=sm]/avatar:text-xs"
794
+ ) : "bg-muted font-normal text-muted-foreground text-sm group-data-[size=sm]/avatar:text-xs",
689
795
  className
690
796
  ),
691
- ...props
797
+ style,
798
+ ...props,
799
+ children
692
800
  }
693
801
  );
694
802
  }
@@ -2317,7 +2425,7 @@ function CommandShortcut({
2317
2425
  }
2318
2426
 
2319
2427
  // src/ui/calendar.tsx
2320
- var React2 = __toESM(require("react"), 1);
2428
+ var React3 = __toESM(require("react"), 1);
2321
2429
  var import_lucide_react11 = require("lucide-react");
2322
2430
  var import_react_day_picker = require("react-day-picker");
2323
2431
  var import_jsx_runtime23 = require("react/jsx-runtime");
@@ -2327,56 +2435,71 @@ function Calendar({
2327
2435
  showOutsideDays = true,
2328
2436
  ...props
2329
2437
  }) {
2438
+ const defaults = (0, import_react_day_picker.getDefaultClassNames)();
2330
2439
  return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
2331
2440
  import_react_day_picker.DayPicker,
2332
2441
  {
2333
2442
  showOutsideDays,
2334
- className: cn("p-3", className),
2443
+ className: cn("p-4", className),
2335
2444
  classNames: {
2336
- months: "flex flex-col gap-4 sm:flex-row sm:gap-4",
2337
- month: "flex flex-col gap-4",
2338
- month_caption: "relative flex items-center justify-center pt-1",
2339
- caption_label: "text-sm font-medium",
2340
- nav: "flex items-center gap-1",
2341
- button_previous: cn(
2342
- buttonVariants({ variant: "outline" }),
2343
- "absolute left-1 size-7 bg-transparent p-0 opacity-70 hover:opacity-100"
2445
+ root: cn("w-fit", defaults.root),
2446
+ months: cn("relative flex flex-col gap-4 sm:flex-row", defaults.months),
2447
+ month: cn("flex w-full flex-col gap-3", defaults.month),
2448
+ nav: cn(
2449
+ "absolute inset-x-0 top-0 flex items-center justify-between",
2450
+ defaults.nav
2451
+ ),
2452
+ button_previous: cn(navButtonClass, defaults.button_previous),
2453
+ button_next: cn(navButtonClass, defaults.button_next),
2454
+ month_caption: cn(
2455
+ "flex h-10 items-center justify-center",
2456
+ defaults.month_caption
2457
+ ),
2458
+ caption_label: cn("text-sm font-semibold", defaults.caption_label),
2459
+ dropdowns: cn(
2460
+ "flex h-10 items-center justify-center gap-1.5 text-sm font-semibold",
2461
+ defaults.dropdowns
2462
+ ),
2463
+ dropdown_root: cn(
2464
+ "relative rounded-md border border-border focus-within:ring-2 focus-within:ring-foreground/10",
2465
+ defaults.dropdown_root
2466
+ ),
2467
+ dropdown: cn("absolute inset-0 bg-popover opacity-0", defaults.dropdown),
2468
+ month_grid: cn("border-separate border-spacing-y-1", defaults.month_grid),
2469
+ weekdays: cn(defaults.weekdays),
2470
+ weekday: cn(
2471
+ "size-10 pb-2 text-xs font-medium text-muted-foreground",
2472
+ defaults.weekday
2344
2473
  ),
2345
- button_next: cn(
2346
- buttonVariants({ variant: "outline" }),
2347
- "absolute right-1 size-7 bg-transparent p-0 opacity-70 hover:opacity-100"
2474
+ week: cn(defaults.week),
2475
+ week_number_header: cn("size-10", defaults.week_number_header),
2476
+ week_number: cn(
2477
+ "text-xs text-muted-foreground",
2478
+ defaults.week_number
2348
2479
  ),
2349
- month_grid: "w-full border-collapse",
2350
- weekdays: "flex",
2351
- weekday: "w-9 rounded-md text-[0.8rem] font-normal text-muted-foreground",
2352
- week: "mt-2 flex w-full",
2353
2480
  day: cn(
2354
- "relative size-9 p-0 text-center text-sm",
2355
- "[&:has([aria-selected].day-range-end)]:rounded-r-md",
2356
- "[&:has([aria-selected].day-outside)]:bg-accent/50",
2357
- "[&:has([aria-selected])]:bg-accent",
2358
- "first:[&:has([aria-selected])]:rounded-l-md",
2359
- "last:[&:has([aria-selected])]:rounded-r-md",
2360
- "focus-within:relative focus-within:z-10"
2481
+ "relative size-10 p-0 text-center text-sm focus-within:relative focus-within:z-10",
2482
+ defaults.day
2361
2483
  ),
2362
- day_button: cn(
2363
- buttonVariants({ variant: "ghost" }),
2364
- "size-9 p-0 font-normal aria-selected:opacity-100"
2484
+ range_start: cn("rounded-l-md", defaults.range_start),
2485
+ range_middle: cn("rounded-none", defaults.range_middle),
2486
+ range_end: cn("rounded-r-md", defaults.range_end),
2487
+ today: cn(
2488
+ "[&>button]:font-semibold [&>button:not([data-selected-single=true]):not([data-range-middle=true])]:text-primary",
2489
+ defaults.today
2365
2490
  ),
2366
- range_start: "day-range-start rounded-l-md",
2367
- range_middle: "day-range-middle aria-selected:bg-accent",
2368
- range_end: "day-range-end rounded-r-md",
2369
- selected: "bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground",
2370
- today: "bg-accent text-accent-foreground",
2371
- outside: "day-outside text-muted-foreground aria-selected:bg-accent/50 aria-selected:text-muted-foreground",
2372
- disabled: "text-muted-foreground opacity-50",
2373
- hidden: "invisible",
2491
+ outside: cn(
2492
+ "text-muted-foreground/60 aria-selected:text-muted-foreground",
2493
+ defaults.outside
2494
+ ),
2495
+ disabled: cn("text-muted-foreground opacity-50", defaults.disabled),
2496
+ hidden: cn("invisible", defaults.hidden),
2374
2497
  ...classNames
2375
2498
  },
2376
2499
  components: {
2377
- Chevron: ({ orientation, className: className2, ...chevronProps }) => {
2378
- const Icon = orientation === "left" ? import_lucide_react11.ChevronLeftIcon : import_lucide_react11.ChevronRightIcon;
2379
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Icon, { className: cn("size-4", className2), ...chevronProps });
2500
+ Chevron: ({ orientation, className: chevronClass, ...chevronProps }) => {
2501
+ const Icon = orientation === "left" ? import_lucide_react11.ChevronLeftIcon : orientation === "right" ? import_lucide_react11.ChevronRightIcon : import_lucide_react11.ChevronDownIcon;
2502
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Icon, { className: cn("size-4", chevronClass), ...chevronProps });
2380
2503
  },
2381
2504
  DayButton: CalendarDayButton
2382
2505
  },
@@ -2384,35 +2507,42 @@ function Calendar({
2384
2507
  }
2385
2508
  );
2386
2509
  }
2510
+ var navButtonClass = cn(
2511
+ "inline-flex size-8 items-center justify-center rounded-md text-muted-foreground transition-colors",
2512
+ "hover:bg-accent hover:text-accent-foreground",
2513
+ "disabled:pointer-events-none disabled:opacity-40",
2514
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-foreground/10"
2515
+ );
2387
2516
  function CalendarDayButton({
2388
2517
  className,
2389
2518
  day,
2390
2519
  modifiers,
2391
2520
  ...props
2392
2521
  }) {
2393
- const ref = React2.useRef(null);
2394
- React2.useEffect(() => {
2522
+ const ref = React3.useRef(null);
2523
+ React3.useEffect(() => {
2395
2524
  if (modifiers.focused) ref.current?.focus();
2396
2525
  }, [modifiers.focused]);
2526
+ const isSingle = modifiers.selected && !modifiers.range_start && !modifiers.range_end && !modifiers.range_middle;
2397
2527
  return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
2398
2528
  "button",
2399
2529
  {
2400
2530
  ref,
2401
2531
  type: "button",
2402
2532
  "data-day": day.date.toLocaleDateString(),
2403
- "data-selected-single": modifiers.selected && !modifiers.range_start && !modifiers.range_end && !modifiers.range_middle,
2404
- "data-range-start": modifiers.range_start,
2405
- "data-range-end": modifiers.range_end,
2406
- "data-range-middle": modifiers.range_middle,
2533
+ "data-selected-single": isSingle || void 0,
2534
+ "data-range-start": modifiers.range_start || void 0,
2535
+ "data-range-end": modifiers.range_end || void 0,
2536
+ "data-range-middle": modifiers.range_middle || void 0,
2407
2537
  className: cn(
2408
- "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors",
2538
+ "inline-flex size-full items-center justify-center rounded-md text-sm font-normal transition-colors",
2409
2539
  "hover:bg-accent hover:text-accent-foreground",
2410
- "focus-visible:ring-2 focus-visible:ring-foreground/10 focus-visible:outline-none",
2540
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-foreground/15",
2411
2541
  "disabled:pointer-events-none disabled:opacity-50",
2412
- "data-[selected-single=true]:bg-primary data-[selected-single=true]:text-primary-foreground",
2413
- "data-[range-middle=true]:bg-accent data-[range-middle=true]:text-accent-foreground",
2414
- "data-[range-start=true]:rounded-l-md data-[range-start=true]:bg-primary data-[range-start=true]:text-primary-foreground",
2415
- "data-[range-end=true]:rounded-r-md data-[range-end=true]:bg-primary data-[range-end=true]:text-primary-foreground",
2542
+ "data-[selected-single=true]:bg-primary data-[selected-single=true]:text-primary-foreground data-[selected-single=true]:hover:bg-primary",
2543
+ "data-[range-middle=true]:rounded-none data-[range-middle=true]:bg-accent data-[range-middle=true]:text-accent-foreground",
2544
+ "data-[range-start=true]:rounded-l-md data-[range-start=true]:rounded-r-none data-[range-start=true]:bg-primary data-[range-start=true]:text-primary-foreground",
2545
+ "data-[range-end=true]:rounded-r-md data-[range-end=true]:rounded-l-none data-[range-end=true]:bg-primary data-[range-end=true]:text-primary-foreground",
2416
2546
  className
2417
2547
  ),
2418
2548
  ...props
@@ -2901,7 +3031,7 @@ function Separator({
2901
3031
  }
2902
3032
 
2903
3033
  // src/ui/slider.tsx
2904
- var React3 = __toESM(require("react"), 1);
3034
+ var React4 = __toESM(require("react"), 1);
2905
3035
  var import_radix_ui21 = require("radix-ui");
2906
3036
  var import_jsx_runtime32 = require("react/jsx-runtime");
2907
3037
  function Slider({
@@ -2912,7 +3042,7 @@ function Slider({
2912
3042
  max = 100,
2913
3043
  ...props
2914
3044
  }) {
2915
- const thumbs = React3.useMemo(() => {
3045
+ const thumbs = React4.useMemo(() => {
2916
3046
  if (Array.isArray(value)) return value;
2917
3047
  if (Array.isArray(defaultValue)) return defaultValue;
2918
3048
  return [min];
@@ -3815,13 +3945,13 @@ function Skeleton({ className, ...props }) {
3815
3945
  }
3816
3946
 
3817
3947
  // src/ui/chart.tsx
3818
- var React4 = __toESM(require("react"), 1);
3948
+ var React5 = __toESM(require("react"), 1);
3819
3949
  var RechartsPrimitive = __toESM(require("recharts"), 1);
3820
3950
  var import_jsx_runtime46 = require("react/jsx-runtime");
3821
3951
  var THEMES = { light: "", dark: ".dark" };
3822
- var ChartContext = React4.createContext(null);
3952
+ var ChartContext = React5.createContext(null);
3823
3953
  function useChart() {
3824
- const context = React4.useContext(ChartContext);
3954
+ const context = React5.useContext(ChartContext);
3825
3955
  if (!context) {
3826
3956
  throw new Error("useChart must be used within a <ChartContainer />");
3827
3957
  }
@@ -3834,7 +3964,7 @@ function ChartContainer({
3834
3964
  config,
3835
3965
  ...props
3836
3966
  }) {
3837
- const uniqueId = React4.useId();
3967
+ const uniqueId = React5.useId();
3838
3968
  const chartId = `chart-${id || uniqueId.replace(/:/g, "")}`;
3839
3969
  return /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(ChartContext.Provider, { value: { config }, children: /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(
3840
3970
  "div",
@@ -3895,7 +4025,7 @@ function ChartTooltipContent({
3895
4025
  labelKey
3896
4026
  }) {
3897
4027
  const { config } = useChart();
3898
- const tooltipLabel = React4.useMemo(() => {
4028
+ const tooltipLabel = React5.useMemo(() => {
3899
4029
  if (hideLabel || !payload?.length) {
3900
4030
  return null;
3901
4031
  }
@@ -4006,7 +4136,7 @@ function ChartLegendContent({
4006
4136
  return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(
4007
4137
  "div",
4008
4138
  {
4009
- className: "[&>svg]:text-muted-foreground flex items-center gap-1.5 [&>svg]:h-3 [&>svg]:w-3",
4139
+ className: "[&>svg]:text-muted-foreground flex min-w-0 max-w-[8rem] items-center gap-1.5 [&>svg]:h-3 [&>svg]:w-3",
4010
4140
  children: [
4011
4141
  itemConfig?.icon && !hideIcon ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(itemConfig.icon, {}) : /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
4012
4142
  "div",
@@ -4015,7 +4145,7 @@ function ChartLegendContent({
4015
4145
  style: { backgroundColor: item.color }
4016
4146
  }
4017
4147
  ),
4018
- itemConfig?.label
4148
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "min-w-0 truncate", children: itemConfig?.label ?? (item.value != null ? String(item.value) : null) })
4019
4149
  ]
4020
4150
  },
4021
4151
  `${item.value ?? index}`
@@ -4240,7 +4370,7 @@ function ToastDescription({
4240
4370
  }
4241
4371
 
4242
4372
  // src/ui/use-toast.ts
4243
- var React5 = __toESM(require("react"), 1);
4373
+ var React6 = __toESM(require("react"), 1);
4244
4374
  var TOAST_LIMIT = 3;
4245
4375
  var TOAST_REMOVE_DELAY = 5e3;
4246
4376
  var listeners = /* @__PURE__ */ new Set();
@@ -4293,8 +4423,8 @@ function toast(input) {
4293
4423
  return memoryState.add(input);
4294
4424
  }
4295
4425
  function useToast() {
4296
- const [state, setState] = React5.useState(memoryState);
4297
- React5.useEffect(() => {
4426
+ const [state, setState] = React6.useState(memoryState);
4427
+ React6.useEffect(() => {
4298
4428
  listeners.add(setState);
4299
4429
  return () => {
4300
4430
  listeners.delete(setState);
@@ -4480,8 +4610,676 @@ var PillSegmentedTabs = ({
4480
4610
  )) });
4481
4611
  };
4482
4612
  var MemoPillSegmentedTabs = (0, import_react3.memo)(PillSegmentedTabs);
4613
+
4614
+ // src/ui/avatar-group.tsx
4615
+ var React7 = __toESM(require("react"), 1);
4616
+ var import_jsx_runtime52 = require("react/jsx-runtime");
4617
+ var spacingClass = {
4618
+ sm: "-space-x-2",
4619
+ md: "-space-x-3"
4620
+ };
4621
+ function AvatarGroup({
4622
+ className,
4623
+ children,
4624
+ max,
4625
+ spacing = "sm",
4626
+ ...props
4627
+ }) {
4628
+ const items = React7.Children.toArray(children);
4629
+ const overflow = typeof max === "number" ? items.length - max : 0;
4630
+ const visible = typeof max === "number" ? items.slice(0, max) : items;
4631
+ return /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)(
4632
+ "div",
4633
+ {
4634
+ "data-slot": "avatar-group",
4635
+ className: cn(
4636
+ "flex items-center",
4637
+ spacingClass[spacing],
4638
+ "[&>*]:rounded-full [&>*]:ring-2 [&>*]:ring-background",
4639
+ className
4640
+ ),
4641
+ ...props,
4642
+ children: [
4643
+ visible,
4644
+ overflow > 0 ? /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)(
4645
+ "span",
4646
+ {
4647
+ "aria-label": `${overflow} more`,
4648
+ className: "inline-flex size-8 items-center justify-center rounded-full bg-muted text-xs font-medium text-muted-foreground ring-2 ring-background",
4649
+ children: [
4650
+ "+",
4651
+ overflow
4652
+ ]
4653
+ }
4654
+ ) : null
4655
+ ]
4656
+ }
4657
+ );
4658
+ }
4659
+
4660
+ // src/ui/stepper.tsx
4661
+ var import_lucide_react19 = require("lucide-react");
4662
+ var import_jsx_runtime53 = require("react/jsx-runtime");
4663
+ function Stepper({
4664
+ steps,
4665
+ current,
4666
+ orientation = "horizontal",
4667
+ className,
4668
+ ...props
4669
+ }) {
4670
+ const isVertical = orientation === "vertical";
4671
+ return /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
4672
+ "ol",
4673
+ {
4674
+ "data-slot": "stepper",
4675
+ className: cn(
4676
+ "flex",
4677
+ isVertical ? "flex-col gap-0" : "items-start gap-2",
4678
+ className
4679
+ ),
4680
+ ...props,
4681
+ children: steps.map((step, index) => {
4682
+ const complete = index < current;
4683
+ const active = index === current;
4684
+ const last = index === steps.length - 1;
4685
+ const connectorFilled = index < current;
4686
+ return /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(
4687
+ "li",
4688
+ {
4689
+ "aria-current": active ? "step" : void 0,
4690
+ className: cn(
4691
+ "flex min-w-0",
4692
+ isVertical ? "gap-3" : "flex-1 flex-col gap-1.5",
4693
+ last && !isVertical && "flex-none"
4694
+ ),
4695
+ children: [
4696
+ /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { className: cn("flex items-center gap-2", isVertical && "flex-col"), children: [
4697
+ /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
4698
+ "span",
4699
+ {
4700
+ className: cn(
4701
+ "inline-flex size-7 shrink-0 items-center justify-center rounded-full border text-xs font-medium transition-colors",
4702
+ complete && "border-primary bg-primary text-primary-foreground",
4703
+ active && "border-primary text-primary",
4704
+ !complete && !active && "border-border text-muted-foreground"
4705
+ ),
4706
+ children: complete ? /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(import_lucide_react19.CheckIcon, { className: "size-3.5", "aria-hidden": true }) : index + 1
4707
+ }
4708
+ ),
4709
+ !last ? /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
4710
+ "span",
4711
+ {
4712
+ "aria-hidden": true,
4713
+ className: cn(
4714
+ isVertical ? "w-px flex-1" : "h-px flex-1",
4715
+ connectorFilled ? "bg-primary" : "bg-border",
4716
+ isVertical && "min-h-6"
4717
+ )
4718
+ }
4719
+ ) : null
4720
+ ] }),
4721
+ /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { className: cn("min-w-0", isVertical && "pb-4"), children: [
4722
+ /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
4723
+ "p",
4724
+ {
4725
+ className: cn(
4726
+ "truncate text-sm font-medium",
4727
+ active ? "text-foreground" : "text-muted-foreground"
4728
+ ),
4729
+ children: step.label
4730
+ }
4731
+ ),
4732
+ step.description ? /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("p", { className: "truncate text-xs text-muted-foreground", children: step.description }) : null
4733
+ ] })
4734
+ ]
4735
+ },
4736
+ step.id
4737
+ );
4738
+ })
4739
+ }
4740
+ );
4741
+ }
4742
+
4743
+ // src/ui/timeline.tsx
4744
+ var import_jsx_runtime54 = require("react/jsx-runtime");
4745
+ var dotToneClass = {
4746
+ default: "border-border bg-card",
4747
+ primary: "border-primary bg-primary",
4748
+ success: "border-emerald-500 bg-emerald-500",
4749
+ warn: "border-amber-500 bg-amber-500",
4750
+ danger: "border-destructive bg-destructive"
4751
+ };
4752
+ function Timeline({ items, className, ...props }) {
4753
+ return /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("ol", { "data-slot": "timeline", className: cn("flex flex-col", className), ...props, children: items.map((item, index) => {
4754
+ const last = index === items.length - 1;
4755
+ const tone = item.tone ?? "default";
4756
+ return /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("li", { className: "relative flex gap-3 pb-5 last:pb-0", children: [
4757
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: "flex flex-col items-center", children: [
4758
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
4759
+ "span",
4760
+ {
4761
+ className: cn(
4762
+ "z-[1] mt-0.5 inline-flex size-3 shrink-0 items-center justify-center rounded-full border-2",
4763
+ dotToneClass[tone],
4764
+ item.icon && "size-6"
4765
+ ),
4766
+ children: item.icon
4767
+ }
4768
+ ),
4769
+ !last ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { "aria-hidden": true, className: "w-px flex-1 bg-border" }) : null
4770
+ ] }),
4771
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: "min-w-0 flex-1 pb-0.5", children: [
4772
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: "flex items-start justify-between gap-2", children: [
4773
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("p", { className: "text-sm font-medium text-foreground", children: item.title }),
4774
+ item.meta ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "shrink-0 text-xs text-muted-foreground tabular-nums", children: item.meta }) : null
4775
+ ] }),
4776
+ item.description ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("p", { className: "mt-0.5 text-sm text-muted-foreground", children: item.description }) : null
4777
+ ] })
4778
+ ] }, item.id);
4779
+ }) });
4780
+ }
4781
+
4782
+ // src/ui/rating.tsx
4783
+ var React8 = __toESM(require("react"), 1);
4784
+ var import_lucide_react20 = require("lucide-react");
4785
+ var import_jsx_runtime55 = require("react/jsx-runtime");
4786
+ var sizeClass = { sm: "size-4", md: "size-5", lg: "size-6" };
4787
+ function Rating({
4788
+ value: valueProp,
4789
+ defaultValue = 0,
4790
+ onChange,
4791
+ max = 5,
4792
+ readOnly = false,
4793
+ disabled = false,
4794
+ size = "md",
4795
+ label = "Rating",
4796
+ className
4797
+ }) {
4798
+ const [uncontrolled, setUncontrolled] = React8.useState(defaultValue);
4799
+ const isControlled = valueProp !== void 0;
4800
+ const value = isControlled ? valueProp : uncontrolled;
4801
+ const [hover, setHover] = React8.useState(null);
4802
+ const interactive = !readOnly && !disabled;
4803
+ const shown = hover ?? value;
4804
+ const set = (next) => {
4805
+ if (!interactive) return;
4806
+ if (!isControlled) setUncontrolled(next);
4807
+ onChange?.(next);
4808
+ };
4809
+ if (!interactive) {
4810
+ return /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
4811
+ "span",
4812
+ {
4813
+ "data-slot": "rating",
4814
+ role: "img",
4815
+ "aria-label": `${label}: ${value} of ${max}`,
4816
+ className: cn("inline-flex items-center gap-0.5", disabled && "opacity-50", className),
4817
+ children: Array.from({ length: max }, (_, i) => /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
4818
+ import_lucide_react20.StarIcon,
4819
+ {
4820
+ "aria-hidden": true,
4821
+ className: cn(
4822
+ sizeClass[size],
4823
+ i < value ? "fill-amber-400 text-amber-400" : "fill-transparent text-muted-foreground/40"
4824
+ )
4825
+ },
4826
+ i
4827
+ ))
4828
+ }
4829
+ );
4830
+ }
4831
+ return /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
4832
+ "span",
4833
+ {
4834
+ "data-slot": "rating",
4835
+ role: "radiogroup",
4836
+ "aria-label": label,
4837
+ className: cn("inline-flex items-center gap-0.5", className),
4838
+ onMouseLeave: () => setHover(null),
4839
+ children: Array.from({ length: max }, (_, i) => {
4840
+ const unit = i + 1;
4841
+ const filled = unit <= shown;
4842
+ return /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
4843
+ "button",
4844
+ {
4845
+ type: "button",
4846
+ role: "radio",
4847
+ "aria-checked": unit === value,
4848
+ "aria-label": `${unit} ${unit === 1 ? "star" : "stars"}`,
4849
+ onClick: () => set(unit === value ? 0 : unit),
4850
+ onMouseEnter: () => setHover(unit),
4851
+ onFocus: () => setHover(unit),
4852
+ onBlur: () => setHover(null),
4853
+ className: "rounded-sm p-0.5 transition-transform hover:scale-110 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-foreground/15",
4854
+ children: /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
4855
+ import_lucide_react20.StarIcon,
4856
+ {
4857
+ className: cn(
4858
+ sizeClass[size],
4859
+ "transition-colors",
4860
+ filled ? "fill-amber-400 text-amber-400" : "fill-transparent text-muted-foreground/40"
4861
+ )
4862
+ }
4863
+ )
4864
+ },
4865
+ i
4866
+ );
4867
+ })
4868
+ }
4869
+ );
4870
+ }
4871
+
4872
+ // src/ui/number-field.tsx
4873
+ var React9 = __toESM(require("react"), 1);
4874
+ var import_lucide_react21 = require("lucide-react");
4875
+ var import_jsx_runtime56 = require("react/jsx-runtime");
4876
+ var heightClass = { sm: "h-9", default: "h-10" };
4877
+ var stepButtonClass = "inline-flex aspect-square h-full items-center justify-center text-muted-foreground transition-colors hover:bg-accent hover:text-foreground disabled:pointer-events-none disabled:opacity-40 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-foreground/15";
4878
+ function clamp(n, min, max) {
4879
+ if (typeof min === "number" && n < min) return min;
4880
+ if (typeof max === "number" && n > max) return max;
4881
+ return n;
4882
+ }
4883
+ function NumberField({
4884
+ value: valueProp,
4885
+ defaultValue = 0,
4886
+ onValueChange,
4887
+ min,
4888
+ max,
4889
+ step = 1,
4890
+ size = "default",
4891
+ disabled,
4892
+ ariaLabel,
4893
+ className,
4894
+ ...inputProps
4895
+ }) {
4896
+ const [uncontrolled, setUncontrolled] = React9.useState(defaultValue);
4897
+ const isControlled = valueProp !== void 0;
4898
+ const value = isControlled ? valueProp : uncontrolled;
4899
+ const commit = (next) => {
4900
+ const clamped = clamp(next, min, max);
4901
+ if (!isControlled) setUncontrolled(clamped);
4902
+ onValueChange?.(clamped);
4903
+ };
4904
+ return /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(
4905
+ "div",
4906
+ {
4907
+ "data-slot": "number-field",
4908
+ className: cn(
4909
+ controlSurfaceClass,
4910
+ "inline-flex w-full items-stretch overflow-hidden rounded-lg p-0",
4911
+ heightClass[size],
4912
+ disabled && "opacity-50",
4913
+ className
4914
+ ),
4915
+ children: [
4916
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
4917
+ "button",
4918
+ {
4919
+ type: "button",
4920
+ tabIndex: -1,
4921
+ "aria-hidden": true,
4922
+ disabled: disabled || typeof min === "number" && value <= min,
4923
+ onClick: () => commit(value - step),
4924
+ className: cn(stepButtonClass, "border-r border-border"),
4925
+ children: /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(import_lucide_react21.MinusIcon, { className: "size-4" })
4926
+ }
4927
+ ),
4928
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
4929
+ "input",
4930
+ {
4931
+ type: "number",
4932
+ inputMode: "decimal",
4933
+ role: "spinbutton",
4934
+ "aria-label": ariaLabel,
4935
+ "aria-valuenow": value,
4936
+ "aria-valuemin": min,
4937
+ "aria-valuemax": max,
4938
+ value: Number.isNaN(value) ? "" : value,
4939
+ disabled,
4940
+ onChange: (e) => {
4941
+ const next = e.target.valueAsNumber;
4942
+ if (Number.isNaN(next)) {
4943
+ if (!isControlled) setUncontrolled(Number.NaN);
4944
+ return;
4945
+ }
4946
+ commit(next);
4947
+ },
4948
+ className: "w-full min-w-0 [appearance:textfield] bg-transparent px-2 text-center text-sm text-foreground outline-none disabled:cursor-not-allowed [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none",
4949
+ ...inputProps
4950
+ }
4951
+ ),
4952
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
4953
+ "button",
4954
+ {
4955
+ type: "button",
4956
+ tabIndex: -1,
4957
+ "aria-hidden": true,
4958
+ disabled: disabled || typeof max === "number" && value >= max,
4959
+ onClick: () => commit(value + step),
4960
+ className: cn(stepButtonClass, "border-l border-border"),
4961
+ children: /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(import_lucide_react21.PlusIcon, { className: "size-4" })
4962
+ }
4963
+ )
4964
+ ]
4965
+ }
4966
+ );
4967
+ }
4968
+
4969
+ // src/ui/tag-input.tsx
4970
+ var React10 = __toESM(require("react"), 1);
4971
+ var import_lucide_react22 = require("lucide-react");
4972
+ var import_jsx_runtime57 = require("react/jsx-runtime");
4973
+ function TagInput({
4974
+ value: valueProp,
4975
+ defaultValue = [],
4976
+ onChange,
4977
+ placeholder,
4978
+ separators = ["Enter", ","],
4979
+ dedupe = true,
4980
+ max,
4981
+ disabled,
4982
+ ariaLabel,
4983
+ className,
4984
+ inputClassName
4985
+ }) {
4986
+ const [uncontrolled, setUncontrolled] = React10.useState(defaultValue);
4987
+ const isControlled = valueProp !== void 0;
4988
+ const tags = isControlled ? valueProp : uncontrolled;
4989
+ const [draft, setDraft] = React10.useState("");
4990
+ const setTags = (next) => {
4991
+ if (!isControlled) setUncontrolled(next);
4992
+ onChange?.(next);
4993
+ };
4994
+ const addTag = (raw) => {
4995
+ const tag = raw.trim();
4996
+ if (!tag) return;
4997
+ if (typeof max === "number" && tags.length >= max) return;
4998
+ if (dedupe && tags.some((t) => t.toLowerCase() === tag.toLowerCase())) {
4999
+ setDraft("");
5000
+ return;
5001
+ }
5002
+ setTags([...tags, tag]);
5003
+ setDraft("");
5004
+ };
5005
+ const removeAt = (index) => {
5006
+ setTags(tags.filter((_, i) => i !== index));
5007
+ };
5008
+ const handleKeyDown = (event) => {
5009
+ if (separators.includes(event.key)) {
5010
+ event.preventDefault();
5011
+ addTag(draft);
5012
+ } else if (event.key === "Backspace" && draft === "" && tags.length > 0) {
5013
+ removeAt(tags.length - 1);
5014
+ }
5015
+ };
5016
+ return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(
5017
+ "div",
5018
+ {
5019
+ "data-slot": "tag-input",
5020
+ className: cn(
5021
+ controlSurfaceClass,
5022
+ "flex min-h-10 w-full flex-wrap items-center gap-1.5 rounded-lg px-2 py-1.5",
5023
+ disabled && "pointer-events-none opacity-50",
5024
+ className
5025
+ ),
5026
+ children: [
5027
+ tags.map((tag, index) => /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(
5028
+ "span",
5029
+ {
5030
+ className: "inline-flex items-center gap-1 rounded-md bg-muted py-0.5 pl-2 pr-1 text-xs font-medium text-foreground",
5031
+ children: [
5032
+ tag,
5033
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
5034
+ "button",
5035
+ {
5036
+ type: "button",
5037
+ "aria-label": `Remove ${tag}`,
5038
+ onClick: () => removeAt(index),
5039
+ className: "inline-flex size-4 items-center justify-center rounded-sm text-muted-foreground transition-colors hover:bg-foreground/10 hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-foreground/20",
5040
+ children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_lucide_react22.XIcon, { className: "size-3", "aria-hidden": true })
5041
+ }
5042
+ )
5043
+ ]
5044
+ },
5045
+ `${tag}-${index}`
5046
+ )),
5047
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
5048
+ "input",
5049
+ {
5050
+ type: "text",
5051
+ "aria-label": ariaLabel ?? placeholder ?? "Add tag",
5052
+ value: draft,
5053
+ disabled,
5054
+ placeholder: tags.length === 0 ? placeholder : void 0,
5055
+ onChange: (e) => setDraft(e.target.value),
5056
+ onKeyDown: handleKeyDown,
5057
+ onBlur: () => addTag(draft),
5058
+ className: cn(
5059
+ "min-w-[6rem] flex-1 bg-transparent text-sm text-foreground outline-none placeholder:text-muted-foreground/70",
5060
+ inputClassName
5061
+ )
5062
+ }
5063
+ )
5064
+ ]
5065
+ }
5066
+ );
5067
+ }
5068
+
5069
+ // src/ui/banner.tsx
5070
+ var import_lucide_react23 = require("lucide-react");
5071
+ var import_jsx_runtime58 = require("react/jsx-runtime");
5072
+ var bannerToneClass = {
5073
+ default: "border-border bg-muted/50 text-foreground",
5074
+ primary: "border-primary/20 bg-primary/10 text-foreground",
5075
+ success: "border-emerald-500/25 bg-emerald-500/10 text-foreground [&_[data-banner-icon]]:text-emerald-600 dark:[&_[data-banner-icon]]:text-emerald-400",
5076
+ warn: "border-amber-500/25 bg-amber-500/10 text-foreground [&_[data-banner-icon]]:text-amber-600 dark:[&_[data-banner-icon]]:text-amber-400",
5077
+ danger: "border-destructive/25 bg-destructive/10 text-foreground [&_[data-banner-icon]]:text-destructive"
5078
+ };
5079
+ function Banner({
5080
+ tone = "default",
5081
+ icon,
5082
+ title,
5083
+ actions,
5084
+ onDismiss,
5085
+ className,
5086
+ children,
5087
+ ...props
5088
+ }) {
5089
+ return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(
5090
+ "div",
5091
+ {
5092
+ "data-slot": "banner",
5093
+ role: "status",
5094
+ className: cn(
5095
+ "flex w-full items-start gap-3 rounded-lg border px-4 py-3 text-sm",
5096
+ bannerToneClass[tone],
5097
+ className
5098
+ ),
5099
+ ...props,
5100
+ children: [
5101
+ icon ? /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { "data-banner-icon": true, className: "mt-0.5 shrink-0 [&_svg]:size-4", children: icon }) : null,
5102
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "min-w-0 flex-1", children: [
5103
+ title ? /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("p", { className: "font-medium", children: title }) : null,
5104
+ children ? /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: cn("text-muted-foreground", title && "mt-0.5"), children }) : null
5105
+ ] }),
5106
+ actions ? /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "flex shrink-0 items-center gap-2", children: actions }) : null,
5107
+ onDismiss ? /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
5108
+ "button",
5109
+ {
5110
+ type: "button",
5111
+ "aria-label": "Dismiss",
5112
+ onClick: onDismiss,
5113
+ className: "-mr-1 -mt-0.5 inline-flex size-7 shrink-0 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-foreground/10 hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-foreground/15",
5114
+ children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(import_lucide_react23.XIcon, { className: "size-4", "aria-hidden": true })
5115
+ }
5116
+ ) : null
5117
+ ]
5118
+ }
5119
+ );
5120
+ }
5121
+
5122
+ // src/ui/copy-button.tsx
5123
+ var React11 = __toESM(require("react"), 1);
5124
+ var import_lucide_react24 = require("lucide-react");
5125
+ var import_jsx_runtime59 = require("react/jsx-runtime");
5126
+ function CopyButton({
5127
+ value,
5128
+ timeout = 1500,
5129
+ onCopied,
5130
+ className,
5131
+ children,
5132
+ onClick,
5133
+ ...props
5134
+ }) {
5135
+ const [copied, setCopied] = React11.useState(false);
5136
+ const timer = React11.useRef(void 0);
5137
+ React11.useEffect(() => () => clearTimeout(timer.current), []);
5138
+ const handleClick = async (event) => {
5139
+ onClick?.(event);
5140
+ if (event.defaultPrevented) return;
5141
+ try {
5142
+ await navigator.clipboard.writeText(value);
5143
+ setCopied(true);
5144
+ onCopied?.(value);
5145
+ clearTimeout(timer.current);
5146
+ timer.current = setTimeout(() => setCopied(false), timeout);
5147
+ } catch {
5148
+ }
5149
+ };
5150
+ const Icon = copied ? import_lucide_react24.CheckIcon : import_lucide_react24.CopyIcon;
5151
+ return /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(
5152
+ "button",
5153
+ {
5154
+ type: "button",
5155
+ "data-slot": "copy-button",
5156
+ "data-copied": copied || void 0,
5157
+ "aria-label": copied ? "Copied" : "Copy",
5158
+ onClick: handleClick,
5159
+ className: cn(
5160
+ "inline-flex items-center justify-center gap-1.5 rounded-md text-sm font-medium text-muted-foreground transition-colors",
5161
+ "hover:bg-accent hover:text-foreground data-[copied=true]:text-emerald-600 dark:data-[copied=true]:text-emerald-400",
5162
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-foreground/15",
5163
+ children ? "h-8 px-2" : "size-8",
5164
+ className
5165
+ ),
5166
+ ...props,
5167
+ children: [
5168
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(Icon, { className: "size-4 shrink-0", "aria-hidden": true }),
5169
+ children
5170
+ ]
5171
+ }
5172
+ );
5173
+ }
5174
+
5175
+ // src/ui/snippet.tsx
5176
+ var import_jsx_runtime60 = require("react/jsx-runtime");
5177
+ function Snippet({
5178
+ children,
5179
+ symbol,
5180
+ hideCopy = false,
5181
+ className,
5182
+ ...props
5183
+ }) {
5184
+ return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(
5185
+ "div",
5186
+ {
5187
+ "data-slot": "snippet",
5188
+ className: cn(
5189
+ "flex items-center gap-2 rounded-lg border border-border bg-muted/40 py-1.5 pl-3 pr-1.5 font-mono text-sm",
5190
+ className
5191
+ ),
5192
+ ...props,
5193
+ children: [
5194
+ symbol ? /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("span", { "aria-hidden": true, className: "select-none text-muted-foreground", children: symbol }) : null,
5195
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("code", { className: "min-w-0 flex-1 truncate text-foreground", children }),
5196
+ hideCopy ? null : /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(CopyButton, { value: children, className: "size-7 shrink-0" })
5197
+ ]
5198
+ }
5199
+ );
5200
+ }
5201
+
5202
+ // src/ui/circular-progress.tsx
5203
+ var import_jsx_runtime61 = require("react/jsx-runtime");
5204
+ var toneClass = {
5205
+ primary: "text-primary",
5206
+ success: "text-emerald-500",
5207
+ warn: "text-amber-500",
5208
+ danger: "text-destructive"
5209
+ };
5210
+ function CircularProgress({
5211
+ value = 0,
5212
+ max = 100,
5213
+ size = 40,
5214
+ thickness = 4,
5215
+ showLabel = false,
5216
+ label,
5217
+ tone = "primary",
5218
+ className,
5219
+ ...props
5220
+ }) {
5221
+ const indeterminate = value === null || value === void 0;
5222
+ const radius = (size - thickness) / 2;
5223
+ const circumference = 2 * Math.PI * radius;
5224
+ const pct = indeterminate ? 0.25 : Math.min(Math.max(value / max, 0), 1);
5225
+ const dashOffset = circumference * (1 - pct);
5226
+ return /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)(
5227
+ "div",
5228
+ {
5229
+ "data-slot": "circular-progress",
5230
+ role: "progressbar",
5231
+ "aria-valuenow": indeterminate ? void 0 : Math.round(pct * 100),
5232
+ "aria-valuemin": 0,
5233
+ "aria-valuemax": 100,
5234
+ className: cn("relative inline-flex shrink-0", className),
5235
+ style: { width: size, height: size },
5236
+ ...props,
5237
+ children: [
5238
+ /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)(
5239
+ "svg",
5240
+ {
5241
+ width: size,
5242
+ height: size,
5243
+ viewBox: `0 0 ${size} ${size}`,
5244
+ className: cn(toneClass[tone], indeterminate && "animate-spin"),
5245
+ children: [
5246
+ /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
5247
+ "circle",
5248
+ {
5249
+ cx: size / 2,
5250
+ cy: size / 2,
5251
+ r: radius,
5252
+ fill: "none",
5253
+ strokeWidth: thickness,
5254
+ className: "stroke-current opacity-15"
5255
+ }
5256
+ ),
5257
+ /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
5258
+ "circle",
5259
+ {
5260
+ cx: size / 2,
5261
+ cy: size / 2,
5262
+ r: radius,
5263
+ fill: "none",
5264
+ strokeWidth: thickness,
5265
+ strokeLinecap: "round",
5266
+ strokeDasharray: circumference,
5267
+ strokeDashoffset: dashOffset,
5268
+ transform: `rotate(-90 ${size / 2} ${size / 2})`,
5269
+ className: cn("stroke-current", !indeterminate && "transition-[stroke-dashoffset] duration-500")
5270
+ }
5271
+ )
5272
+ ]
5273
+ }
5274
+ ),
5275
+ showLabel && !indeterminate ? /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("span", { className: "absolute inset-0 flex items-center justify-center text-[0.7rem] font-medium tabular-nums text-foreground", children: label ?? `${Math.round(pct * 100)}%` }) : null
5276
+ ]
5277
+ }
5278
+ );
5279
+ }
4483
5280
  // Annotate the CommonJS export names for ESM import in node:
4484
5281
  0 && (module.exports = {
5282
+ AVATAR_PRIMARY_FALLBACK_CLASS,
4485
5283
  Accordion,
4486
5284
  AccordionContent,
4487
5285
  AccordionItem,
@@ -4503,8 +5301,10 @@ var MemoPillSegmentedTabs = (0, import_react3.memo)(PillSegmentedTabs);
4503
5301
  AspectRatio,
4504
5302
  Avatar,
4505
5303
  AvatarFallback,
5304
+ AvatarGroup,
4506
5305
  AvatarImage,
4507
5306
  Badge,
5307
+ Banner,
4508
5308
  Breadcrumb,
4509
5309
  BreadcrumbEllipsis,
4510
5310
  BreadcrumbItem,
@@ -4529,6 +5329,7 @@ var MemoPillSegmentedTabs = (0, import_react3.memo)(PillSegmentedTabs);
4529
5329
  ChartTooltip,
4530
5330
  ChartTooltipContent,
4531
5331
  Checkbox,
5332
+ CircularProgress,
4532
5333
  Collapsible,
4533
5334
  CollapsibleContent,
4534
5335
  CollapsibleTrigger,
@@ -4567,6 +5368,7 @@ var MemoPillSegmentedTabs = (0, import_react3.memo)(PillSegmentedTabs);
4567
5368
  ContextMenuSubContent,
4568
5369
  ContextMenuSubTrigger,
4569
5370
  ContextMenuTrigger,
5371
+ CopyButton,
4570
5372
  DatePicker,
4571
5373
  DatePickerButton,
4572
5374
  DatePickerCalendar,
@@ -4642,6 +5444,7 @@ var MemoPillSegmentedTabs = (0, import_react3.memo)(PillSegmentedTabs);
4642
5444
  NavigationMenuList,
4643
5445
  NavigationMenuTrigger,
4644
5446
  NavigationMenuViewport,
5447
+ NumberField,
4645
5448
  Pagination,
4646
5449
  PaginationContent,
4647
5450
  PaginationEllipsis,
@@ -4657,6 +5460,7 @@ var MemoPillSegmentedTabs = (0, import_react3.memo)(PillSegmentedTabs);
4657
5460
  Progress,
4658
5461
  RadioGroup,
4659
5462
  RadioGroupItem,
5463
+ Rating,
4660
5464
  ScrollArea,
4661
5465
  ScrollBar,
4662
5466
  Select,
@@ -4681,7 +5485,9 @@ var MemoPillSegmentedTabs = (0, import_react3.memo)(PillSegmentedTabs);
4681
5485
  Shimmer,
4682
5486
  Skeleton,
4683
5487
  Slider,
5488
+ Snippet,
4684
5489
  Spinner,
5490
+ Stepper,
4685
5491
  Switch,
4686
5492
  Table,
4687
5493
  TableBody,
@@ -4691,8 +5497,10 @@ var MemoPillSegmentedTabs = (0, import_react3.memo)(PillSegmentedTabs);
4691
5497
  TableHead,
4692
5498
  TableHeader,
4693
5499
  TableRow,
5500
+ TagInput,
4694
5501
  Textarea,
4695
5502
  TimbalV2Button,
5503
+ Timeline,
4696
5504
  Toast,
4697
5505
  ToastAction,
4698
5506
  ToastClose,
@@ -4715,6 +5523,7 @@ var MemoPillSegmentedTabs = (0, import_react3.memo)(PillSegmentedTabs);
4715
5523
  TooltipProvider,
4716
5524
  TooltipTrigger,
4717
5525
  alertVariants,
5526
+ avatarChartVariantClass,
4718
5527
  badgeVariants,
4719
5528
  controlClass,
4720
5529
  controlSurfaceClass,