@glyphui/ui 0.2.0 → 0.4.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 (116) hide show
  1. package/README.md +65 -12
  2. package/dist/chart.d.ts +202 -0
  3. package/dist/chart.js +466 -0
  4. package/dist/color-mode-script-Bf7LYkOj.js +13 -0
  5. package/dist/color-mode-script-KdwItKN2.d.ts +16 -0
  6. package/dist/data-table.js +3 -2
  7. package/dist/{field-CCecIzdq.js → field-CVbywksE.js} +21 -5
  8. package/dist/{field-context-B6WOcK5m.js → field-context-7I-cWvvS.js} +3 -57
  9. package/dist/form.d.ts +11 -4
  10. package/dist/form.js +34 -8
  11. package/dist/glyph-context-DxGJrdvr.d.ts +50 -0
  12. package/dist/{index-BWK4czIG.d.ts → index-Bi7rZ6ba.d.ts} +11 -0
  13. package/dist/index.d.ts +2334 -283
  14. package/dist/index.js +2952 -326
  15. package/dist/react-router.d.ts +18 -0
  16. package/dist/react-router.js +44 -0
  17. package/dist/{states-Rp8wZ_jH.js → states-IvhjBgna.js} +2 -1
  18. package/dist/tv-DLbT66dC.js +70 -0
  19. package/dist/vite.d.ts +27 -0
  20. package/dist/vite.js +29 -0
  21. package/fonts.css +10 -0
  22. package/package.json +47 -5
  23. package/src/components/accordion/accordion.styles.ts +4 -4
  24. package/src/components/badge/badge.styles.ts +11 -16
  25. package/src/components/banner/banner.styles.ts +4 -4
  26. package/src/components/button/button.styles.ts +3 -1
  27. package/src/components/calendar/calendar.styles.ts +51 -0
  28. package/src/components/calendar/calendar.tsx +84 -0
  29. package/src/components/calendar/index.ts +3 -0
  30. package/src/components/carousel/carousel.styles.ts +43 -0
  31. package/src/components/carousel/carousel.tsx +278 -0
  32. package/src/components/carousel/index.ts +13 -0
  33. package/src/components/collapsible/collapsible.tsx +66 -0
  34. package/src/components/collapsible/index.ts +6 -0
  35. package/src/components/context-menu/context-menu.styles.ts +19 -0
  36. package/src/components/context-menu/context-menu.tsx +226 -0
  37. package/src/components/context-menu/index.ts +19 -0
  38. package/src/components/copy-button/copy-button.tsx +117 -0
  39. package/src/components/copy-button/index.ts +1 -0
  40. package/src/components/date-picker/date-picker.styles.ts +42 -0
  41. package/src/components/date-picker/date-picker.tsx +322 -0
  42. package/src/components/date-picker/index.ts +8 -0
  43. package/src/components/dropdown-menu/dropdown-menu.styles.ts +2 -2
  44. package/src/components/eyebrow/eyebrow.styles.ts +1 -1
  45. package/src/components/field/field-context.ts +2 -0
  46. package/src/components/field/field.styles.ts +4 -2
  47. package/src/components/field/field.tsx +25 -4
  48. package/src/components/file-upload/file-upload.styles.ts +43 -0
  49. package/src/components/file-upload/file-upload.tsx +343 -0
  50. package/src/components/file-upload/index.ts +10 -0
  51. package/src/components/hover-card/hover-card.tsx +41 -0
  52. package/src/components/hover-card/index.ts +1 -0
  53. package/src/components/input-otp/index.ts +10 -0
  54. package/src/components/input-otp/input-otp.styles.ts +38 -0
  55. package/src/components/input-otp/input-otp.tsx +116 -0
  56. package/src/components/link/link.styles.ts +1 -1
  57. package/src/components/modal/index.ts +2 -0
  58. package/src/components/modal/modal.styles.ts +20 -0
  59. package/src/components/modal/modal.tsx +111 -0
  60. package/src/components/navigation-menu/index.ts +14 -0
  61. package/src/components/navigation-menu/navigation-menu.styles.ts +48 -0
  62. package/src/components/navigation-menu/navigation-menu.tsx +208 -0
  63. package/src/components/number-input/index.ts +2 -0
  64. package/src/components/number-input/number-input.styles.ts +41 -0
  65. package/src/components/number-input/number-input.tsx +211 -0
  66. package/src/components/password-input/index.ts +7 -0
  67. package/src/components/password-input/password-input.styles.ts +30 -0
  68. package/src/components/password-input/password-input.tsx +127 -0
  69. package/src/components/prose/prose.tsx +1 -1
  70. package/src/components/resizable/index.ts +9 -0
  71. package/src/components/resizable/resizable.styles.ts +28 -0
  72. package/src/components/resizable/resizable.tsx +69 -0
  73. package/src/components/scroll-area/scroll-area.tsx +23 -1
  74. package/src/components/segmented-control/segmented-control.tsx +17 -2
  75. package/src/components/sheet/sheet.styles.ts +7 -7
  76. package/src/components/slider/slider.tsx +9 -2
  77. package/src/components/stepper/index.ts +2 -0
  78. package/src/components/stepper/stepper.styles.ts +74 -0
  79. package/src/components/stepper/stepper.tsx +138 -0
  80. package/src/components/tag-input/index.ts +2 -0
  81. package/src/components/tag-input/tag-input.styles.ts +39 -0
  82. package/src/components/tag-input/tag-input.tsx +198 -0
  83. package/src/components/text/text.styles.ts +4 -4
  84. package/src/components/timeline/index.ts +8 -0
  85. package/src/components/timeline/timeline.styles.ts +56 -0
  86. package/src/components/timeline/timeline.tsx +91 -0
  87. package/src/components/toggle/index.ts +9 -0
  88. package/src/components/toggle/toggle.styles.ts +39 -0
  89. package/src/components/toggle/toggle.tsx +61 -0
  90. package/src/components/tree-view/index.ts +2 -0
  91. package/src/components/tree-view/tree-view.styles.ts +42 -0
  92. package/src/components/tree-view/tree-view.tsx +274 -0
  93. package/src/components/visually-hidden/index.ts +1 -0
  94. package/src/components/visually-hidden/visually-hidden.tsx +10 -0
  95. package/src/index.ts +20 -0
  96. package/src/integrations/react-router.tsx +39 -0
  97. package/src/integrations/vite.test-d.ts +6 -0
  98. package/src/integrations/vite.test.ts +28 -0
  99. package/src/integrations/vite.ts +33 -0
  100. package/src/internal/dev.ts +12 -0
  101. package/src/patterns/app-shell/app-shell.styles.ts +1 -1
  102. package/src/patterns/app-shell/navbar.tsx +34 -16
  103. package/src/patterns/app-shell/sidebar.tsx +7 -2
  104. package/src/patterns/chart/chart-parts.tsx +179 -0
  105. package/src/patterns/chart/chart.styles.ts +35 -0
  106. package/src/patterns/chart/chart.tsx +386 -0
  107. package/src/patterns/chart/index.ts +13 -0
  108. package/src/patterns/form/form.tsx +48 -6
  109. package/src/patterns/form/index.ts +1 -0
  110. package/src/provider/color-mode-script.ts +28 -0
  111. package/src/provider/color-mode.tsx +14 -20
  112. package/src/provider/glyph-context.ts +38 -0
  113. package/src/provider/glyph-provider.tsx +16 -4
  114. package/src/provider/index.ts +4 -0
  115. package/src/provider/theme-scope.tsx +7 -3
  116. package/styles.css +88 -0
package/dist/index.js CHANGED
@@ -1,15 +1,22 @@
1
1
  "use client";
2
- import { A as useGlyph, C as MenuIcon, D as XIcon, E as SearchIcon, O as useComponentConfig, T as PanelLeftIcon, _ as CheckIcon$1, a as buttonStyles, b as ChevronRightIcon$1, c as tv, d as popover, f as themedBorder, i as IconButton, j as useLinkComponent, k as GlyphContext, l as twMergeConfig, n as useFieldControl, o as Spinner, p as transition, r as Button, s as spinnerStyles, t as FieldContext, u as focusRing, v as ChevronDownIcon, x as ChevronsUpDownIcon, y as ChevronLeftIcon } from "./field-context-B6WOcK5m.js";
3
- import { _ as inputStyles, a as Table, c as TableCell, d as TableRow, f as tableStyles, g as fieldControl, h as Input, i as stateStyles, l as TableHead, m as skeletonStyles, n as ErrorState, o as TableBody, p as Skeleton, r as LoadingState, s as TableCaption, t as EmptyState, u as TableHeader, v as Checkbox, y as checkboxStyles } from "./states-Rp8wZ_jH.js";
4
- import { i as labelStyles, n as fieldStyles, r as Label, t as Field } from "./field-CCecIzdq.js";
2
+ import { a as themedBorder, c as GlyphContext, d as useIsActive, f as useLinkComponent, i as popover, l as neverActive, n as twMergeConfig, o as transition, r as focusRing, s as useComponentConfig, t as tv, u as useGlyph } from "./tv-DLbT66dC.js";
3
+ import { _ as MenuIcon, a as buttonStyles, b as SearchIcon, d as CheckIcon$4, f as ChevronDownIcon$1, h as ChevronsUpDownIcon, i as IconButton, m as ChevronRightIcon$2, n as useFieldControl, o as Spinner, p as ChevronLeftIcon, r as Button, s as spinnerStyles, t as FieldContext, x as XIcon$2, y as PanelLeftIcon } from "./field-context-7I-cWvvS.js";
4
+ import { _ as inputStyles, a as Table, c as TableCell, d as TableRow, f as tableStyles, g as fieldControl, h as Input, i as stateStyles, l as TableHead, m as skeletonStyles, n as ErrorState, o as TableBody, p as Skeleton, r as LoadingState, s as TableCaption, t as EmptyState, u as TableHeader, v as Checkbox, y as checkboxStyles } from "./states-IvhjBgna.js";
5
+ import { i as labelStyles, n as fieldStyles, r as Label, t as Field } from "./field-CVbywksE.js";
6
+ import { n as DEFAULT_STORAGE_KEY, r as getColorModeScript, t as DARK_QUERY } from "./color-mode-script-Bf7LYkOj.js";
5
7
  import { defineTheme, defineTheme as defineTheme$1, presets as presets$1, scopeSelector, themeToCss, themeToCss as themeToCss$1, tokenVar } from "@glyphui/tokens";
6
- import { Accordion as Accordion$1, AlertDialog as AlertDialog$1, AspectRatio as AspectRatio$1, Avatar as Avatar$1, Dialog as Dialog$1, DropdownMenu as DropdownMenu$1, Popover as Popover$1, Progress as Progress$1, RadioGroup as RadioGroup$1, ScrollArea as ScrollArea$1, Select as Select$1, Separator as Separator$1, Slider as Slider$1, Slot, Switch as Switch$1, Tabs as Tabs$1, ToggleGroup, Tooltip as Tooltip$1 } from "radix-ui";
7
- import { createContext, useCallback, useContext, useEffect, useId, useMemo, useRef, useState, useSyncExternalStore } from "react";
8
+ import { Accordion as Accordion$1, AlertDialog as AlertDialog$1, AspectRatio as AspectRatio$1, Avatar as Avatar$1, Collapsible as Collapsible$1, ContextMenu as ContextMenu$1, Dialog as Dialog$1, DropdownMenu as DropdownMenu$1, HoverCard as HoverCard$1, NavigationMenu as NavigationMenu$1, Popover as Popover$1, Progress as Progress$1, RadioGroup as RadioGroup$1, ScrollArea as ScrollArea$1, Select as Select$1, Separator as Separator$1, Slider as Slider$1, Slot, Switch as Switch$1, Tabs as Tabs$1, Toggle as Toggle$1, ToggleGroup as ToggleGroup$1, Tooltip as Tooltip$1, VisuallyHidden as VisuallyHidden$1 } from "radix-ui";
9
+ import { Children, createContext, useCallback, useContext, useEffect, useId, useMemo, useRef, useState, useSyncExternalStore } from "react";
8
10
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
9
- import { Command as Command$1 } from "cmdk";
10
- import { Toaster as Toaster$1, toast } from "sonner";
11
+ import { DayPicker } from "react-day-picker";
12
+ import useEmblaCarousel from "embla-carousel-react";
11
13
  import { clsx } from "clsx";
12
14
  import { extendTailwindMerge } from "tailwind-merge";
15
+ import { Command as Command$1 } from "cmdk";
16
+ import { format, isSameDay } from "date-fns";
17
+ import { OTPInput, OTPInputContext, REGEXP_ONLY_CHARS, REGEXP_ONLY_DIGITS, REGEXP_ONLY_DIGITS_AND_CHARS } from "input-otp";
18
+ import { Panel, PanelGroup, PanelResizeHandle } from "react-resizable-panels";
19
+ import { Toaster as Toaster$1, toast } from "sonner";
13
20
  //#region src/components/accordion/accordion.styles.ts
14
21
  const accordionStyles = tv({
15
22
  slots: {
@@ -23,8 +30,8 @@ const accordionStyles = tv({
23
30
  "hover:text-foreground/80 disabled:cursor-not-allowed disabled:opacity-50"
24
31
  ],
25
32
  chevron: "size-4 shrink-0 text-faint-foreground transition-transform duration-(--glyph-duration-base) ease-standard group-data-[state=open]:rotate-180",
26
- content: "overflow-hidden text-small text-muted-foreground",
27
- contentInner: "pb-4 transition-[opacity,translate] duration-(--glyph-duration-base) ease-standard starting:-translate-y-1 starting:opacity-0"
33
+ content: "overflow-hidden text-small text-muted-foreground data-[state=open]:animate-collapse-down data-[state=closed]:animate-collapse-up",
34
+ contentInner: "pb-4"
28
35
  },
29
36
  variants: { variant: {
30
37
  default: { item: "border-b border-border last:border-b-0" },
@@ -38,7 +45,7 @@ const accordionStyles = tv({
38
45
  //#endregion
39
46
  //#region src/components/accordion/accordion.tsx
40
47
  const AccordionContext = createContext(null);
41
- function useParts$4() {
48
+ function useParts$6() {
42
49
  return useContext(AccordionContext) ?? {
43
50
  s: accordionStyles(),
44
51
  slots: {}
@@ -65,7 +72,7 @@ function Accordion(inProps) {
65
72
  });
66
73
  }
67
74
  function AccordionItem({ className, ...props }) {
68
- const { s, slots } = useParts$4();
75
+ const { s, slots } = useParts$6();
69
76
  return /* @__PURE__ */ jsx(Accordion$1.Item, {
70
77
  "data-slot": "accordion-item",
71
78
  className: s.item({ class: [slots.item, className] }),
@@ -73,19 +80,19 @@ function AccordionItem({ className, ...props }) {
73
80
  });
74
81
  }
75
82
  function AccordionTrigger({ className, children, ...props }) {
76
- const { s, slots } = useParts$4();
83
+ const { s, slots } = useParts$6();
77
84
  return /* @__PURE__ */ jsx(Accordion$1.Header, {
78
85
  className: s.header({ class: slots.header }),
79
86
  children: /* @__PURE__ */ jsxs(Accordion$1.Trigger, {
80
87
  "data-slot": "accordion-trigger",
81
88
  className: s.trigger({ class: [slots.trigger, className] }),
82
89
  ...props,
83
- children: [children, /* @__PURE__ */ jsx(ChevronDownIcon, { className: s.chevron({ class: slots.chevron }) })]
90
+ children: [children, /* @__PURE__ */ jsx(ChevronDownIcon$1, { className: s.chevron({ class: slots.chevron }) })]
84
91
  })
85
92
  });
86
93
  }
87
94
  function AccordionContent({ className, children, ...props }) {
88
- const { s, slots } = useParts$4();
95
+ const { s, slots } = useParts$6();
89
96
  return /* @__PURE__ */ jsx(Accordion$1.Content, {
90
97
  "data-slot": "accordion-content",
91
98
  className: s.content({ class: slots.content }),
@@ -285,7 +292,7 @@ function Alert(inProps) {
285
292
  }),
286
293
  onDismiss && /* @__PURE__ */ jsx(IconButton, {
287
294
  size: "sm",
288
- icon: /* @__PURE__ */ jsx(XIcon, {}),
295
+ icon: /* @__PURE__ */ jsx(XIcon$2, {}),
289
296
  "aria-label": dismissLabel,
290
297
  onClick: onDismiss,
291
298
  className: s.dismiss({ class: slots.dismiss })
@@ -309,7 +316,7 @@ const alertDialogStyles = tv({ slots: {
309
316
  } });
310
317
  //#endregion
311
318
  //#region src/components/alert-dialog/alert-dialog.tsx
312
- function useParts$3() {
319
+ function useParts$5() {
313
320
  const [, slots] = useComponentConfig("AlertDialog", {});
314
321
  return {
315
322
  s: alertDialogStyles(),
@@ -336,7 +343,7 @@ function AlertDialogContent(inProps) {
336
343
  })] });
337
344
  }
338
345
  function AlertDialogHeader({ className, ...props }) {
339
- const { s, slots } = useParts$3();
346
+ const { s, slots } = useParts$5();
340
347
  return /* @__PURE__ */ jsx("div", {
341
348
  "data-slot": "alert-dialog-header",
342
349
  className: s.header({ class: [slots.header, className] }),
@@ -344,7 +351,7 @@ function AlertDialogHeader({ className, ...props }) {
344
351
  });
345
352
  }
346
353
  function AlertDialogTitle({ className, ...props }) {
347
- const { s, slots } = useParts$3();
354
+ const { s, slots } = useParts$5();
348
355
  return /* @__PURE__ */ jsx(AlertDialog$1.Title, {
349
356
  "data-slot": "alert-dialog-title",
350
357
  className: s.title({ class: [slots.title, className] }),
@@ -352,7 +359,7 @@ function AlertDialogTitle({ className, ...props }) {
352
359
  });
353
360
  }
354
361
  function AlertDialogDescription({ className, ...props }) {
355
- const { s, slots } = useParts$3();
362
+ const { s, slots } = useParts$5();
356
363
  return /* @__PURE__ */ jsx(AlertDialog$1.Description, {
357
364
  "data-slot": "alert-dialog-description",
358
365
  className: s.description({ class: [slots.description, className] }),
@@ -360,7 +367,7 @@ function AlertDialogDescription({ className, ...props }) {
360
367
  });
361
368
  }
362
369
  function AlertDialogFooter({ className, ...props }) {
363
- const { s, slots } = useParts$3();
370
+ const { s, slots } = useParts$5();
364
371
  return /* @__PURE__ */ jsx("div", {
365
372
  "data-slot": "alert-dialog-footer",
366
373
  className: s.footer({ class: [slots.footer, className] }),
@@ -555,29 +562,29 @@ const tones = {
555
562
  outline: "border-border-strong text-foreground"
556
563
  },
557
564
  primary: {
558
- soft: "bg-primary/14 text-[color-mix(in_oklab,var(--color-primary)_62%,var(--color-foreground))]",
565
+ soft: "bg-primary/14 text-primary-text",
559
566
  solid: "bg-primary text-primary-foreground",
560
- outline: "border-primary/50 text-[color-mix(in_oklab,var(--color-primary)_62%,var(--color-foreground))]"
567
+ outline: "border-primary/50 text-primary-text"
561
568
  },
562
569
  success: {
563
- soft: "bg-success/14 text-[color-mix(in_oklab,var(--color-success)_62%,var(--color-foreground))]",
570
+ soft: "bg-success/14 text-success-text",
564
571
  solid: "bg-success text-success-foreground",
565
- outline: "border-success/50 text-[color-mix(in_oklab,var(--color-success)_62%,var(--color-foreground))]"
572
+ outline: "border-success/50 text-success-text"
566
573
  },
567
574
  warning: {
568
- soft: "bg-warning/16 text-[color-mix(in_oklab,var(--color-warning)_62%,var(--color-foreground))]",
575
+ soft: "bg-warning/14 text-warning-text",
569
576
  solid: "bg-warning text-warning-foreground",
570
- outline: "border-warning/50 text-[color-mix(in_oklab,var(--color-warning)_62%,var(--color-foreground))]"
577
+ outline: "border-warning/50 text-warning-text"
571
578
  },
572
579
  danger: {
573
- soft: "bg-danger/14 text-[color-mix(in_oklab,var(--color-danger)_62%,var(--color-foreground))]",
580
+ soft: "bg-danger/14 text-danger-text",
574
581
  solid: "bg-danger text-danger-foreground",
575
- outline: "border-danger/50 text-[color-mix(in_oklab,var(--color-danger)_62%,var(--color-foreground))]"
582
+ outline: "border-danger/50 text-danger-text"
576
583
  },
577
584
  info: {
578
- soft: "bg-info/14 text-[color-mix(in_oklab,var(--color-info)_62%,var(--color-foreground))]",
585
+ soft: "bg-info/14 text-info-text",
579
586
  solid: "bg-info text-info-foreground",
580
- outline: "border-info/50 text-[color-mix(in_oklab,var(--color-info)_62%,var(--color-foreground))]"
587
+ outline: "border-info/50 text-info-text"
581
588
  }
582
589
  };
583
590
  const badgeStyles = tv({
@@ -653,10 +660,10 @@ const bannerStyles = tv({
653
660
  icon: "text-muted-foreground"
654
661
  },
655
662
  primary: { root: "border-primary bg-primary text-primary-foreground" },
656
- info: { root: "border-info/25 bg-info/10 text-[color-mix(in_oklab,var(--color-info)_55%,var(--color-foreground))]" },
657
- success: { root: "border-success/25 bg-success/10 text-[color-mix(in_oklab,var(--color-success)_55%,var(--color-foreground))]" },
658
- warning: { root: "border-warning/30 bg-warning/14 text-[color-mix(in_oklab,var(--color-warning)_50%,var(--color-foreground))]" },
659
- danger: { root: "border-danger/25 bg-danger/10 text-[color-mix(in_oklab,var(--color-danger)_55%,var(--color-foreground))]" }
663
+ info: { root: "border-info/25 bg-info/10 text-info-text" },
664
+ success: { root: "border-success/25 bg-success/10 text-success-text" },
665
+ warning: { root: "border-warning/30 bg-warning/14 text-warning-text" },
666
+ danger: { root: "border-danger/25 bg-danger/10 text-danger-text" }
660
667
  } },
661
668
  defaultVariants: { tone: "neutral" }
662
669
  });
@@ -713,7 +720,7 @@ function Banner(inProps) {
713
720
  }),
714
721
  dismissible && /* @__PURE__ */ jsx(IconButton, {
715
722
  size: "sm",
716
- icon: /* @__PURE__ */ jsx(XIcon, {}),
723
+ icon: /* @__PURE__ */ jsx(XIcon$2, {}),
717
724
  "aria-label": dismissLabel,
718
725
  onClick: dismiss,
719
726
  className: s.dismiss({ class: slots.dismiss })
@@ -780,17 +787,17 @@ const breadcrumbStyles = tv({ slots: {
780
787
  } });
781
788
  //#endregion
782
789
  //#region src/components/breadcrumb/breadcrumb.tsx
783
- const s$2 = breadcrumbStyles();
784
- function useSlots$2() {
790
+ const s$5 = breadcrumbStyles();
791
+ function useSlots$4() {
785
792
  return useComponentConfig("Breadcrumb", {})[1];
786
793
  }
787
794
  /** Shows where the current page sits in the hierarchy. */
788
795
  function Breadcrumb({ items, separator, className, children, ...props }) {
789
- const slots = useSlots$2();
796
+ const slots = useSlots$4();
790
797
  return /* @__PURE__ */ jsx("nav", {
791
798
  "aria-label": "Breadcrumb",
792
799
  "data-slot": "breadcrumb",
793
- className: s$2.root({ class: [slots.root, className] }),
800
+ className: s$5.root({ class: [slots.root, className] }),
794
801
  ...props,
795
802
  children: items ? /* @__PURE__ */ jsx(BreadcrumbList, { children: items.map((item, index) => {
796
803
  const last = index === items.length - 1;
@@ -805,25 +812,25 @@ function Breadcrumb({ items, separator, className, children, ...props }) {
805
812
  });
806
813
  }
807
814
  function BreadcrumbList({ className, ...props }) {
808
- const slots = useSlots$2();
815
+ const slots = useSlots$4();
809
816
  return /* @__PURE__ */ jsx("ol", {
810
817
  "data-slot": "breadcrumb-list",
811
- className: s$2.list({ class: [slots.list, className] }),
818
+ className: s$5.list({ class: [slots.list, className] }),
812
819
  ...props
813
820
  });
814
821
  }
815
822
  function BreadcrumbItem({ className, ...props }) {
816
- const slots = useSlots$2();
823
+ const slots = useSlots$4();
817
824
  return /* @__PURE__ */ jsx("li", {
818
825
  "data-slot": "breadcrumb-item",
819
- className: s$2.item({ class: [slots.item, className] }),
826
+ className: s$5.item({ class: [slots.item, className] }),
820
827
  ...props
821
828
  });
822
829
  }
823
830
  function BreadcrumbLink({ href, className, children, asChild }) {
824
831
  const Link = useLinkComponent();
825
- const slots = useSlots$2();
826
- const classes = s$2.link({ class: [slots.link, className] });
832
+ const slots = useSlots$4();
833
+ const classes = s$5.link({ class: [slots.link, className] });
827
834
  if (asChild) return /* @__PURE__ */ jsx(Slot.Root, {
828
835
  "data-slot": "breadcrumb-link",
829
836
  className: classes,
@@ -836,23 +843,130 @@ function BreadcrumbLink({ href, className, children, asChild }) {
836
843
  });
837
844
  }
838
845
  function BreadcrumbPage({ className, ...props }) {
839
- const slots = useSlots$2();
846
+ const slots = useSlots$4();
840
847
  return /* @__PURE__ */ jsx("span", {
841
848
  "data-slot": "breadcrumb-page",
842
849
  "aria-current": "page",
843
- className: s$2.page({ class: [slots.page, className] }),
850
+ className: s$5.page({ class: [slots.page, className] }),
844
851
  ...props
845
852
  });
846
853
  }
847
854
  function BreadcrumbSeparator({ className, children, ...props }) {
848
- const slots = useSlots$2();
855
+ const slots = useSlots$4();
849
856
  return /* @__PURE__ */ jsx("span", {
850
857
  "data-slot": "breadcrumb-separator",
851
858
  role: "presentation",
852
859
  "aria-hidden": "true",
853
- className: s$2.separator({ class: [slots.separator, className] }),
860
+ className: s$5.separator({ class: [slots.separator, className] }),
854
861
  ...props,
855
- children: children ?? /* @__PURE__ */ jsx(ChevronRightIcon$1, {})
862
+ children: children ?? /* @__PURE__ */ jsx(ChevronRightIcon$2, {})
863
+ });
864
+ }
865
+ //#endregion
866
+ //#region src/components/calendar/calendar.styles.ts
867
+ const calendarStyles = tv({ slots: {
868
+ root: "relative w-fit p-3 text-small text-foreground",
869
+ months: "relative flex flex-col gap-6 sm:flex-row",
870
+ month: "grid content-start gap-3",
871
+ monthCaption: "flex h-8 items-center justify-center px-9",
872
+ captionLabel: "font-medium text-foreground",
873
+ nav: "pointer-events-none absolute inset-x-3 top-3 z-10 flex items-center justify-between",
874
+ navButton: [
875
+ "pointer-events-auto inline-flex size-8 cursor-pointer items-center justify-center rounded-md text-muted-foreground",
876
+ "hover:bg-muted hover:text-foreground disabled:pointer-events-none disabled:opacity-40",
877
+ transition,
878
+ focusRing
879
+ ],
880
+ chevron: "size-4",
881
+ monthGrid: "border-collapse",
882
+ weekdays: "",
883
+ weekday: "size-9 p-0 text-caption font-normal text-faint-foreground",
884
+ weeks: "",
885
+ week: "",
886
+ day: "size-9 p-0 text-center align-middle",
887
+ dayButton: [
888
+ "inline-flex size-9 cursor-pointer items-center justify-center rounded-md text-small tabular-nums text-foreground",
889
+ "hover:bg-muted",
890
+ transition,
891
+ focusRing
892
+ ],
893
+ today: "[&>button]:font-semibold [&:not([data-selected])>button]:text-primary-text",
894
+ selected: "[&>button]:bg-primary [&>button]:text-primary-foreground [&>button]:hover:bg-primary/90",
895
+ outside: "[&:not([data-selected])>button]:text-faint-foreground",
896
+ disabled: "[&>button]:pointer-events-none [&>button]:opacity-35 [&>button]:line-through",
897
+ rangeStart: "rounded-l-md bg-primary/14",
898
+ rangeMiddle: "bg-primary/14 [&>button]:rounded-none [&>button]:bg-transparent! [&>button]:text-foreground! [&>button]:hover:bg-primary/10!",
899
+ rangeEnd: "rounded-r-md bg-primary/14",
900
+ hidden: "invisible",
901
+ footer: "pt-2 text-small text-muted-foreground"
902
+ } });
903
+ //#endregion
904
+ //#region src/components/calendar/calendar.tsx
905
+ function ChevronIcon({ className, orientation = "left" }) {
906
+ const d = {
907
+ left: "m15 18-6-6 6-6",
908
+ right: "m9 18 6-6-6-6",
909
+ up: "m18 15-6-6-6 6",
910
+ down: "m6 9 6 6 6-6"
911
+ }[orientation];
912
+ return /* @__PURE__ */ jsx("svg", {
913
+ viewBox: "0 0 24 24",
914
+ fill: "none",
915
+ stroke: "currentColor",
916
+ strokeWidth: "2",
917
+ strokeLinecap: "round",
918
+ strokeLinejoin: "round",
919
+ "aria-hidden": "true",
920
+ className,
921
+ children: /* @__PURE__ */ jsx("path", { d })
922
+ });
923
+ }
924
+ /**
925
+ * A month grid for picking dates, built on react-day-picker and styled by the theme.
926
+ * Supports `mode="single" | "multiple" | "range"`, disabled dates and several months.
927
+ */
928
+ function Calendar(inProps) {
929
+ const [props, slots] = useComponentConfig("Calendar", inProps);
930
+ const { className, classNames, components, showOutsideDays = true, ...rest } = props;
931
+ const s = calendarStyles();
932
+ return /* @__PURE__ */ jsx(DayPicker, {
933
+ showOutsideDays,
934
+ className: s.root({ class: [slots.root, className] }),
935
+ classNames: {
936
+ months: s.months({ class: slots.months }),
937
+ month: s.month({ class: slots.month }),
938
+ month_caption: s.monthCaption({ class: slots.monthCaption }),
939
+ caption_label: s.captionLabel({ class: slots.captionLabel }),
940
+ nav: s.nav({ class: slots.nav }),
941
+ button_previous: s.navButton({ class: slots.navButton }),
942
+ button_next: s.navButton({ class: slots.navButton }),
943
+ chevron: s.chevron({ class: slots.chevron }),
944
+ month_grid: s.monthGrid({ class: slots.monthGrid }),
945
+ weekdays: s.weekdays({ class: slots.weekdays }),
946
+ weekday: s.weekday({ class: slots.weekday }),
947
+ weeks: s.weeks({ class: slots.weeks }),
948
+ week: s.week({ class: slots.week }),
949
+ day: s.day({ class: slots.day }),
950
+ day_button: s.dayButton({ class: slots.dayButton }),
951
+ today: s.today({ class: slots.today }),
952
+ selected: s.selected({ class: slots.selected }),
953
+ outside: s.outside({ class: slots.outside }),
954
+ disabled: s.disabled({ class: slots.disabled }),
955
+ range_start: s.rangeStart({ class: slots.rangeStart }),
956
+ range_middle: s.rangeMiddle({ class: slots.rangeMiddle }),
957
+ range_end: s.rangeEnd({ class: slots.rangeEnd }),
958
+ hidden: s.hidden({ class: slots.hidden }),
959
+ footer: s.footer({ class: slots.footer }),
960
+ ...classNames
961
+ },
962
+ components: {
963
+ Chevron: ({ className: chevronClass, orientation }) => /* @__PURE__ */ jsx(ChevronIcon, {
964
+ className: chevronClass,
965
+ orientation
966
+ }),
967
+ ...components
968
+ },
969
+ ...rest
856
970
  });
857
971
  }
858
972
  //#endregion
@@ -962,6 +1076,225 @@ function CardFooter({ className, ...props }) {
962
1076
  });
963
1077
  }
964
1078
  //#endregion
1079
+ //#region src/utils/cn.ts
1080
+ const twMerge = extendTailwindMerge(twMergeConfig);
1081
+ /** Joins class names and resolves Tailwind conflicts (last one wins). */
1082
+ function cn(...inputs) {
1083
+ return twMerge(clsx(inputs));
1084
+ }
1085
+ //#endregion
1086
+ //#region src/components/carousel/carousel.styles.ts
1087
+ const carouselStyles = tv({
1088
+ slots: {
1089
+ root: "relative",
1090
+ viewport: "overflow-hidden rounded-lg",
1091
+ container: "flex",
1092
+ item: "min-w-0 shrink-0 grow-0 basis-full",
1093
+ control: "absolute z-10 border-border bg-surface/85 shadow-sm backdrop-blur disabled:opacity-0",
1094
+ dots: "mt-3 flex items-center justify-center gap-1.5",
1095
+ dot: [
1096
+ "h-2 w-2 cursor-pointer rounded-pill bg-border-strong",
1097
+ transition,
1098
+ focusRing,
1099
+ "hover:bg-muted-foreground aria-[current=true]:w-5 aria-[current=true]:bg-primary"
1100
+ ]
1101
+ },
1102
+ variants: { orientation: {
1103
+ horizontal: {
1104
+ container: "-ml-4",
1105
+ item: "pl-4",
1106
+ control: "top-1/2 -translate-y-1/2"
1107
+ },
1108
+ vertical: {
1109
+ container: "-mt-4 h-full flex-col",
1110
+ item: "pt-4",
1111
+ control: "left-1/2 -translate-x-1/2 [&_svg]:rotate-90"
1112
+ }
1113
+ } },
1114
+ defaultVariants: { orientation: "horizontal" }
1115
+ });
1116
+ //#endregion
1117
+ //#region src/components/carousel/carousel.tsx
1118
+ const CarouselContext = createContext(null);
1119
+ function useCarousel() {
1120
+ const value = useContext(CarouselContext);
1121
+ if (!value) throw new Error("Carousel parts must be used inside <Carousel>.");
1122
+ return value;
1123
+ }
1124
+ /**
1125
+ * Swipeable, keyboard-accessible slides. Compose with CarouselContent, CarouselItem,
1126
+ * CarouselPrevious, CarouselNext and CarouselDots.
1127
+ */
1128
+ function Carousel(inProps) {
1129
+ const [props, slots] = useComponentConfig("Carousel", inProps);
1130
+ const { opts, plugins, loop, setApi, orientation = "horizontal", className, children, ...rest } = props;
1131
+ const [viewportRef, api] = useEmblaCarousel({
1132
+ ...opts,
1133
+ ...loop !== void 0 && { loop },
1134
+ axis: orientation === "horizontal" ? "x" : "y"
1135
+ }, plugins);
1136
+ const [state, setState] = useState({
1137
+ selectedIndex: 0,
1138
+ snapCount: 0,
1139
+ canScrollPrev: false,
1140
+ canScrollNext: false
1141
+ });
1142
+ const sync = useCallback((embla) => {
1143
+ setState({
1144
+ selectedIndex: embla.selectedScrollSnap(),
1145
+ snapCount: embla.scrollSnapList().length,
1146
+ canScrollPrev: embla.canScrollPrev(),
1147
+ canScrollNext: embla.canScrollNext()
1148
+ });
1149
+ }, []);
1150
+ useEffect(() => {
1151
+ if (!api) return;
1152
+ setApi?.(api);
1153
+ sync(api);
1154
+ api.on("select", sync).on("reInit", sync);
1155
+ return () => {
1156
+ api.off("select", sync).off("reInit", sync);
1157
+ };
1158
+ }, [
1159
+ api,
1160
+ setApi,
1161
+ sync
1162
+ ]);
1163
+ const scrollPrev = useCallback(() => api?.scrollPrev(), [api]);
1164
+ const scrollNext = useCallback(() => api?.scrollNext(), [api]);
1165
+ const scrollTo = useCallback((index) => api?.scrollTo(index), [api]);
1166
+ const onKeyDownCapture = (event) => {
1167
+ const prevKey = orientation === "horizontal" ? "ArrowLeft" : "ArrowUp";
1168
+ const nextKey = orientation === "horizontal" ? "ArrowRight" : "ArrowDown";
1169
+ if (event.key === prevKey) {
1170
+ event.preventDefault();
1171
+ scrollPrev();
1172
+ } else if (event.key === nextKey) {
1173
+ event.preventDefault();
1174
+ scrollNext();
1175
+ }
1176
+ };
1177
+ const s = carouselStyles({ orientation });
1178
+ return /* @__PURE__ */ jsx(CarouselContext.Provider, {
1179
+ value: {
1180
+ viewportRef,
1181
+ api,
1182
+ orientation,
1183
+ ...state,
1184
+ scrollPrev,
1185
+ scrollNext,
1186
+ scrollTo,
1187
+ s,
1188
+ slots
1189
+ },
1190
+ children: /* @__PURE__ */ jsx("section", {
1191
+ "data-slot": "carousel",
1192
+ "aria-roledescription": "carousel",
1193
+ onKeyDownCapture,
1194
+ className: s.root({ class: [slots.root, className] }),
1195
+ ...rest,
1196
+ children
1197
+ })
1198
+ });
1199
+ }
1200
+ const SlideContext = createContext(null);
1201
+ function CarouselContent({ className, children, ...props }) {
1202
+ const { viewportRef, s, slots } = useCarousel();
1203
+ const items = Children.toArray(children);
1204
+ return /* @__PURE__ */ jsx("div", {
1205
+ ref: viewportRef,
1206
+ "data-slot": "carousel-viewport",
1207
+ className: s.viewport({ class: slots.viewport }),
1208
+ children: /* @__PURE__ */ jsx("div", {
1209
+ "data-slot": "carousel-content",
1210
+ className: s.container({ class: [slots.container, className] }),
1211
+ ...props,
1212
+ children: items.map((child, index) => /* @__PURE__ */ jsx(SlideContext.Provider, {
1213
+ value: {
1214
+ index,
1215
+ total: items.length
1216
+ },
1217
+ children: child
1218
+ }, index))
1219
+ })
1220
+ });
1221
+ }
1222
+ function CarouselItem({ className, ...props }) {
1223
+ const { s, slots } = useCarousel();
1224
+ const slide = useContext(SlideContext);
1225
+ return /* @__PURE__ */ jsx("div", {
1226
+ role: "group",
1227
+ "aria-roledescription": "slide",
1228
+ "aria-label": slide ? `${slide.index + 1} of ${slide.total}` : void 0,
1229
+ "data-slot": "carousel-item",
1230
+ className: s.item({ class: [slots.item, className] }),
1231
+ ...props
1232
+ });
1233
+ }
1234
+ function Chevron({ direction }) {
1235
+ return /* @__PURE__ */ jsx("svg", {
1236
+ viewBox: "0 0 24 24",
1237
+ fill: "none",
1238
+ stroke: "currentColor",
1239
+ strokeWidth: "2",
1240
+ strokeLinecap: "round",
1241
+ strokeLinejoin: "round",
1242
+ "aria-hidden": "true",
1243
+ children: /* @__PURE__ */ jsx("path", { d: direction === "left" ? "m15 18-6-6 6-6" : "m9 18 6-6-6-6" })
1244
+ });
1245
+ }
1246
+ function CarouselPrevious({ className, icon, ...props }) {
1247
+ const { scrollPrev, canScrollPrev, orientation, s, slots } = useCarousel();
1248
+ return /* @__PURE__ */ jsx(IconButton, {
1249
+ variant: "outline",
1250
+ size: "sm",
1251
+ "aria-label": "Previous slide",
1252
+ icon: icon ?? /* @__PURE__ */ jsx(Chevron, { direction: "left" }),
1253
+ disabled: !canScrollPrev,
1254
+ onClick: scrollPrev,
1255
+ className: s.control({ class: [
1256
+ slots.control,
1257
+ orientation === "horizontal" ? "left-3" : "top-3",
1258
+ className
1259
+ ] }),
1260
+ ...props
1261
+ });
1262
+ }
1263
+ function CarouselNext({ className, icon, ...props }) {
1264
+ const { scrollNext, canScrollNext, orientation, s, slots } = useCarousel();
1265
+ return /* @__PURE__ */ jsx(IconButton, {
1266
+ variant: "outline",
1267
+ size: "sm",
1268
+ "aria-label": "Next slide",
1269
+ icon: icon ?? /* @__PURE__ */ jsx(Chevron, { direction: "right" }),
1270
+ disabled: !canScrollNext,
1271
+ onClick: scrollNext,
1272
+ className: s.control({ class: [
1273
+ slots.control,
1274
+ orientation === "horizontal" ? "right-3" : "bottom-3",
1275
+ className
1276
+ ] }),
1277
+ ...props
1278
+ });
1279
+ }
1280
+ /** One button per snap point; the current one is highlighted. */
1281
+ function CarouselDots({ className, ...props }) {
1282
+ const { snapCount, selectedIndex, scrollTo, s, slots } = useCarousel();
1283
+ if (snapCount < 2) return null;
1284
+ return /* @__PURE__ */ jsx("div", {
1285
+ "data-slot": "carousel-dots",
1286
+ className: s.dots({ class: [slots.dots, className] }),
1287
+ ...props,
1288
+ children: Array.from({ length: snapCount }, (_, index) => /* @__PURE__ */ jsx("button", {
1289
+ type: "button",
1290
+ "aria-label": `Go to slide ${index + 1}`,
1291
+ "aria-current": index === selectedIndex,
1292
+ onClick: () => scrollTo(index),
1293
+ className: cn(s.dot({ class: slots.dot }))
1294
+ }, index))
1295
+ });
1296
+ }
1297
+ //#endregion
965
1298
  //#region src/components/code/code.styles.ts
966
1299
  const codeStyles = tv({ slots: { base: "rounded-xs bg-muted px-[0.3em] py-[0.15em] font-mono text-[0.875em] text-foreground" } });
967
1300
  const codeBlockStyles = tv({
@@ -986,7 +1319,7 @@ function Code(inProps) {
986
1319
  ...rest
987
1320
  });
988
1321
  }
989
- const CopyIcon = () => /* @__PURE__ */ jsxs("svg", {
1322
+ const CopyIcon$1 = () => /* @__PURE__ */ jsxs("svg", {
990
1323
  viewBox: "0 0 24 24",
991
1324
  fill: "none",
992
1325
  stroke: "currentColor",
@@ -1021,7 +1354,7 @@ function CodeBlock(inProps) {
1021
1354
  };
1022
1355
  const copyButton = copyable ? /* @__PURE__ */ jsx(IconButton, {
1023
1356
  size: "sm",
1024
- icon: copied ? /* @__PURE__ */ jsx(CheckIcon$1, {}) : /* @__PURE__ */ jsx(CopyIcon, {}),
1357
+ icon: copied ? /* @__PURE__ */ jsx(CheckIcon$4, {}) : /* @__PURE__ */ jsx(CopyIcon$1, {}),
1025
1358
  "aria-label": copied ? "Copied" : "Copy code",
1026
1359
  onClick: copy,
1027
1360
  className: heading ? s.copy({ class: slots.copy }) : s.floatingCopy({ class: slots.floatingCopy })
@@ -1043,6 +1376,43 @@ function CodeBlock(inProps) {
1043
1376
  });
1044
1377
  }
1045
1378
  //#endregion
1379
+ //#region src/components/collapsible/collapsible.tsx
1380
+ const collapsibleStyles = tv({ slots: {
1381
+ root: "",
1382
+ trigger: "",
1383
+ content: "overflow-hidden data-[state=closed]:animate-collapse-up data-[state=open]:animate-collapse-down"
1384
+ } });
1385
+ const s$4 = collapsibleStyles();
1386
+ /**
1387
+ * Shows and hides one region, e.g. "Show advanced options". For a list of expandable
1388
+ * sections use Accordion.
1389
+ */
1390
+ function Collapsible(inProps) {
1391
+ const [{ className, ...rest }, slots] = useComponentConfig("Collapsible", inProps);
1392
+ return /* @__PURE__ */ jsx(Collapsible$1.Root, {
1393
+ "data-slot": "collapsible",
1394
+ className: s$4.root({ class: [slots.root, className] }),
1395
+ ...rest
1396
+ });
1397
+ }
1398
+ function CollapsibleTrigger({ className, ...props }) {
1399
+ const [, slots] = useComponentConfig("Collapsible", {});
1400
+ return /* @__PURE__ */ jsx(Collapsible$1.Trigger, {
1401
+ "data-slot": "collapsible-trigger",
1402
+ className: s$4.trigger({ class: [slots.trigger, className] }),
1403
+ ...props
1404
+ });
1405
+ }
1406
+ /** Animates its height open and closed; stays mounted until the closing animation ends. */
1407
+ function CollapsibleContent({ className, ...props }) {
1408
+ const [, slots] = useComponentConfig("Collapsible", {});
1409
+ return /* @__PURE__ */ jsx(Collapsible$1.Content, {
1410
+ "data-slot": "collapsible-content",
1411
+ className: s$4.content({ class: [slots.content, className] }),
1412
+ ...props
1413
+ });
1414
+ }
1415
+ //#endregion
1046
1416
  //#region src/hooks/use-controllable-state.ts
1047
1417
  /** State that can be controlled by a parent (`value` + `onChange`) or left uncontrolled. */
1048
1418
  function useControllableState({ value, defaultValue, onChange }) {
@@ -1215,7 +1585,7 @@ function Combobox(inProps) {
1215
1585
  className: s.itemDescription({ class: slots.itemDescription }),
1216
1586
  children: option.description
1217
1587
  })]
1218
- }), checked && /* @__PURE__ */ jsx(CheckIcon$1, { className: s.check({ class: slots.check }) })]
1588
+ }), checked && /* @__PURE__ */ jsx(CheckIcon$4, { className: s.check({ class: slots.check }) })]
1219
1589
  }, option.value);
1220
1590
  })]
1221
1591
  })]
@@ -1260,9 +1630,9 @@ const commandMenuStyles = tv({ slots: {
1260
1630
  } });
1261
1631
  //#endregion
1262
1632
  //#region src/components/command-menu/command-menu.tsx
1263
- const s$1 = commandMenuStyles();
1633
+ const s$3 = commandMenuStyles();
1264
1634
  const CommandMenuContext = createContext(null);
1265
- function useSlots$1() {
1635
+ function useSlots$3() {
1266
1636
  return useComponentConfig("CommandMenu", {})[1];
1267
1637
  }
1268
1638
  /**
@@ -1280,10 +1650,10 @@ function CommandMenu(inProps) {
1280
1650
  return /* @__PURE__ */ jsx(Dialog$1.Root, {
1281
1651
  open,
1282
1652
  onOpenChange: setOpen,
1283
- children: /* @__PURE__ */ jsxs(Dialog$1.Portal, { children: [/* @__PURE__ */ jsx(Dialog$1.Overlay, { className: s$1.overlay({ class: slots.overlay }) }), /* @__PURE__ */ jsxs(Dialog$1.Content, {
1653
+ children: /* @__PURE__ */ jsxs(Dialog$1.Portal, { children: [/* @__PURE__ */ jsx(Dialog$1.Overlay, { className: s$3.overlay({ class: slots.overlay }) }), /* @__PURE__ */ jsxs(Dialog$1.Content, {
1284
1654
  "data-slot": "command-menu",
1285
1655
  "aria-describedby": void 0,
1286
- className: s$1.content({ class: [slots.content, className] }),
1656
+ className: s$3.content({ class: [slots.content, className] }),
1287
1657
  children: [/* @__PURE__ */ jsx(Dialog$1.Title, {
1288
1658
  className: "sr-only",
1289
1659
  children: label
@@ -1301,51 +1671,51 @@ function CommandMenu(inProps) {
1301
1671
  }
1302
1672
  /** The palette without a dialog, for inline search panels. */
1303
1673
  function Command({ className, ...props }) {
1304
- const slots = useSlots$1();
1674
+ const slots = useSlots$3();
1305
1675
  return /* @__PURE__ */ jsx(Command$1, {
1306
1676
  "data-slot": "command",
1307
- className: s$1.root({ class: [slots.root, className] }),
1677
+ className: s$3.root({ class: [slots.root, className] }),
1308
1678
  ...props
1309
1679
  });
1310
1680
  }
1311
1681
  function CommandInput({ className, ...props }) {
1312
- const slots = useSlots$1();
1682
+ const slots = useSlots$3();
1313
1683
  return /* @__PURE__ */ jsxs("div", {
1314
- className: s$1.search({ class: slots.search }),
1684
+ className: s$3.search({ class: slots.search }),
1315
1685
  children: [/* @__PURE__ */ jsx(SearchIcon, {}), /* @__PURE__ */ jsx(Command$1.Input, {
1316
1686
  "data-slot": "command-input",
1317
- className: s$1.input({ class: [slots.input, className] }),
1687
+ className: s$3.input({ class: [slots.input, className] }),
1318
1688
  ...props
1319
1689
  })]
1320
1690
  });
1321
1691
  }
1322
1692
  function CommandList({ className, ...props }) {
1323
- const slots = useSlots$1();
1693
+ const slots = useSlots$3();
1324
1694
  return /* @__PURE__ */ jsx(Command$1.List, {
1325
1695
  "data-slot": "command-list",
1326
- className: s$1.list({ class: [slots.list, className] }),
1696
+ className: s$3.list({ class: [slots.list, className] }),
1327
1697
  ...props
1328
1698
  });
1329
1699
  }
1330
1700
  function CommandEmpty({ className, children = "No results", ...props }) {
1331
- const slots = useSlots$1();
1701
+ const slots = useSlots$3();
1332
1702
  return /* @__PURE__ */ jsx(Command$1.Empty, {
1333
1703
  "data-slot": "command-empty",
1334
- className: s$1.empty({ class: [slots.empty, className] }),
1704
+ className: s$3.empty({ class: [slots.empty, className] }),
1335
1705
  ...props,
1336
1706
  children
1337
1707
  });
1338
1708
  }
1339
1709
  function CommandGroup({ className, ...props }) {
1340
- const slots = useSlots$1();
1710
+ const slots = useSlots$3();
1341
1711
  return /* @__PURE__ */ jsx(Command$1.Group, {
1342
1712
  "data-slot": "command-group",
1343
- className: s$1.group({ class: [slots.group, className] }),
1713
+ className: s$3.group({ class: [slots.group, className] }),
1344
1714
  ...props
1345
1715
  });
1346
1716
  }
1347
1717
  function CommandItem({ icon, shortcut, closeOnSelect = true, onSelect, className, children, ...props }) {
1348
- const slots = useSlots$1();
1718
+ const slots = useSlots$3();
1349
1719
  const menu = useContext(CommandMenuContext);
1350
1720
  const keys = shortcut === void 0 ? [] : typeof shortcut === "string" ? [shortcut] : shortcut;
1351
1721
  return /* @__PURE__ */ jsxs(Command$1.Item, {
@@ -1354,20 +1724,20 @@ function CommandItem({ icon, shortcut, closeOnSelect = true, onSelect, className
1354
1724
  onSelect?.(value);
1355
1725
  if (closeOnSelect) menu?.close();
1356
1726
  },
1357
- className: s$1.item({ class: [slots.item, className] }),
1727
+ className: s$3.item({ class: [slots.item, className] }),
1358
1728
  ...props,
1359
1729
  children: [
1360
1730
  icon && /* @__PURE__ */ jsx("span", {
1361
- className: s$1.itemIcon({ class: slots.itemIcon }),
1731
+ className: s$3.itemIcon({ class: slots.itemIcon }),
1362
1732
  "aria-hidden": "true",
1363
1733
  children: icon
1364
1734
  }),
1365
1735
  /* @__PURE__ */ jsx("span", {
1366
- className: s$1.itemLabel({ class: slots.itemLabel }),
1736
+ className: s$3.itemLabel({ class: slots.itemLabel }),
1367
1737
  children
1368
1738
  }),
1369
1739
  keys.length > 0 && /* @__PURE__ */ jsx("span", {
1370
- className: s$1.shortcut({ class: slots.shortcut }),
1740
+ className: s$3.shortcut({ class: slots.shortcut }),
1371
1741
  "aria-hidden": "true",
1372
1742
  children: keys.map((key) => /* @__PURE__ */ jsx(Kbd, { children: key }, key))
1373
1743
  })
@@ -1375,10 +1745,10 @@ function CommandItem({ icon, shortcut, closeOnSelect = true, onSelect, className
1375
1745
  });
1376
1746
  }
1377
1747
  function CommandSeparator({ className, ...props }) {
1378
- const slots = useSlots$1();
1748
+ const slots = useSlots$3();
1379
1749
  return /* @__PURE__ */ jsx(Command$1.Separator, {
1380
1750
  "data-slot": "command-separator",
1381
- className: s$1.separator({ class: [slots.separator, className] }),
1751
+ className: s$3.separator({ class: [slots.separator, className] }),
1382
1752
  ...props
1383
1753
  });
1384
1754
  }
@@ -1421,89 +1791,631 @@ function Container({ size, asChild, className, ...props }) {
1421
1791
  });
1422
1792
  }
1423
1793
  //#endregion
1424
- //#region src/components/description-list/description-list.styles.ts
1425
- const descriptionListStyles = tv({
1794
+ //#region src/components/dropdown-menu/dropdown-menu.styles.ts
1795
+ const item = [
1796
+ "relative flex h-8 cursor-pointer select-none items-center gap-2 rounded-sm px-2 text-small text-foreground outline-none",
1797
+ "data-highlighted:bg-muted data-disabled:pointer-events-none data-disabled:opacity-50",
1798
+ "[&_svg]:size-4 [&_svg]:shrink-0"
1799
+ ];
1800
+ const dropdownMenuStyles = tv({
1426
1801
  slots: {
1427
- root: "grid w-full",
1428
- item: "grid min-w-0 gap-1",
1429
- term: "text-small text-muted-foreground",
1430
- details: "min-w-0 break-words text-small text-foreground"
1802
+ content: [popover, "min-w-48 max-h-(--radix-dropdown-menu-content-available-height) overflow-y-auto p-1"],
1803
+ item,
1804
+ icon: "flex size-4 shrink-0 items-center justify-center text-muted-foreground",
1805
+ indicator: "absolute left-2 flex size-4 items-center justify-center text-primary",
1806
+ label: "px-2 pt-1.5 pb-1 text-caption font-medium text-faint-foreground",
1807
+ separator: "-mx-1 my-1 h-px bg-border",
1808
+ shortcut: "ml-auto pl-4 font-mono text-caption tracking-wider text-faint-foreground",
1809
+ subTrigger: [...item, "data-[state=open]:bg-muted"],
1810
+ subContent: [popover, "min-w-40 p-1"]
1431
1811
  },
1432
1812
  variants: {
1433
- layout: {
1434
- stacked: { root: "gap-4" },
1435
- inline: { item: "sm:grid-cols-[minmax(0,12rem)_1fr] sm:gap-4" }
1813
+ tone: {
1814
+ default: {},
1815
+ danger: {
1816
+ item: "text-danger-text data-highlighted:bg-danger/10",
1817
+ icon: "text-danger-text"
1818
+ }
1436
1819
  },
1437
- dividers: {
1438
- true: {
1439
- root: "gap-0 divide-y divide-border",
1440
- item: "py-3 first:pt-0 last:pb-0"
1441
- },
1442
- false: {}
1443
- }
1820
+ inset: { true: {
1821
+ item: "pl-8",
1822
+ label: "pl-8"
1823
+ } }
1444
1824
  },
1445
- compoundVariants: [{
1446
- layout: "inline",
1447
- dividers: false,
1448
- class: { root: "gap-3" }
1449
- }],
1450
- defaultVariants: {
1451
- layout: "stacked",
1452
- dividers: false
1453
- }
1825
+ defaultVariants: { tone: "default" }
1454
1826
  });
1455
1827
  //#endregion
1456
- //#region src/components/description-list/description-list.tsx
1457
- const DescriptionListContext = createContext(null);
1458
- /**
1459
- * Label–value pairs, such as account details or order metadata.
1460
- * `layout="inline"` puts terms and details side by side from the `sm` breakpoint.
1461
- */
1462
- function DescriptionList(inProps) {
1463
- const [props, slots] = useComponentConfig("DescriptionList", inProps);
1464
- const { layout, dividers, className, ...rest } = props;
1465
- const s = descriptionListStyles({
1466
- layout,
1467
- dividers
1468
- });
1469
- return /* @__PURE__ */ jsx(DescriptionListContext.Provider, {
1470
- value: {
1471
- s,
1472
- slots
1473
- },
1474
- children: /* @__PURE__ */ jsx("dl", {
1475
- "data-slot": "description-list",
1476
- className: s.root({ class: [slots.root, className] }),
1477
- ...rest
1478
- })
1479
- });
1480
- }
1481
- function DescriptionItem({ term, children, className, ...props }) {
1482
- const ctx = useContext(DescriptionListContext);
1483
- const s = ctx?.s ?? descriptionListStyles();
1484
- const slots = ctx?.slots ?? {};
1485
- return /* @__PURE__ */ jsxs("div", {
1486
- "data-slot": "description-item",
1487
- className: s.item({ class: [slots.item, className] }),
1488
- ...props,
1489
- children: [/* @__PURE__ */ jsx("dt", {
1490
- "data-slot": "description-term",
1491
- className: s.term({ class: slots.term }),
1492
- children: term
1493
- }), /* @__PURE__ */ jsx("dd", {
1494
- "data-slot": "description-details",
1495
- className: s.details({ class: slots.details }),
1496
- children
1497
- })]
1498
- });
1499
- }
1828
+ //#region src/components/context-menu/context-menu.styles.ts
1829
+ /** Same look as DropdownMenu; only the available-height variable differs. */
1830
+ const contextMenuStyles = tv({
1831
+ extend: dropdownMenuStyles,
1832
+ slots: { content: "max-h-(--radix-context-menu-content-available-height)" }
1833
+ });
1500
1834
  //#endregion
1501
- //#region src/components/dialog/close-icon.tsx
1502
- /** Local close icon so overlay components stay self-contained. */
1503
- function CloseIcon(props) {
1504
- return /* @__PURE__ */ jsx("svg", {
1505
- xmlns: "http://www.w3.org/2000/svg",
1506
- width: "16",
1835
+ //#region src/components/context-menu/context-menu.tsx
1836
+ function useParts$4(tone, inset) {
1837
+ const [, slots] = useComponentConfig("ContextMenu", {});
1838
+ return {
1839
+ s: contextMenuStyles({
1840
+ tone,
1841
+ inset
1842
+ }),
1843
+ slots
1844
+ };
1845
+ }
1846
+ const svg$1 = {
1847
+ xmlns: "http://www.w3.org/2000/svg",
1848
+ viewBox: "0 0 24 24",
1849
+ fill: "none",
1850
+ stroke: "currentColor",
1851
+ strokeWidth: 2,
1852
+ strokeLinecap: "round",
1853
+ strokeLinejoin: "round"
1854
+ };
1855
+ const CheckIcon$3 = () => /* @__PURE__ */ jsx("svg", {
1856
+ "aria-hidden": "true",
1857
+ ...svg$1,
1858
+ children: /* @__PURE__ */ jsx("path", { d: "M20 6 9 17l-5-5" })
1859
+ });
1860
+ const DotIcon$1 = () => /* @__PURE__ */ jsx("svg", {
1861
+ "aria-hidden": "true",
1862
+ ...svg$1,
1863
+ children: /* @__PURE__ */ jsx("circle", {
1864
+ cx: "12",
1865
+ cy: "12",
1866
+ r: "4",
1867
+ fill: "currentColor"
1868
+ })
1869
+ });
1870
+ const ChevronRightIcon$1 = () => /* @__PURE__ */ jsx("svg", {
1871
+ "aria-hidden": "true",
1872
+ ...svg$1,
1873
+ children: /* @__PURE__ */ jsx("path", { d: "m9 18 6-6-6-6" })
1874
+ });
1875
+ /** A menu opened by right-click or long-press on an area. Same items as DropdownMenu. */
1876
+ const ContextMenu = ContextMenu$1.Root;
1877
+ const ContextMenuTrigger = ContextMenu$1.Trigger;
1878
+ const ContextMenuGroup = ContextMenu$1.Group;
1879
+ const ContextMenuRadioGroup = ContextMenu$1.RadioGroup;
1880
+ const ContextMenuSub = ContextMenu$1.Sub;
1881
+ function ContextMenuContent(inProps) {
1882
+ const [props, slots] = useComponentConfig("ContextMenu", inProps);
1883
+ const { className, ...rest } = props;
1884
+ const s = contextMenuStyles();
1885
+ return /* @__PURE__ */ jsx(ContextMenu$1.Portal, { children: /* @__PURE__ */ jsx(ContextMenu$1.Content, {
1886
+ "data-slot": "context-menu-content",
1887
+ className: s.content({ class: [slots.content, className] }),
1888
+ ...rest
1889
+ }) });
1890
+ }
1891
+ function ContextMenuItem({ icon, shortcut, tone, inset, className, children, ...props }) {
1892
+ const { s, slots } = useParts$4(tone, inset);
1893
+ return /* @__PURE__ */ jsxs(ContextMenu$1.Item, {
1894
+ "data-slot": "context-menu-item",
1895
+ "data-tone": tone ?? "default",
1896
+ className: s.item({ class: [slots.item, className] }),
1897
+ ...props,
1898
+ children: [
1899
+ icon && /* @__PURE__ */ jsx("span", {
1900
+ className: s.icon({ class: slots.icon }),
1901
+ "aria-hidden": "true",
1902
+ children: icon
1903
+ }),
1904
+ children,
1905
+ shortcut && /* @__PURE__ */ jsx(ContextMenuShortcut, { children: shortcut })
1906
+ ]
1907
+ });
1908
+ }
1909
+ function ContextMenuCheckboxItem({ className, children, ...props }) {
1910
+ const { s, slots } = useParts$4(void 0, true);
1911
+ return /* @__PURE__ */ jsxs(ContextMenu$1.CheckboxItem, {
1912
+ "data-slot": "context-menu-checkbox-item",
1913
+ className: s.item({ class: [slots.item, className] }),
1914
+ ...props,
1915
+ children: [/* @__PURE__ */ jsx("span", {
1916
+ className: s.indicator({ class: slots.indicator }),
1917
+ children: /* @__PURE__ */ jsx(ContextMenu$1.ItemIndicator, { children: /* @__PURE__ */ jsx(CheckIcon$3, {}) })
1918
+ }), children]
1919
+ });
1920
+ }
1921
+ function ContextMenuRadioItem({ className, children, ...props }) {
1922
+ const { s, slots } = useParts$4(void 0, true);
1923
+ return /* @__PURE__ */ jsxs(ContextMenu$1.RadioItem, {
1924
+ "data-slot": "context-menu-radio-item",
1925
+ className: s.item({ class: [slots.item, className] }),
1926
+ ...props,
1927
+ children: [/* @__PURE__ */ jsx("span", {
1928
+ className: s.indicator({ class: slots.indicator }),
1929
+ children: /* @__PURE__ */ jsx(ContextMenu$1.ItemIndicator, { children: /* @__PURE__ */ jsx(DotIcon$1, {}) })
1930
+ }), children]
1931
+ });
1932
+ }
1933
+ function ContextMenuLabel({ inset, className, ...props }) {
1934
+ const { s, slots } = useParts$4(void 0, inset);
1935
+ return /* @__PURE__ */ jsx(ContextMenu$1.Label, {
1936
+ "data-slot": "context-menu-label",
1937
+ className: s.label({ class: [slots.label, className] }),
1938
+ ...props
1939
+ });
1940
+ }
1941
+ function ContextMenuSeparator({ className, ...props }) {
1942
+ const { s, slots } = useParts$4();
1943
+ return /* @__PURE__ */ jsx(ContextMenu$1.Separator, {
1944
+ "data-slot": "context-menu-separator",
1945
+ className: s.separator({ class: [slots.separator, className] }),
1946
+ ...props
1947
+ });
1948
+ }
1949
+ function ContextMenuShortcut({ className, ...props }) {
1950
+ const { s, slots } = useParts$4();
1951
+ return /* @__PURE__ */ jsx("span", {
1952
+ "data-slot": "context-menu-shortcut",
1953
+ className: s.shortcut({ class: [slots.shortcut, className] }),
1954
+ ...props
1955
+ });
1956
+ }
1957
+ function ContextMenuSubTrigger({ icon, className, children, ...props }) {
1958
+ const { s, slots } = useParts$4();
1959
+ return /* @__PURE__ */ jsxs(ContextMenu$1.SubTrigger, {
1960
+ "data-slot": "context-menu-sub-trigger",
1961
+ className: s.subTrigger({ class: [slots.subTrigger, className] }),
1962
+ ...props,
1963
+ children: [
1964
+ icon && /* @__PURE__ */ jsx("span", {
1965
+ className: s.icon({ class: slots.icon }),
1966
+ "aria-hidden": "true",
1967
+ children: icon
1968
+ }),
1969
+ children,
1970
+ /* @__PURE__ */ jsx("span", {
1971
+ className: "ml-auto flex text-faint-foreground",
1972
+ children: /* @__PURE__ */ jsx(ChevronRightIcon$1, {})
1973
+ })
1974
+ ]
1975
+ });
1976
+ }
1977
+ function ContextMenuSubContent({ className, ...props }) {
1978
+ const { s, slots } = useParts$4();
1979
+ return /* @__PURE__ */ jsx(ContextMenu$1.Portal, { children: /* @__PURE__ */ jsx(ContextMenu$1.SubContent, {
1980
+ "data-slot": "context-menu-sub-content",
1981
+ className: s.subContent({ class: [slots.subContent, className] }),
1982
+ ...props
1983
+ }) });
1984
+ }
1985
+ //#endregion
1986
+ //#region src/components/copy-button/copy-button.tsx
1987
+ const copyButtonStyles = tv({ slots: {
1988
+ base: "",
1989
+ icon: "size-4",
1990
+ status: "sr-only"
1991
+ } });
1992
+ const icon$1 = {
1993
+ xmlns: "http://www.w3.org/2000/svg",
1994
+ viewBox: "0 0 24 24",
1995
+ fill: "none",
1996
+ stroke: "currentColor",
1997
+ strokeWidth: 2,
1998
+ strokeLinecap: "round",
1999
+ strokeLinejoin: "round"
2000
+ };
2001
+ const CopyIcon = ({ className }) => /* @__PURE__ */ jsxs("svg", {
2002
+ "aria-hidden": "true",
2003
+ ...icon$1,
2004
+ className,
2005
+ children: [/* @__PURE__ */ jsx("rect", {
2006
+ width: "13",
2007
+ height: "13",
2008
+ x: "9",
2009
+ y: "9",
2010
+ rx: "2"
2011
+ }), /* @__PURE__ */ jsx("path", { d: "M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" })]
2012
+ });
2013
+ const CheckIcon$2 = ({ className }) => /* @__PURE__ */ jsx("svg", {
2014
+ "aria-hidden": "true",
2015
+ ...icon$1,
2016
+ className,
2017
+ children: /* @__PURE__ */ jsx("path", { d: "M20 6 9 17l-5-5" })
2018
+ });
2019
+ /** Copies a value to the clipboard and confirms it visually and to screen readers. */
2020
+ function CopyButton(inProps) {
2021
+ const [props, slots] = useComponentConfig("CopyButton", inProps);
2022
+ const { value, children, copiedLabel = "Copied", timeout = 1500, onCopy, variant = "outline", className, "aria-label": ariaLabel, ...rest } = props;
2023
+ const [copied, setCopied] = useState(false);
2024
+ const timer = useRef(void 0);
2025
+ const s = copyButtonStyles();
2026
+ useEffect(() => () => clearTimeout(timer.current), []);
2027
+ const copy = async () => {
2028
+ try {
2029
+ await navigator.clipboard.writeText(value);
2030
+ } catch {
2031
+ return;
2032
+ }
2033
+ setCopied(true);
2034
+ onCopy?.(value);
2035
+ clearTimeout(timer.current);
2036
+ timer.current = setTimeout(() => setCopied(false), timeout);
2037
+ };
2038
+ const glyph = copied ? /* @__PURE__ */ jsx(CheckIcon$2, { className: s.icon({ class: slots.icon }) }) : /* @__PURE__ */ jsx(CopyIcon, { className: s.icon({ class: slots.icon }) });
2039
+ const iconOnly = children === void 0;
2040
+ return /* @__PURE__ */ jsxs(Button, {
2041
+ "data-slot": "copy-button",
2042
+ "data-copied": copied || void 0,
2043
+ variant,
2044
+ iconOnly,
2045
+ onClick: copy,
2046
+ className: s.base({ class: [slots.base, className] }),
2047
+ "aria-label": iconOnly ? copied ? copiedLabel : ariaLabel ?? "Copy" : ariaLabel,
2048
+ ...!iconOnly && { leftIcon: glyph },
2049
+ ...rest,
2050
+ children: [iconOnly ? glyph : copied ? copiedLabel : children, /* @__PURE__ */ jsx("span", {
2051
+ role: "status",
2052
+ className: s.status({ class: slots.status }),
2053
+ children: copied ? copiedLabel : ""
2054
+ })]
2055
+ });
2056
+ }
2057
+ //#endregion
2058
+ //#region src/components/popover/popover.tsx
2059
+ const popoverStyles = tv({ slots: {
2060
+ content: [popover, "w-72 max-w-[calc(100vw-2rem)] overflow-visible p-4 text-small outline-none"],
2061
+ arrow: "fill-raised"
2062
+ } });
2063
+ /** Floating content anchored to a trigger: quick settings, details, small forms. */
2064
+ const Popover = Popover$1.Root;
2065
+ const PopoverTrigger = Popover$1.Trigger;
2066
+ const PopoverAnchor = Popover$1.Anchor;
2067
+ const PopoverClose = Popover$1.Close;
2068
+ function PopoverContent(inProps) {
2069
+ const [props, slots] = useComponentConfig("Popover", inProps);
2070
+ const { showArrow = false, sideOffset = 6, align = "center", className, children, ...rest } = props;
2071
+ const s = popoverStyles();
2072
+ return /* @__PURE__ */ jsx(Popover$1.Portal, { children: /* @__PURE__ */ jsxs(Popover$1.Content, {
2073
+ "data-slot": "popover-content",
2074
+ sideOffset,
2075
+ align,
2076
+ className: s.content({ class: [slots.content, className] }),
2077
+ ...rest,
2078
+ children: [children, showArrow && /* @__PURE__ */ jsx(Popover$1.Arrow, {
2079
+ width: 12,
2080
+ height: 6,
2081
+ className: s.arrow({ class: slots.arrow })
2082
+ })]
2083
+ }) });
2084
+ }
2085
+ //#endregion
2086
+ //#region src/components/date-picker/date-picker.styles.ts
2087
+ const datePickerStyles = tv({
2088
+ slots: {
2089
+ trigger: [
2090
+ ...fieldControl,
2091
+ "flex cursor-pointer items-center gap-2 px-3 text-left outline-none",
2092
+ "focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/20",
2093
+ "disabled:cursor-not-allowed disabled:opacity-50"
2094
+ ],
2095
+ icon: "size-4 shrink-0 text-faint-foreground",
2096
+ value: "min-w-0 flex-1 truncate",
2097
+ placeholder: "min-w-0 flex-1 truncate text-faint-foreground",
2098
+ clear: "inline-flex size-5 shrink-0 cursor-pointer items-center justify-center rounded-xs text-faint-foreground hover:bg-muted hover:text-foreground [&>svg]:size-3.5",
2099
+ content: [popover, "w-auto p-0"],
2100
+ layout: "flex flex-col sm:flex-row",
2101
+ presets: "flex gap-1 overflow-x-auto border-b border-border p-2 sm:w-40 sm:flex-col sm:overflow-visible sm:border-r sm:border-b-0",
2102
+ preset: "shrink-0 cursor-pointer rounded-sm px-2 py-1.5 text-left text-small whitespace-nowrap text-muted-foreground hover:bg-muted hover:text-foreground data-[active=true]:bg-muted data-[active=true]:text-foreground"
2103
+ },
2104
+ variants: { size: {
2105
+ sm: { trigger: "h-(--glyph-control-sm) text-small" },
2106
+ md: { trigger: "h-(--glyph-control-md) text-small" },
2107
+ lg: { trigger: "h-(--glyph-control-lg) text-body" }
2108
+ } },
2109
+ defaultVariants: { size: "md" }
2110
+ });
2111
+ //#endregion
2112
+ //#region src/components/date-picker/date-picker.tsx
2113
+ function CalendarIcon({ className }) {
2114
+ return /* @__PURE__ */ jsxs("svg", {
2115
+ viewBox: "0 0 24 24",
2116
+ fill: "none",
2117
+ stroke: "currentColor",
2118
+ strokeWidth: "2",
2119
+ strokeLinecap: "round",
2120
+ strokeLinejoin: "round",
2121
+ "aria-hidden": "true",
2122
+ className,
2123
+ children: [/* @__PURE__ */ jsx("rect", {
2124
+ x: "3",
2125
+ y: "4",
2126
+ width: "18",
2127
+ height: "18",
2128
+ rx: "2"
2129
+ }), /* @__PURE__ */ jsx("path", { d: "M16 2v4M8 2v4M3 10h18" })]
2130
+ });
2131
+ }
2132
+ function ClearIcon() {
2133
+ return /* @__PURE__ */ jsx("svg", {
2134
+ viewBox: "0 0 24 24",
2135
+ fill: "none",
2136
+ stroke: "currentColor",
2137
+ strokeWidth: "2",
2138
+ strokeLinecap: "round",
2139
+ "aria-hidden": "true",
2140
+ children: /* @__PURE__ */ jsx("path", { d: "M18 6 6 18M6 6l12 12" })
2141
+ });
2142
+ }
2143
+ function disabledMatchers({ minDate, maxDate, disabledDates }) {
2144
+ const list = [];
2145
+ if (minDate) list.push({ before: minDate });
2146
+ if (maxDate) list.push({ after: maxDate });
2147
+ if (disabledDates) list.push(...Array.isArray(disabledDates) ? disabledDates : [disabledDates]);
2148
+ return list;
2149
+ }
2150
+ const iso = (date) => format(date, "yyyy-MM-dd");
2151
+ /** A date field that opens a calendar. Works with Field and with `Form` (`value` + `onValueChange`). */
2152
+ function DatePicker(inProps) {
2153
+ const [props, slots] = useComponentConfig("DatePicker", useFieldControl(inProps));
2154
+ const { value: valueProp, defaultValue, onValueChange, placeholder = "Pick a date", format: format$1 = "MMM d, yyyy", clearable = false, size, disabled, name, id, className, contentClassName, "aria-label": ariaLabel, "aria-describedby": ariaDescribedBy, "aria-invalid": ariaInvalid } = props;
2155
+ const [open, setOpen] = useState(false);
2156
+ const [value, setValue] = useControllableState({
2157
+ value: valueProp,
2158
+ defaultValue,
2159
+ onChange: onValueChange
2160
+ });
2161
+ const current = "value" in inProps ? valueProp : value;
2162
+ const s = datePickerStyles({ size });
2163
+ return /* @__PURE__ */ jsxs(Popover, {
2164
+ open,
2165
+ onOpenChange: setOpen,
2166
+ children: [
2167
+ /* @__PURE__ */ jsx(PopoverTrigger, {
2168
+ asChild: true,
2169
+ children: /* @__PURE__ */ jsxs("button", {
2170
+ type: "button",
2171
+ id,
2172
+ "data-slot": "date-picker",
2173
+ disabled,
2174
+ "aria-label": ariaLabel,
2175
+ "aria-describedby": ariaDescribedBy,
2176
+ "aria-invalid": ariaInvalid,
2177
+ className: s.trigger({ class: [slots.trigger, className] }),
2178
+ children: [
2179
+ /* @__PURE__ */ jsx(CalendarIcon, { className: s.icon({ class: slots.icon }) }),
2180
+ current ? /* @__PURE__ */ jsx("span", {
2181
+ className: s.value({ class: slots.value }),
2182
+ children: format(current, format$1)
2183
+ }) : /* @__PURE__ */ jsx("span", {
2184
+ className: s.placeholder({ class: slots.placeholder }),
2185
+ children: placeholder
2186
+ }),
2187
+ clearable && current && !disabled && /* @__PURE__ */ jsx("span", {
2188
+ role: "button",
2189
+ tabIndex: 0,
2190
+ "aria-label": "Clear date",
2191
+ className: s.clear({ class: slots.clear }),
2192
+ onPointerDown: (event) => event.stopPropagation(),
2193
+ onClick: (event) => {
2194
+ event.stopPropagation();
2195
+ setValue(void 0);
2196
+ },
2197
+ onKeyDown: (event) => {
2198
+ if (event.key === "Enter" || event.key === " ") {
2199
+ event.preventDefault();
2200
+ event.stopPropagation();
2201
+ setValue(void 0);
2202
+ }
2203
+ },
2204
+ children: /* @__PURE__ */ jsx(ClearIcon, {})
2205
+ })
2206
+ ]
2207
+ })
2208
+ }),
2209
+ /* @__PURE__ */ jsx(PopoverContent, {
2210
+ align: "start",
2211
+ className: s.content({ class: [slots.content, contentClassName] }),
2212
+ children: /* @__PURE__ */ jsx(Calendar, {
2213
+ mode: "single",
2214
+ selected: current,
2215
+ defaultMonth: current,
2216
+ disabled: disabledMatchers(props),
2217
+ onSelect: (date) => {
2218
+ setValue(date);
2219
+ if (date) setOpen(false);
2220
+ },
2221
+ autoFocus: true
2222
+ })
2223
+ }),
2224
+ name && /* @__PURE__ */ jsx("input", {
2225
+ type: "hidden",
2226
+ name,
2227
+ value: current ? iso(current) : ""
2228
+ })
2229
+ ]
2230
+ });
2231
+ }
2232
+ function formatRange(range, format$2) {
2233
+ if (!range.from) return "";
2234
+ if (!range.to || isSameDay(range.from, range.to)) return format(range.from, format$2);
2235
+ return `${format(range.from, format$2)} – ${format(range.to, format$2)}`;
2236
+ }
2237
+ /** A date-range field with a two-month calendar and optional presets. */
2238
+ function DateRangePicker(inProps) {
2239
+ const [props, slots] = useComponentConfig("DatePicker", useFieldControl(inProps));
2240
+ const { value: valueProp, defaultValue, onValueChange, presets, numberOfMonths = 2, placeholder = "Pick a date range", format = "MMM d, yyyy", clearable = false, size, disabled, name, id, className, contentClassName, "aria-label": ariaLabel, "aria-describedby": ariaDescribedBy, "aria-invalid": ariaInvalid } = props;
2241
+ const [open, setOpen] = useState(false);
2242
+ const [value, setValue] = useControllableState({
2243
+ value: valueProp,
2244
+ defaultValue,
2245
+ onChange: onValueChange
2246
+ });
2247
+ const current = "value" in inProps ? valueProp : value;
2248
+ const s = datePickerStyles({ size });
2249
+ const label = current ? formatRange(current, format) : "";
2250
+ return /* @__PURE__ */ jsxs(Popover, {
2251
+ open,
2252
+ onOpenChange: setOpen,
2253
+ children: [
2254
+ /* @__PURE__ */ jsx(PopoverTrigger, {
2255
+ asChild: true,
2256
+ children: /* @__PURE__ */ jsxs("button", {
2257
+ type: "button",
2258
+ id,
2259
+ "data-slot": "date-range-picker",
2260
+ disabled,
2261
+ "aria-label": ariaLabel,
2262
+ "aria-describedby": ariaDescribedBy,
2263
+ "aria-invalid": ariaInvalid,
2264
+ className: s.trigger({ class: [slots.trigger, className] }),
2265
+ children: [
2266
+ /* @__PURE__ */ jsx(CalendarIcon, { className: s.icon({ class: slots.icon }) }),
2267
+ label ? /* @__PURE__ */ jsx("span", {
2268
+ className: s.value({ class: slots.value }),
2269
+ children: label
2270
+ }) : /* @__PURE__ */ jsx("span", {
2271
+ className: s.placeholder({ class: slots.placeholder }),
2272
+ children: placeholder
2273
+ }),
2274
+ clearable && current?.from && !disabled && /* @__PURE__ */ jsx("span", {
2275
+ role: "button",
2276
+ tabIndex: 0,
2277
+ "aria-label": "Clear dates",
2278
+ className: s.clear({ class: slots.clear }),
2279
+ onPointerDown: (event) => event.stopPropagation(),
2280
+ onClick: (event) => {
2281
+ event.stopPropagation();
2282
+ setValue(void 0);
2283
+ },
2284
+ onKeyDown: (event) => {
2285
+ if (event.key === "Enter" || event.key === " ") {
2286
+ event.preventDefault();
2287
+ event.stopPropagation();
2288
+ setValue(void 0);
2289
+ }
2290
+ },
2291
+ children: /* @__PURE__ */ jsx(ClearIcon, {})
2292
+ })
2293
+ ]
2294
+ })
2295
+ }),
2296
+ /* @__PURE__ */ jsx(PopoverContent, {
2297
+ align: "start",
2298
+ className: s.content({ class: [slots.content, contentClassName] }),
2299
+ children: /* @__PURE__ */ jsxs("div", {
2300
+ className: s.layout({ class: slots.layout }),
2301
+ children: [presets && presets.length > 0 && /* @__PURE__ */ jsx("div", {
2302
+ className: s.presets({ class: slots.presets }),
2303
+ children: presets.map((preset) => /* @__PURE__ */ jsx("button", {
2304
+ type: "button",
2305
+ className: s.preset({ class: slots.preset }),
2306
+ onClick: () => {
2307
+ setValue(preset.range());
2308
+ setOpen(false);
2309
+ },
2310
+ children: preset.label
2311
+ }, preset.label))
2312
+ }), /* @__PURE__ */ jsx(Calendar, {
2313
+ mode: "range",
2314
+ selected: current,
2315
+ defaultMonth: current?.from,
2316
+ numberOfMonths,
2317
+ disabled: disabledMatchers(props),
2318
+ onSelect: (range) => setValue(range),
2319
+ autoFocus: true
2320
+ })]
2321
+ })
2322
+ }),
2323
+ name && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("input", {
2324
+ type: "hidden",
2325
+ name: `${name}.from`,
2326
+ value: current?.from ? iso(current.from) : ""
2327
+ }), /* @__PURE__ */ jsx("input", {
2328
+ type: "hidden",
2329
+ name: `${name}.to`,
2330
+ value: current?.to ? iso(current.to) : ""
2331
+ })] })
2332
+ ]
2333
+ });
2334
+ }
2335
+ //#endregion
2336
+ //#region src/components/description-list/description-list.styles.ts
2337
+ const descriptionListStyles = tv({
2338
+ slots: {
2339
+ root: "grid w-full",
2340
+ item: "grid min-w-0 gap-1",
2341
+ term: "text-small text-muted-foreground",
2342
+ details: "min-w-0 break-words text-small text-foreground"
2343
+ },
2344
+ variants: {
2345
+ layout: {
2346
+ stacked: { root: "gap-4" },
2347
+ inline: { item: "sm:grid-cols-[minmax(0,12rem)_1fr] sm:gap-4" }
2348
+ },
2349
+ dividers: {
2350
+ true: {
2351
+ root: "gap-0 divide-y divide-border",
2352
+ item: "py-3 first:pt-0 last:pb-0"
2353
+ },
2354
+ false: {}
2355
+ }
2356
+ },
2357
+ compoundVariants: [{
2358
+ layout: "inline",
2359
+ dividers: false,
2360
+ class: { root: "gap-3" }
2361
+ }],
2362
+ defaultVariants: {
2363
+ layout: "stacked",
2364
+ dividers: false
2365
+ }
2366
+ });
2367
+ //#endregion
2368
+ //#region src/components/description-list/description-list.tsx
2369
+ const DescriptionListContext = createContext(null);
2370
+ /**
2371
+ * Label–value pairs, such as account details or order metadata.
2372
+ * `layout="inline"` puts terms and details side by side from the `sm` breakpoint.
2373
+ */
2374
+ function DescriptionList(inProps) {
2375
+ const [props, slots] = useComponentConfig("DescriptionList", inProps);
2376
+ const { layout, dividers, className, ...rest } = props;
2377
+ const s = descriptionListStyles({
2378
+ layout,
2379
+ dividers
2380
+ });
2381
+ return /* @__PURE__ */ jsx(DescriptionListContext.Provider, {
2382
+ value: {
2383
+ s,
2384
+ slots
2385
+ },
2386
+ children: /* @__PURE__ */ jsx("dl", {
2387
+ "data-slot": "description-list",
2388
+ className: s.root({ class: [slots.root, className] }),
2389
+ ...rest
2390
+ })
2391
+ });
2392
+ }
2393
+ function DescriptionItem({ term, children, className, ...props }) {
2394
+ const ctx = useContext(DescriptionListContext);
2395
+ const s = ctx?.s ?? descriptionListStyles();
2396
+ const slots = ctx?.slots ?? {};
2397
+ return /* @__PURE__ */ jsxs("div", {
2398
+ "data-slot": "description-item",
2399
+ className: s.item({ class: [slots.item, className] }),
2400
+ ...props,
2401
+ children: [/* @__PURE__ */ jsx("dt", {
2402
+ "data-slot": "description-term",
2403
+ className: s.term({ class: slots.term }),
2404
+ children: term
2405
+ }), /* @__PURE__ */ jsx("dd", {
2406
+ "data-slot": "description-details",
2407
+ className: s.details({ class: slots.details }),
2408
+ children
2409
+ })]
2410
+ });
2411
+ }
2412
+ //#endregion
2413
+ //#region src/components/dialog/close-icon.tsx
2414
+ /** Local close icon so overlay components stay self-contained. */
2415
+ function CloseIcon(props) {
2416
+ return /* @__PURE__ */ jsx("svg", {
2417
+ xmlns: "http://www.w3.org/2000/svg",
2418
+ width: "16",
1507
2419
  height: "16",
1508
2420
  viewBox: "0 0 24 24",
1509
2421
  fill: "none",
@@ -1547,7 +2459,7 @@ const dialogStyles = tv({
1547
2459
  });
1548
2460
  //#endregion
1549
2461
  //#region src/components/dialog/dialog.tsx
1550
- function useParts$2() {
2462
+ function useParts$3() {
1551
2463
  const [, slots] = useComponentConfig("Dialog", {});
1552
2464
  return {
1553
2465
  s: dialogStyles(),
@@ -1578,7 +2490,7 @@ function DialogContent(inProps) {
1578
2490
  })] });
1579
2491
  }
1580
2492
  function DialogHeader({ className, ...props }) {
1581
- const { s, slots } = useParts$2();
2493
+ const { s, slots } = useParts$3();
1582
2494
  return /* @__PURE__ */ jsx("div", {
1583
2495
  "data-slot": "dialog-header",
1584
2496
  className: s.header({ class: [slots.header, className] }),
@@ -1586,7 +2498,7 @@ function DialogHeader({ className, ...props }) {
1586
2498
  });
1587
2499
  }
1588
2500
  function DialogTitle({ className, ...props }) {
1589
- const { s, slots } = useParts$2();
2501
+ const { s, slots } = useParts$3();
1590
2502
  return /* @__PURE__ */ jsx(Dialog$1.Title, {
1591
2503
  "data-slot": "dialog-title",
1592
2504
  className: s.title({ class: [slots.title, className] }),
@@ -1594,7 +2506,7 @@ function DialogTitle({ className, ...props }) {
1594
2506
  });
1595
2507
  }
1596
2508
  function DialogDescription({ className, ...props }) {
1597
- const { s, slots } = useParts$2();
2509
+ const { s, slots } = useParts$3();
1598
2510
  return /* @__PURE__ */ jsx(Dialog$1.Description, {
1599
2511
  "data-slot": "dialog-description",
1600
2512
  className: s.description({ class: [slots.description, className] }),
@@ -1602,7 +2514,7 @@ function DialogDescription({ className, ...props }) {
1602
2514
  });
1603
2515
  }
1604
2516
  function DialogBody({ className, ...props }) {
1605
- const { s, slots } = useParts$2();
2517
+ const { s, slots } = useParts$3();
1606
2518
  return /* @__PURE__ */ jsx("div", {
1607
2519
  "data-slot": "dialog-body",
1608
2520
  className: s.body({ class: [slots.body, className] }),
@@ -1610,7 +2522,7 @@ function DialogBody({ className, ...props }) {
1610
2522
  });
1611
2523
  }
1612
2524
  function DialogFooter({ className, ...props }) {
1613
- const { s, slots } = useParts$2();
2525
+ const { s, slots } = useParts$3();
1614
2526
  return /* @__PURE__ */ jsx("div", {
1615
2527
  "data-slot": "dialog-footer",
1616
2528
  className: s.footer({ class: [slots.footer, className] }),
@@ -1618,42 +2530,8 @@ function DialogFooter({ className, ...props }) {
1618
2530
  });
1619
2531
  }
1620
2532
  //#endregion
1621
- //#region src/components/dropdown-menu/dropdown-menu.styles.ts
1622
- const item = [
1623
- "relative flex h-8 cursor-pointer select-none items-center gap-2 rounded-sm px-2 text-small text-foreground outline-none",
1624
- "data-highlighted:bg-muted data-disabled:pointer-events-none data-disabled:opacity-50",
1625
- "[&_svg]:size-4 [&_svg]:shrink-0"
1626
- ];
1627
- const dropdownMenuStyles = tv({
1628
- slots: {
1629
- content: [popover, "min-w-48 max-h-(--radix-dropdown-menu-content-available-height) overflow-y-auto p-1"],
1630
- item,
1631
- icon: "flex size-4 shrink-0 items-center justify-center text-muted-foreground",
1632
- indicator: "absolute left-2 flex size-4 items-center justify-center text-primary",
1633
- label: "px-2 pt-1.5 pb-1 text-caption font-medium text-faint-foreground",
1634
- separator: "-mx-1 my-1 h-px bg-border",
1635
- shortcut: "ml-auto pl-4 font-mono text-caption tracking-wider text-faint-foreground",
1636
- subTrigger: [...item, "data-[state=open]:bg-muted"],
1637
- subContent: [popover, "min-w-40 p-1"]
1638
- },
1639
- variants: {
1640
- tone: {
1641
- default: {},
1642
- danger: {
1643
- item: "text-danger data-highlighted:bg-danger/10",
1644
- icon: "text-danger"
1645
- }
1646
- },
1647
- inset: { true: {
1648
- item: "pl-8",
1649
- label: "pl-8"
1650
- } }
1651
- },
1652
- defaultVariants: { tone: "default" }
1653
- });
1654
- //#endregion
1655
2533
  //#region src/components/dropdown-menu/dropdown-menu.tsx
1656
- function useParts$1(tone, inset) {
2534
+ function useParts$2(tone, inset) {
1657
2535
  const [, slots] = useComponentConfig("DropdownMenu", {});
1658
2536
  return {
1659
2537
  s: dropdownMenuStyles({
@@ -1672,7 +2550,7 @@ const svg = {
1672
2550
  strokeLinecap: "round",
1673
2551
  strokeLinejoin: "round"
1674
2552
  };
1675
- const CheckIcon = () => /* @__PURE__ */ jsx("svg", {
2553
+ const CheckIcon$1 = () => /* @__PURE__ */ jsx("svg", {
1676
2554
  "aria-hidden": "true",
1677
2555
  ...svg,
1678
2556
  children: /* @__PURE__ */ jsx("path", { d: "M20 6 9 17l-5-5" })
@@ -1711,7 +2589,7 @@ function DropdownMenuContent(inProps) {
1711
2589
  }) });
1712
2590
  }
1713
2591
  function DropdownMenuItem({ icon, shortcut, tone, inset, className, children, ...props }) {
1714
- const { s, slots } = useParts$1(tone, inset);
2592
+ const { s, slots } = useParts$2(tone, inset);
1715
2593
  return /* @__PURE__ */ jsxs(DropdownMenu$1.Item, {
1716
2594
  "data-slot": "dropdown-menu-item",
1717
2595
  "data-tone": tone ?? "default",
@@ -1729,19 +2607,19 @@ function DropdownMenuItem({ icon, shortcut, tone, inset, className, children, ..
1729
2607
  });
1730
2608
  }
1731
2609
  function DropdownMenuCheckboxItem({ className, children, ...props }) {
1732
- const { s, slots } = useParts$1(void 0, true);
2610
+ const { s, slots } = useParts$2(void 0, true);
1733
2611
  return /* @__PURE__ */ jsxs(DropdownMenu$1.CheckboxItem, {
1734
2612
  "data-slot": "dropdown-menu-checkbox-item",
1735
2613
  className: s.item({ class: [slots.item, className] }),
1736
2614
  ...props,
1737
2615
  children: [/* @__PURE__ */ jsx("span", {
1738
2616
  className: s.indicator({ class: slots.indicator }),
1739
- children: /* @__PURE__ */ jsx(DropdownMenu$1.ItemIndicator, { children: /* @__PURE__ */ jsx(CheckIcon, {}) })
2617
+ children: /* @__PURE__ */ jsx(DropdownMenu$1.ItemIndicator, { children: /* @__PURE__ */ jsx(CheckIcon$1, {}) })
1740
2618
  }), children]
1741
2619
  });
1742
2620
  }
1743
2621
  function DropdownMenuRadioItem({ className, children, ...props }) {
1744
- const { s, slots } = useParts$1(void 0, true);
2622
+ const { s, slots } = useParts$2(void 0, true);
1745
2623
  return /* @__PURE__ */ jsxs(DropdownMenu$1.RadioItem, {
1746
2624
  "data-slot": "dropdown-menu-radio-item",
1747
2625
  className: s.item({ class: [slots.item, className] }),
@@ -1753,7 +2631,7 @@ function DropdownMenuRadioItem({ className, children, ...props }) {
1753
2631
  });
1754
2632
  }
1755
2633
  function DropdownMenuLabel({ inset, className, ...props }) {
1756
- const { s, slots } = useParts$1(void 0, inset);
2634
+ const { s, slots } = useParts$2(void 0, inset);
1757
2635
  return /* @__PURE__ */ jsx(DropdownMenu$1.Label, {
1758
2636
  "data-slot": "dropdown-menu-label",
1759
2637
  className: s.label({ class: [slots.label, className] }),
@@ -1761,7 +2639,7 @@ function DropdownMenuLabel({ inset, className, ...props }) {
1761
2639
  });
1762
2640
  }
1763
2641
  function DropdownMenuSeparator({ className, ...props }) {
1764
- const { s, slots } = useParts$1();
2642
+ const { s, slots } = useParts$2();
1765
2643
  return /* @__PURE__ */ jsx(DropdownMenu$1.Separator, {
1766
2644
  "data-slot": "dropdown-menu-separator",
1767
2645
  className: s.separator({ class: [slots.separator, className] }),
@@ -1769,7 +2647,7 @@ function DropdownMenuSeparator({ className, ...props }) {
1769
2647
  });
1770
2648
  }
1771
2649
  function DropdownMenuShortcut({ className, ...props }) {
1772
- const { s, slots } = useParts$1();
2650
+ const { s, slots } = useParts$2();
1773
2651
  return /* @__PURE__ */ jsx("span", {
1774
2652
  "data-slot": "dropdown-menu-shortcut",
1775
2653
  className: s.shortcut({ class: [slots.shortcut, className] }),
@@ -1777,7 +2655,7 @@ function DropdownMenuShortcut({ className, ...props }) {
1777
2655
  });
1778
2656
  }
1779
2657
  function DropdownMenuSubTrigger({ icon, className, children, ...props }) {
1780
- const { s, slots } = useParts$1();
2658
+ const { s, slots } = useParts$2();
1781
2659
  return /* @__PURE__ */ jsxs(DropdownMenu$1.SubTrigger, {
1782
2660
  "data-slot": "dropdown-menu-sub-trigger",
1783
2661
  className: s.subTrigger({ class: [slots.subTrigger, className] }),
@@ -1797,7 +2675,7 @@ function DropdownMenuSubTrigger({ icon, className, children, ...props }) {
1797
2675
  });
1798
2676
  }
1799
2677
  function DropdownMenuSubContent({ sideOffset = 4, className, ...props }) {
1800
- const { s, slots } = useParts$1();
2678
+ const { s, slots } = useParts$2();
1801
2679
  return /* @__PURE__ */ jsx(DropdownMenu$1.Portal, { children: /* @__PURE__ */ jsx(DropdownMenu$1.SubContent, {
1802
2680
  "data-slot": "dropdown-menu-sub-content",
1803
2681
  sideOffset,
@@ -1811,7 +2689,7 @@ const eyebrowStyles = tv({
1811
2689
  slots: { base: "font-mono text-caption uppercase tracking-[0.12em]" },
1812
2690
  variants: { tone: {
1813
2691
  muted: { base: "text-muted-foreground" },
1814
- primary: { base: "text-primary" }
2692
+ primary: { base: "text-primary-text" }
1815
2693
  } },
1816
2694
  defaultVariants: { tone: "muted" }
1817
2695
  });
@@ -1830,6 +2708,290 @@ function Eyebrow(inProps) {
1830
2708
  });
1831
2709
  }
1832
2710
  //#endregion
2711
+ //#region src/components/file-upload/file-upload.styles.ts
2712
+ const fileUploadStyles = tv({ slots: {
2713
+ root: "grid gap-3",
2714
+ dropzone: [
2715
+ "flex w-full cursor-pointer flex-col items-center justify-center gap-2 rounded-lg border-dashed border-border-strong bg-subtle px-6 py-8 text-center",
2716
+ themedBorder,
2717
+ transition,
2718
+ focusRing,
2719
+ "hover:border-primary/60 hover:bg-primary/4",
2720
+ "data-[dragging=true]:border-primary data-[dragging=true]:bg-primary/8",
2721
+ "disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-danger"
2722
+ ],
2723
+ icon: "flex size-10 items-center justify-center rounded-md border border-border bg-surface text-muted-foreground shadow-xs [&>svg]:size-5",
2724
+ title: "text-small font-medium text-foreground",
2725
+ highlight: "text-primary-text",
2726
+ hint: "text-caption text-faint-foreground",
2727
+ rejections: "grid gap-1 text-small font-medium text-danger-text",
2728
+ list: "grid gap-2",
2729
+ item: ["grid grid-cols-[auto_1fr_auto] items-center gap-3 rounded-md border-border bg-surface px-3 py-2.5", themedBorder],
2730
+ fileIcon: "flex size-8 items-center justify-center rounded-sm bg-muted text-muted-foreground [&>svg]:size-4",
2731
+ fileText: "grid min-w-0 gap-1",
2732
+ fileName: "truncate text-small font-medium text-foreground",
2733
+ fileMeta: "text-caption tabular-nums text-faint-foreground",
2734
+ fileError: "text-caption font-medium text-danger-text",
2735
+ progress: "h-1 overflow-hidden rounded-pill bg-muted",
2736
+ progressBar: "h-full rounded-pill bg-primary transition-[width] duration-(--glyph-duration-base)"
2737
+ } });
2738
+ //#endregion
2739
+ //#region src/components/file-upload/file-upload.tsx
2740
+ /** Formats bytes for people: 1 KB = 1024 bytes. */
2741
+ function formatBytes(bytes) {
2742
+ if (bytes < 1024) return `${bytes} B`;
2743
+ const units = [
2744
+ "KB",
2745
+ "MB",
2746
+ "GB",
2747
+ "TB"
2748
+ ];
2749
+ let value = bytes / 1024;
2750
+ let unit = 0;
2751
+ while (value >= 1024 && unit < units.length - 1) {
2752
+ value /= 1024;
2753
+ unit++;
2754
+ }
2755
+ return `${value >= 10 ? Math.round(value) : value.toFixed(1)} ${units[unit]}`;
2756
+ }
2757
+ /** Matches a file against an `accept` string like `"image/*,.pdf,application/zip"`. */
2758
+ function matchesAccept(file, accept) {
2759
+ if (!accept) return true;
2760
+ const name = file.name.toLowerCase();
2761
+ const type = file.type.toLowerCase();
2762
+ return accept.split(",").map((rule) => rule.trim().toLowerCase()).filter(Boolean).some((rule) => {
2763
+ if (rule.startsWith(".")) return name.endsWith(rule);
2764
+ if (rule.endsWith("/*")) return type.startsWith(rule.slice(0, -1));
2765
+ return type === rule;
2766
+ });
2767
+ }
2768
+ let counter = 0;
2769
+ const newId = () => `file-${Date.now().toString(36)}-${(counter++).toString(36)}`;
2770
+ function UploadIcon() {
2771
+ return /* @__PURE__ */ jsxs("svg", {
2772
+ viewBox: "0 0 24 24",
2773
+ fill: "none",
2774
+ stroke: "currentColor",
2775
+ strokeWidth: "2",
2776
+ strokeLinecap: "round",
2777
+ strokeLinejoin: "round",
2778
+ "aria-hidden": "true",
2779
+ children: [/* @__PURE__ */ jsx("path", { d: "M12 16V4M7 9l5-5 5 5" }), /* @__PURE__ */ jsx("path", { d: "M20 16v2a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2v-2" })]
2780
+ });
2781
+ }
2782
+ function FileIcon() {
2783
+ return /* @__PURE__ */ jsxs("svg", {
2784
+ viewBox: "0 0 24 24",
2785
+ fill: "none",
2786
+ stroke: "currentColor",
2787
+ strokeWidth: "2",
2788
+ strokeLinecap: "round",
2789
+ strokeLinejoin: "round",
2790
+ "aria-hidden": "true",
2791
+ children: [/* @__PURE__ */ jsx("path", { d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8Z" }), /* @__PURE__ */ jsx("path", { d: "M14 2v6h6" })]
2792
+ });
2793
+ }
2794
+ function XIcon$1() {
2795
+ return /* @__PURE__ */ jsx("svg", {
2796
+ viewBox: "0 0 24 24",
2797
+ fill: "none",
2798
+ stroke: "currentColor",
2799
+ strokeWidth: "2",
2800
+ strokeLinecap: "round",
2801
+ "aria-hidden": "true",
2802
+ children: /* @__PURE__ */ jsx("path", { d: "M18 6 6 18M6 6l12 12" })
2803
+ });
2804
+ }
2805
+ /**
2806
+ * Drag-and-drop or click to choose files, with type, size and count checks and a file
2807
+ * list. It does no uploading: you get `File` objects and can set `progress` and `error`
2808
+ * on each item while your own code uploads them.
2809
+ */
2810
+ function FileUpload(inProps) {
2811
+ const [props, slots] = useComponentConfig("FileUpload", useFieldControl(inProps));
2812
+ const { files: filesProp, defaultFiles = [], onFilesChange, onReject, accept, maxSize, maxFiles, multiple = true, disabled, label, hint, id, className, "aria-describedby": ariaDescribedBy, "aria-invalid": ariaInvalid } = props;
2813
+ const [files, setFiles] = useControllableState({
2814
+ value: filesProp,
2815
+ defaultValue: defaultFiles,
2816
+ onChange: onFilesChange
2817
+ });
2818
+ const [dragging, setDragging] = useState(false);
2819
+ const [rejections, setRejections] = useState([]);
2820
+ const inputRef = useRef(null);
2821
+ const hintId = useId();
2822
+ const rejectionsId = useId();
2823
+ const s = fileUploadStyles();
2824
+ const limit = multiple ? maxFiles ?? Number.POSITIVE_INFINITY : 1;
2825
+ const full = files.length >= limit;
2826
+ const addFiles = (incoming) => {
2827
+ const accepted = [];
2828
+ const rejected = [];
2829
+ let room = limit - (multiple ? files.length : 0);
2830
+ for (const file of incoming) if (!matchesAccept(file, accept)) rejected.push({
2831
+ file,
2832
+ reason: "wrong-type",
2833
+ message: `${file.name} isn't an allowed file type.`
2834
+ });
2835
+ else if (maxSize !== void 0 && file.size > maxSize) rejected.push({
2836
+ file,
2837
+ reason: "too-large",
2838
+ message: `${file.name} is too large (${formatBytes(file.size)}). The limit is ${formatBytes(maxSize)}.`
2839
+ });
2840
+ else if (room <= 0) rejected.push({
2841
+ file,
2842
+ reason: "too-many",
2843
+ message: `${file.name} wasn't added: the limit is ${limit} file${limit === 1 ? "" : "s"}.`
2844
+ });
2845
+ else {
2846
+ accepted.push({
2847
+ id: newId(),
2848
+ file
2849
+ });
2850
+ room--;
2851
+ }
2852
+ if (accepted.length > 0) setFiles(multiple ? [...files, ...accepted] : accepted);
2853
+ setRejections(rejected);
2854
+ if (rejected.length > 0) onReject?.(rejected);
2855
+ };
2856
+ const onDrop = (event) => {
2857
+ event.preventDefault();
2858
+ setDragging(false);
2859
+ if (disabled) return;
2860
+ addFiles(Array.from(event.dataTransfer.files));
2861
+ };
2862
+ const defaultHint = [
2863
+ accept ? `Accepted: ${accept.split(",").map((a) => a.trim()).join(", ")}` : null,
2864
+ maxSize !== void 0 ? `up to ${formatBytes(maxSize)} each` : null,
2865
+ multiple && maxFiles !== void 0 ? `max ${maxFiles} files` : null
2866
+ ].filter(Boolean).join(" · ");
2867
+ const describedBy = [
2868
+ ariaDescribedBy,
2869
+ hintId,
2870
+ rejections.length > 0 ? rejectionsId : void 0
2871
+ ].filter(Boolean).join(" ") || void 0;
2872
+ return /* @__PURE__ */ jsxs("div", {
2873
+ "data-slot": "file-upload",
2874
+ className: s.root({ class: [slots.root, className] }),
2875
+ children: [
2876
+ /* @__PURE__ */ jsxs("button", {
2877
+ type: "button",
2878
+ id,
2879
+ "data-dragging": dragging,
2880
+ disabled: disabled || full,
2881
+ "aria-describedby": describedBy,
2882
+ "aria-invalid": ariaInvalid,
2883
+ className: s.dropzone({ class: slots.dropzone }),
2884
+ onClick: () => inputRef.current?.click(),
2885
+ onDragEnter: (event) => {
2886
+ event.preventDefault();
2887
+ if (!disabled) setDragging(true);
2888
+ },
2889
+ onDragOver: (event) => event.preventDefault(),
2890
+ onDragLeave: (event) => {
2891
+ if (!event.currentTarget.contains(event.relatedTarget)) setDragging(false);
2892
+ },
2893
+ onDrop,
2894
+ children: [
2895
+ /* @__PURE__ */ jsx("span", {
2896
+ className: s.icon({ class: slots.icon }),
2897
+ children: /* @__PURE__ */ jsx(UploadIcon, {})
2898
+ }),
2899
+ /* @__PURE__ */ jsx("span", {
2900
+ className: s.title({ class: slots.title }),
2901
+ children: label ?? /* @__PURE__ */ jsxs(Fragment$1, { children: [
2902
+ "Drop ",
2903
+ multiple ? "files" : "a file",
2904
+ " here or",
2905
+ " ",
2906
+ /* @__PURE__ */ jsx("span", {
2907
+ className: s.highlight({ class: slots.highlight }),
2908
+ children: "browse"
2909
+ })
2910
+ ] })
2911
+ }),
2912
+ /* @__PURE__ */ jsx("span", {
2913
+ id: hintId,
2914
+ className: s.hint({ class: slots.hint }),
2915
+ children: full ? "File limit reached. Remove a file to add another." : hint ?? defaultHint
2916
+ })
2917
+ ]
2918
+ }),
2919
+ /* @__PURE__ */ jsx("input", {
2920
+ ref: inputRef,
2921
+ type: "file",
2922
+ tabIndex: -1,
2923
+ "aria-hidden": "true",
2924
+ className: "sr-only",
2925
+ accept,
2926
+ multiple,
2927
+ disabled,
2928
+ onChange: (event) => {
2929
+ addFiles(Array.from(event.target.files ?? []));
2930
+ event.target.value = "";
2931
+ }
2932
+ }),
2933
+ rejections.length > 0 && /* @__PURE__ */ jsx("ul", {
2934
+ id: rejectionsId,
2935
+ role: "alert",
2936
+ className: s.rejections({ class: slots.rejections }),
2937
+ children: rejections.map((r) => /* @__PURE__ */ jsx("li", { children: r.message }, `${r.file.name}-${r.reason}`))
2938
+ }),
2939
+ files.length > 0 && /* @__PURE__ */ jsx("ul", {
2940
+ className: s.list({ class: slots.list }),
2941
+ "aria-label": "Selected files",
2942
+ children: files.map((item) => /* @__PURE__ */ jsxs("li", {
2943
+ "data-slot": "file-upload-item",
2944
+ className: s.item({ class: slots.item }),
2945
+ children: [
2946
+ /* @__PURE__ */ jsx("span", {
2947
+ className: s.fileIcon({ class: slots.fileIcon }),
2948
+ children: /* @__PURE__ */ jsx(FileIcon, {})
2949
+ }),
2950
+ /* @__PURE__ */ jsxs("span", {
2951
+ className: s.fileText({ class: slots.fileText }),
2952
+ children: [
2953
+ /* @__PURE__ */ jsx("span", {
2954
+ className: s.fileName({ class: slots.fileName }),
2955
+ children: item.file.name
2956
+ }),
2957
+ item.error ? /* @__PURE__ */ jsx("span", {
2958
+ className: s.fileError({ class: slots.fileError }),
2959
+ children: item.error
2960
+ }) : /* @__PURE__ */ jsxs("span", {
2961
+ className: s.fileMeta({ class: slots.fileMeta }),
2962
+ children: [formatBytes(item.file.size), item.progress !== void 0 && item.progress < 100 && ` · ${Math.round(item.progress)}%`]
2963
+ }),
2964
+ item.progress !== void 0 && item.progress < 100 && !item.error && /* @__PURE__ */ jsx("span", {
2965
+ role: "progressbar",
2966
+ "aria-label": `Uploading ${item.file.name}`,
2967
+ "aria-valuemin": 0,
2968
+ "aria-valuemax": 100,
2969
+ "aria-valuenow": Math.round(item.progress),
2970
+ className: s.progress({ class: slots.progress }),
2971
+ children: /* @__PURE__ */ jsx("span", {
2972
+ className: s.progressBar({ class: slots.progressBar }),
2973
+ style: { width: `${Math.max(0, Math.min(100, item.progress))}%` }
2974
+ })
2975
+ })
2976
+ ]
2977
+ }),
2978
+ /* @__PURE__ */ jsx(IconButton, {
2979
+ size: "sm",
2980
+ icon: /* @__PURE__ */ jsx(XIcon$1, {}),
2981
+ "aria-label": `Remove ${item.file.name}`,
2982
+ disabled,
2983
+ onClick: () => {
2984
+ setFiles(files.filter((f) => f.id !== item.id));
2985
+ setRejections([]);
2986
+ }
2987
+ })
2988
+ ]
2989
+ }, item.id))
2990
+ })
2991
+ ]
2992
+ });
2993
+ }
2994
+ //#endregion
1833
2995
  //#region src/components/grid/grid.tsx
1834
2996
  const colClasses = {
1835
2997
  base: {
@@ -1949,38 +3111,162 @@ function Grid(inProps) {
1949
3111
  ...rest
1950
3112
  });
1951
3113
  }
1952
- //#endregion
1953
- //#region src/components/heading/heading.styles.ts
1954
- const headingStyles = tv({
1955
- slots: { base: "font-display text-balance text-foreground" },
1956
- variants: { size: {
1957
- display: { base: "text-display" },
1958
- h1: { base: "text-h1" },
1959
- h2: { base: "text-h2" },
1960
- h3: { base: "text-h3" },
1961
- h4: { base: "text-h4" }
1962
- } }
1963
- });
1964
- //#endregion
1965
- //#region src/components/heading/heading.tsx
1966
- const sizeForLevel = {
1967
- 1: "h1",
1968
- 2: "h2",
1969
- 3: "h3",
1970
- 4: "h4",
1971
- 5: "h4",
1972
- 6: "h4"
1973
- };
1974
- /** A heading whose semantic level and visual size are set independently. */
1975
- function Heading(inProps) {
1976
- const [props, slots] = useComponentConfig("Heading", inProps);
1977
- const { level = 2, size, asChild, className, ...rest } = props;
1978
- const s = headingStyles({ size: size ?? sizeForLevel[level] });
1979
- const Comp = asChild ? Slot.Root : `h${level}`;
1980
- return /* @__PURE__ */ jsx(Comp, {
1981
- "data-slot": "heading",
1982
- className: s.base({ class: [slots.base, className] }),
1983
- ...rest
3114
+ //#endregion
3115
+ //#region src/components/heading/heading.styles.ts
3116
+ const headingStyles = tv({
3117
+ slots: { base: "font-display text-balance text-foreground" },
3118
+ variants: { size: {
3119
+ display: { base: "text-display" },
3120
+ h1: { base: "text-h1" },
3121
+ h2: { base: "text-h2" },
3122
+ h3: { base: "text-h3" },
3123
+ h4: { base: "text-h4" }
3124
+ } }
3125
+ });
3126
+ //#endregion
3127
+ //#region src/components/heading/heading.tsx
3128
+ const sizeForLevel = {
3129
+ 1: "h1",
3130
+ 2: "h2",
3131
+ 3: "h3",
3132
+ 4: "h4",
3133
+ 5: "h4",
3134
+ 6: "h4"
3135
+ };
3136
+ /** A heading whose semantic level and visual size are set independently. */
3137
+ function Heading(inProps) {
3138
+ const [props, slots] = useComponentConfig("Heading", inProps);
3139
+ const { level = 2, size, asChild, className, ...rest } = props;
3140
+ const s = headingStyles({ size: size ?? sizeForLevel[level] });
3141
+ const Comp = asChild ? Slot.Root : `h${level}`;
3142
+ return /* @__PURE__ */ jsx(Comp, {
3143
+ "data-slot": "heading",
3144
+ className: s.base({ class: [slots.base, className] }),
3145
+ ...rest
3146
+ });
3147
+ }
3148
+ //#endregion
3149
+ //#region src/components/hover-card/hover-card.tsx
3150
+ const hoverCardStyles = tv({ slots: { content: [popover, "w-72 max-w-[calc(100vw-2rem)] p-4 text-small outline-none"] } });
3151
+ /**
3152
+ * A rich preview shown while hovering or focusing a link, such as a user or repository card.
3153
+ * Sighted mouse users only see it on hover; keep the same information reachable elsewhere.
3154
+ */
3155
+ const HoverCard = HoverCard$1.Root;
3156
+ const HoverCardTrigger = HoverCard$1.Trigger;
3157
+ function HoverCardContent(inProps) {
3158
+ const [props, slots] = useComponentConfig("HoverCard", inProps);
3159
+ const { sideOffset = 6, align = "center", className, ...rest } = props;
3160
+ return /* @__PURE__ */ jsx(HoverCard$1.Portal, { children: /* @__PURE__ */ jsx(HoverCard$1.Content, {
3161
+ "data-slot": "hover-card-content",
3162
+ sideOffset,
3163
+ align,
3164
+ className: hoverCardStyles().content({ class: [slots.content, className] }),
3165
+ ...rest
3166
+ }) });
3167
+ }
3168
+ //#endregion
3169
+ //#region src/components/input-otp/input-otp.styles.ts
3170
+ const inputOtpStyles = tv({
3171
+ slots: {
3172
+ root: "flex items-center gap-2 has-disabled:opacity-50",
3173
+ input: "disabled:cursor-not-allowed",
3174
+ group: "flex items-center",
3175
+ slot: [
3176
+ "relative flex items-center justify-center border-input bg-surface font-medium tabular-nums text-foreground shadow-xs",
3177
+ "border-y-(length:--glyph-border-width) border-r-(length:--glyph-border-width)",
3178
+ "first:rounded-l-md first:border-l-(length:--glyph-border-width) last:rounded-r-md",
3179
+ "data-[active=true]:z-10 data-[active=true]:border-ring data-[active=true]:ring-3 data-[active=true]:ring-ring/20",
3180
+ "aria-invalid:border-danger",
3181
+ transition
3182
+ ],
3183
+ caret: "pointer-events-none absolute inset-0 flex items-center justify-center",
3184
+ caretBar: "h-4 w-px animate-pulse bg-foreground",
3185
+ separator: "flex items-center text-faint-foreground [&>svg]:size-4"
3186
+ },
3187
+ variants: { size: {
3188
+ sm: { slot: "size-8 text-small" },
3189
+ md: { slot: "size-10 text-body" },
3190
+ lg: { slot: "size-12 text-h4" }
3191
+ } },
3192
+ defaultVariants: { size: "md" }
3193
+ });
3194
+ //#endregion
3195
+ //#region src/components/input-otp/input-otp.tsx
3196
+ const PartsContext = createContext(null);
3197
+ function useParts$1() {
3198
+ return useContext(PartsContext) ?? {
3199
+ s: inputOtpStyles(),
3200
+ slots: {},
3201
+ invalid: false
3202
+ };
3203
+ }
3204
+ /**
3205
+ * One-time code input: one box per character, paste support, and autofill from SMS on
3206
+ * mobile. Built on input-otp. Restrict characters with `pattern`, e.g. `REGEXP_ONLY_DIGITS`.
3207
+ */
3208
+ function InputOTP(inProps) {
3209
+ const [props, slots] = useComponentConfig("InputOTP", useFieldControl(inProps));
3210
+ const { length = 6, size, children, className, containerClassName, ...rest } = props;
3211
+ const s = inputOtpStyles({ size });
3212
+ const invalid = rest["aria-invalid"] === true || rest["aria-invalid"] === "true";
3213
+ return /* @__PURE__ */ jsx(PartsContext.Provider, {
3214
+ value: {
3215
+ s,
3216
+ slots,
3217
+ invalid
3218
+ },
3219
+ children: /* @__PURE__ */ jsx(OTPInput, {
3220
+ "data-slot": "input-otp",
3221
+ maxLength: length,
3222
+ autoComplete: "one-time-code",
3223
+ inputMode: "numeric",
3224
+ containerClassName: s.root({ class: [slots.root, containerClassName] }),
3225
+ className: s.input({ class: [slots.input, className] }),
3226
+ ...rest,
3227
+ children: children ?? /* @__PURE__ */ jsx(InputOTPGroup, { children: Array.from({ length }, (_, index) => /* @__PURE__ */ jsx(InputOTPSlot, { index }, index)) })
3228
+ })
3229
+ });
3230
+ }
3231
+ function InputOTPGroup({ className, ...props }) {
3232
+ const { s, slots } = useParts$1();
3233
+ return /* @__PURE__ */ jsx("div", {
3234
+ "data-slot": "input-otp-group",
3235
+ className: s.group({ class: [slots.group, className] }),
3236
+ ...props
3237
+ });
3238
+ }
3239
+ function InputOTPSlot({ index, className, ...props }) {
3240
+ const { s, slots, invalid } = useParts$1();
3241
+ const slot = useContext(OTPInputContext).slots[index];
3242
+ return /* @__PURE__ */ jsxs("div", {
3243
+ "data-slot": "input-otp-slot",
3244
+ "data-active": slot?.isActive ?? false,
3245
+ "aria-invalid": invalid || void 0,
3246
+ className: s.slot({ class: [slots.slot, className] }),
3247
+ ...props,
3248
+ children: [slot?.char ?? slot?.placeholderChar, slot?.hasFakeCaret && /* @__PURE__ */ jsx("div", {
3249
+ className: s.caret({ class: slots.caret }),
3250
+ children: /* @__PURE__ */ jsx("div", { className: s.caretBar({ class: slots.caretBar }) })
3251
+ })]
3252
+ });
3253
+ }
3254
+ function InputOTPSeparator({ className, ...props }) {
3255
+ const { s, slots } = useParts$1();
3256
+ return /* @__PURE__ */ jsx("div", {
3257
+ "data-slot": "input-otp-separator",
3258
+ "aria-hidden": "true",
3259
+ className: s.separator({ class: [slots.separator, className] }),
3260
+ ...props,
3261
+ children: /* @__PURE__ */ jsx("svg", {
3262
+ viewBox: "0 0 24 24",
3263
+ fill: "none",
3264
+ stroke: "currentColor",
3265
+ strokeWidth: "2",
3266
+ strokeLinecap: "round",
3267
+ "aria-hidden": "true",
3268
+ children: /* @__PURE__ */ jsx("path", { d: "M6 12h12" })
3269
+ })
1984
3270
  });
1985
3271
  }
1986
3272
  //#endregion
@@ -1999,7 +3285,7 @@ const linkStyles = tv({
1999
3285
  tone: {
2000
3286
  default: { base: "text-foreground" },
2001
3287
  muted: { base: "text-muted-foreground hover:text-foreground" },
2002
- primary: { base: "text-primary" }
3288
+ primary: { base: "text-primary-text" }
2003
3289
  },
2004
3290
  underline: {
2005
3291
  hover: { base: "bg-[length:0%_1px] hover:bg-[length:100%_1px] focus-visible:bg-[length:100%_1px]" },
@@ -2064,6 +3350,406 @@ function Link(inProps) {
2064
3350
  });
2065
3351
  }
2066
3352
  //#endregion
3353
+ //#region src/components/modal/modal.styles.ts
3354
+ /** Modal is built from Dialog parts; these slots add Modal-specific classes on top. */
3355
+ const modalStyles = tv({ slots: {
3356
+ content: "",
3357
+ header: "",
3358
+ body: "grid gap-4",
3359
+ footer: "",
3360
+ /** Wraps body and footer when `onSubmit` is set; `contents` keeps the dialog layout. */
3361
+ form: "contents"
3362
+ } });
3363
+ //#endregion
3364
+ //#region src/components/modal/modal.tsx
3365
+ /**
3366
+ * The everyday modal in one component: title, description, body and footer as props.
3367
+ * For custom layouts use the Dialog parts; for yes/no decisions use `useConfirm()`.
3368
+ */
3369
+ function Modal(inProps) {
3370
+ const [props, slots] = useComponentConfig("Modal", inProps);
3371
+ const { open, defaultOpen, onOpenChange, title, description, trigger, footer, closeOnOverlayClick = true, onSubmit, onPointerDownOutside, className, children, ...rest } = props;
3372
+ const s = modalStyles();
3373
+ const content = /* @__PURE__ */ jsxs(Fragment$1, { children: [children && /* @__PURE__ */ jsx(DialogBody, {
3374
+ className: s.body({ class: slots.body }),
3375
+ children
3376
+ }), footer && /* @__PURE__ */ jsx(DialogFooter, {
3377
+ className: s.footer({ class: slots.footer }),
3378
+ children: footer
3379
+ })] });
3380
+ return /* @__PURE__ */ jsxs(Dialog, {
3381
+ ...open !== void 0 && { open },
3382
+ ...defaultOpen !== void 0 && { defaultOpen },
3383
+ ...onOpenChange && { onOpenChange },
3384
+ children: [trigger && /* @__PURE__ */ jsx(DialogTrigger, {
3385
+ asChild: true,
3386
+ children: trigger
3387
+ }), /* @__PURE__ */ jsxs(DialogContent, {
3388
+ "data-slot": "modal",
3389
+ className: s.content({ class: [slots.content, className] }),
3390
+ onPointerDownOutside: (event) => {
3391
+ onPointerDownOutside?.(event);
3392
+ if (!closeOnOverlayClick) event.preventDefault();
3393
+ },
3394
+ ...!description && { "aria-describedby": void 0 },
3395
+ ...rest,
3396
+ children: [/* @__PURE__ */ jsxs(DialogHeader, {
3397
+ className: s.header({ class: slots.header }),
3398
+ children: [/* @__PURE__ */ jsx(DialogTitle, { children: title }), description && /* @__PURE__ */ jsx(DialogDescription, { children: description })]
3399
+ }), onSubmit ? /* @__PURE__ */ jsx("form", {
3400
+ "data-slot": "modal-form",
3401
+ className: s.form({ class: slots.form }),
3402
+ onSubmit: (event) => {
3403
+ event.preventDefault();
3404
+ onSubmit(event);
3405
+ },
3406
+ children: content
3407
+ }) : content]
3408
+ })]
3409
+ });
3410
+ }
3411
+ /** Closes the surrounding Modal. Use with `asChild` around a button. */
3412
+ const ModalClose = DialogClose;
3413
+ //#endregion
3414
+ //#region src/components/navigation-menu/navigation-menu.styles.ts
3415
+ const topLevel = [
3416
+ "group inline-flex h-9 cursor-pointer select-none items-center justify-center gap-1 rounded-md px-3 text-small font-medium text-muted-foreground",
3417
+ transition,
3418
+ focusRing,
3419
+ "hover:bg-muted hover:text-foreground data-[state=open]:bg-muted data-[state=open]:text-foreground",
3420
+ "data-active:text-foreground"
3421
+ ];
3422
+ const navigationMenuStyles = tv({ slots: {
3423
+ root: "relative z-10 flex max-w-max flex-1 items-center justify-center",
3424
+ list: "group flex flex-1 list-none items-center justify-center gap-1",
3425
+ item: "relative",
3426
+ trigger: topLevel,
3427
+ chevron: "size-3 text-faint-foreground transition-transform duration-(--glyph-duration-base) ease-standard group-data-[state=open]:rotate-180",
3428
+ content: "top-0 left-0 w-full p-2 animate-fade-in md:absolute md:w-auto",
3429
+ viewportWrapper: "absolute top-full left-0 flex justify-center",
3430
+ viewport: [
3431
+ "relative mt-1.5 h-(--radix-navigation-menu-viewport-height) w-[calc(100vw-2rem)] origin-top overflow-hidden rounded-lg border-border bg-raised text-foreground shadow-lg animate-pop-in",
3432
+ "md:w-(--radix-navigation-menu-viewport-width)",
3433
+ "transition-[width,height] duration-(--glyph-duration-base) ease-standard",
3434
+ themedBorder
3435
+ ],
3436
+ link: topLevel,
3437
+ card: [
3438
+ "flex select-none gap-3 rounded-md p-3 text-foreground no-underline outline-none",
3439
+ transition,
3440
+ focusRing,
3441
+ "hover:bg-muted focus-visible:bg-muted"
3442
+ ],
3443
+ cardIcon: "flex size-9 shrink-0 items-center justify-center rounded-md border border-border bg-surface text-muted-foreground shadow-xs [&_svg]:size-4",
3444
+ cardText: "grid min-w-0 gap-0.5",
3445
+ cardTitle: "text-small font-medium text-foreground",
3446
+ cardDescription: "text-small text-muted-foreground"
3447
+ } });
3448
+ //#endregion
3449
+ //#region src/components/navigation-menu/navigation-menu.tsx
3450
+ const s$2 = navigationMenuStyles();
3451
+ function useSlots$2() {
3452
+ return useComponentConfig("NavigationMenu", {})[1];
3453
+ }
3454
+ const ChevronDownIcon = ({ className }) => /* @__PURE__ */ jsx("svg", {
3455
+ xmlns: "http://www.w3.org/2000/svg",
3456
+ viewBox: "0 0 24 24",
3457
+ fill: "none",
3458
+ stroke: "currentColor",
3459
+ strokeWidth: "2",
3460
+ strokeLinecap: "round",
3461
+ strokeLinejoin: "round",
3462
+ "aria-hidden": "true",
3463
+ className,
3464
+ children: /* @__PURE__ */ jsx("path", { d: "m6 9 6 6 6-6" })
3465
+ });
3466
+ /**
3467
+ * Site navigation with dropdown panels (mega menus) for marketing headers.
3468
+ * Keyboard: Tab between items, arrows inside panels, Escape to close.
3469
+ */
3470
+ function NavigationMenu(inProps) {
3471
+ const [props, slots] = useComponentConfig("NavigationMenu", inProps);
3472
+ const { viewport = true, className, children, ...rest } = props;
3473
+ return /* @__PURE__ */ jsxs(NavigationMenu$1.Root, {
3474
+ "data-slot": "navigation-menu",
3475
+ className: s$2.root({ class: [slots.root, className] }),
3476
+ ...rest,
3477
+ children: [children, viewport && /* @__PURE__ */ jsx(NavigationMenuViewport, {})]
3478
+ });
3479
+ }
3480
+ function NavigationMenuList({ className, ...props }) {
3481
+ const slots = useSlots$2();
3482
+ return /* @__PURE__ */ jsx(NavigationMenu$1.List, {
3483
+ "data-slot": "navigation-menu-list",
3484
+ className: s$2.list({ class: [slots.list, className] }),
3485
+ ...props
3486
+ });
3487
+ }
3488
+ function NavigationMenuItem({ className, ...props }) {
3489
+ const slots = useSlots$2();
3490
+ return /* @__PURE__ */ jsx(NavigationMenu$1.Item, {
3491
+ "data-slot": "navigation-menu-item",
3492
+ className: s$2.item({ class: [slots.item, className] }),
3493
+ ...props
3494
+ });
3495
+ }
3496
+ function NavigationMenuTrigger({ className, children, ...props }) {
3497
+ const slots = useSlots$2();
3498
+ return /* @__PURE__ */ jsxs(NavigationMenu$1.Trigger, {
3499
+ "data-slot": "navigation-menu-trigger",
3500
+ className: s$2.trigger({ class: [slots.trigger, className] }),
3501
+ ...props,
3502
+ children: [children, /* @__PURE__ */ jsx(ChevronDownIcon, { className: s$2.chevron({ class: slots.chevron }) })]
3503
+ });
3504
+ }
3505
+ function NavigationMenuContent({ className, ...props }) {
3506
+ const slots = useSlots$2();
3507
+ return /* @__PURE__ */ jsx(NavigationMenu$1.Content, {
3508
+ "data-slot": "navigation-menu-content",
3509
+ className: s$2.content({ class: [slots.content, className] }),
3510
+ ...props
3511
+ });
3512
+ }
3513
+ function NavigationMenuViewport({ className, ...props }) {
3514
+ const slots = useSlots$2();
3515
+ return /* @__PURE__ */ jsx("div", {
3516
+ className: s$2.viewportWrapper({ class: slots.viewportWrapper }),
3517
+ children: /* @__PURE__ */ jsx(NavigationMenu$1.Viewport, {
3518
+ "data-slot": "navigation-menu-viewport",
3519
+ className: s$2.viewport({ class: [slots.viewport, className] }),
3520
+ ...props
3521
+ })
3522
+ });
3523
+ }
3524
+ /**
3525
+ * A top-level link (no panel). Marked active automatically from the provider's `router`;
3526
+ * set `active` to override.
3527
+ */
3528
+ function NavigationMenuLink({ href, active: activeProp, className, children, ...props }) {
3529
+ const slots = useSlots$2();
3530
+ const Link = useLinkComponent();
3531
+ const active = useIsActive(href, { explicit: activeProp });
3532
+ const cls = s$2.link({ class: [slots.link, className] });
3533
+ if (href === void 0) return /* @__PURE__ */ jsx(NavigationMenu$1.Link, {
3534
+ "data-slot": "navigation-menu-link",
3535
+ className: cls,
3536
+ active,
3537
+ ...props,
3538
+ children
3539
+ });
3540
+ return /* @__PURE__ */ jsx(NavigationMenu$1.Link, {
3541
+ "data-slot": "navigation-menu-link",
3542
+ asChild: true,
3543
+ active,
3544
+ ...props,
3545
+ children: /* @__PURE__ */ jsx(Link, {
3546
+ href,
3547
+ className: cls,
3548
+ children
3549
+ })
3550
+ });
3551
+ }
3552
+ /** A link tile for mega-menu panels: icon, title and one line of description. */
3553
+ function NavigationMenuCard({ href, title, description, icon, className }) {
3554
+ const slots = useSlots$2();
3555
+ const Link = useLinkComponent();
3556
+ return /* @__PURE__ */ jsx(NavigationMenu$1.Link, {
3557
+ "data-slot": "navigation-menu-card",
3558
+ asChild: true,
3559
+ children: /* @__PURE__ */ jsxs(Link, {
3560
+ href,
3561
+ className: s$2.card({ class: [slots.card, className] }),
3562
+ children: [icon && /* @__PURE__ */ jsx("span", {
3563
+ className: s$2.cardIcon({ class: slots.cardIcon }),
3564
+ "aria-hidden": "true",
3565
+ children: icon
3566
+ }), /* @__PURE__ */ jsxs("span", {
3567
+ className: s$2.cardText({ class: slots.cardText }),
3568
+ children: [/* @__PURE__ */ jsx("span", {
3569
+ className: s$2.cardTitle({ class: slots.cardTitle }),
3570
+ children: title
3571
+ }), description && /* @__PURE__ */ jsx("span", {
3572
+ className: s$2.cardDescription({ class: slots.cardDescription }),
3573
+ children: description
3574
+ })]
3575
+ })]
3576
+ })
3577
+ });
3578
+ }
3579
+ //#endregion
3580
+ //#region src/components/number-input/number-input.styles.ts
3581
+ const numberInputStyles = tv({
3582
+ slots: {
3583
+ root: [
3584
+ ...fieldControl,
3585
+ "flex items-center gap-2 pl-3",
3586
+ "focus-within:border-ring focus-within:ring-3 focus-within:ring-ring/20",
3587
+ "data-invalid:focus-within:ring-danger/20",
3588
+ "has-[input:disabled]:cursor-not-allowed has-[input:disabled]:opacity-50"
3589
+ ],
3590
+ input: "h-full w-full min-w-0 bg-transparent tabular-nums text-foreground outline-none placeholder:text-faint-foreground disabled:cursor-not-allowed",
3591
+ adornment: "flex shrink-0 items-center text-faint-foreground [&>svg]:size-4",
3592
+ steppers: "flex h-full shrink-0 items-stretch border-l border-input",
3593
+ stepper: [
3594
+ "inline-flex w-8 cursor-pointer items-center justify-center text-muted-foreground hover:bg-muted hover:text-foreground",
3595
+ "disabled:pointer-events-none disabled:opacity-40 [&>svg]:size-3.5 last:rounded-r-[calc(var(--radius-md)-1px)]",
3596
+ focusRing
3597
+ ]
3598
+ },
3599
+ variants: { size: {
3600
+ sm: { root: "h-(--glyph-control-sm) text-small" },
3601
+ md: { root: "h-(--glyph-control-md) text-small" },
3602
+ lg: {
3603
+ root: "h-(--glyph-control-lg) text-body",
3604
+ stepper: "w-10"
3605
+ }
3606
+ } },
3607
+ defaultVariants: { size: "md" }
3608
+ });
3609
+ //#endregion
3610
+ //#region src/components/number-input/number-input.tsx
3611
+ function clamp(value, min, max) {
3612
+ return Math.min(max ?? Number.POSITIVE_INFINITY, Math.max(min ?? Number.NEGATIVE_INFINITY, value));
3613
+ }
3614
+ /** Parses user text leniently: keeps digits, one leading minus and the decimal point. */
3615
+ function parse(text) {
3616
+ const cleaned = text.replace(/[^\d.-]/g, "").replace(/(?!^)-/g, "");
3617
+ if (cleaned === "" || cleaned === "-" || cleaned === ".") return null;
3618
+ const n = Number(cleaned);
3619
+ return Number.isFinite(n) ? n : null;
3620
+ }
3621
+ /** Round away float noise from repeated steps (0.1 + 0.2). */
3622
+ function roundToStep(value, step) {
3623
+ const decimals = (String(step).split(".")[1] ?? "").length;
3624
+ return Number(value.toFixed(Math.min(decimals + 2, 10)));
3625
+ }
3626
+ /**
3627
+ * A number field with − / + steppers, arrow-key stepping, min/max clamping on blur, and
3628
+ * locale formatting when not focused. The value is a `number`, never a string.
3629
+ */
3630
+ function NumberInput(inProps) {
3631
+ const [props, slots] = useComponentConfig("NumberInput", useFieldControl(inProps));
3632
+ const { value: valueProp, defaultValue = null, onValueChange, min, max, step = 1, formatOptions, locale, prefix, suffix, hideSteppers = false, size, className, inputClassName, disabled, readOnly, onBlur, onFocus, onKeyDown, ...rest } = props;
3633
+ const [value, setValue] = useControllableState({
3634
+ value: valueProp,
3635
+ defaultValue,
3636
+ onChange: onValueChange
3637
+ });
3638
+ const [draft, setDraft] = useState(null);
3639
+ const s = numberInputStyles({ size });
3640
+ const invalid = rest["aria-invalid"] === true || rest["aria-invalid"] === "true";
3641
+ const display = draft ?? (value === null || value === void 0 ? "" : formatOptions ? new Intl.NumberFormat(locale, formatOptions).format(value) : String(value));
3642
+ const commit = (next) => {
3643
+ setValue(next === null ? null : roundToStep(clamp(next, min, max), step));
3644
+ };
3645
+ const stepBy = (direction, multiplier = 1) => {
3646
+ const base = draft !== null ? parse(draft) : value;
3647
+ commit((base ?? min ?? 0) + direction * step * multiplier);
3648
+ setDraft(null);
3649
+ };
3650
+ const handleKeyDown = (event) => {
3651
+ onKeyDown?.(event);
3652
+ if (event.defaultPrevented || readOnly) return;
3653
+ const multiplier = event.shiftKey ? 10 : 1;
3654
+ if (event.key === "ArrowUp") {
3655
+ event.preventDefault();
3656
+ stepBy(1, multiplier);
3657
+ } else if (event.key === "ArrowDown") {
3658
+ event.preventDefault();
3659
+ stepBy(-1, multiplier);
3660
+ } else if (event.key === "Home" && min !== void 0) {
3661
+ event.preventDefault();
3662
+ commit(min);
3663
+ setDraft(null);
3664
+ } else if (event.key === "End" && max !== void 0) {
3665
+ event.preventDefault();
3666
+ commit(max);
3667
+ setDraft(null);
3668
+ } else if (event.key === "Enter" && draft !== null) {
3669
+ commit(parse(draft));
3670
+ setDraft(null);
3671
+ }
3672
+ };
3673
+ const atMin = value !== null && value !== void 0 && min !== void 0 && value <= min;
3674
+ const atMax = value !== null && value !== void 0 && max !== void 0 && value >= max;
3675
+ return /* @__PURE__ */ jsxs("div", {
3676
+ "data-slot": "number-input",
3677
+ "data-invalid": invalid || void 0,
3678
+ className: s.root({ class: [slots.root, className] }),
3679
+ children: [
3680
+ prefix && /* @__PURE__ */ jsx("span", {
3681
+ className: s.adornment({ class: slots.adornment }),
3682
+ children: prefix
3683
+ }),
3684
+ /* @__PURE__ */ jsx("input", {
3685
+ type: "text",
3686
+ inputMode: "decimal",
3687
+ role: "spinbutton",
3688
+ "aria-valuenow": value ?? void 0,
3689
+ "aria-valuemin": min,
3690
+ "aria-valuemax": max,
3691
+ autoComplete: "off",
3692
+ disabled,
3693
+ readOnly,
3694
+ value: display,
3695
+ className: s.input({ class: [slots.input, inputClassName] }),
3696
+ onFocus: (event) => {
3697
+ setDraft(value === null || value === void 0 ? "" : String(value));
3698
+ onFocus?.(event);
3699
+ },
3700
+ onChange: (event) => setDraft(event.target.value),
3701
+ onBlur: (event) => {
3702
+ if (draft !== null) commit(parse(draft));
3703
+ setDraft(null);
3704
+ onBlur?.(event);
3705
+ },
3706
+ onKeyDown: handleKeyDown,
3707
+ ...rest
3708
+ }),
3709
+ suffix && /* @__PURE__ */ jsx("span", {
3710
+ className: s.adornment({ class: slots.adornment }),
3711
+ children: suffix
3712
+ }),
3713
+ !hideSteppers && /* @__PURE__ */ jsxs("span", {
3714
+ className: s.steppers({ class: slots.steppers }),
3715
+ children: [/* @__PURE__ */ jsx("button", {
3716
+ type: "button",
3717
+ tabIndex: -1,
3718
+ "aria-label": "Decrease",
3719
+ disabled: disabled || readOnly || atMin,
3720
+ className: s.stepper({ class: slots.stepper }),
3721
+ onClick: () => stepBy(-1),
3722
+ children: /* @__PURE__ */ jsx("svg", {
3723
+ viewBox: "0 0 24 24",
3724
+ fill: "none",
3725
+ stroke: "currentColor",
3726
+ strokeWidth: "2",
3727
+ strokeLinecap: "round",
3728
+ "aria-hidden": "true",
3729
+ children: /* @__PURE__ */ jsx("path", { d: "M5 12h14" })
3730
+ })
3731
+ }), /* @__PURE__ */ jsx("button", {
3732
+ type: "button",
3733
+ tabIndex: -1,
3734
+ "aria-label": "Increase",
3735
+ disabled: disabled || readOnly || atMax,
3736
+ className: s.stepper({ class: slots.stepper }),
3737
+ onClick: () => stepBy(1),
3738
+ children: /* @__PURE__ */ jsx("svg", {
3739
+ viewBox: "0 0 24 24",
3740
+ fill: "none",
3741
+ stroke: "currentColor",
3742
+ strokeWidth: "2",
3743
+ strokeLinecap: "round",
3744
+ "aria-hidden": "true",
3745
+ children: /* @__PURE__ */ jsx("path", { d: "M12 5v14M5 12h14" })
3746
+ })
3747
+ })]
3748
+ })
3749
+ ]
3750
+ });
3751
+ }
3752
+ //#endregion
2067
3753
  //#region src/components/pagination/pagination.styles.ts
2068
3754
  const paginationStyles = tv({
2069
3755
  slots: {
@@ -2205,39 +3891,127 @@ function Pagination(inProps) {
2205
3891
  "aria-hidden": "true",
2206
3892
  children: "…"
2207
3893
  }, `gap-${index}`) : /* @__PURE__ */ jsx("li", { children: control(item, `Page ${item}`, item, { current: item === current }) }, item)),
2208
- /* @__PURE__ */ jsx("li", { children: control(current + 1, "Next page", /* @__PURE__ */ jsx(ChevronRightIcon$1, {})) }),
3894
+ /* @__PURE__ */ jsx("li", { children: control(current + 1, "Next page", /* @__PURE__ */ jsx(ChevronRightIcon$2, {})) }),
2209
3895
  showEdges && /* @__PURE__ */ jsx("li", { children: control(pageCount, "Last page", /* @__PURE__ */ jsx(ChevronsRightIcon, {})) })
2210
3896
  ]
2211
3897
  })
2212
3898
  });
2213
3899
  }
2214
3900
  //#endregion
2215
- //#region src/components/popover/popover.tsx
2216
- const popoverStyles = tv({ slots: {
2217
- content: [popover, "w-72 max-w-[calc(100vw-2rem)] overflow-visible p-4 text-small outline-none"],
2218
- arrow: "fill-raised"
2219
- } });
2220
- /** Floating content anchored to a trigger: quick settings, details, small forms. */
2221
- const Popover = Popover$1.Root;
2222
- const PopoverTrigger = Popover$1.Trigger;
2223
- const PopoverAnchor = Popover$1.Anchor;
2224
- const PopoverClose = Popover$1.Close;
2225
- function PopoverContent(inProps) {
2226
- const [props, slots] = useComponentConfig("Popover", inProps);
2227
- const { showArrow = false, sideOffset = 6, align = "center", className, children, ...rest } = props;
2228
- const s = popoverStyles();
2229
- return /* @__PURE__ */ jsx(Popover$1.Portal, { children: /* @__PURE__ */ jsxs(Popover$1.Content, {
2230
- "data-slot": "popover-content",
2231
- sideOffset,
2232
- align,
2233
- className: s.content({ class: [slots.content, className] }),
2234
- ...rest,
2235
- children: [children, showArrow && /* @__PURE__ */ jsx(Popover$1.Arrow, {
2236
- width: 12,
2237
- height: 6,
2238
- className: s.arrow({ class: slots.arrow })
3901
+ //#region src/components/password-input/password-input.styles.ts
3902
+ const passwordInputStyles = tv({
3903
+ slots: {
3904
+ root: "grid gap-1.5",
3905
+ toggle: ["-mr-1 inline-flex size-7 cursor-pointer items-center justify-center rounded-sm text-faint-foreground hover:bg-muted hover:text-foreground [&>svg]:size-4", focusRing],
3906
+ meter: "flex items-center gap-2",
3907
+ bars: "grid flex-1 grid-cols-3 gap-1",
3908
+ bar: "h-1 rounded-pill bg-muted transition-colors duration-(--glyph-duration-base)",
3909
+ label: "w-14 text-right text-caption text-muted-foreground"
3910
+ },
3911
+ variants: { strength: {
3912
+ weak: { label: "text-danger-text" },
3913
+ fair: { label: "text-warning-text" },
3914
+ strong: { label: "text-success-text" }
3915
+ } }
3916
+ });
3917
+ //#endregion
3918
+ //#region src/components/password-input/password-input.tsx
3919
+ /**
3920
+ * A quick strength estimate from length and character variety. A hint for users,
3921
+ * not a security check: enforce real rules on the server.
3922
+ */
3923
+ function passwordStrength(password) {
3924
+ let score = 0;
3925
+ if (password.length >= 8) score++;
3926
+ if (password.length >= 12) score++;
3927
+ if (/[a-z]/.test(password) && /[A-Z]/.test(password)) score++;
3928
+ if (/\d/.test(password)) score++;
3929
+ if (/[^A-Za-z0-9]/.test(password)) score++;
3930
+ return {
3931
+ score,
3932
+ strength: score >= 4 ? "strong" : score >= 3 ? "fair" : "weak"
3933
+ };
3934
+ }
3935
+ const filled = {
3936
+ weak: 1,
3937
+ fair: 2,
3938
+ strong: 3
3939
+ };
3940
+ const barColor = {
3941
+ weak: "bg-danger",
3942
+ fair: "bg-warning",
3943
+ strong: "bg-success"
3944
+ };
3945
+ const labels = {
3946
+ weak: "Weak",
3947
+ fair: "Fair",
3948
+ strong: "Strong"
3949
+ };
3950
+ function EyeIcon({ off }) {
3951
+ return /* @__PURE__ */ jsx("svg", {
3952
+ viewBox: "0 0 24 24",
3953
+ fill: "none",
3954
+ stroke: "currentColor",
3955
+ strokeWidth: "2",
3956
+ strokeLinecap: "round",
3957
+ strokeLinejoin: "round",
3958
+ "aria-hidden": "true",
3959
+ children: off ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("path", { d: "M10.7 5.1A10.4 10.4 0 0 1 12 5c7 0 10 7 10 7a13 13 0 0 1-1.7 2.7M6.6 6.6A13.5 13.5 0 0 0 2 12s3 7 10 7a9.7 9.7 0 0 0 5.4-1.6" }), /* @__PURE__ */ jsx("path", { d: "M9.9 9.9a3 3 0 1 0 4.2 4.2M2 2l20 20" })] }) : /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("path", { d: "M2 12s3-7 10-7 10 7 10 7-3 7-10 7S2 12 2 12Z" }), /* @__PURE__ */ jsx("circle", {
3960
+ cx: "12",
3961
+ cy: "12",
3962
+ r: "3"
3963
+ })] })
3964
+ });
3965
+ }
3966
+ /** A password field with a show/hide toggle and an optional strength meter. */
3967
+ function PasswordInput(inProps) {
3968
+ const [props, slots] = useComponentConfig("PasswordInput", inProps);
3969
+ const { showStrength = false, defaultVisible = false, value, defaultValue, onChange, className, ...rest } = props;
3970
+ const [visible, setVisible] = useState(defaultVisible);
3971
+ const [typed, setTyped] = useState(String(defaultValue ?? ""));
3972
+ const current = value !== void 0 ? String(value) : typed;
3973
+ const { strength } = passwordStrength(current);
3974
+ const s = passwordInputStyles({ strength });
3975
+ return /* @__PURE__ */ jsxs("div", {
3976
+ "data-slot": "password-input",
3977
+ className: s.root({ class: [slots.root, className] }),
3978
+ children: [/* @__PURE__ */ jsx(Input, {
3979
+ ...rest,
3980
+ ...value !== void 0 && { value },
3981
+ ...defaultValue !== void 0 && { defaultValue },
3982
+ type: visible ? "text" : "password",
3983
+ autoComplete: rest.autoComplete ?? "current-password",
3984
+ spellCheck: false,
3985
+ onChange: (event) => {
3986
+ setTyped(event.target.value);
3987
+ onChange?.(event);
3988
+ },
3989
+ suffix: /* @__PURE__ */ jsx("button", {
3990
+ type: "button",
3991
+ "aria-label": visible ? "Hide password" : "Show password",
3992
+ "aria-pressed": visible,
3993
+ disabled: rest.disabled,
3994
+ className: s.toggle({ class: slots.toggle }),
3995
+ onClick: () => setVisible((v) => !v),
3996
+ children: /* @__PURE__ */ jsx(EyeIcon, { off: visible })
3997
+ })
3998
+ }), showStrength && current.length > 0 && /* @__PURE__ */ jsxs("div", {
3999
+ className: s.meter({ class: slots.meter }),
4000
+ children: [/* @__PURE__ */ jsx("div", {
4001
+ className: s.bars({ class: slots.bars }),
4002
+ "aria-hidden": "true",
4003
+ children: [
4004
+ 1,
4005
+ 2,
4006
+ 3
4007
+ ].map((n) => /* @__PURE__ */ jsx("span", { className: s.bar({ class: [slots.bar, n <= filled[strength] && barColor[strength]] }) }, n))
4008
+ }), /* @__PURE__ */ jsx("span", {
4009
+ className: s.label({ class: slots.label }),
4010
+ "aria-live": "polite",
4011
+ children: labels[strength]
4012
+ })]
2239
4013
  })]
2240
- }) });
4014
+ });
2241
4015
  }
2242
4016
  //#endregion
2243
4017
  //#region src/components/progress/progress.styles.ts
@@ -2421,7 +4195,7 @@ const proseStyles = tv({
2421
4195
  "[&_h4]:mt-[1.4em] [&_h4]:mb-[0.4em] [&_h4]:font-display [&_h4]:text-h4",
2422
4196
  "[&_p]:my-[1em] [&_p]:text-pretty",
2423
4197
  "[&_strong]:font-semibold [&_strong]:text-foreground",
2424
- "[&_a]:font-medium [&_a]:text-primary [&_a]:underline [&_a]:decoration-primary/40 [&_a]:underline-offset-4 [&_a:hover]:decoration-primary",
4198
+ "[&_a]:font-medium [&_a]:text-primary-text [&_a]:underline [&_a]:decoration-primary/40 [&_a]:underline-offset-4 [&_a:hover]:decoration-primary",
2425
4199
  "[&_ul]:my-[1em] [&_ul]:list-disc [&_ul]:pl-[1.5em] [&_ol]:my-[1em] [&_ol]:list-decimal [&_ol]:pl-[1.5em]",
2426
4200
  "[&_li]:my-[0.35em] [&_li]:pl-[0.25em] [&_li::marker]:text-faint-foreground",
2427
4201
  "[&_blockquote]:my-[1.5em] [&_blockquote]:border-l-2 [&_blockquote]:border-primary [&_blockquote]:pl-[1em] [&_blockquote]:font-display [&_blockquote]:text-muted-foreground",
@@ -2595,22 +4369,113 @@ function RadioGroupItem({ label, description, children, className, id, ...props
2595
4369
  ...props,
2596
4370
  children: /* @__PURE__ */ jsx(RadioGroup$1.Indicator, { className: s.indicator({ class: slots.indicator }) })
2597
4371
  });
2598
- if (!label) return control;
2599
- return /* @__PURE__ */ jsxs("div", {
2600
- "data-slot": "radio-group-option",
2601
- className: s.option({ class: [slots.option, className] }),
2602
- children: [control, /* @__PURE__ */ jsxs("span", {
2603
- className: s.text({ class: slots.text }),
2604
- children: [/* @__PURE__ */ jsx("label", {
2605
- htmlFor: itemId,
2606
- className: s.label({ class: slots.label }),
2607
- children: label
2608
- }), description && /* @__PURE__ */ jsx("span", {
2609
- id: descriptionId,
2610
- className: s.description({ class: slots.description }),
2611
- children: description
2612
- })]
2613
- })]
4372
+ if (!label) return control;
4373
+ return /* @__PURE__ */ jsxs("div", {
4374
+ "data-slot": "radio-group-option",
4375
+ className: s.option({ class: [slots.option, className] }),
4376
+ children: [control, /* @__PURE__ */ jsxs("span", {
4377
+ className: s.text({ class: slots.text }),
4378
+ children: [/* @__PURE__ */ jsx("label", {
4379
+ htmlFor: itemId,
4380
+ className: s.label({ class: slots.label }),
4381
+ children: label
4382
+ }), description && /* @__PURE__ */ jsx("span", {
4383
+ id: descriptionId,
4384
+ className: s.description({ class: slots.description }),
4385
+ children: description
4386
+ })]
4387
+ })]
4388
+ });
4389
+ }
4390
+ //#endregion
4391
+ //#region src/components/resizable/resizable.styles.ts
4392
+ const resizableStyles = tv({ slots: {
4393
+ group: "flex h-full w-full data-[panel-group-direction=vertical]:flex-col",
4394
+ panel: "min-w-0",
4395
+ handle: [
4396
+ "relative flex w-px shrink-0 items-center justify-center bg-border outline-none",
4397
+ "transition-colors duration-(--glyph-duration-fast)",
4398
+ "after:absolute after:inset-y-0 after:left-1/2 after:w-2 after:-translate-x-1/2",
4399
+ "hover:bg-border-strong data-[resize-handle-state=drag]:bg-primary",
4400
+ "focus-visible:bg-primary focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-background",
4401
+ "data-[panel-group-direction=vertical]:h-px data-[panel-group-direction=vertical]:w-full",
4402
+ "data-[panel-group-direction=vertical]:after:inset-x-0 data-[panel-group-direction=vertical]:after:inset-y-auto data-[panel-group-direction=vertical]:after:left-0 data-[panel-group-direction=vertical]:after:top-1/2 data-[panel-group-direction=vertical]:after:h-2 data-[panel-group-direction=vertical]:after:w-full data-[panel-group-direction=vertical]:after:translate-x-0 data-[panel-group-direction=vertical]:after:-translate-y-1/2"
4403
+ ],
4404
+ grip: "z-10 flex h-5 w-3 items-center justify-center rounded-xs border border-border bg-surface text-faint-foreground shadow-xs in-data-[panel-group-direction=vertical]:h-3 in-data-[panel-group-direction=vertical]:w-5 [&>svg]:size-2.5 in-data-[panel-group-direction=vertical]:[&>svg]:rotate-90"
4405
+ } });
4406
+ //#endregion
4407
+ //#region src/components/resizable/resizable.tsx
4408
+ const s$1 = resizableStyles();
4409
+ function useSlots$1() {
4410
+ return useComponentConfig("Resizable", {})[1];
4411
+ }
4412
+ /**
4413
+ * Panels separated by draggable, keyboard-accessible dividers, for editors and split views.
4414
+ * Set `direction` to "horizontal" or "vertical"; pass `autoSaveId` to remember sizes.
4415
+ */
4416
+ function ResizablePanelGroup({ className, ...props }) {
4417
+ const slots = useSlots$1();
4418
+ return /* @__PURE__ */ jsx(PanelGroup, {
4419
+ "data-slot": "resizable-group",
4420
+ className: s$1.group({ class: [slots.group, className] }),
4421
+ ...props
4422
+ });
4423
+ }
4424
+ function ResizablePanel({ className, ...props }) {
4425
+ const slots = useSlots$1();
4426
+ return /* @__PURE__ */ jsx(Panel, {
4427
+ "data-slot": "resizable-panel",
4428
+ className: s$1.panel({ class: [slots.panel, className] }),
4429
+ ...props
4430
+ });
4431
+ }
4432
+ function ResizableHandle({ withHandle, className, ...props }) {
4433
+ const slots = useSlots$1();
4434
+ return /* @__PURE__ */ jsx(PanelResizeHandle, {
4435
+ "data-slot": "resizable-handle",
4436
+ className: s$1.handle({ class: [slots.handle, className] }),
4437
+ ...props,
4438
+ children: withHandle && /* @__PURE__ */ jsx("div", {
4439
+ className: s$1.grip({ class: slots.grip }),
4440
+ "aria-hidden": "true",
4441
+ children: /* @__PURE__ */ jsxs("svg", {
4442
+ viewBox: "0 0 24 24",
4443
+ fill: "currentColor",
4444
+ "aria-hidden": "true",
4445
+ children: [
4446
+ /* @__PURE__ */ jsx("circle", {
4447
+ cx: "9",
4448
+ cy: "6",
4449
+ r: "1.5"
4450
+ }),
4451
+ /* @__PURE__ */ jsx("circle", {
4452
+ cx: "15",
4453
+ cy: "6",
4454
+ r: "1.5"
4455
+ }),
4456
+ /* @__PURE__ */ jsx("circle", {
4457
+ cx: "9",
4458
+ cy: "12",
4459
+ r: "1.5"
4460
+ }),
4461
+ /* @__PURE__ */ jsx("circle", {
4462
+ cx: "15",
4463
+ cy: "12",
4464
+ r: "1.5"
4465
+ }),
4466
+ /* @__PURE__ */ jsx("circle", {
4467
+ cx: "9",
4468
+ cy: "18",
4469
+ r: "1.5"
4470
+ }),
4471
+ /* @__PURE__ */ jsx("circle", {
4472
+ cx: "15",
4473
+ cy: "18",
4474
+ r: "1.5"
4475
+ })
4476
+ ]
4477
+ })
4478
+ })
2614
4479
  });
2615
4480
  }
2616
4481
  //#endregion
@@ -2626,6 +4491,22 @@ const scrollAreaStyles = tv({ slots: {
2626
4491
  thumb: "relative flex-1 rounded-pill bg-border-strong hover:bg-faint-foreground",
2627
4492
  corner: "bg-transparent"
2628
4493
  } });
4494
+ /** True while the element's content overflows it, so keyboard users need to reach it. */
4495
+ function useOverflowing() {
4496
+ const ref = useRef(null);
4497
+ const [overflowing, setOverflowing] = useState(false);
4498
+ useEffect(() => {
4499
+ const el = ref.current;
4500
+ if (!el) return;
4501
+ const measure = () => setOverflowing(el.scrollHeight > el.clientHeight || el.scrollWidth > el.clientWidth);
4502
+ measure();
4503
+ const observer = new ResizeObserver(measure);
4504
+ observer.observe(el);
4505
+ if (el.firstElementChild) observer.observe(el.firstElementChild);
4506
+ return () => observer.disconnect();
4507
+ }, []);
4508
+ return [ref, overflowing];
4509
+ }
2629
4510
  /**
2630
4511
  * A scrollable region with slim, theme-colored scrollbars. Give it a height (or width)
2631
4512
  * with `className`, e.g. `h-72`.
@@ -2634,6 +4515,7 @@ function ScrollArea(inProps) {
2634
4515
  const [props, slots] = useComponentConfig("ScrollArea", inProps);
2635
4516
  const { orientation = "vertical", viewportClassName, className, children, ...rest } = props;
2636
4517
  const s = scrollAreaStyles();
4518
+ const [viewportRef, overflowing] = useOverflowing();
2637
4519
  const bar = (o) => /* @__PURE__ */ jsx(ScrollArea$1.Scrollbar, {
2638
4520
  "data-slot": "scroll-area-scrollbar",
2639
4521
  orientation: o,
@@ -2646,7 +4528,9 @@ function ScrollArea(inProps) {
2646
4528
  ...rest,
2647
4529
  children: [
2648
4530
  /* @__PURE__ */ jsx(ScrollArea$1.Viewport, {
4531
+ ref: viewportRef,
2649
4532
  "data-slot": "scroll-area-viewport",
4533
+ tabIndex: overflowing ? 0 : void 0,
2650
4534
  className: s.viewport({ class: [slots.viewport, viewportClassName] }),
2651
4535
  children
2652
4536
  }),
@@ -2693,6 +4577,16 @@ function Section({ spacing, tone, divided, asChild, className, ...props }) {
2693
4577
  });
2694
4578
  }
2695
4579
  //#endregion
4580
+ //#region src/internal/dev.ts
4581
+ const warned = /* @__PURE__ */ new Set();
4582
+ /** Logs a console warning once per key, in development only. */
4583
+ function warnOnce(key, message) {
4584
+ if (typeof process === "undefined" || process.env.NODE_ENV === "production") return;
4585
+ if (warned.has(key)) return;
4586
+ warned.add(key);
4587
+ console.warn(`[glyph] ${message}`);
4588
+ }
4589
+ //#endregion
2696
4590
  //#region src/components/segmented-control/segmented-control.tsx
2697
4591
  const segmentedControlStyles = tv({
2698
4592
  slots: {
@@ -2730,19 +4624,25 @@ const segmentedControlStyles = tv({
2730
4624
  function SegmentedControl(inProps) {
2731
4625
  const [props, slots] = useComponentConfig("SegmentedControl", inProps);
2732
4626
  const { options, value, defaultValue, onValueChange, size, fullWidth, className, ...rest } = props;
4627
+ const field = useContext(FieldContext);
2733
4628
  const s = segmentedControlStyles({
2734
4629
  size,
2735
4630
  fullWidth
2736
4631
  });
2737
- return /* @__PURE__ */ jsx(ToggleGroup.Root, {
4632
+ const labelledBy = rest["aria-labelledby"] ?? (rest["aria-label"] ? void 0 : field?.labelId);
4633
+ if (!rest["aria-label"] && !labelledBy) warnOnce("segmented-control-label", "SegmentedControl needs a label: pass aria-label, or place it in a <Field label=\"…\">.");
4634
+ const describedBy = [field?.descriptionId, field?.errorId].filter(Boolean).join(" ");
4635
+ return /* @__PURE__ */ jsx(ToggleGroup$1.Root, {
2738
4636
  type: "single",
2739
4637
  "data-slot": "segmented-control",
2740
4638
  ...value !== void 0 && { value },
2741
4639
  ...defaultValue !== void 0 && { defaultValue },
2742
4640
  onValueChange: (next) => next && onValueChange?.(next),
2743
4641
  className: s.root({ class: [slots.root, className] }),
4642
+ "aria-labelledby": labelledBy,
4643
+ "aria-describedby": describedBy || void 0,
2744
4644
  ...rest,
2745
- children: options.map((option) => /* @__PURE__ */ jsx(ToggleGroup.Item, {
4645
+ children: options.map((option) => /* @__PURE__ */ jsx(ToggleGroup$1.Item, {
2746
4646
  value: option.value,
2747
4647
  disabled: option.disabled,
2748
4648
  className: s.item({ class: slots.item }),
@@ -2794,7 +4694,7 @@ function Select(inProps) {
2794
4694
  className: s.trigger({ class: [slots.trigger, className] }),
2795
4695
  children: [/* @__PURE__ */ jsx(Select$1.Value, { placeholder }), /* @__PURE__ */ jsx(Select$1.Icon, {
2796
4696
  asChild: true,
2797
- children: /* @__PURE__ */ jsx(ChevronDownIcon, { className: s.icon({ class: slots.icon }) })
4697
+ children: /* @__PURE__ */ jsx(ChevronDownIcon$1, { className: s.icon({ class: slots.icon }) })
2798
4698
  })]
2799
4699
  }), /* @__PURE__ */ jsx(Select$1.Portal, { children: /* @__PURE__ */ jsx(Select$1.Content, {
2800
4700
  position: "popper",
@@ -2817,7 +4717,7 @@ function SelectItem({ className, children, ...props }) {
2817
4717
  ...props,
2818
4718
  children: [/* @__PURE__ */ jsx(Select$1.ItemText, { children }), /* @__PURE__ */ jsx(Select$1.ItemIndicator, {
2819
4719
  className: s.indicator({ class: slots.indicator }),
2820
- children: /* @__PURE__ */ jsx(CheckIcon$1, {})
4720
+ children: /* @__PURE__ */ jsx(CheckIcon$4, {})
2821
4721
  })]
2822
4722
  });
2823
4723
  }
@@ -2846,8 +4746,8 @@ function Separator(inProps) {
2846
4746
  //#region src/components/sheet/sheet.styles.ts
2847
4747
  const sheetStyles = tv({
2848
4748
  slots: {
2849
- overlay: "fixed inset-0 z-50 animate-fade-in bg-overlay",
2850
- content: ["fixed z-50 flex flex-col gap-5 border-border bg-surface p-6 text-foreground shadow-lg outline-none", "transition-[translate] duration-(--glyph-duration-slow) ease-standard"],
4749
+ overlay: "fixed inset-0 z-50 bg-overlay data-[state=open]:animate-fade-in data-[state=closed]:animate-fade-out",
4750
+ content: ["fixed z-50 flex flex-col gap-5 border-border bg-surface p-6 text-foreground shadow-lg outline-none"],
2851
4751
  close: [
2852
4752
  "absolute top-4 right-4 inline-flex size-7 cursor-pointer items-center justify-center rounded-sm text-muted-foreground hover:bg-muted hover:text-foreground [&>svg]:size-4",
2853
4753
  transition,
@@ -2861,10 +4761,10 @@ const sheetStyles = tv({
2861
4761
  },
2862
4762
  variants: {
2863
4763
  side: {
2864
- right: { content: "inset-y-0 right-0 h-full w-full border-l-(length:--glyph-border-width) starting:translate-x-full" },
2865
- left: { content: "inset-y-0 left-0 h-full w-full border-r-(length:--glyph-border-width) starting:-translate-x-full" },
2866
- top: { content: "inset-x-0 top-0 max-h-[85dvh] border-b-(length:--glyph-border-width) starting:-translate-y-full" },
2867
- bottom: { content: "inset-x-0 bottom-0 max-h-[85dvh] rounded-t-xl border-t-(length:--glyph-border-width) starting:translate-y-full" }
4764
+ right: { content: "inset-y-0 right-0 h-full w-full border-l-(length:--glyph-border-width) data-[state=open]:animate-sheet-in-right data-[state=closed]:animate-sheet-out-right" },
4765
+ left: { content: "inset-y-0 left-0 h-full w-full border-r-(length:--glyph-border-width) data-[state=open]:animate-sheet-in-left data-[state=closed]:animate-sheet-out-left" },
4766
+ top: { content: "inset-x-0 top-0 max-h-[85dvh] border-b-(length:--glyph-border-width) data-[state=open]:animate-sheet-in-top data-[state=closed]:animate-sheet-out-top" },
4767
+ bottom: { content: "inset-x-0 bottom-0 max-h-[85dvh] rounded-t-xl border-t-(length:--glyph-border-width) data-[state=open]:animate-sheet-in-bottom data-[state=closed]:animate-sheet-out-bottom" }
2868
4768
  },
2869
4769
  size: {
2870
4770
  sm: {},
@@ -3002,7 +4902,9 @@ const toArray = (value) => value === void 0 ? void 0 : typeof value === "number"
3002
4902
  /** Choose a number, or a range with two thumbs, by dragging or with arrow keys. */
3003
4903
  function Slider(inProps) {
3004
4904
  const [props, slots] = useComponentConfig("Slider", useFieldControl(inProps));
3005
- const { value, defaultValue, onValueChange, onValueCommit, min = 0, max = 100, step = 1, minStepsBetweenThumbs, marks, showValue = false, disabled, name, id, className, thumbLabels = ["Minimum", "Maximum"], "aria-label": ariaLabel, "aria-describedby": ariaDescribedBy, "aria-invalid": ariaInvalid } = props;
4905
+ const { value, defaultValue, onValueChange, onValueCommit, min = 0, max = 100, step = 1, minStepsBetweenThumbs, marks, showValue = false, disabled, name, id, className, thumbLabels = ["Minimum", "Maximum"], "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, "aria-describedby": ariaDescribedBy, "aria-invalid": ariaInvalid } = props;
4906
+ const field = useContext(FieldContext);
4907
+ const labelledBy = ariaLabelledBy ?? (ariaLabel ? void 0 : field?.labelId);
3006
4908
  const isRange = Array.isArray(value ?? defaultValue);
3007
4909
  const fromArray = (next) => isRange ? [next[0], next[1]] : next[0];
3008
4910
  const current = toArray(value) ?? toArray(defaultValue) ?? [min];
@@ -3029,6 +4931,7 @@ function Slider(inProps) {
3029
4931
  }), current.map((thumbValue, index) => /* @__PURE__ */ jsx(Slider$1.Thumb, {
3030
4932
  id: index === 0 ? id : void 0,
3031
4933
  "aria-label": isRange ? thumbLabels[index] : ariaLabel,
4934
+ "aria-labelledby": isRange ? void 0 : labelledBy,
3032
4935
  "aria-describedby": ariaDescribedBy,
3033
4936
  "aria-invalid": ariaInvalid,
3034
4937
  className: s.thumb({ class: slots.thumb }),
@@ -3199,6 +5102,164 @@ function StatCard(inProps) {
3199
5102
  });
3200
5103
  }
3201
5104
  //#endregion
5105
+ //#region src/components/stepper/stepper.styles.ts
5106
+ const stepperStyles = tv({
5107
+ slots: {
5108
+ root: "flex w-full list-none p-0",
5109
+ step: "relative flex min-w-0",
5110
+ trigger: ["flex min-w-0 rounded-md text-left", focusRing],
5111
+ indicator: [
5112
+ "relative z-10 flex size-8 shrink-0 items-center justify-center rounded-pill text-small font-medium tabular-nums [&>svg]:size-4",
5113
+ themedBorder,
5114
+ transition
5115
+ ],
5116
+ connector: "absolute transition-colors duration-(--glyph-duration-base)",
5117
+ text: "grid min-w-0 gap-0.5",
5118
+ title: "text-small font-medium",
5119
+ description: "text-caption text-muted-foreground"
5120
+ },
5121
+ variants: {
5122
+ orientation: {
5123
+ horizontal: {
5124
+ root: "items-start",
5125
+ step: "flex-1 flex-col items-center text-center",
5126
+ trigger: "flex-col items-center gap-2 text-center",
5127
+ connector: "top-4 right-[calc(-50%+1.25rem)] left-[calc(50%+1.25rem)] h-px",
5128
+ text: "px-2"
5129
+ },
5130
+ vertical: {
5131
+ root: "flex-col",
5132
+ step: "gap-3 pb-7 last:pb-0",
5133
+ trigger: "items-start gap-3",
5134
+ connector: "top-9.5 bottom-1.5 left-4 w-px -translate-x-1/2",
5135
+ text: "pt-1.5"
5136
+ }
5137
+ },
5138
+ status: {
5139
+ complete: {
5140
+ indicator: "border-primary bg-primary text-primary-foreground",
5141
+ connector: "bg-primary",
5142
+ title: "text-foreground"
5143
+ },
5144
+ current: {
5145
+ indicator: "border-primary bg-surface text-primary-text ring-4 ring-primary/15",
5146
+ connector: "bg-border",
5147
+ title: "text-foreground"
5148
+ },
5149
+ upcoming: {
5150
+ indicator: "border-border bg-surface text-muted-foreground",
5151
+ connector: "bg-border",
5152
+ title: "text-muted-foreground"
5153
+ },
5154
+ error: {
5155
+ indicator: "border-danger bg-danger text-danger-foreground",
5156
+ connector: "bg-border",
5157
+ title: "text-danger-text"
5158
+ }
5159
+ },
5160
+ clickable: { true: { trigger: "cursor-pointer hover:[&_[data-slot=stepper-title]]:underline underline-offset-4" } }
5161
+ },
5162
+ defaultVariants: {
5163
+ orientation: "horizontal",
5164
+ status: "upcoming"
5165
+ }
5166
+ });
5167
+ //#endregion
5168
+ //#region src/components/stepper/stepper.tsx
5169
+ const statusText = {
5170
+ complete: "completed",
5171
+ current: "current step",
5172
+ upcoming: "not started",
5173
+ error: "needs attention"
5174
+ };
5175
+ const icon = {
5176
+ xmlns: "http://www.w3.org/2000/svg",
5177
+ viewBox: "0 0 24 24",
5178
+ fill: "none",
5179
+ stroke: "currentColor",
5180
+ strokeWidth: 2.5,
5181
+ strokeLinecap: "round",
5182
+ strokeLinejoin: "round"
5183
+ };
5184
+ const CheckIcon = () => /* @__PURE__ */ jsx("svg", {
5185
+ "aria-hidden": "true",
5186
+ ...icon,
5187
+ children: /* @__PURE__ */ jsx("path", { d: "M20 6 9 17l-5-5" })
5188
+ });
5189
+ const AlertIcon = () => /* @__PURE__ */ jsx("svg", {
5190
+ "aria-hidden": "true",
5191
+ ...icon,
5192
+ children: /* @__PURE__ */ jsx("path", { d: "M12 7v6M12 17h.01" })
5193
+ });
5194
+ function statusOf(step, index, current) {
5195
+ if (step.status) return step.status;
5196
+ if (index < current) return "complete";
5197
+ return index === current ? "current" : "upcoming";
5198
+ }
5199
+ /** Progress through a multi-step flow such as onboarding or checkout. */
5200
+ function Stepper(inProps) {
5201
+ const [props, slots] = useComponentConfig("Stepper", inProps);
5202
+ const { steps, current, orientation = "horizontal", onStepClick, className, "aria-label": ariaLabel = "Progress", ...rest } = props;
5203
+ const root = stepperStyles({ orientation });
5204
+ return /* @__PURE__ */ jsx("ol", {
5205
+ "data-slot": "stepper",
5206
+ "data-orientation": orientation,
5207
+ "aria-label": ariaLabel,
5208
+ className: root.root({ class: [slots.root, className] }),
5209
+ ...rest,
5210
+ children: steps.map((step, index) => {
5211
+ const status = statusOf(step, index, current);
5212
+ const clickable = Boolean(onStepClick) && status === "complete";
5213
+ const s = stepperStyles({
5214
+ orientation,
5215
+ status,
5216
+ clickable
5217
+ });
5218
+ const content = /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("span", {
5219
+ "data-slot": "stepper-indicator",
5220
+ className: s.indicator({ class: slots.indicator }),
5221
+ children: status === "complete" ? /* @__PURE__ */ jsx(CheckIcon, {}) : status === "error" ? /* @__PURE__ */ jsx(AlertIcon, {}) : index + 1
5222
+ }), /* @__PURE__ */ jsxs("span", {
5223
+ className: s.text({ class: slots.text }),
5224
+ children: [
5225
+ /* @__PURE__ */ jsx("span", {
5226
+ "data-slot": "stepper-title",
5227
+ className: s.title({ class: slots.title }),
5228
+ children: step.title
5229
+ }),
5230
+ step.description && /* @__PURE__ */ jsx("span", {
5231
+ className: s.description({ class: slots.description }),
5232
+ children: step.description
5233
+ }),
5234
+ /* @__PURE__ */ jsxs("span", {
5235
+ className: "sr-only",
5236
+ children: [", ", statusText[status]]
5237
+ })
5238
+ ]
5239
+ })] });
5240
+ return /* @__PURE__ */ jsxs("li", {
5241
+ "data-slot": "stepper-step",
5242
+ "data-status": status,
5243
+ "aria-current": status === "current" ? "step" : void 0,
5244
+ className: s.step({ class: slots.step }),
5245
+ children: [index < steps.length - 1 && /* @__PURE__ */ jsx("span", {
5246
+ "data-slot": "stepper-connector",
5247
+ "aria-hidden": "true",
5248
+ className: s.connector({ class: slots.connector })
5249
+ }), clickable ? /* @__PURE__ */ jsx("button", {
5250
+ type: "button",
5251
+ onClick: () => onStepClick?.(index),
5252
+ className: s.trigger({ class: slots.trigger }),
5253
+ children: content
5254
+ }) : /* @__PURE__ */ jsx("span", {
5255
+ className: s.trigger({ class: slots.trigger }),
5256
+ children: content
5257
+ })]
5258
+ }, index);
5259
+ })
5260
+ });
5261
+ }
5262
+ //#endregion
3202
5263
  //#region src/components/switch/switch.tsx
3203
5264
  const switchStyles = tv({
3204
5265
  slots: {
@@ -3305,6 +5366,170 @@ function TabsContent({ className, ...props }) {
3305
5366
  });
3306
5367
  }
3307
5368
  //#endregion
5369
+ //#region src/components/tag-input/tag-input.styles.ts
5370
+ const tagInputStyles = tv({
5371
+ slots: {
5372
+ root: "grid gap-1.5",
5373
+ frame: [
5374
+ ...fieldControl,
5375
+ "flex cursor-text flex-wrap items-center gap-1.5 px-2 py-1",
5376
+ "focus-within:border-ring focus-within:ring-3 focus-within:ring-ring/20",
5377
+ "data-invalid:focus-within:ring-danger/20",
5378
+ "has-[input:disabled]:cursor-not-allowed has-[input:disabled]:opacity-50"
5379
+ ],
5380
+ tag: "inline-flex h-6 max-w-full items-center gap-1 rounded-pill bg-muted pr-1 pl-2.5 text-caption text-foreground",
5381
+ tagLabel: "truncate",
5382
+ remove: "inline-flex size-4 shrink-0 cursor-pointer items-center justify-center rounded-pill text-muted-foreground hover:bg-border-strong/40 hover:text-foreground focus-visible:outline-2 focus-visible:outline-ring [&>svg]:size-3",
5383
+ input: "h-7 min-w-24 flex-1 bg-transparent px-1 text-foreground outline-none placeholder:text-faint-foreground disabled:cursor-not-allowed",
5384
+ message: "text-small font-medium text-danger-text"
5385
+ },
5386
+ variants: { size: {
5387
+ sm: { frame: "min-h-(--glyph-control-sm) text-small" },
5388
+ md: { frame: "min-h-(--glyph-control-md) text-small" },
5389
+ lg: { frame: "min-h-(--glyph-control-lg) text-body" }
5390
+ } },
5391
+ defaultVariants: { size: "md" }
5392
+ });
5393
+ //#endregion
5394
+ //#region src/components/tag-input/tag-input.tsx
5395
+ function XIcon() {
5396
+ return /* @__PURE__ */ jsx("svg", {
5397
+ viewBox: "0 0 24 24",
5398
+ fill: "none",
5399
+ stroke: "currentColor",
5400
+ strokeWidth: "2.5",
5401
+ strokeLinecap: "round",
5402
+ "aria-hidden": "true",
5403
+ children: /* @__PURE__ */ jsx("path", { d: "M18 6 6 18M6 6l12 12" })
5404
+ });
5405
+ }
5406
+ /**
5407
+ * Free-form multi-value input. Enter or a comma turns the text into a removable tag;
5408
+ * Backspace on an empty input removes the last one. Pasting a comma-separated list adds them all.
5409
+ */
5410
+ function TagInput(inProps) {
5411
+ const [props, slots] = useComponentConfig("TagInput", useFieldControl(inProps));
5412
+ const { value: valueProp, defaultValue = [], onValueChange, placeholder = "Add a tag…", maxTags, validate, allowDuplicates = false, separators = [","], disabled, name, id, size, className, "aria-label": ariaLabel, "aria-describedby": ariaDescribedBy, "aria-invalid": ariaInvalid } = props;
5413
+ const [tags, setTags] = useControllableState({
5414
+ value: valueProp,
5415
+ defaultValue,
5416
+ onChange: onValueChange
5417
+ });
5418
+ const [draft, setDraft] = useState("");
5419
+ const [error, setError] = useState(null);
5420
+ const inputRef = useRef(null);
5421
+ const errorId = useId();
5422
+ const s = tagInputStyles({ size });
5423
+ const full = maxTags !== void 0 && tags.length >= maxTags;
5424
+ const invalid = Boolean(error) || ariaInvalid === true;
5425
+ const add = (raw) => {
5426
+ let next = [...tags];
5427
+ let problem = null;
5428
+ for (const candidate of raw.map((t) => t.trim()).filter(Boolean)) {
5429
+ if (maxTags !== void 0 && next.length >= maxTags) {
5430
+ problem = `You can add up to ${maxTags} tags.`;
5431
+ break;
5432
+ }
5433
+ if (!allowDuplicates && next.includes(candidate)) {
5434
+ problem = `“${candidate}” is already added.`;
5435
+ continue;
5436
+ }
5437
+ const verdict = validate?.(candidate, next) ?? true;
5438
+ if (verdict !== true) {
5439
+ problem = verdict;
5440
+ continue;
5441
+ }
5442
+ next = [...next, candidate];
5443
+ }
5444
+ if (next.length !== tags.length) setTags(next);
5445
+ setError(problem);
5446
+ return problem === null;
5447
+ };
5448
+ const commitDraft = () => {
5449
+ if (!draft.trim()) return;
5450
+ if (add([draft])) setDraft("");
5451
+ };
5452
+ const remove = (index) => {
5453
+ setTags(tags.filter((_, i) => i !== index));
5454
+ setError(null);
5455
+ inputRef.current?.focus();
5456
+ };
5457
+ const handleKeyDown = (event) => {
5458
+ if (event.key === "Enter" || separators.includes(event.key)) {
5459
+ if (event.key === "Enter" && !draft.trim()) return;
5460
+ event.preventDefault();
5461
+ commitDraft();
5462
+ } else if (event.key === "Backspace" && draft === "" && tags.length > 0) {
5463
+ event.preventDefault();
5464
+ remove(tags.length - 1);
5465
+ }
5466
+ };
5467
+ const handlePaste = (event) => {
5468
+ const text = event.clipboardData.getData("text");
5469
+ const pattern = new RegExp(`[${["\n", ...separators].map((s) => s.replace(/[-\\^\]]/g, "\\$&")).join("")}]`);
5470
+ if (!pattern.test(text)) return;
5471
+ event.preventDefault();
5472
+ add(text.split(pattern));
5473
+ };
5474
+ const describedBy = [ariaDescribedBy, error ? errorId : void 0].filter(Boolean).join(" ") || void 0;
5475
+ return /* @__PURE__ */ jsxs("div", {
5476
+ "data-slot": "tag-input",
5477
+ className: s.root({ class: [slots.root, className] }),
5478
+ children: [
5479
+ /* @__PURE__ */ jsxs("div", {
5480
+ "data-invalid": invalid || void 0,
5481
+ className: s.frame({ class: slots.frame }),
5482
+ onClick: () => inputRef.current?.focus(),
5483
+ children: [tags.map((tag, index) => /* @__PURE__ */ jsxs("span", {
5484
+ "data-slot": "tag",
5485
+ className: s.tag({ class: slots.tag }),
5486
+ children: [/* @__PURE__ */ jsx("span", {
5487
+ className: s.tagLabel({ class: slots.tagLabel }),
5488
+ children: tag
5489
+ }), !disabled && /* @__PURE__ */ jsx("button", {
5490
+ type: "button",
5491
+ "aria-label": `Remove ${tag}`,
5492
+ className: s.remove({ class: slots.remove }),
5493
+ onClick: (event) => {
5494
+ event.stopPropagation();
5495
+ remove(index);
5496
+ },
5497
+ children: /* @__PURE__ */ jsx(XIcon, {})
5498
+ })]
5499
+ }, `${tag}-${index}`)), /* @__PURE__ */ jsx("input", {
5500
+ ref: inputRef,
5501
+ id,
5502
+ value: draft,
5503
+ disabled: disabled || full,
5504
+ placeholder: full ? void 0 : tags.length === 0 ? placeholder : void 0,
5505
+ "aria-label": ariaLabel,
5506
+ "aria-describedby": describedBy,
5507
+ "aria-invalid": invalid || void 0,
5508
+ className: s.input({ class: slots.input }),
5509
+ onChange: (event) => {
5510
+ setDraft(event.target.value);
5511
+ if (error) setError(null);
5512
+ },
5513
+ onKeyDown: handleKeyDown,
5514
+ onPaste: handlePaste,
5515
+ onBlur: commitDraft
5516
+ })]
5517
+ }),
5518
+ error && /* @__PURE__ */ jsx("p", {
5519
+ id: errorId,
5520
+ role: "alert",
5521
+ className: s.message({ class: slots.message }),
5522
+ children: error
5523
+ }),
5524
+ name && tags.map((tag, index) => /* @__PURE__ */ jsx("input", {
5525
+ type: "hidden",
5526
+ name,
5527
+ value: tag
5528
+ }, `${tag}-${index}`))
5529
+ ]
5530
+ });
5531
+ }
5532
+ //#endregion
3308
5533
  //#region src/components/text/text.styles.ts
3309
5534
  const textStyles = tv({
3310
5535
  slots: { base: "" },
@@ -3319,10 +5544,10 @@ const textStyles = tv({
3319
5544
  default: { base: "text-foreground" },
3320
5545
  muted: { base: "text-muted-foreground" },
3321
5546
  faint: { base: "text-faint-foreground" },
3322
- primary: { base: "text-primary" },
3323
- success: { base: "text-success" },
3324
- warning: { base: "text-warning" },
3325
- danger: { base: "text-danger" }
5547
+ primary: { base: "text-primary-text" },
5548
+ success: { base: "text-success-text" },
5549
+ warning: { base: "text-warning-text" },
5550
+ danger: { base: "text-danger-text" }
3326
5551
  },
3327
5552
  weight: {
3328
5553
  regular: { base: "font-normal" },
@@ -3373,6 +5598,87 @@ function Textarea(inProps) {
3373
5598
  });
3374
5599
  }
3375
5600
  //#endregion
5601
+ //#region src/components/timeline/timeline.styles.ts
5602
+ const timelineStyles = tv({
5603
+ slots: {
5604
+ root: "grid",
5605
+ item: "group/item relative grid grid-cols-[auto_1fr] gap-x-3",
5606
+ rail: "flex flex-col items-center",
5607
+ marker: ["z-10 flex size-6 shrink-0 items-center justify-center rounded-pill bg-surface [&>svg]:size-3.5", themedBorder],
5608
+ dot: "size-2 rounded-pill bg-current",
5609
+ connector: "my-1 w-px flex-1 bg-border group-last/item:hidden",
5610
+ content: "grid min-w-0 gap-0.5 pt-0.5 pb-6 group-last/item:pb-0",
5611
+ header: "flex flex-wrap items-baseline justify-between gap-x-3 gap-y-0.5",
5612
+ title: "text-small font-medium text-foreground",
5613
+ time: "font-mono text-caption text-faint-foreground tabular-nums",
5614
+ description: "text-small text-muted-foreground"
5615
+ },
5616
+ variants: { tone: {
5617
+ neutral: { marker: "border-border text-muted-foreground" },
5618
+ primary: { marker: "border-primary/40 text-[color-mix(in_oklab,var(--color-primary)_80%,var(--color-foreground))]" },
5619
+ info: { marker: "border-info/40 text-[color-mix(in_oklab,var(--color-info)_80%,var(--color-foreground))]" },
5620
+ success: { marker: "border-success/40 text-[color-mix(in_oklab,var(--color-success)_80%,var(--color-foreground))]" },
5621
+ warning: { marker: "border-warning/50 text-[color-mix(in_oklab,var(--color-warning)_80%,var(--color-foreground))]" },
5622
+ danger: { marker: "border-danger/40 text-[color-mix(in_oklab,var(--color-danger)_80%,var(--color-foreground))]" }
5623
+ } },
5624
+ defaultVariants: { tone: "neutral" }
5625
+ });
5626
+ //#endregion
5627
+ //#region src/components/timeline/timeline.tsx
5628
+ const TimelineContext = createContext({});
5629
+ /** A vertical list of events in order, for activity feeds, changelogs and order tracking. */
5630
+ function Timeline(inProps) {
5631
+ const [props, slots] = useComponentConfig("Timeline", inProps);
5632
+ const { items, className, children, ...rest } = props;
5633
+ const s = timelineStyles();
5634
+ return /* @__PURE__ */ jsx(TimelineContext.Provider, {
5635
+ value: slots,
5636
+ children: /* @__PURE__ */ jsx("ol", {
5637
+ "data-slot": "timeline",
5638
+ className: s.root({ class: [slots.root, className] }),
5639
+ ...rest,
5640
+ children: items ? items.map(({ id, description, ...item }, index) => /* @__PURE__ */ jsx(TimelineItem, {
5641
+ ...item,
5642
+ children: description
5643
+ }, id ?? index)) : children
5644
+ })
5645
+ });
5646
+ }
5647
+ function TimelineItem({ title, time, dateTime, icon, tone, className, children, ...props }) {
5648
+ const slots = useContext(TimelineContext);
5649
+ const s = timelineStyles({ tone });
5650
+ return /* @__PURE__ */ jsxs("li", {
5651
+ "data-slot": "timeline-item",
5652
+ "data-tone": tone ?? "neutral",
5653
+ className: s.item({ class: [slots.item, className] }),
5654
+ ...props,
5655
+ children: [/* @__PURE__ */ jsxs("div", {
5656
+ className: s.rail({ class: slots.rail }),
5657
+ "aria-hidden": "true",
5658
+ children: [/* @__PURE__ */ jsx("span", {
5659
+ className: s.marker({ class: slots.marker }),
5660
+ children: icon ?? /* @__PURE__ */ jsx("span", { className: s.dot({ class: slots.dot }) })
5661
+ }), /* @__PURE__ */ jsx("span", { className: s.connector({ class: slots.connector }) })]
5662
+ }), /* @__PURE__ */ jsxs("div", {
5663
+ className: s.content({ class: slots.content }),
5664
+ children: [/* @__PURE__ */ jsxs("div", {
5665
+ className: s.header({ class: slots.header }),
5666
+ children: [/* @__PURE__ */ jsx("p", {
5667
+ className: s.title({ class: slots.title }),
5668
+ children: title
5669
+ }), time && /* @__PURE__ */ jsx("time", {
5670
+ dateTime,
5671
+ className: s.time({ class: slots.time }),
5672
+ children: time
5673
+ })]
5674
+ }), children && /* @__PURE__ */ jsx("div", {
5675
+ className: s.description({ class: slots.description }),
5676
+ children
5677
+ })]
5678
+ })]
5679
+ });
5680
+ }
5681
+ //#endregion
3376
5682
  //#region src/components/toast/toast.tsx
3377
5683
  const toastStyles = tv({ slots: {
3378
5684
  toast: ["group flex w-(--width) items-start gap-3 rounded-lg border-border bg-raised p-4 text-small text-foreground shadow-lg", themedBorder],
@@ -3441,6 +5747,87 @@ function Toaster(inProps) {
3441
5747
  });
3442
5748
  }
3443
5749
  //#endregion
5750
+ //#region src/components/toggle/toggle.styles.ts
5751
+ const toggleStyles = tv({
5752
+ slots: {
5753
+ base: [
5754
+ "inline-flex shrink-0 cursor-pointer select-none items-center justify-center gap-2 whitespace-nowrap rounded-md font-medium text-muted-foreground",
5755
+ transition,
5756
+ focusRing,
5757
+ "hover:bg-muted hover:text-foreground",
5758
+ "data-[state=on]:bg-muted data-[state=on]:text-foreground",
5759
+ "disabled:pointer-events-none disabled:opacity-50 [&_svg]:size-4 [&_svg]:shrink-0"
5760
+ ],
5761
+ group: "inline-flex items-center gap-1"
5762
+ },
5763
+ variants: {
5764
+ variant: {
5765
+ default: { base: "bg-transparent" },
5766
+ outline: { base: ["border-border bg-transparent shadow-xs hover:border-border-strong", themedBorder] }
5767
+ },
5768
+ size: {
5769
+ sm: { base: "h-(--glyph-control-sm) min-w-(--glyph-control-sm) px-2 text-caption" },
5770
+ md: { base: "h-(--glyph-control-md) min-w-(--glyph-control-md) px-2.5 text-small" },
5771
+ lg: { base: "h-(--glyph-control-lg) min-w-(--glyph-control-lg) px-3 text-small" }
5772
+ }
5773
+ },
5774
+ defaultVariants: {
5775
+ variant: "default",
5776
+ size: "md"
5777
+ }
5778
+ });
5779
+ //#endregion
5780
+ //#region src/components/toggle/toggle.tsx
5781
+ /**
5782
+ * A two-state button, e.g. Bold in a toolbar. Use Switch for settings that take effect
5783
+ * immediately, and Checkbox inside forms.
5784
+ */
5785
+ function Toggle(inProps) {
5786
+ const [props, slots] = useComponentConfig("Toggle", inProps);
5787
+ const { variant, size, className, ...rest } = props;
5788
+ return /* @__PURE__ */ jsx(Toggle$1.Root, {
5789
+ "data-slot": "toggle",
5790
+ className: toggleStyles({
5791
+ variant,
5792
+ size
5793
+ }).base({ class: [slots.base, className] }),
5794
+ ...rest
5795
+ });
5796
+ }
5797
+ const ToggleGroupContext = createContext({});
5798
+ /**
5799
+ * A set of toggles. `type="single"` behaves like a radio group (text alignment),
5800
+ * `type="multiple"` like checkboxes (bold, italic, underline). Arrow keys move between items.
5801
+ */
5802
+ function ToggleGroup(inProps) {
5803
+ const [props, slots] = useComponentConfig("Toggle", inProps);
5804
+ const { variant, size, className, ...rest } = props;
5805
+ return /* @__PURE__ */ jsx(ToggleGroupContext.Provider, {
5806
+ value: {
5807
+ variant,
5808
+ size
5809
+ },
5810
+ children: /* @__PURE__ */ jsx(ToggleGroup$1.Root, {
5811
+ "data-slot": "toggle-group",
5812
+ className: toggleStyles().group({ class: [slots.group, className] }),
5813
+ ...rest
5814
+ })
5815
+ });
5816
+ }
5817
+ function ToggleGroupItem({ variant, size, className, ...props }) {
5818
+ const group = useContext(ToggleGroupContext);
5819
+ const [, slots] = useComponentConfig("Toggle", {});
5820
+ const s = toggleStyles({
5821
+ variant: variant ?? group.variant,
5822
+ size: size ?? group.size
5823
+ });
5824
+ return /* @__PURE__ */ jsx(ToggleGroup$1.Item, {
5825
+ "data-slot": "toggle-group-item",
5826
+ className: s.base({ class: [slots.base, className] }),
5827
+ ...props
5828
+ });
5829
+ }
5830
+ //#endregion
3444
5831
  //#region src/components/tooltip/tooltip.tsx
3445
5832
  const tooltipStyles = tv({ slots: { content: "z-50 max-w-xs animate-pop-in rounded-sm bg-secondary px-2 py-1 text-caption text-secondary-foreground shadow-md" } });
3446
5833
  /** A short hint on hover or focus. The child must be focusable (a button or link). */
@@ -3463,6 +5850,231 @@ function Tooltip(inProps) {
3463
5850
  });
3464
5851
  }
3465
5852
  //#endregion
5853
+ //#region src/components/tree-view/tree-view.styles.ts
5854
+ const treeViewStyles = tv({
5855
+ slots: {
5856
+ root: "grid gap-px text-small",
5857
+ item: [
5858
+ "outline-none",
5859
+ "focus-visible:[&>[data-slot=tree-row]]:ring-2 focus-visible:[&>[data-slot=tree-row]]:ring-ring",
5860
+ "aria-selected:[&>[data-slot=tree-row]]:bg-muted aria-selected:[&>[data-slot=tree-row]]:text-foreground aria-selected:[&>[data-slot=tree-row]]:font-medium",
5861
+ "aria-disabled:[&>[data-slot=tree-row]]:pointer-events-none aria-disabled:[&>[data-slot=tree-row]]:opacity-50"
5862
+ ],
5863
+ row: [
5864
+ "group/row flex h-8 cursor-pointer select-none items-center gap-1.5 rounded-sm pr-2 text-muted-foreground",
5865
+ transition,
5866
+ "hover:bg-muted hover:text-foreground"
5867
+ ],
5868
+ chevron: "size-4 shrink-0 text-faint-foreground transition-transform duration-(--glyph-duration-fast) ease-standard group-data-[state=open]/row:rotate-90",
5869
+ spacer: "size-4 shrink-0",
5870
+ icon: "flex size-4 shrink-0 items-center justify-center text-faint-foreground [&>svg]:size-4",
5871
+ label: "min-w-0 flex-1 truncate",
5872
+ group: "grid gap-px"
5873
+ },
5874
+ variants: { size: {
5875
+ sm: { row: "h-7 text-caption" },
5876
+ md: {}
5877
+ } },
5878
+ defaultVariants: { size: "md" }
5879
+ });
5880
+ //#endregion
5881
+ //#region src/components/tree-view/tree-view.tsx
5882
+ function flattenVisible(nodes, expanded) {
5883
+ const out = [];
5884
+ const walk = (list, level, parentId) => {
5885
+ for (const node of list) {
5886
+ out.push({
5887
+ node,
5888
+ level,
5889
+ parentId
5890
+ });
5891
+ if (node.children?.length && expanded.has(node.id)) walk(node.children, level + 1, node.id);
5892
+ }
5893
+ };
5894
+ walk(nodes, 1, null);
5895
+ return out;
5896
+ }
5897
+ function textOf(node) {
5898
+ return (node.textValue ?? (typeof node.label === "string" ? node.label : "")).toLowerCase();
5899
+ }
5900
+ const NO_IDS = [];
5901
+ /**
5902
+ * An accessible tree for file browsers and nested navigation. Arrow keys move and
5903
+ * expand/collapse, Home/End jump, typing a letter finds the next match, Enter or Space selects.
5904
+ */
5905
+ function TreeView(inProps) {
5906
+ const [props, slots] = useComponentConfig("TreeView", inProps);
5907
+ const { nodes, expanded: expandedProp, defaultExpanded = NO_IDS, onExpandedChange, selected: selectedProp, defaultSelected = null, onSelect, size, className, ...rest } = props;
5908
+ const [expandedList, setExpandedList] = useControllableState({
5909
+ value: expandedProp,
5910
+ defaultValue: defaultExpanded,
5911
+ onChange: onExpandedChange
5912
+ });
5913
+ const [selected, setSelected] = useControllableState({
5914
+ value: selectedProp,
5915
+ defaultValue: defaultSelected
5916
+ });
5917
+ const expanded = useMemo(() => new Set(expandedList), [expandedList]);
5918
+ const visible = useMemo(() => flattenVisible(nodes, expanded), [nodes, expanded]);
5919
+ const [focusedId, setFocusedId] = useState(null);
5920
+ const refs = useRef(/* @__PURE__ */ new Map());
5921
+ const baseId = useId();
5922
+ const tabbableId = focusedId && visible.some((v) => v.node.id === focusedId) && focusedId || selected && visible.some((v) => v.node.id === selected) && selected || visible[0]?.node.id;
5923
+ const focus = useCallback((id) => {
5924
+ if (!id) return;
5925
+ setFocusedId(id);
5926
+ refs.current.get(id)?.focus();
5927
+ }, []);
5928
+ const toggle = useCallback((id, open) => {
5929
+ const isOpen = expanded.has(id);
5930
+ const next = open ?? !isOpen;
5931
+ if (next === isOpen) return;
5932
+ setExpandedList(next ? [...expandedList, id] : expandedList.filter((x) => x !== id));
5933
+ }, [
5934
+ expanded,
5935
+ expandedList,
5936
+ setExpandedList
5937
+ ]);
5938
+ const select = useCallback((node) => {
5939
+ if (node.disabled) return;
5940
+ setSelected(node.id);
5941
+ onSelect?.(node.id, node);
5942
+ }, [onSelect, setSelected]);
5943
+ const onKeyDown = (event) => {
5944
+ const index = visible.findIndex((v) => v.node.id === tabbableId);
5945
+ const current = visible[index];
5946
+ if (!current) return;
5947
+ const { node } = current;
5948
+ const hasChildren = Boolean(node.children?.length);
5949
+ const isOpen = expanded.has(node.id);
5950
+ let handled = true;
5951
+ switch (event.key) {
5952
+ case "ArrowDown":
5953
+ focus(visible[index + 1]?.node.id);
5954
+ break;
5955
+ case "ArrowUp":
5956
+ focus(visible[index - 1]?.node.id);
5957
+ break;
5958
+ case "ArrowRight":
5959
+ if (hasChildren && !isOpen) toggle(node.id, true);
5960
+ else if (hasChildren) focus(node.children?.[0]?.id);
5961
+ break;
5962
+ case "ArrowLeft":
5963
+ if (hasChildren && isOpen) toggle(node.id, false);
5964
+ else if (current.parentId) focus(current.parentId);
5965
+ break;
5966
+ case "Home":
5967
+ focus(visible[0]?.node.id);
5968
+ break;
5969
+ case "End":
5970
+ focus(visible.at(-1)?.node.id);
5971
+ break;
5972
+ case "Enter":
5973
+ case " ":
5974
+ select(node);
5975
+ break;
5976
+ default:
5977
+ handled = false;
5978
+ if (event.key.length === 1 && /\S/.test(event.key) && !event.metaKey && !event.ctrlKey) {
5979
+ const char = event.key.toLowerCase();
5980
+ const match = [...visible.slice(index + 1), ...visible.slice(0, index + 1)].find((v) => textOf(v.node).startsWith(char));
5981
+ if (match) {
5982
+ focus(match.node.id);
5983
+ handled = true;
5984
+ }
5985
+ }
5986
+ }
5987
+ if (handled) event.preventDefault();
5988
+ };
5989
+ const s = treeViewStyles({ size });
5990
+ /** Clicks bubble from nested items; only handle the item whose own row was clicked. */
5991
+ const onItemClick = (event, node, hasChildren) => {
5992
+ if (event.target.closest("[data-slot=tree-row]")?.parentElement !== event.currentTarget) return;
5993
+ focus(node.id);
5994
+ if (hasChildren) toggle(node.id);
5995
+ select(node);
5996
+ };
5997
+ const renderNodes = (list, level) => list.map((node, i) => {
5998
+ const hasChildren = Boolean(node.children?.length);
5999
+ const isOpen = hasChildren && expanded.has(node.id);
6000
+ return /* @__PURE__ */ jsxs("div", {
6001
+ ref: (el) => {
6002
+ if (el) refs.current.set(node.id, el);
6003
+ else refs.current.delete(node.id);
6004
+ },
6005
+ role: "treeitem",
6006
+ "data-slot": "tree-item",
6007
+ "aria-labelledby": `${baseId}-${node.id}`,
6008
+ "aria-level": level,
6009
+ "aria-setsize": list.length,
6010
+ "aria-posinset": i + 1,
6011
+ "aria-expanded": hasChildren ? isOpen : void 0,
6012
+ "aria-selected": selected === node.id,
6013
+ "aria-disabled": node.disabled || void 0,
6014
+ tabIndex: node.id === tabbableId ? 0 : -1,
6015
+ onFocus: (event) => {
6016
+ if (event.target === event.currentTarget) setFocusedId(node.id);
6017
+ },
6018
+ onClick: (event) => onItemClick(event, node, hasChildren),
6019
+ className: s.item({ class: slots.item }),
6020
+ children: [/* @__PURE__ */ jsxs("div", {
6021
+ "data-slot": "tree-row",
6022
+ "data-state": isOpen ? "open" : "closed",
6023
+ className: s.row({ class: slots.row }),
6024
+ style: { paddingInlineStart: `calc(${level - 1} * 1rem + 0.25rem)` },
6025
+ children: [
6026
+ hasChildren ? /* @__PURE__ */ jsx("svg", {
6027
+ "data-slot": "tree-chevron",
6028
+ viewBox: "0 0 24 24",
6029
+ fill: "none",
6030
+ stroke: "currentColor",
6031
+ strokeWidth: "2",
6032
+ strokeLinecap: "round",
6033
+ strokeLinejoin: "round",
6034
+ "aria-hidden": "true",
6035
+ className: s.chevron({ class: slots.chevron }),
6036
+ children: /* @__PURE__ */ jsx("path", { d: "m9 18 6-6-6-6" })
6037
+ }) : /* @__PURE__ */ jsx("span", { className: s.spacer({ class: slots.spacer }) }),
6038
+ node.icon && /* @__PURE__ */ jsx("span", {
6039
+ className: s.icon({ class: slots.icon }),
6040
+ "aria-hidden": "true",
6041
+ children: node.icon
6042
+ }),
6043
+ /* @__PURE__ */ jsx("span", {
6044
+ id: `${baseId}-${node.id}`,
6045
+ className: s.label({ class: slots.label }),
6046
+ children: node.label
6047
+ })
6048
+ ]
6049
+ }), isOpen && /* @__PURE__ */ jsx("div", {
6050
+ role: "group",
6051
+ className: s.group({ class: slots.group }),
6052
+ children: renderNodes(node.children ?? [], level + 1)
6053
+ })]
6054
+ }, node.id);
6055
+ });
6056
+ return /* @__PURE__ */ jsx("div", {
6057
+ role: "tree",
6058
+ "data-slot": "tree-view",
6059
+ onKeyDown,
6060
+ className: s.root({ class: [slots.root, className] }),
6061
+ ...rest,
6062
+ children: renderNodes(nodes, 1)
6063
+ });
6064
+ }
6065
+ //#endregion
6066
+ //#region src/components/visually-hidden/visually-hidden.tsx
6067
+ /**
6068
+ * Hides content visually while keeping it available to screen readers, e.g. a label for an
6069
+ * icon-only control or extra context in a table cell.
6070
+ */
6071
+ function VisuallyHidden(props) {
6072
+ return /* @__PURE__ */ jsx(VisuallyHidden$1.Root, {
6073
+ "data-slot": "visually-hidden",
6074
+ ...props
6075
+ });
6076
+ }
6077
+ //#endregion
3466
6078
  //#region src/hooks/use-media-query.ts
3467
6079
  /** Subscribes to a CSS media query. Returns `fallback` during SSR. */
3468
6080
  function useMediaQuery(query, fallback = false) {
@@ -3531,7 +6143,7 @@ const sidebarStyles = tv({ slots: {
3531
6143
  "group-data-[collapsed=true]/sidebar:justify-center group-data-[collapsed=true]/sidebar:px-0"
3532
6144
  ],
3533
6145
  itemIcon: "flex size-4 shrink-0 items-center justify-center [&>svg]:size-4",
3534
- itemLabel: "min-w-0 flex-1 truncate text-left group-data-[collapsed=true]/sidebar:hidden",
6146
+ itemLabel: "min-w-0 flex-1 truncate text-left group-data-[collapsed=true]/sidebar:sr-only",
3535
6147
  itemBadge: "ml-auto font-mono text-caption text-faint-foreground tabular-nums group-data-[collapsed=true]/sidebar:hidden",
3536
6148
  footer: ["mt-auto flex shrink-0 items-center gap-2 border-t-border px-3 py-3 group-data-[collapsed=true]/sidebar:justify-center", "border-t-(length:--glyph-border-width)"]
3537
6149
  } });
@@ -3646,7 +6258,11 @@ function SidebarSection({ label, className, children, ...props }) {
3646
6258
  }), children]
3647
6259
  });
3648
6260
  }
3649
- function SidebarItem({ href, icon, badge, active, onClick, className, children }) {
6261
+ function SidebarItem({ href, icon, badge, active: activeProp, end, onClick, className, children }) {
6262
+ const active = useIsActive(href, {
6263
+ explicit: activeProp,
6264
+ ...end !== void 0 && { end }
6265
+ });
3650
6266
  const { collapsed, inDrawer, setMobileOpen } = useAppShell();
3651
6267
  const Link = useLinkComponent();
3652
6268
  const slots = useSlots();
@@ -3787,6 +6403,20 @@ function AppShell(inProps) {
3787
6403
  }
3788
6404
  //#endregion
3789
6405
  //#region src/patterns/app-shell/navbar.tsx
6406
+ function NavbarLink({ link, className, onClick }) {
6407
+ const Link = useLinkComponent();
6408
+ const active = useIsActive(link.href, {
6409
+ explicit: link.active,
6410
+ ...link.end !== void 0 && { end: link.end }
6411
+ });
6412
+ return /* @__PURE__ */ jsx(Link, {
6413
+ href: link.href,
6414
+ "aria-current": active ? "page" : void 0,
6415
+ className,
6416
+ ...onClick && { onClick },
6417
+ children: link.label
6418
+ });
6419
+ }
3790
6420
  /**
3791
6421
  * Site header from data: brand, links, actions. Responsive out of the box: links collapse
3792
6422
  * into a focus-trapped menu panel on small screens.
@@ -3796,7 +6426,6 @@ function Navbar(inProps) {
3796
6426
  const { brand, links = [], actions, sticky = true, blurOnScroll = true, containerSize, className, ...rest } = props;
3797
6427
  const [open, setOpen] = useState(false);
3798
6428
  const scrolled = useScrolled(8, blurOnScroll);
3799
- const Link = useLinkComponent();
3800
6429
  const s = navbarStyles({
3801
6430
  sticky,
3802
6431
  blur: blurOnScroll
@@ -3817,11 +6446,9 @@ function Navbar(inProps) {
3817
6446
  links.length > 0 && /* @__PURE__ */ jsx("nav", {
3818
6447
  "aria-label": "Main",
3819
6448
  className: s.links({ class: slots.links }),
3820
- children: links.map((link) => /* @__PURE__ */ jsx(Link, {
3821
- href: link.href,
3822
- "aria-current": link.active ? "page" : void 0,
3823
- className: s.link({ class: slots.link }),
3824
- children: link.label
6449
+ children: links.map((link) => /* @__PURE__ */ jsx(NavbarLink, {
6450
+ link,
6451
+ className: s.link({ class: slots.link })
3825
6452
  }, link.href))
3826
6453
  }),
3827
6454
  actions && /* @__PURE__ */ jsx("div", {
@@ -3853,7 +6480,7 @@ function Navbar(inProps) {
3853
6480
  }), /* @__PURE__ */ jsx(Dialog$1.Close, {
3854
6481
  asChild: true,
3855
6482
  children: /* @__PURE__ */ jsx(IconButton, {
3856
- icon: /* @__PURE__ */ jsx(XIcon, {}),
6483
+ icon: /* @__PURE__ */ jsx(XIcon$2, {}),
3857
6484
  "aria-label": "Close menu"
3858
6485
  })
3859
6486
  })]
@@ -3861,12 +6488,10 @@ function Navbar(inProps) {
3861
6488
  /* @__PURE__ */ jsx("nav", {
3862
6489
  "aria-label": "Main",
3863
6490
  className: s.panelLinks({ class: slots.panelLinks }),
3864
- children: links.map((link) => /* @__PURE__ */ jsx(Link, {
3865
- href: link.href,
3866
- "aria-current": link.active ? "page" : void 0,
6491
+ children: links.map((link) => /* @__PURE__ */ jsx(NavbarLink, {
6492
+ link,
3867
6493
  className: s.panelLink({ class: slots.panelLink }),
3868
- onClick: () => setOpen(false),
3869
- children: link.label
6494
+ onClick: () => setOpen(false)
3870
6495
  }, link.href))
3871
6496
  }),
3872
6497
  actions && /* @__PURE__ */ jsx("div", {
@@ -3972,7 +6597,6 @@ function useAsync(fn, deps) {
3972
6597
  //#endregion
3973
6598
  //#region src/provider/color-mode.tsx
3974
6599
  const ColorModeContext = createContext(null);
3975
- const DARK_QUERY = "(prefers-color-scheme: dark)";
3976
6600
  const isBrowser = typeof window !== "undefined";
3977
6601
  function readStoredMode(storageKey) {
3978
6602
  if (!isBrowser || !storageKey) return null;
@@ -3984,7 +6608,7 @@ function readStoredMode(storageKey) {
3984
6608
  }
3985
6609
  }
3986
6610
  function systemMode() {
3987
- return isBrowser && window.matchMedia(DARK_QUERY).matches ? "dark" : "light";
6611
+ return isBrowser && window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
3988
6612
  }
3989
6613
  /** Disables transitions for one frame so a mode switch doesn't animate every color. */
3990
6614
  function suppressTransitions() {
@@ -3996,7 +6620,7 @@ function suppressTransitions() {
3996
6620
  requestAnimationFrame(() => style.remove());
3997
6621
  };
3998
6622
  }
3999
- function ColorModeProvider({ children, defaultMode = "system", storageKey = "glyph-mode" }) {
6623
+ function ColorModeProvider({ children, defaultMode = "system", storageKey = DEFAULT_STORAGE_KEY }) {
4000
6624
  const [mode, setModeState] = useState(() => readStoredMode(storageKey) ?? defaultMode);
4001
6625
  const [system, setSystem] = useState(systemMode);
4002
6626
  useEffect(() => {
@@ -4045,9 +6669,6 @@ function useColorMode() {
4045
6669
  * Inline script that sets `data-mode` on `<html>` before first paint, so a dark-mode
4046
6670
  * visitor never sees a light flash. Put it in `<head>`.
4047
6671
  */
4048
- function getColorModeScript({ defaultMode = "system", storageKey = "glyph-mode" } = {}) {
4049
- return `(function(){try{var d=${JSON.stringify(defaultMode)},m=null;${storageKey ? `m=localStorage.getItem(${JSON.stringify(storageKey)});` : ""}if(m!=='light'&&m!=='dark'&&m!=='system')m=d;if(m==='system')m=matchMedia('${DARK_QUERY}').matches?'dark':'light';var r=document.documentElement;r.dataset.mode=m;r.style.colorScheme=m}catch(e){}})()`;
4050
- }
4051
6672
  /** `<script>` element version of `getColorModeScript` for SSR frameworks. */
4052
6673
  function ColorModeScript(props) {
4053
6674
  return /* @__PURE__ */ jsx("script", {
@@ -4114,11 +6735,18 @@ function ThemeStyle({ theme, selector }) {
4114
6735
  //#endregion
4115
6736
  //#region src/provider/glyph-provider.tsx
4116
6737
  /** Provides the theme, color mode, tooltips, `useConfirm()` and (optionally) toasts. Render once at the root. */
4117
- function GlyphProvider({ children, theme = glyph, defaultMode, storageKey, linkComponent = "a", toaster = false }) {
6738
+ function GlyphProvider({ children, theme = glyph, defaultMode, storageKey, router, linkComponent, toaster = false }) {
6739
+ const Link = router?.Link ?? linkComponent ?? "a";
6740
+ const useIsActive = router?.useIsActive ?? neverActive;
4118
6741
  const value = useMemo(() => ({
4119
6742
  theme,
4120
- linkComponent
4121
- }), [theme, linkComponent]);
6743
+ linkComponent: Link,
6744
+ useIsActive
6745
+ }), [
6746
+ theme,
6747
+ Link,
6748
+ useIsActive
6749
+ ]);
4122
6750
  return /* @__PURE__ */ jsx(ColorModeProvider, {
4123
6751
  ...defaultMode !== void 0 && { defaultMode },
4124
6752
  ...storageKey !== void 0 && { storageKey },
@@ -4132,21 +6760,19 @@ function GlyphProvider({ children, theme = glyph, defaultMode, storageKey, linkC
4132
6760
  });
4133
6761
  }
4134
6762
  //#endregion
4135
- //#region src/utils/cn.ts
4136
- const twMerge = extendTailwindMerge(twMergeConfig);
4137
- /** Joins class names and resolves Tailwind conflicts (last one wins). */
4138
- function cn(...inputs) {
4139
- return twMerge(clsx(inputs));
4140
- }
4141
- //#endregion
4142
6763
  //#region src/provider/theme-scope.tsx
4143
6764
  /** Renders a subtree with a different theme, e.g. to compare themes side by side. */
4144
6765
  function ThemeScope({ theme, mode, asChild, children, ...props }) {
4145
6766
  const parent = useContext(GlyphContext);
4146
6767
  const value = useMemo(() => ({
4147
6768
  theme,
4148
- linkComponent: parent?.linkComponent ?? "a"
4149
- }), [theme, parent?.linkComponent]);
6769
+ linkComponent: parent?.linkComponent ?? "a",
6770
+ useIsActive: parent?.useIsActive ?? neverActive
6771
+ }), [
6772
+ theme,
6773
+ parent?.linkComponent,
6774
+ parent?.useIsActive
6775
+ ]);
4150
6776
  const Comp = asChild ? Slot.Root : "div";
4151
6777
  return /* @__PURE__ */ jsxs(GlyphContext.Provider, {
4152
6778
  value,
@@ -4163,4 +6789,4 @@ function ThemeScope({ theme, mode, asChild, children, ...props }) {
4163
6789
  });
4164
6790
  }
4165
6791
  //#endregion
4166
- export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, Alert, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger, AppShell, AspectRatio, Async, Avatar, AvatarGroup, Badge, Banner, Blockquote, Breadcrumb, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, Card, CardBody, CardDescription, CardFooter, CardHeader, CardTitle, Checkbox, Code, CodeBlock, ColorModeProvider, ColorModeScript, Combobox, Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandMenu, CommandSeparator, ConfirmProvider, Container, DescriptionItem, DescriptionList, Dialog, DialogBody, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyState, ErrorState, Eyebrow, Field, FieldContext, GlyphProvider, Grid, Heading, IconButton, Input, Kbd, Label, Link, LoadingState, Navbar, PageHeader, Pagination, Popover, PopoverAnchor, PopoverClose, PopoverContent, PopoverTrigger, Progress, ProgressCircle, Prose, RadioGroup, RadioGroupItem, ScrollArea, Section, SegmentedControl, Select, SelectItem, Separator, Sheet, SheetBody, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger, Sidebar, SidebarContent, SidebarFooter, SidebarHeader, SidebarItem, SidebarSection, SidebarTrigger, Skeleton, Slider, Spinner, Stack, StatCard, Switch, Table, TableBody, TableCaption, TableCell, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Text, Textarea, ThemeScope, Toaster, Tooltip, accordionStyles, alertDialogStyles, alertStyles, appShellStyles, aspectRatioStyles, avatarStyles, badgeStyles, bannerStyles, blockquoteStyles, breadcrumbStyles, brutalist, buttonStyles, cardStyles, checkboxStyles, cn, codeBlockStyles, codeStyles, comboboxStyles, commandMenuStyles, containerStyles, defineTheme, descriptionListStyles, dialogStyles, dropdownMenuStyles, editorial, eyebrowStyles, fieldControl, fieldStyles, getColorModeScript, glyph, gridStyles, headingStyles, inputStyles, kbdStyles, labelStyles, linkStyles, navbarStyles, pageHeaderStyles, paginationRange, paginationStyles, playful, popoverStyles, presets, progressCircleStyles, progressStyles, proseStyles, radioGroupStyles, scrollAreaStyles, sectionStyles, segmentedControlStyles, selectStyles, separatorStyles, sheetStyles, sidebarStyles, skeletonStyles, sliderStyles, spinnerStyles, stackStyles, statCardStyles, stateStyles, switchStyles, tableStyles, tabsStyles, textStyles, textareaStyles, themeToCss, toast, toastStyles, tokenVar, tooltipStyles, tv, useAppShell, useAsync, useColorMode, useCommandMenuShortcut, useComponentConfig, useConfirm, useControllableState, useFieldControl, useGlyph, useLinkComponent, useMediaQuery, useScrolled };
6792
+ export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, Alert, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger, AppShell, AspectRatio, Async, Avatar, AvatarGroup, Badge, Banner, Blockquote, Breadcrumb, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, Calendar, Card, CardBody, CardDescription, CardFooter, CardHeader, CardTitle, Carousel, CarouselContent, CarouselDots, CarouselItem, CarouselNext, CarouselPrevious, Checkbox, Code, CodeBlock, Collapsible, CollapsibleContent, CollapsibleTrigger, ColorModeProvider, ColorModeScript, Combobox, Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandMenu, CommandSeparator, ConfirmProvider, Container, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, CopyButton, DatePicker, DateRangePicker, DescriptionItem, DescriptionList, Dialog, DialogBody, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyState, ErrorState, Eyebrow, Field, FieldContext, FileUpload, GlyphProvider, Grid, Heading, HoverCard, HoverCardContent, HoverCardTrigger, IconButton, Input, InputOTP, InputOTPGroup, InputOTPSeparator, InputOTPSlot, Kbd, Label, Link, LoadingState, Modal, ModalClose, Navbar, NavigationMenu, NavigationMenuCard, NavigationMenuContent, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, NavigationMenuViewport, NumberInput, PageHeader, Pagination, PasswordInput, Popover, PopoverAnchor, PopoverClose, PopoverContent, PopoverTrigger, Progress, ProgressCircle, Prose, REGEXP_ONLY_CHARS, REGEXP_ONLY_DIGITS, REGEXP_ONLY_DIGITS_AND_CHARS, RadioGroup, RadioGroupItem, ResizableHandle, ResizablePanel, ResizablePanelGroup, ScrollArea, Section, SegmentedControl, Select, SelectItem, Separator, Sheet, SheetBody, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger, Sidebar, SidebarContent, SidebarFooter, SidebarHeader, SidebarItem, SidebarSection, SidebarTrigger, Skeleton, Slider, Spinner, Stack, StatCard, Stepper, Switch, Table, TableBody, TableCaption, TableCell, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, TagInput, Text, Textarea, ThemeScope, Timeline, TimelineItem, Toaster, Toggle, ToggleGroup, ToggleGroupItem, Tooltip, TreeView, VisuallyHidden, accordionStyles, alertDialogStyles, alertStyles, appShellStyles, aspectRatioStyles, avatarStyles, badgeStyles, bannerStyles, blockquoteStyles, breadcrumbStyles, brutalist, buttonStyles, calendarStyles, cardStyles, carouselStyles, checkboxStyles, cn, codeBlockStyles, codeStyles, collapsibleStyles, comboboxStyles, commandMenuStyles, containerStyles, contextMenuStyles, copyButtonStyles, datePickerStyles, defineTheme, descriptionListStyles, dialogStyles, dropdownMenuStyles, editorial, eyebrowStyles, fieldControl, fieldStyles, fileUploadStyles, formatBytes, getColorModeScript, glyph, gridStyles, headingStyles, hoverCardStyles, inputOtpStyles, inputStyles, kbdStyles, labelStyles, linkStyles, matchesAccept, modalStyles, navbarStyles, navigationMenuStyles, numberInputStyles, pageHeaderStyles, paginationRange, paginationStyles, passwordInputStyles, passwordStrength, playful, popoverStyles, presets, progressCircleStyles, progressStyles, proseStyles, radioGroupStyles, resizableStyles, scrollAreaStyles, sectionStyles, segmentedControlStyles, selectStyles, separatorStyles, sheetStyles, sidebarStyles, skeletonStyles, sliderStyles, spinnerStyles, stackStyles, statCardStyles, stateStyles, stepperStyles, switchStyles, tableStyles, tabsStyles, tagInputStyles, textStyles, textareaStyles, themeToCss, timelineStyles, toast, toastStyles, toggleStyles, tokenVar, tooltipStyles, treeViewStyles, tv, useAppShell, useAsync, useColorMode, useCommandMenuShortcut, useComponentConfig, useConfirm, useControllableState, useFieldControl, useGlyph, useIsActive, useLinkComponent, useMediaQuery, useScrolled };