@glyphui/ui 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/dist/chart.d.ts +202 -0
  2. package/dist/chart.js +457 -0
  3. package/dist/data-table.js +3 -2
  4. package/dist/{field-CCecIzdq.js → field-CWZ_FdkD.js} +2 -1
  5. package/dist/{field-context-B6WOcK5m.js → field-context-anGPYXbW.js} +2 -56
  6. package/dist/form.js +3 -2
  7. package/dist/index.d.ts +2285 -241
  8. package/dist/index.js +2819 -266
  9. package/dist/{states-Rp8wZ_jH.js → states-DR-OoDT-.js} +2 -1
  10. package/dist/tv-DBAGlgXJ.js +58 -0
  11. package/package.json +17 -2
  12. package/src/components/accordion/accordion.styles.ts +4 -4
  13. package/src/components/calendar/calendar.styles.ts +50 -0
  14. package/src/components/calendar/calendar.tsx +84 -0
  15. package/src/components/calendar/index.ts +3 -0
  16. package/src/components/carousel/carousel.styles.ts +43 -0
  17. package/src/components/carousel/carousel.tsx +278 -0
  18. package/src/components/carousel/index.ts +13 -0
  19. package/src/components/collapsible/collapsible.tsx +66 -0
  20. package/src/components/collapsible/index.ts +6 -0
  21. package/src/components/context-menu/context-menu.styles.ts +19 -0
  22. package/src/components/context-menu/context-menu.tsx +226 -0
  23. package/src/components/context-menu/index.ts +19 -0
  24. package/src/components/copy-button/copy-button.tsx +117 -0
  25. package/src/components/copy-button/index.ts +1 -0
  26. package/src/components/date-picker/date-picker.styles.ts +42 -0
  27. package/src/components/date-picker/date-picker.tsx +322 -0
  28. package/src/components/date-picker/index.ts +8 -0
  29. package/src/components/file-upload/file-upload.styles.ts +43 -0
  30. package/src/components/file-upload/file-upload.tsx +343 -0
  31. package/src/components/file-upload/index.ts +10 -0
  32. package/src/components/hover-card/hover-card.tsx +41 -0
  33. package/src/components/hover-card/index.ts +1 -0
  34. package/src/components/input-otp/index.ts +10 -0
  35. package/src/components/input-otp/input-otp.styles.ts +38 -0
  36. package/src/components/input-otp/input-otp.tsx +116 -0
  37. package/src/components/modal/index.ts +2 -0
  38. package/src/components/modal/modal.styles.ts +18 -0
  39. package/src/components/modal/modal.tsx +86 -0
  40. package/src/components/navigation-menu/index.ts +14 -0
  41. package/src/components/navigation-menu/navigation-menu.styles.ts +48 -0
  42. package/src/components/navigation-menu/navigation-menu.tsx +198 -0
  43. package/src/components/number-input/index.ts +2 -0
  44. package/src/components/number-input/number-input.styles.ts +41 -0
  45. package/src/components/number-input/number-input.tsx +211 -0
  46. package/src/components/password-input/index.ts +7 -0
  47. package/src/components/password-input/password-input.styles.ts +30 -0
  48. package/src/components/password-input/password-input.tsx +127 -0
  49. package/src/components/resizable/index.ts +9 -0
  50. package/src/components/resizable/resizable.styles.ts +28 -0
  51. package/src/components/resizable/resizable.tsx +69 -0
  52. package/src/components/sheet/sheet.styles.ts +7 -7
  53. package/src/components/stepper/index.ts +2 -0
  54. package/src/components/stepper/stepper.styles.ts +74 -0
  55. package/src/components/stepper/stepper.tsx +138 -0
  56. package/src/components/tag-input/index.ts +2 -0
  57. package/src/components/tag-input/tag-input.styles.ts +39 -0
  58. package/src/components/tag-input/tag-input.tsx +198 -0
  59. package/src/components/timeline/index.ts +8 -0
  60. package/src/components/timeline/timeline.styles.ts +56 -0
  61. package/src/components/timeline/timeline.tsx +91 -0
  62. package/src/components/toggle/index.ts +9 -0
  63. package/src/components/toggle/toggle.styles.ts +39 -0
  64. package/src/components/toggle/toggle.tsx +61 -0
  65. package/src/components/tree-view/index.ts +2 -0
  66. package/src/components/tree-view/tree-view.styles.ts +42 -0
  67. package/src/components/tree-view/tree-view.tsx +274 -0
  68. package/src/components/visually-hidden/index.ts +1 -0
  69. package/src/components/visually-hidden/visually-hidden.tsx +10 -0
  70. package/src/index.ts +20 -0
  71. package/src/patterns/chart/chart-parts.tsx +171 -0
  72. package/src/patterns/chart/chart.styles.ts +35 -0
  73. package/src/patterns/chart/chart.tsx +369 -0
  74. package/src/patterns/chart/index.ts +13 -0
  75. package/styles.css +16 -0
package/dist/index.js CHANGED
@@ -1,15 +1,21 @@
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, i as popover, l as useGlyph, n as twMergeConfig, o as transition, r as focusRing, s as useComponentConfig, t as tv, u as useLinkComponent } from "./tv-DBAGlgXJ.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-anGPYXbW.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-DR-OoDT-.js";
5
+ import { i as labelStyles, n as fieldStyles, r as Label, t as Field } from "./field-CWZ_FdkD.js";
5
6
  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";
7
+ 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";
8
+ import { Children, createContext, useCallback, useContext, useEffect, useId, useMemo, useRef, useState, useSyncExternalStore } from "react";
8
9
  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";
10
+ import { DayPicker } from "react-day-picker";
11
+ import useEmblaCarousel from "embla-carousel-react";
11
12
  import { clsx } from "clsx";
12
13
  import { extendTailwindMerge } from "tailwind-merge";
14
+ import { Command as Command$1 } from "cmdk";
15
+ import { format, isSameDay } from "date-fns";
16
+ import { OTPInput, OTPInputContext, REGEXP_ONLY_CHARS, REGEXP_ONLY_DIGITS, REGEXP_ONLY_DIGITS_AND_CHARS } from "input-otp";
17
+ import { Panel, PanelGroup, PanelResizeHandle } from "react-resizable-panels";
18
+ import { Toaster as Toaster$1, toast } from "sonner";
13
19
  //#region src/components/accordion/accordion.styles.ts
14
20
  const accordionStyles = tv({
15
21
  slots: {
@@ -23,8 +29,8 @@ const accordionStyles = tv({
23
29
  "hover:text-foreground/80 disabled:cursor-not-allowed disabled:opacity-50"
24
30
  ],
25
31
  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"
32
+ content: "overflow-hidden text-small text-muted-foreground data-[state=open]:animate-collapse-down data-[state=closed]:animate-collapse-up",
33
+ contentInner: "pb-4"
28
34
  },
29
35
  variants: { variant: {
30
36
  default: { item: "border-b border-border last:border-b-0" },
@@ -38,7 +44,7 @@ const accordionStyles = tv({
38
44
  //#endregion
39
45
  //#region src/components/accordion/accordion.tsx
40
46
  const AccordionContext = createContext(null);
41
- function useParts$4() {
47
+ function useParts$6() {
42
48
  return useContext(AccordionContext) ?? {
43
49
  s: accordionStyles(),
44
50
  slots: {}
@@ -65,7 +71,7 @@ function Accordion(inProps) {
65
71
  });
66
72
  }
67
73
  function AccordionItem({ className, ...props }) {
68
- const { s, slots } = useParts$4();
74
+ const { s, slots } = useParts$6();
69
75
  return /* @__PURE__ */ jsx(Accordion$1.Item, {
70
76
  "data-slot": "accordion-item",
71
77
  className: s.item({ class: [slots.item, className] }),
@@ -73,19 +79,19 @@ function AccordionItem({ className, ...props }) {
73
79
  });
74
80
  }
75
81
  function AccordionTrigger({ className, children, ...props }) {
76
- const { s, slots } = useParts$4();
82
+ const { s, slots } = useParts$6();
77
83
  return /* @__PURE__ */ jsx(Accordion$1.Header, {
78
84
  className: s.header({ class: slots.header }),
79
85
  children: /* @__PURE__ */ jsxs(Accordion$1.Trigger, {
80
86
  "data-slot": "accordion-trigger",
81
87
  className: s.trigger({ class: [slots.trigger, className] }),
82
88
  ...props,
83
- children: [children, /* @__PURE__ */ jsx(ChevronDownIcon, { className: s.chevron({ class: slots.chevron }) })]
89
+ children: [children, /* @__PURE__ */ jsx(ChevronDownIcon$1, { className: s.chevron({ class: slots.chevron }) })]
84
90
  })
85
91
  });
86
92
  }
87
93
  function AccordionContent({ className, children, ...props }) {
88
- const { s, slots } = useParts$4();
94
+ const { s, slots } = useParts$6();
89
95
  return /* @__PURE__ */ jsx(Accordion$1.Content, {
90
96
  "data-slot": "accordion-content",
91
97
  className: s.content({ class: slots.content }),
@@ -285,7 +291,7 @@ function Alert(inProps) {
285
291
  }),
286
292
  onDismiss && /* @__PURE__ */ jsx(IconButton, {
287
293
  size: "sm",
288
- icon: /* @__PURE__ */ jsx(XIcon, {}),
294
+ icon: /* @__PURE__ */ jsx(XIcon$2, {}),
289
295
  "aria-label": dismissLabel,
290
296
  onClick: onDismiss,
291
297
  className: s.dismiss({ class: slots.dismiss })
@@ -309,7 +315,7 @@ const alertDialogStyles = tv({ slots: {
309
315
  } });
310
316
  //#endregion
311
317
  //#region src/components/alert-dialog/alert-dialog.tsx
312
- function useParts$3() {
318
+ function useParts$5() {
313
319
  const [, slots] = useComponentConfig("AlertDialog", {});
314
320
  return {
315
321
  s: alertDialogStyles(),
@@ -336,7 +342,7 @@ function AlertDialogContent(inProps) {
336
342
  })] });
337
343
  }
338
344
  function AlertDialogHeader({ className, ...props }) {
339
- const { s, slots } = useParts$3();
345
+ const { s, slots } = useParts$5();
340
346
  return /* @__PURE__ */ jsx("div", {
341
347
  "data-slot": "alert-dialog-header",
342
348
  className: s.header({ class: [slots.header, className] }),
@@ -344,7 +350,7 @@ function AlertDialogHeader({ className, ...props }) {
344
350
  });
345
351
  }
346
352
  function AlertDialogTitle({ className, ...props }) {
347
- const { s, slots } = useParts$3();
353
+ const { s, slots } = useParts$5();
348
354
  return /* @__PURE__ */ jsx(AlertDialog$1.Title, {
349
355
  "data-slot": "alert-dialog-title",
350
356
  className: s.title({ class: [slots.title, className] }),
@@ -352,7 +358,7 @@ function AlertDialogTitle({ className, ...props }) {
352
358
  });
353
359
  }
354
360
  function AlertDialogDescription({ className, ...props }) {
355
- const { s, slots } = useParts$3();
361
+ const { s, slots } = useParts$5();
356
362
  return /* @__PURE__ */ jsx(AlertDialog$1.Description, {
357
363
  "data-slot": "alert-dialog-description",
358
364
  className: s.description({ class: [slots.description, className] }),
@@ -360,7 +366,7 @@ function AlertDialogDescription({ className, ...props }) {
360
366
  });
361
367
  }
362
368
  function AlertDialogFooter({ className, ...props }) {
363
- const { s, slots } = useParts$3();
369
+ const { s, slots } = useParts$5();
364
370
  return /* @__PURE__ */ jsx("div", {
365
371
  "data-slot": "alert-dialog-footer",
366
372
  className: s.footer({ class: [slots.footer, className] }),
@@ -713,7 +719,7 @@ function Banner(inProps) {
713
719
  }),
714
720
  dismissible && /* @__PURE__ */ jsx(IconButton, {
715
721
  size: "sm",
716
- icon: /* @__PURE__ */ jsx(XIcon, {}),
722
+ icon: /* @__PURE__ */ jsx(XIcon$2, {}),
717
723
  "aria-label": dismissLabel,
718
724
  onClick: dismiss,
719
725
  className: s.dismiss({ class: slots.dismiss })
@@ -780,17 +786,17 @@ const breadcrumbStyles = tv({ slots: {
780
786
  } });
781
787
  //#endregion
782
788
  //#region src/components/breadcrumb/breadcrumb.tsx
783
- const s$2 = breadcrumbStyles();
784
- function useSlots$2() {
789
+ const s$5 = breadcrumbStyles();
790
+ function useSlots$4() {
785
791
  return useComponentConfig("Breadcrumb", {})[1];
786
792
  }
787
793
  /** Shows where the current page sits in the hierarchy. */
788
794
  function Breadcrumb({ items, separator, className, children, ...props }) {
789
- const slots = useSlots$2();
795
+ const slots = useSlots$4();
790
796
  return /* @__PURE__ */ jsx("nav", {
791
797
  "aria-label": "Breadcrumb",
792
798
  "data-slot": "breadcrumb",
793
- className: s$2.root({ class: [slots.root, className] }),
799
+ className: s$5.root({ class: [slots.root, className] }),
794
800
  ...props,
795
801
  children: items ? /* @__PURE__ */ jsx(BreadcrumbList, { children: items.map((item, index) => {
796
802
  const last = index === items.length - 1;
@@ -805,25 +811,25 @@ function Breadcrumb({ items, separator, className, children, ...props }) {
805
811
  });
806
812
  }
807
813
  function BreadcrumbList({ className, ...props }) {
808
- const slots = useSlots$2();
814
+ const slots = useSlots$4();
809
815
  return /* @__PURE__ */ jsx("ol", {
810
816
  "data-slot": "breadcrumb-list",
811
- className: s$2.list({ class: [slots.list, className] }),
817
+ className: s$5.list({ class: [slots.list, className] }),
812
818
  ...props
813
819
  });
814
820
  }
815
821
  function BreadcrumbItem({ className, ...props }) {
816
- const slots = useSlots$2();
822
+ const slots = useSlots$4();
817
823
  return /* @__PURE__ */ jsx("li", {
818
824
  "data-slot": "breadcrumb-item",
819
- className: s$2.item({ class: [slots.item, className] }),
825
+ className: s$5.item({ class: [slots.item, className] }),
820
826
  ...props
821
827
  });
822
828
  }
823
829
  function BreadcrumbLink({ href, className, children, asChild }) {
824
830
  const Link = useLinkComponent();
825
- const slots = useSlots$2();
826
- const classes = s$2.link({ class: [slots.link, className] });
831
+ const slots = useSlots$4();
832
+ const classes = s$5.link({ class: [slots.link, className] });
827
833
  if (asChild) return /* @__PURE__ */ jsx(Slot.Root, {
828
834
  "data-slot": "breadcrumb-link",
829
835
  className: classes,
@@ -836,23 +842,130 @@ function BreadcrumbLink({ href, className, children, asChild }) {
836
842
  });
837
843
  }
838
844
  function BreadcrumbPage({ className, ...props }) {
839
- const slots = useSlots$2();
845
+ const slots = useSlots$4();
840
846
  return /* @__PURE__ */ jsx("span", {
841
847
  "data-slot": "breadcrumb-page",
842
848
  "aria-current": "page",
843
- className: s$2.page({ class: [slots.page, className] }),
849
+ className: s$5.page({ class: [slots.page, className] }),
844
850
  ...props
845
851
  });
846
852
  }
847
853
  function BreadcrumbSeparator({ className, children, ...props }) {
848
- const slots = useSlots$2();
854
+ const slots = useSlots$4();
849
855
  return /* @__PURE__ */ jsx("span", {
850
856
  "data-slot": "breadcrumb-separator",
851
857
  role: "presentation",
852
858
  "aria-hidden": "true",
853
- className: s$2.separator({ class: [slots.separator, className] }),
859
+ className: s$5.separator({ class: [slots.separator, className] }),
854
860
  ...props,
855
- children: children ?? /* @__PURE__ */ jsx(ChevronRightIcon$1, {})
861
+ children: children ?? /* @__PURE__ */ jsx(ChevronRightIcon$2, {})
862
+ });
863
+ }
864
+ //#endregion
865
+ //#region src/components/calendar/calendar.styles.ts
866
+ const calendarStyles = tv({ slots: {
867
+ root: "relative w-fit p-3 text-small text-foreground",
868
+ months: "relative flex flex-col gap-6 sm:flex-row",
869
+ month: "grid content-start gap-3",
870
+ monthCaption: "flex h-8 items-center justify-center px-9",
871
+ captionLabel: "font-medium text-foreground",
872
+ nav: "pointer-events-none absolute inset-x-3 top-3 z-10 flex items-center justify-between",
873
+ navButton: [
874
+ "pointer-events-auto inline-flex size-8 cursor-pointer items-center justify-center rounded-md text-muted-foreground",
875
+ "hover:bg-muted hover:text-foreground disabled:pointer-events-none disabled:opacity-40",
876
+ transition,
877
+ focusRing
878
+ ],
879
+ chevron: "size-4",
880
+ monthGrid: "border-collapse",
881
+ weekdays: "",
882
+ weekday: "size-9 p-0 text-caption font-normal text-faint-foreground",
883
+ weeks: "",
884
+ week: "",
885
+ day: "size-9 p-0 text-center align-middle",
886
+ dayButton: [
887
+ "inline-flex size-9 cursor-pointer items-center justify-center rounded-md text-small tabular-nums text-foreground",
888
+ "hover:bg-muted",
889
+ transition,
890
+ focusRing
891
+ ],
892
+ today: "[&>button]:font-semibold [&>button]:text-primary",
893
+ selected: "[&>button]:bg-primary [&>button]:text-primary-foreground [&>button]:hover:bg-primary/90",
894
+ outside: "[&>button]:text-faint-foreground [&>button]:opacity-60",
895
+ disabled: "[&>button]:pointer-events-none [&>button]:opacity-35 [&>button]:line-through",
896
+ rangeStart: "rounded-l-md bg-primary/14",
897
+ rangeMiddle: "bg-primary/14 [&>button]:rounded-none [&>button]:bg-transparent! [&>button]:text-foreground! [&>button]:hover:bg-primary/10!",
898
+ rangeEnd: "rounded-r-md bg-primary/14",
899
+ hidden: "invisible",
900
+ footer: "pt-2 text-small text-muted-foreground"
901
+ } });
902
+ //#endregion
903
+ //#region src/components/calendar/calendar.tsx
904
+ function ChevronIcon({ className, orientation = "left" }) {
905
+ const d = {
906
+ left: "m15 18-6-6 6-6",
907
+ right: "m9 18 6-6-6-6",
908
+ up: "m18 15-6-6-6 6",
909
+ down: "m6 9 6 6 6-6"
910
+ }[orientation];
911
+ return /* @__PURE__ */ jsx("svg", {
912
+ viewBox: "0 0 24 24",
913
+ fill: "none",
914
+ stroke: "currentColor",
915
+ strokeWidth: "2",
916
+ strokeLinecap: "round",
917
+ strokeLinejoin: "round",
918
+ "aria-hidden": "true",
919
+ className,
920
+ children: /* @__PURE__ */ jsx("path", { d })
921
+ });
922
+ }
923
+ /**
924
+ * A month grid for picking dates, built on react-day-picker and styled by the theme.
925
+ * Supports `mode="single" | "multiple" | "range"`, disabled dates and several months.
926
+ */
927
+ function Calendar(inProps) {
928
+ const [props, slots] = useComponentConfig("Calendar", inProps);
929
+ const { className, classNames, components, showOutsideDays = true, ...rest } = props;
930
+ const s = calendarStyles();
931
+ return /* @__PURE__ */ jsx(DayPicker, {
932
+ showOutsideDays,
933
+ className: s.root({ class: [slots.root, className] }),
934
+ classNames: {
935
+ months: s.months({ class: slots.months }),
936
+ month: s.month({ class: slots.month }),
937
+ month_caption: s.monthCaption({ class: slots.monthCaption }),
938
+ caption_label: s.captionLabel({ class: slots.captionLabel }),
939
+ nav: s.nav({ class: slots.nav }),
940
+ button_previous: s.navButton({ class: slots.navButton }),
941
+ button_next: s.navButton({ class: slots.navButton }),
942
+ chevron: s.chevron({ class: slots.chevron }),
943
+ month_grid: s.monthGrid({ class: slots.monthGrid }),
944
+ weekdays: s.weekdays({ class: slots.weekdays }),
945
+ weekday: s.weekday({ class: slots.weekday }),
946
+ weeks: s.weeks({ class: slots.weeks }),
947
+ week: s.week({ class: slots.week }),
948
+ day: s.day({ class: slots.day }),
949
+ day_button: s.dayButton({ class: slots.dayButton }),
950
+ today: s.today({ class: slots.today }),
951
+ selected: s.selected({ class: slots.selected }),
952
+ outside: s.outside({ class: slots.outside }),
953
+ disabled: s.disabled({ class: slots.disabled }),
954
+ range_start: s.rangeStart({ class: slots.rangeStart }),
955
+ range_middle: s.rangeMiddle({ class: slots.rangeMiddle }),
956
+ range_end: s.rangeEnd({ class: slots.rangeEnd }),
957
+ hidden: s.hidden({ class: slots.hidden }),
958
+ footer: s.footer({ class: slots.footer }),
959
+ ...classNames
960
+ },
961
+ components: {
962
+ Chevron: ({ className: chevronClass, orientation }) => /* @__PURE__ */ jsx(ChevronIcon, {
963
+ className: chevronClass,
964
+ orientation
965
+ }),
966
+ ...components
967
+ },
968
+ ...rest
856
969
  });
857
970
  }
858
971
  //#endregion
@@ -962,6 +1075,225 @@ function CardFooter({ className, ...props }) {
962
1075
  });
963
1076
  }
964
1077
  //#endregion
1078
+ //#region src/utils/cn.ts
1079
+ const twMerge = extendTailwindMerge(twMergeConfig);
1080
+ /** Joins class names and resolves Tailwind conflicts (last one wins). */
1081
+ function cn(...inputs) {
1082
+ return twMerge(clsx(inputs));
1083
+ }
1084
+ //#endregion
1085
+ //#region src/components/carousel/carousel.styles.ts
1086
+ const carouselStyles = tv({
1087
+ slots: {
1088
+ root: "relative",
1089
+ viewport: "overflow-hidden rounded-lg",
1090
+ container: "flex",
1091
+ item: "min-w-0 shrink-0 grow-0 basis-full",
1092
+ control: "absolute z-10 border-border bg-surface/85 shadow-sm backdrop-blur disabled:opacity-0",
1093
+ dots: "mt-3 flex items-center justify-center gap-1.5",
1094
+ dot: [
1095
+ "h-2 w-2 cursor-pointer rounded-pill bg-border-strong",
1096
+ transition,
1097
+ focusRing,
1098
+ "hover:bg-muted-foreground aria-[current=true]:w-5 aria-[current=true]:bg-primary"
1099
+ ]
1100
+ },
1101
+ variants: { orientation: {
1102
+ horizontal: {
1103
+ container: "-ml-4",
1104
+ item: "pl-4",
1105
+ control: "top-1/2 -translate-y-1/2"
1106
+ },
1107
+ vertical: {
1108
+ container: "-mt-4 h-full flex-col",
1109
+ item: "pt-4",
1110
+ control: "left-1/2 -translate-x-1/2 [&_svg]:rotate-90"
1111
+ }
1112
+ } },
1113
+ defaultVariants: { orientation: "horizontal" }
1114
+ });
1115
+ //#endregion
1116
+ //#region src/components/carousel/carousel.tsx
1117
+ const CarouselContext = createContext(null);
1118
+ function useCarousel() {
1119
+ const value = useContext(CarouselContext);
1120
+ if (!value) throw new Error("Carousel parts must be used inside <Carousel>.");
1121
+ return value;
1122
+ }
1123
+ /**
1124
+ * Swipeable, keyboard-accessible slides. Compose with CarouselContent, CarouselItem,
1125
+ * CarouselPrevious, CarouselNext and CarouselDots.
1126
+ */
1127
+ function Carousel(inProps) {
1128
+ const [props, slots] = useComponentConfig("Carousel", inProps);
1129
+ const { opts, plugins, loop, setApi, orientation = "horizontal", className, children, ...rest } = props;
1130
+ const [viewportRef, api] = useEmblaCarousel({
1131
+ ...opts,
1132
+ ...loop !== void 0 && { loop },
1133
+ axis: orientation === "horizontal" ? "x" : "y"
1134
+ }, plugins);
1135
+ const [state, setState] = useState({
1136
+ selectedIndex: 0,
1137
+ snapCount: 0,
1138
+ canScrollPrev: false,
1139
+ canScrollNext: false
1140
+ });
1141
+ const sync = useCallback((embla) => {
1142
+ setState({
1143
+ selectedIndex: embla.selectedScrollSnap(),
1144
+ snapCount: embla.scrollSnapList().length,
1145
+ canScrollPrev: embla.canScrollPrev(),
1146
+ canScrollNext: embla.canScrollNext()
1147
+ });
1148
+ }, []);
1149
+ useEffect(() => {
1150
+ if (!api) return;
1151
+ setApi?.(api);
1152
+ sync(api);
1153
+ api.on("select", sync).on("reInit", sync);
1154
+ return () => {
1155
+ api.off("select", sync).off("reInit", sync);
1156
+ };
1157
+ }, [
1158
+ api,
1159
+ setApi,
1160
+ sync
1161
+ ]);
1162
+ const scrollPrev = useCallback(() => api?.scrollPrev(), [api]);
1163
+ const scrollNext = useCallback(() => api?.scrollNext(), [api]);
1164
+ const scrollTo = useCallback((index) => api?.scrollTo(index), [api]);
1165
+ const onKeyDownCapture = (event) => {
1166
+ const prevKey = orientation === "horizontal" ? "ArrowLeft" : "ArrowUp";
1167
+ const nextKey = orientation === "horizontal" ? "ArrowRight" : "ArrowDown";
1168
+ if (event.key === prevKey) {
1169
+ event.preventDefault();
1170
+ scrollPrev();
1171
+ } else if (event.key === nextKey) {
1172
+ event.preventDefault();
1173
+ scrollNext();
1174
+ }
1175
+ };
1176
+ const s = carouselStyles({ orientation });
1177
+ return /* @__PURE__ */ jsx(CarouselContext.Provider, {
1178
+ value: {
1179
+ viewportRef,
1180
+ api,
1181
+ orientation,
1182
+ ...state,
1183
+ scrollPrev,
1184
+ scrollNext,
1185
+ scrollTo,
1186
+ s,
1187
+ slots
1188
+ },
1189
+ children: /* @__PURE__ */ jsx("section", {
1190
+ "data-slot": "carousel",
1191
+ "aria-roledescription": "carousel",
1192
+ onKeyDownCapture,
1193
+ className: s.root({ class: [slots.root, className] }),
1194
+ ...rest,
1195
+ children
1196
+ })
1197
+ });
1198
+ }
1199
+ const SlideContext = createContext(null);
1200
+ function CarouselContent({ className, children, ...props }) {
1201
+ const { viewportRef, s, slots } = useCarousel();
1202
+ const items = Children.toArray(children);
1203
+ return /* @__PURE__ */ jsx("div", {
1204
+ ref: viewportRef,
1205
+ "data-slot": "carousel-viewport",
1206
+ className: s.viewport({ class: slots.viewport }),
1207
+ children: /* @__PURE__ */ jsx("div", {
1208
+ "data-slot": "carousel-content",
1209
+ className: s.container({ class: [slots.container, className] }),
1210
+ ...props,
1211
+ children: items.map((child, index) => /* @__PURE__ */ jsx(SlideContext.Provider, {
1212
+ value: {
1213
+ index,
1214
+ total: items.length
1215
+ },
1216
+ children: child
1217
+ }, index))
1218
+ })
1219
+ });
1220
+ }
1221
+ function CarouselItem({ className, ...props }) {
1222
+ const { s, slots } = useCarousel();
1223
+ const slide = useContext(SlideContext);
1224
+ return /* @__PURE__ */ jsx("div", {
1225
+ role: "group",
1226
+ "aria-roledescription": "slide",
1227
+ "aria-label": slide ? `${slide.index + 1} of ${slide.total}` : void 0,
1228
+ "data-slot": "carousel-item",
1229
+ className: s.item({ class: [slots.item, className] }),
1230
+ ...props
1231
+ });
1232
+ }
1233
+ function Chevron({ direction }) {
1234
+ return /* @__PURE__ */ jsx("svg", {
1235
+ viewBox: "0 0 24 24",
1236
+ fill: "none",
1237
+ stroke: "currentColor",
1238
+ strokeWidth: "2",
1239
+ strokeLinecap: "round",
1240
+ strokeLinejoin: "round",
1241
+ "aria-hidden": "true",
1242
+ children: /* @__PURE__ */ jsx("path", { d: direction === "left" ? "m15 18-6-6 6-6" : "m9 18 6-6-6-6" })
1243
+ });
1244
+ }
1245
+ function CarouselPrevious({ className, icon, ...props }) {
1246
+ const { scrollPrev, canScrollPrev, orientation, s, slots } = useCarousel();
1247
+ return /* @__PURE__ */ jsx(IconButton, {
1248
+ variant: "outline",
1249
+ size: "sm",
1250
+ "aria-label": "Previous slide",
1251
+ icon: icon ?? /* @__PURE__ */ jsx(Chevron, { direction: "left" }),
1252
+ disabled: !canScrollPrev,
1253
+ onClick: scrollPrev,
1254
+ className: s.control({ class: [
1255
+ slots.control,
1256
+ orientation === "horizontal" ? "left-3" : "top-3",
1257
+ className
1258
+ ] }),
1259
+ ...props
1260
+ });
1261
+ }
1262
+ function CarouselNext({ className, icon, ...props }) {
1263
+ const { scrollNext, canScrollNext, orientation, s, slots } = useCarousel();
1264
+ return /* @__PURE__ */ jsx(IconButton, {
1265
+ variant: "outline",
1266
+ size: "sm",
1267
+ "aria-label": "Next slide",
1268
+ icon: icon ?? /* @__PURE__ */ jsx(Chevron, { direction: "right" }),
1269
+ disabled: !canScrollNext,
1270
+ onClick: scrollNext,
1271
+ className: s.control({ class: [
1272
+ slots.control,
1273
+ orientation === "horizontal" ? "right-3" : "bottom-3",
1274
+ className
1275
+ ] }),
1276
+ ...props
1277
+ });
1278
+ }
1279
+ /** One button per snap point; the current one is highlighted. */
1280
+ function CarouselDots({ className, ...props }) {
1281
+ const { snapCount, selectedIndex, scrollTo, s, slots } = useCarousel();
1282
+ if (snapCount < 2) return null;
1283
+ return /* @__PURE__ */ jsx("div", {
1284
+ "data-slot": "carousel-dots",
1285
+ className: s.dots({ class: [slots.dots, className] }),
1286
+ ...props,
1287
+ children: Array.from({ length: snapCount }, (_, index) => /* @__PURE__ */ jsx("button", {
1288
+ type: "button",
1289
+ "aria-label": `Go to slide ${index + 1}`,
1290
+ "aria-current": index === selectedIndex,
1291
+ onClick: () => scrollTo(index),
1292
+ className: cn(s.dot({ class: slots.dot }))
1293
+ }, index))
1294
+ });
1295
+ }
1296
+ //#endregion
965
1297
  //#region src/components/code/code.styles.ts
966
1298
  const codeStyles = tv({ slots: { base: "rounded-xs bg-muted px-[0.3em] py-[0.15em] font-mono text-[0.875em] text-foreground" } });
967
1299
  const codeBlockStyles = tv({
@@ -986,7 +1318,7 @@ function Code(inProps) {
986
1318
  ...rest
987
1319
  });
988
1320
  }
989
- const CopyIcon = () => /* @__PURE__ */ jsxs("svg", {
1321
+ const CopyIcon$1 = () => /* @__PURE__ */ jsxs("svg", {
990
1322
  viewBox: "0 0 24 24",
991
1323
  fill: "none",
992
1324
  stroke: "currentColor",
@@ -1021,7 +1353,7 @@ function CodeBlock(inProps) {
1021
1353
  };
1022
1354
  const copyButton = copyable ? /* @__PURE__ */ jsx(IconButton, {
1023
1355
  size: "sm",
1024
- icon: copied ? /* @__PURE__ */ jsx(CheckIcon$1, {}) : /* @__PURE__ */ jsx(CopyIcon, {}),
1356
+ icon: copied ? /* @__PURE__ */ jsx(CheckIcon$4, {}) : /* @__PURE__ */ jsx(CopyIcon$1, {}),
1025
1357
  "aria-label": copied ? "Copied" : "Copy code",
1026
1358
  onClick: copy,
1027
1359
  className: heading ? s.copy({ class: slots.copy }) : s.floatingCopy({ class: slots.floatingCopy })
@@ -1043,6 +1375,43 @@ function CodeBlock(inProps) {
1043
1375
  });
1044
1376
  }
1045
1377
  //#endregion
1378
+ //#region src/components/collapsible/collapsible.tsx
1379
+ const collapsibleStyles = tv({ slots: {
1380
+ root: "",
1381
+ trigger: "",
1382
+ content: "overflow-hidden data-[state=closed]:animate-collapse-up data-[state=open]:animate-collapse-down"
1383
+ } });
1384
+ const s$4 = collapsibleStyles();
1385
+ /**
1386
+ * Shows and hides one region, e.g. "Show advanced options". For a list of expandable
1387
+ * sections use Accordion.
1388
+ */
1389
+ function Collapsible(inProps) {
1390
+ const [{ className, ...rest }, slots] = useComponentConfig("Collapsible", inProps);
1391
+ return /* @__PURE__ */ jsx(Collapsible$1.Root, {
1392
+ "data-slot": "collapsible",
1393
+ className: s$4.root({ class: [slots.root, className] }),
1394
+ ...rest
1395
+ });
1396
+ }
1397
+ function CollapsibleTrigger({ className, ...props }) {
1398
+ const [, slots] = useComponentConfig("Collapsible", {});
1399
+ return /* @__PURE__ */ jsx(Collapsible$1.Trigger, {
1400
+ "data-slot": "collapsible-trigger",
1401
+ className: s$4.trigger({ class: [slots.trigger, className] }),
1402
+ ...props
1403
+ });
1404
+ }
1405
+ /** Animates its height open and closed; stays mounted until the closing animation ends. */
1406
+ function CollapsibleContent({ className, ...props }) {
1407
+ const [, slots] = useComponentConfig("Collapsible", {});
1408
+ return /* @__PURE__ */ jsx(Collapsible$1.Content, {
1409
+ "data-slot": "collapsible-content",
1410
+ className: s$4.content({ class: [slots.content, className] }),
1411
+ ...props
1412
+ });
1413
+ }
1414
+ //#endregion
1046
1415
  //#region src/hooks/use-controllable-state.ts
1047
1416
  /** State that can be controlled by a parent (`value` + `onChange`) or left uncontrolled. */
1048
1417
  function useControllableState({ value, defaultValue, onChange }) {
@@ -1215,7 +1584,7 @@ function Combobox(inProps) {
1215
1584
  className: s.itemDescription({ class: slots.itemDescription }),
1216
1585
  children: option.description
1217
1586
  })]
1218
- }), checked && /* @__PURE__ */ jsx(CheckIcon$1, { className: s.check({ class: slots.check }) })]
1587
+ }), checked && /* @__PURE__ */ jsx(CheckIcon$4, { className: s.check({ class: slots.check }) })]
1219
1588
  }, option.value);
1220
1589
  })]
1221
1590
  })]
@@ -1260,9 +1629,9 @@ const commandMenuStyles = tv({ slots: {
1260
1629
  } });
1261
1630
  //#endregion
1262
1631
  //#region src/components/command-menu/command-menu.tsx
1263
- const s$1 = commandMenuStyles();
1632
+ const s$3 = commandMenuStyles();
1264
1633
  const CommandMenuContext = createContext(null);
1265
- function useSlots$1() {
1634
+ function useSlots$3() {
1266
1635
  return useComponentConfig("CommandMenu", {})[1];
1267
1636
  }
1268
1637
  /**
@@ -1280,10 +1649,10 @@ function CommandMenu(inProps) {
1280
1649
  return /* @__PURE__ */ jsx(Dialog$1.Root, {
1281
1650
  open,
1282
1651
  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, {
1652
+ 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
1653
  "data-slot": "command-menu",
1285
1654
  "aria-describedby": void 0,
1286
- className: s$1.content({ class: [slots.content, className] }),
1655
+ className: s$3.content({ class: [slots.content, className] }),
1287
1656
  children: [/* @__PURE__ */ jsx(Dialog$1.Title, {
1288
1657
  className: "sr-only",
1289
1658
  children: label
@@ -1301,51 +1670,51 @@ function CommandMenu(inProps) {
1301
1670
  }
1302
1671
  /** The palette without a dialog, for inline search panels. */
1303
1672
  function Command({ className, ...props }) {
1304
- const slots = useSlots$1();
1673
+ const slots = useSlots$3();
1305
1674
  return /* @__PURE__ */ jsx(Command$1, {
1306
1675
  "data-slot": "command",
1307
- className: s$1.root({ class: [slots.root, className] }),
1676
+ className: s$3.root({ class: [slots.root, className] }),
1308
1677
  ...props
1309
1678
  });
1310
1679
  }
1311
1680
  function CommandInput({ className, ...props }) {
1312
- const slots = useSlots$1();
1681
+ const slots = useSlots$3();
1313
1682
  return /* @__PURE__ */ jsxs("div", {
1314
- className: s$1.search({ class: slots.search }),
1683
+ className: s$3.search({ class: slots.search }),
1315
1684
  children: [/* @__PURE__ */ jsx(SearchIcon, {}), /* @__PURE__ */ jsx(Command$1.Input, {
1316
1685
  "data-slot": "command-input",
1317
- className: s$1.input({ class: [slots.input, className] }),
1686
+ className: s$3.input({ class: [slots.input, className] }),
1318
1687
  ...props
1319
1688
  })]
1320
1689
  });
1321
1690
  }
1322
1691
  function CommandList({ className, ...props }) {
1323
- const slots = useSlots$1();
1692
+ const slots = useSlots$3();
1324
1693
  return /* @__PURE__ */ jsx(Command$1.List, {
1325
1694
  "data-slot": "command-list",
1326
- className: s$1.list({ class: [slots.list, className] }),
1695
+ className: s$3.list({ class: [slots.list, className] }),
1327
1696
  ...props
1328
1697
  });
1329
1698
  }
1330
1699
  function CommandEmpty({ className, children = "No results", ...props }) {
1331
- const slots = useSlots$1();
1700
+ const slots = useSlots$3();
1332
1701
  return /* @__PURE__ */ jsx(Command$1.Empty, {
1333
1702
  "data-slot": "command-empty",
1334
- className: s$1.empty({ class: [slots.empty, className] }),
1703
+ className: s$3.empty({ class: [slots.empty, className] }),
1335
1704
  ...props,
1336
1705
  children
1337
1706
  });
1338
1707
  }
1339
1708
  function CommandGroup({ className, ...props }) {
1340
- const slots = useSlots$1();
1709
+ const slots = useSlots$3();
1341
1710
  return /* @__PURE__ */ jsx(Command$1.Group, {
1342
1711
  "data-slot": "command-group",
1343
- className: s$1.group({ class: [slots.group, className] }),
1712
+ className: s$3.group({ class: [slots.group, className] }),
1344
1713
  ...props
1345
1714
  });
1346
1715
  }
1347
1716
  function CommandItem({ icon, shortcut, closeOnSelect = true, onSelect, className, children, ...props }) {
1348
- const slots = useSlots$1();
1717
+ const slots = useSlots$3();
1349
1718
  const menu = useContext(CommandMenuContext);
1350
1719
  const keys = shortcut === void 0 ? [] : typeof shortcut === "string" ? [shortcut] : shortcut;
1351
1720
  return /* @__PURE__ */ jsxs(Command$1.Item, {
@@ -1354,20 +1723,20 @@ function CommandItem({ icon, shortcut, closeOnSelect = true, onSelect, className
1354
1723
  onSelect?.(value);
1355
1724
  if (closeOnSelect) menu?.close();
1356
1725
  },
1357
- className: s$1.item({ class: [slots.item, className] }),
1726
+ className: s$3.item({ class: [slots.item, className] }),
1358
1727
  ...props,
1359
1728
  children: [
1360
1729
  icon && /* @__PURE__ */ jsx("span", {
1361
- className: s$1.itemIcon({ class: slots.itemIcon }),
1730
+ className: s$3.itemIcon({ class: slots.itemIcon }),
1362
1731
  "aria-hidden": "true",
1363
1732
  children: icon
1364
1733
  }),
1365
1734
  /* @__PURE__ */ jsx("span", {
1366
- className: s$1.itemLabel({ class: slots.itemLabel }),
1735
+ className: s$3.itemLabel({ class: slots.itemLabel }),
1367
1736
  children
1368
1737
  }),
1369
1738
  keys.length > 0 && /* @__PURE__ */ jsx("span", {
1370
- className: s$1.shortcut({ class: slots.shortcut }),
1739
+ className: s$3.shortcut({ class: slots.shortcut }),
1371
1740
  "aria-hidden": "true",
1372
1741
  children: keys.map((key) => /* @__PURE__ */ jsx(Kbd, { children: key }, key))
1373
1742
  })
@@ -1375,10 +1744,10 @@ function CommandItem({ icon, shortcut, closeOnSelect = true, onSelect, className
1375
1744
  });
1376
1745
  }
1377
1746
  function CommandSeparator({ className, ...props }) {
1378
- const slots = useSlots$1();
1747
+ const slots = useSlots$3();
1379
1748
  return /* @__PURE__ */ jsx(Command$1.Separator, {
1380
1749
  "data-slot": "command-separator",
1381
- className: s$1.separator({ class: [slots.separator, className] }),
1750
+ className: s$3.separator({ class: [slots.separator, className] }),
1382
1751
  ...props
1383
1752
  });
1384
1753
  }
@@ -1421,87 +1790,629 @@ function Container({ size, asChild, className, ...props }) {
1421
1790
  });
1422
1791
  }
1423
1792
  //#endregion
1424
- //#region src/components/description-list/description-list.styles.ts
1425
- const descriptionListStyles = tv({
1793
+ //#region src/components/dropdown-menu/dropdown-menu.styles.ts
1794
+ const item = [
1795
+ "relative flex h-8 cursor-pointer select-none items-center gap-2 rounded-sm px-2 text-small text-foreground outline-none",
1796
+ "data-highlighted:bg-muted data-disabled:pointer-events-none data-disabled:opacity-50",
1797
+ "[&_svg]:size-4 [&_svg]:shrink-0"
1798
+ ];
1799
+ const dropdownMenuStyles = tv({
1426
1800
  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"
1801
+ content: [popover, "min-w-48 max-h-(--radix-dropdown-menu-content-available-height) overflow-y-auto p-1"],
1802
+ item,
1803
+ icon: "flex size-4 shrink-0 items-center justify-center text-muted-foreground",
1804
+ indicator: "absolute left-2 flex size-4 items-center justify-center text-primary",
1805
+ label: "px-2 pt-1.5 pb-1 text-caption font-medium text-faint-foreground",
1806
+ separator: "-mx-1 my-1 h-px bg-border",
1807
+ shortcut: "ml-auto pl-4 font-mono text-caption tracking-wider text-faint-foreground",
1808
+ subTrigger: [...item, "data-[state=open]:bg-muted"],
1809
+ subContent: [popover, "min-w-40 p-1"]
1431
1810
  },
1432
1811
  variants: {
1433
- layout: {
1434
- stacked: { root: "gap-4" },
1435
- inline: { item: "sm:grid-cols-[minmax(0,12rem)_1fr] sm:gap-4" }
1812
+ tone: {
1813
+ default: {},
1814
+ danger: {
1815
+ item: "text-danger data-highlighted:bg-danger/10",
1816
+ icon: "text-danger"
1817
+ }
1436
1818
  },
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
- }
1819
+ inset: { true: {
1820
+ item: "pl-8",
1821
+ label: "pl-8"
1822
+ } }
1444
1823
  },
1445
- compoundVariants: [{
1446
- layout: "inline",
1447
- dividers: false,
1448
- class: { root: "gap-3" }
1449
- }],
1450
- defaultVariants: {
1451
- layout: "stacked",
1452
- dividers: false
1453
- }
1824
+ defaultVariants: { tone: "default" }
1454
1825
  });
1455
1826
  //#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
- }
1827
+ //#region src/components/context-menu/context-menu.styles.ts
1828
+ /** Same look as DropdownMenu; only the available-height variable differs. */
1829
+ const contextMenuStyles = tv({
1830
+ extend: dropdownMenuStyles,
1831
+ slots: { content: "max-h-(--radix-context-menu-content-available-height)" }
1832
+ });
1500
1833
  //#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", {
1834
+ //#region src/components/context-menu/context-menu.tsx
1835
+ function useParts$4(tone, inset) {
1836
+ const [, slots] = useComponentConfig("ContextMenu", {});
1837
+ return {
1838
+ s: contextMenuStyles({
1839
+ tone,
1840
+ inset
1841
+ }),
1842
+ slots
1843
+ };
1844
+ }
1845
+ const svg$1 = {
1846
+ xmlns: "http://www.w3.org/2000/svg",
1847
+ viewBox: "0 0 24 24",
1848
+ fill: "none",
1849
+ stroke: "currentColor",
1850
+ strokeWidth: 2,
1851
+ strokeLinecap: "round",
1852
+ strokeLinejoin: "round"
1853
+ };
1854
+ const CheckIcon$3 = () => /* @__PURE__ */ jsx("svg", {
1855
+ "aria-hidden": "true",
1856
+ ...svg$1,
1857
+ children: /* @__PURE__ */ jsx("path", { d: "M20 6 9 17l-5-5" })
1858
+ });
1859
+ const DotIcon$1 = () => /* @__PURE__ */ jsx("svg", {
1860
+ "aria-hidden": "true",
1861
+ ...svg$1,
1862
+ children: /* @__PURE__ */ jsx("circle", {
1863
+ cx: "12",
1864
+ cy: "12",
1865
+ r: "4",
1866
+ fill: "currentColor"
1867
+ })
1868
+ });
1869
+ const ChevronRightIcon$1 = () => /* @__PURE__ */ jsx("svg", {
1870
+ "aria-hidden": "true",
1871
+ ...svg$1,
1872
+ children: /* @__PURE__ */ jsx("path", { d: "m9 18 6-6-6-6" })
1873
+ });
1874
+ /** A menu opened by right-click or long-press on an area. Same items as DropdownMenu. */
1875
+ const ContextMenu = ContextMenu$1.Root;
1876
+ const ContextMenuTrigger = ContextMenu$1.Trigger;
1877
+ const ContextMenuGroup = ContextMenu$1.Group;
1878
+ const ContextMenuRadioGroup = ContextMenu$1.RadioGroup;
1879
+ const ContextMenuSub = ContextMenu$1.Sub;
1880
+ function ContextMenuContent(inProps) {
1881
+ const [props, slots] = useComponentConfig("ContextMenu", inProps);
1882
+ const { className, ...rest } = props;
1883
+ const s = contextMenuStyles();
1884
+ return /* @__PURE__ */ jsx(ContextMenu$1.Portal, { children: /* @__PURE__ */ jsx(ContextMenu$1.Content, {
1885
+ "data-slot": "context-menu-content",
1886
+ className: s.content({ class: [slots.content, className] }),
1887
+ ...rest
1888
+ }) });
1889
+ }
1890
+ function ContextMenuItem({ icon, shortcut, tone, inset, className, children, ...props }) {
1891
+ const { s, slots } = useParts$4(tone, inset);
1892
+ return /* @__PURE__ */ jsxs(ContextMenu$1.Item, {
1893
+ "data-slot": "context-menu-item",
1894
+ "data-tone": tone ?? "default",
1895
+ className: s.item({ class: [slots.item, className] }),
1896
+ ...props,
1897
+ children: [
1898
+ icon && /* @__PURE__ */ jsx("span", {
1899
+ className: s.icon({ class: slots.icon }),
1900
+ "aria-hidden": "true",
1901
+ children: icon
1902
+ }),
1903
+ children,
1904
+ shortcut && /* @__PURE__ */ jsx(ContextMenuShortcut, { children: shortcut })
1905
+ ]
1906
+ });
1907
+ }
1908
+ function ContextMenuCheckboxItem({ className, children, ...props }) {
1909
+ const { s, slots } = useParts$4(void 0, true);
1910
+ return /* @__PURE__ */ jsxs(ContextMenu$1.CheckboxItem, {
1911
+ "data-slot": "context-menu-checkbox-item",
1912
+ className: s.item({ class: [slots.item, className] }),
1913
+ ...props,
1914
+ children: [/* @__PURE__ */ jsx("span", {
1915
+ className: s.indicator({ class: slots.indicator }),
1916
+ children: /* @__PURE__ */ jsx(ContextMenu$1.ItemIndicator, { children: /* @__PURE__ */ jsx(CheckIcon$3, {}) })
1917
+ }), children]
1918
+ });
1919
+ }
1920
+ function ContextMenuRadioItem({ className, children, ...props }) {
1921
+ const { s, slots } = useParts$4(void 0, true);
1922
+ return /* @__PURE__ */ jsxs(ContextMenu$1.RadioItem, {
1923
+ "data-slot": "context-menu-radio-item",
1924
+ className: s.item({ class: [slots.item, className] }),
1925
+ ...props,
1926
+ children: [/* @__PURE__ */ jsx("span", {
1927
+ className: s.indicator({ class: slots.indicator }),
1928
+ children: /* @__PURE__ */ jsx(ContextMenu$1.ItemIndicator, { children: /* @__PURE__ */ jsx(DotIcon$1, {}) })
1929
+ }), children]
1930
+ });
1931
+ }
1932
+ function ContextMenuLabel({ inset, className, ...props }) {
1933
+ const { s, slots } = useParts$4(void 0, inset);
1934
+ return /* @__PURE__ */ jsx(ContextMenu$1.Label, {
1935
+ "data-slot": "context-menu-label",
1936
+ className: s.label({ class: [slots.label, className] }),
1937
+ ...props
1938
+ });
1939
+ }
1940
+ function ContextMenuSeparator({ className, ...props }) {
1941
+ const { s, slots } = useParts$4();
1942
+ return /* @__PURE__ */ jsx(ContextMenu$1.Separator, {
1943
+ "data-slot": "context-menu-separator",
1944
+ className: s.separator({ class: [slots.separator, className] }),
1945
+ ...props
1946
+ });
1947
+ }
1948
+ function ContextMenuShortcut({ className, ...props }) {
1949
+ const { s, slots } = useParts$4();
1950
+ return /* @__PURE__ */ jsx("span", {
1951
+ "data-slot": "context-menu-shortcut",
1952
+ className: s.shortcut({ class: [slots.shortcut, className] }),
1953
+ ...props
1954
+ });
1955
+ }
1956
+ function ContextMenuSubTrigger({ icon, className, children, ...props }) {
1957
+ const { s, slots } = useParts$4();
1958
+ return /* @__PURE__ */ jsxs(ContextMenu$1.SubTrigger, {
1959
+ "data-slot": "context-menu-sub-trigger",
1960
+ className: s.subTrigger({ class: [slots.subTrigger, className] }),
1961
+ ...props,
1962
+ children: [
1963
+ icon && /* @__PURE__ */ jsx("span", {
1964
+ className: s.icon({ class: slots.icon }),
1965
+ "aria-hidden": "true",
1966
+ children: icon
1967
+ }),
1968
+ children,
1969
+ /* @__PURE__ */ jsx("span", {
1970
+ className: "ml-auto flex text-faint-foreground",
1971
+ children: /* @__PURE__ */ jsx(ChevronRightIcon$1, {})
1972
+ })
1973
+ ]
1974
+ });
1975
+ }
1976
+ function ContextMenuSubContent({ className, ...props }) {
1977
+ const { s, slots } = useParts$4();
1978
+ return /* @__PURE__ */ jsx(ContextMenu$1.Portal, { children: /* @__PURE__ */ jsx(ContextMenu$1.SubContent, {
1979
+ "data-slot": "context-menu-sub-content",
1980
+ className: s.subContent({ class: [slots.subContent, className] }),
1981
+ ...props
1982
+ }) });
1983
+ }
1984
+ //#endregion
1985
+ //#region src/components/copy-button/copy-button.tsx
1986
+ const copyButtonStyles = tv({ slots: {
1987
+ base: "",
1988
+ icon: "size-4",
1989
+ status: "sr-only"
1990
+ } });
1991
+ const icon$1 = {
1992
+ xmlns: "http://www.w3.org/2000/svg",
1993
+ viewBox: "0 0 24 24",
1994
+ fill: "none",
1995
+ stroke: "currentColor",
1996
+ strokeWidth: 2,
1997
+ strokeLinecap: "round",
1998
+ strokeLinejoin: "round"
1999
+ };
2000
+ const CopyIcon = ({ className }) => /* @__PURE__ */ jsxs("svg", {
2001
+ "aria-hidden": "true",
2002
+ ...icon$1,
2003
+ className,
2004
+ children: [/* @__PURE__ */ jsx("rect", {
2005
+ width: "13",
2006
+ height: "13",
2007
+ x: "9",
2008
+ y: "9",
2009
+ rx: "2"
2010
+ }), /* @__PURE__ */ jsx("path", { d: "M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" })]
2011
+ });
2012
+ const CheckIcon$2 = ({ className }) => /* @__PURE__ */ jsx("svg", {
2013
+ "aria-hidden": "true",
2014
+ ...icon$1,
2015
+ className,
2016
+ children: /* @__PURE__ */ jsx("path", { d: "M20 6 9 17l-5-5" })
2017
+ });
2018
+ /** Copies a value to the clipboard and confirms it visually and to screen readers. */
2019
+ function CopyButton(inProps) {
2020
+ const [props, slots] = useComponentConfig("CopyButton", inProps);
2021
+ const { value, children, copiedLabel = "Copied", timeout = 1500, onCopy, variant = "outline", className, "aria-label": ariaLabel, ...rest } = props;
2022
+ const [copied, setCopied] = useState(false);
2023
+ const timer = useRef(void 0);
2024
+ const s = copyButtonStyles();
2025
+ useEffect(() => () => clearTimeout(timer.current), []);
2026
+ const copy = async () => {
2027
+ try {
2028
+ await navigator.clipboard.writeText(value);
2029
+ } catch {
2030
+ return;
2031
+ }
2032
+ setCopied(true);
2033
+ onCopy?.(value);
2034
+ clearTimeout(timer.current);
2035
+ timer.current = setTimeout(() => setCopied(false), timeout);
2036
+ };
2037
+ const glyph = copied ? /* @__PURE__ */ jsx(CheckIcon$2, { className: s.icon({ class: slots.icon }) }) : /* @__PURE__ */ jsx(CopyIcon, { className: s.icon({ class: slots.icon }) });
2038
+ const iconOnly = children === void 0;
2039
+ return /* @__PURE__ */ jsxs(Button, {
2040
+ "data-slot": "copy-button",
2041
+ "data-copied": copied || void 0,
2042
+ variant,
2043
+ iconOnly,
2044
+ onClick: copy,
2045
+ className: s.base({ class: [slots.base, className] }),
2046
+ "aria-label": iconOnly ? copied ? copiedLabel : ariaLabel ?? "Copy" : ariaLabel,
2047
+ ...!iconOnly && { leftIcon: glyph },
2048
+ ...rest,
2049
+ children: [iconOnly ? glyph : copied ? copiedLabel : children, /* @__PURE__ */ jsx("span", {
2050
+ role: "status",
2051
+ className: s.status({ class: slots.status }),
2052
+ children: copied ? copiedLabel : ""
2053
+ })]
2054
+ });
2055
+ }
2056
+ //#endregion
2057
+ //#region src/components/popover/popover.tsx
2058
+ const popoverStyles = tv({ slots: {
2059
+ content: [popover, "w-72 max-w-[calc(100vw-2rem)] overflow-visible p-4 text-small outline-none"],
2060
+ arrow: "fill-raised"
2061
+ } });
2062
+ /** Floating content anchored to a trigger: quick settings, details, small forms. */
2063
+ const Popover = Popover$1.Root;
2064
+ const PopoverTrigger = Popover$1.Trigger;
2065
+ const PopoverAnchor = Popover$1.Anchor;
2066
+ const PopoverClose = Popover$1.Close;
2067
+ function PopoverContent(inProps) {
2068
+ const [props, slots] = useComponentConfig("Popover", inProps);
2069
+ const { showArrow = false, sideOffset = 6, align = "center", className, children, ...rest } = props;
2070
+ const s = popoverStyles();
2071
+ return /* @__PURE__ */ jsx(Popover$1.Portal, { children: /* @__PURE__ */ jsxs(Popover$1.Content, {
2072
+ "data-slot": "popover-content",
2073
+ sideOffset,
2074
+ align,
2075
+ className: s.content({ class: [slots.content, className] }),
2076
+ ...rest,
2077
+ children: [children, showArrow && /* @__PURE__ */ jsx(Popover$1.Arrow, {
2078
+ width: 12,
2079
+ height: 6,
2080
+ className: s.arrow({ class: slots.arrow })
2081
+ })]
2082
+ }) });
2083
+ }
2084
+ //#endregion
2085
+ //#region src/components/date-picker/date-picker.styles.ts
2086
+ const datePickerStyles = tv({
2087
+ slots: {
2088
+ trigger: [
2089
+ ...fieldControl,
2090
+ "flex cursor-pointer items-center gap-2 px-3 text-left outline-none",
2091
+ "focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/20",
2092
+ "disabled:cursor-not-allowed disabled:opacity-50"
2093
+ ],
2094
+ icon: "size-4 shrink-0 text-faint-foreground",
2095
+ value: "min-w-0 flex-1 truncate",
2096
+ placeholder: "min-w-0 flex-1 truncate text-faint-foreground",
2097
+ 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",
2098
+ content: [popover, "w-auto p-0"],
2099
+ layout: "flex flex-col sm:flex-row",
2100
+ 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",
2101
+ 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"
2102
+ },
2103
+ variants: { size: {
2104
+ sm: { trigger: "h-(--glyph-control-sm) text-small" },
2105
+ md: { trigger: "h-(--glyph-control-md) text-small" },
2106
+ lg: { trigger: "h-(--glyph-control-lg) text-body" }
2107
+ } },
2108
+ defaultVariants: { size: "md" }
2109
+ });
2110
+ //#endregion
2111
+ //#region src/components/date-picker/date-picker.tsx
2112
+ function CalendarIcon({ className }) {
2113
+ return /* @__PURE__ */ jsxs("svg", {
2114
+ viewBox: "0 0 24 24",
2115
+ fill: "none",
2116
+ stroke: "currentColor",
2117
+ strokeWidth: "2",
2118
+ strokeLinecap: "round",
2119
+ strokeLinejoin: "round",
2120
+ "aria-hidden": "true",
2121
+ className,
2122
+ children: [/* @__PURE__ */ jsx("rect", {
2123
+ x: "3",
2124
+ y: "4",
2125
+ width: "18",
2126
+ height: "18",
2127
+ rx: "2"
2128
+ }), /* @__PURE__ */ jsx("path", { d: "M16 2v4M8 2v4M3 10h18" })]
2129
+ });
2130
+ }
2131
+ function ClearIcon() {
2132
+ return /* @__PURE__ */ jsx("svg", {
2133
+ viewBox: "0 0 24 24",
2134
+ fill: "none",
2135
+ stroke: "currentColor",
2136
+ strokeWidth: "2",
2137
+ strokeLinecap: "round",
2138
+ "aria-hidden": "true",
2139
+ children: /* @__PURE__ */ jsx("path", { d: "M18 6 6 18M6 6l12 12" })
2140
+ });
2141
+ }
2142
+ function disabledMatchers({ minDate, maxDate, disabledDates }) {
2143
+ const list = [];
2144
+ if (minDate) list.push({ before: minDate });
2145
+ if (maxDate) list.push({ after: maxDate });
2146
+ if (disabledDates) list.push(...Array.isArray(disabledDates) ? disabledDates : [disabledDates]);
2147
+ return list;
2148
+ }
2149
+ const iso = (date) => format(date, "yyyy-MM-dd");
2150
+ /** A date field that opens a calendar. Works with Field and with `Form` (`value` + `onValueChange`). */
2151
+ function DatePicker(inProps) {
2152
+ const [props, slots] = useComponentConfig("DatePicker", useFieldControl(inProps));
2153
+ 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;
2154
+ const [open, setOpen] = useState(false);
2155
+ const [value, setValue] = useControllableState({
2156
+ value: valueProp,
2157
+ defaultValue,
2158
+ onChange: onValueChange
2159
+ });
2160
+ const current = "value" in inProps ? valueProp : value;
2161
+ const s = datePickerStyles({ size });
2162
+ return /* @__PURE__ */ jsxs(Popover, {
2163
+ open,
2164
+ onOpenChange: setOpen,
2165
+ children: [
2166
+ /* @__PURE__ */ jsx(PopoverTrigger, {
2167
+ asChild: true,
2168
+ children: /* @__PURE__ */ jsxs("button", {
2169
+ type: "button",
2170
+ id,
2171
+ "data-slot": "date-picker",
2172
+ disabled,
2173
+ "aria-label": ariaLabel,
2174
+ "aria-describedby": ariaDescribedBy,
2175
+ "aria-invalid": ariaInvalid,
2176
+ className: s.trigger({ class: [slots.trigger, className] }),
2177
+ children: [
2178
+ /* @__PURE__ */ jsx(CalendarIcon, { className: s.icon({ class: slots.icon }) }),
2179
+ current ? /* @__PURE__ */ jsx("span", {
2180
+ className: s.value({ class: slots.value }),
2181
+ children: format(current, format$1)
2182
+ }) : /* @__PURE__ */ jsx("span", {
2183
+ className: s.placeholder({ class: slots.placeholder }),
2184
+ children: placeholder
2185
+ }),
2186
+ clearable && current && !disabled && /* @__PURE__ */ jsx("span", {
2187
+ role: "button",
2188
+ tabIndex: 0,
2189
+ "aria-label": "Clear date",
2190
+ className: s.clear({ class: slots.clear }),
2191
+ onPointerDown: (event) => event.stopPropagation(),
2192
+ onClick: (event) => {
2193
+ event.stopPropagation();
2194
+ setValue(void 0);
2195
+ },
2196
+ onKeyDown: (event) => {
2197
+ if (event.key === "Enter" || event.key === " ") {
2198
+ event.preventDefault();
2199
+ event.stopPropagation();
2200
+ setValue(void 0);
2201
+ }
2202
+ },
2203
+ children: /* @__PURE__ */ jsx(ClearIcon, {})
2204
+ })
2205
+ ]
2206
+ })
2207
+ }),
2208
+ /* @__PURE__ */ jsx(PopoverContent, {
2209
+ align: "start",
2210
+ className: s.content({ class: [slots.content, contentClassName] }),
2211
+ children: /* @__PURE__ */ jsx(Calendar, {
2212
+ mode: "single",
2213
+ selected: current,
2214
+ defaultMonth: current,
2215
+ disabled: disabledMatchers(props),
2216
+ onSelect: (date) => {
2217
+ setValue(date);
2218
+ if (date) setOpen(false);
2219
+ },
2220
+ autoFocus: true
2221
+ })
2222
+ }),
2223
+ name && /* @__PURE__ */ jsx("input", {
2224
+ type: "hidden",
2225
+ name,
2226
+ value: current ? iso(current) : ""
2227
+ })
2228
+ ]
2229
+ });
2230
+ }
2231
+ function formatRange(range, format$2) {
2232
+ if (!range.from) return "";
2233
+ if (!range.to || isSameDay(range.from, range.to)) return format(range.from, format$2);
2234
+ return `${format(range.from, format$2)} – ${format(range.to, format$2)}`;
2235
+ }
2236
+ /** A date-range field with a two-month calendar and optional presets. */
2237
+ function DateRangePicker(inProps) {
2238
+ const [props, slots] = useComponentConfig("DatePicker", useFieldControl(inProps));
2239
+ 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;
2240
+ const [open, setOpen] = useState(false);
2241
+ const [value, setValue] = useControllableState({
2242
+ value: valueProp,
2243
+ defaultValue,
2244
+ onChange: onValueChange
2245
+ });
2246
+ const current = "value" in inProps ? valueProp : value;
2247
+ const s = datePickerStyles({ size });
2248
+ const label = current ? formatRange(current, format) : "";
2249
+ return /* @__PURE__ */ jsxs(Popover, {
2250
+ open,
2251
+ onOpenChange: setOpen,
2252
+ children: [
2253
+ /* @__PURE__ */ jsx(PopoverTrigger, {
2254
+ asChild: true,
2255
+ children: /* @__PURE__ */ jsxs("button", {
2256
+ type: "button",
2257
+ id,
2258
+ "data-slot": "date-range-picker",
2259
+ disabled,
2260
+ "aria-label": ariaLabel,
2261
+ "aria-describedby": ariaDescribedBy,
2262
+ "aria-invalid": ariaInvalid,
2263
+ className: s.trigger({ class: [slots.trigger, className] }),
2264
+ children: [
2265
+ /* @__PURE__ */ jsx(CalendarIcon, { className: s.icon({ class: slots.icon }) }),
2266
+ label ? /* @__PURE__ */ jsx("span", {
2267
+ className: s.value({ class: slots.value }),
2268
+ children: label
2269
+ }) : /* @__PURE__ */ jsx("span", {
2270
+ className: s.placeholder({ class: slots.placeholder }),
2271
+ children: placeholder
2272
+ }),
2273
+ clearable && current?.from && !disabled && /* @__PURE__ */ jsx("span", {
2274
+ role: "button",
2275
+ tabIndex: 0,
2276
+ "aria-label": "Clear dates",
2277
+ className: s.clear({ class: slots.clear }),
2278
+ onPointerDown: (event) => event.stopPropagation(),
2279
+ onClick: (event) => {
2280
+ event.stopPropagation();
2281
+ setValue(void 0);
2282
+ },
2283
+ onKeyDown: (event) => {
2284
+ if (event.key === "Enter" || event.key === " ") {
2285
+ event.preventDefault();
2286
+ event.stopPropagation();
2287
+ setValue(void 0);
2288
+ }
2289
+ },
2290
+ children: /* @__PURE__ */ jsx(ClearIcon, {})
2291
+ })
2292
+ ]
2293
+ })
2294
+ }),
2295
+ /* @__PURE__ */ jsx(PopoverContent, {
2296
+ align: "start",
2297
+ className: s.content({ class: [slots.content, contentClassName] }),
2298
+ children: /* @__PURE__ */ jsxs("div", {
2299
+ className: s.layout({ class: slots.layout }),
2300
+ children: [presets && presets.length > 0 && /* @__PURE__ */ jsx("div", {
2301
+ className: s.presets({ class: slots.presets }),
2302
+ children: presets.map((preset) => /* @__PURE__ */ jsx("button", {
2303
+ type: "button",
2304
+ className: s.preset({ class: slots.preset }),
2305
+ onClick: () => {
2306
+ setValue(preset.range());
2307
+ setOpen(false);
2308
+ },
2309
+ children: preset.label
2310
+ }, preset.label))
2311
+ }), /* @__PURE__ */ jsx(Calendar, {
2312
+ mode: "range",
2313
+ selected: current,
2314
+ defaultMonth: current?.from,
2315
+ numberOfMonths,
2316
+ disabled: disabledMatchers(props),
2317
+ onSelect: (range) => setValue(range),
2318
+ autoFocus: true
2319
+ })]
2320
+ })
2321
+ }),
2322
+ name && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("input", {
2323
+ type: "hidden",
2324
+ name: `${name}.from`,
2325
+ value: current?.from ? iso(current.from) : ""
2326
+ }), /* @__PURE__ */ jsx("input", {
2327
+ type: "hidden",
2328
+ name: `${name}.to`,
2329
+ value: current?.to ? iso(current.to) : ""
2330
+ })] })
2331
+ ]
2332
+ });
2333
+ }
2334
+ //#endregion
2335
+ //#region src/components/description-list/description-list.styles.ts
2336
+ const descriptionListStyles = tv({
2337
+ slots: {
2338
+ root: "grid w-full",
2339
+ item: "grid min-w-0 gap-1",
2340
+ term: "text-small text-muted-foreground",
2341
+ details: "min-w-0 break-words text-small text-foreground"
2342
+ },
2343
+ variants: {
2344
+ layout: {
2345
+ stacked: { root: "gap-4" },
2346
+ inline: { item: "sm:grid-cols-[minmax(0,12rem)_1fr] sm:gap-4" }
2347
+ },
2348
+ dividers: {
2349
+ true: {
2350
+ root: "gap-0 divide-y divide-border",
2351
+ item: "py-3 first:pt-0 last:pb-0"
2352
+ },
2353
+ false: {}
2354
+ }
2355
+ },
2356
+ compoundVariants: [{
2357
+ layout: "inline",
2358
+ dividers: false,
2359
+ class: { root: "gap-3" }
2360
+ }],
2361
+ defaultVariants: {
2362
+ layout: "stacked",
2363
+ dividers: false
2364
+ }
2365
+ });
2366
+ //#endregion
2367
+ //#region src/components/description-list/description-list.tsx
2368
+ const DescriptionListContext = createContext(null);
2369
+ /**
2370
+ * Label–value pairs, such as account details or order metadata.
2371
+ * `layout="inline"` puts terms and details side by side from the `sm` breakpoint.
2372
+ */
2373
+ function DescriptionList(inProps) {
2374
+ const [props, slots] = useComponentConfig("DescriptionList", inProps);
2375
+ const { layout, dividers, className, ...rest } = props;
2376
+ const s = descriptionListStyles({
2377
+ layout,
2378
+ dividers
2379
+ });
2380
+ return /* @__PURE__ */ jsx(DescriptionListContext.Provider, {
2381
+ value: {
2382
+ s,
2383
+ slots
2384
+ },
2385
+ children: /* @__PURE__ */ jsx("dl", {
2386
+ "data-slot": "description-list",
2387
+ className: s.root({ class: [slots.root, className] }),
2388
+ ...rest
2389
+ })
2390
+ });
2391
+ }
2392
+ function DescriptionItem({ term, children, className, ...props }) {
2393
+ const ctx = useContext(DescriptionListContext);
2394
+ const s = ctx?.s ?? descriptionListStyles();
2395
+ const slots = ctx?.slots ?? {};
2396
+ return /* @__PURE__ */ jsxs("div", {
2397
+ "data-slot": "description-item",
2398
+ className: s.item({ class: [slots.item, className] }),
2399
+ ...props,
2400
+ children: [/* @__PURE__ */ jsx("dt", {
2401
+ "data-slot": "description-term",
2402
+ className: s.term({ class: slots.term }),
2403
+ children: term
2404
+ }), /* @__PURE__ */ jsx("dd", {
2405
+ "data-slot": "description-details",
2406
+ className: s.details({ class: slots.details }),
2407
+ children
2408
+ })]
2409
+ });
2410
+ }
2411
+ //#endregion
2412
+ //#region src/components/dialog/close-icon.tsx
2413
+ /** Local close icon so overlay components stay self-contained. */
2414
+ function CloseIcon(props) {
2415
+ return /* @__PURE__ */ jsx("svg", {
1505
2416
  xmlns: "http://www.w3.org/2000/svg",
1506
2417
  width: "16",
1507
2418
  height: "16",
@@ -1547,7 +2458,7 @@ const dialogStyles = tv({
1547
2458
  });
1548
2459
  //#endregion
1549
2460
  //#region src/components/dialog/dialog.tsx
1550
- function useParts$2() {
2461
+ function useParts$3() {
1551
2462
  const [, slots] = useComponentConfig("Dialog", {});
1552
2463
  return {
1553
2464
  s: dialogStyles(),
@@ -1578,7 +2489,7 @@ function DialogContent(inProps) {
1578
2489
  })] });
1579
2490
  }
1580
2491
  function DialogHeader({ className, ...props }) {
1581
- const { s, slots } = useParts$2();
2492
+ const { s, slots } = useParts$3();
1582
2493
  return /* @__PURE__ */ jsx("div", {
1583
2494
  "data-slot": "dialog-header",
1584
2495
  className: s.header({ class: [slots.header, className] }),
@@ -1586,7 +2497,7 @@ function DialogHeader({ className, ...props }) {
1586
2497
  });
1587
2498
  }
1588
2499
  function DialogTitle({ className, ...props }) {
1589
- const { s, slots } = useParts$2();
2500
+ const { s, slots } = useParts$3();
1590
2501
  return /* @__PURE__ */ jsx(Dialog$1.Title, {
1591
2502
  "data-slot": "dialog-title",
1592
2503
  className: s.title({ class: [slots.title, className] }),
@@ -1594,7 +2505,7 @@ function DialogTitle({ className, ...props }) {
1594
2505
  });
1595
2506
  }
1596
2507
  function DialogDescription({ className, ...props }) {
1597
- const { s, slots } = useParts$2();
2508
+ const { s, slots } = useParts$3();
1598
2509
  return /* @__PURE__ */ jsx(Dialog$1.Description, {
1599
2510
  "data-slot": "dialog-description",
1600
2511
  className: s.description({ class: [slots.description, className] }),
@@ -1602,7 +2513,7 @@ function DialogDescription({ className, ...props }) {
1602
2513
  });
1603
2514
  }
1604
2515
  function DialogBody({ className, ...props }) {
1605
- const { s, slots } = useParts$2();
2516
+ const { s, slots } = useParts$3();
1606
2517
  return /* @__PURE__ */ jsx("div", {
1607
2518
  "data-slot": "dialog-body",
1608
2519
  className: s.body({ class: [slots.body, className] }),
@@ -1610,7 +2521,7 @@ function DialogBody({ className, ...props }) {
1610
2521
  });
1611
2522
  }
1612
2523
  function DialogFooter({ className, ...props }) {
1613
- const { s, slots } = useParts$2();
2524
+ const { s, slots } = useParts$3();
1614
2525
  return /* @__PURE__ */ jsx("div", {
1615
2526
  "data-slot": "dialog-footer",
1616
2527
  className: s.footer({ class: [slots.footer, className] }),
@@ -1618,42 +2529,8 @@ function DialogFooter({ className, ...props }) {
1618
2529
  });
1619
2530
  }
1620
2531
  //#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
2532
  //#region src/components/dropdown-menu/dropdown-menu.tsx
1656
- function useParts$1(tone, inset) {
2533
+ function useParts$2(tone, inset) {
1657
2534
  const [, slots] = useComponentConfig("DropdownMenu", {});
1658
2535
  return {
1659
2536
  s: dropdownMenuStyles({
@@ -1672,7 +2549,7 @@ const svg = {
1672
2549
  strokeLinecap: "round",
1673
2550
  strokeLinejoin: "round"
1674
2551
  };
1675
- const CheckIcon = () => /* @__PURE__ */ jsx("svg", {
2552
+ const CheckIcon$1 = () => /* @__PURE__ */ jsx("svg", {
1676
2553
  "aria-hidden": "true",
1677
2554
  ...svg,
1678
2555
  children: /* @__PURE__ */ jsx("path", { d: "M20 6 9 17l-5-5" })
@@ -1711,7 +2588,7 @@ function DropdownMenuContent(inProps) {
1711
2588
  }) });
1712
2589
  }
1713
2590
  function DropdownMenuItem({ icon, shortcut, tone, inset, className, children, ...props }) {
1714
- const { s, slots } = useParts$1(tone, inset);
2591
+ const { s, slots } = useParts$2(tone, inset);
1715
2592
  return /* @__PURE__ */ jsxs(DropdownMenu$1.Item, {
1716
2593
  "data-slot": "dropdown-menu-item",
1717
2594
  "data-tone": tone ?? "default",
@@ -1729,19 +2606,19 @@ function DropdownMenuItem({ icon, shortcut, tone, inset, className, children, ..
1729
2606
  });
1730
2607
  }
1731
2608
  function DropdownMenuCheckboxItem({ className, children, ...props }) {
1732
- const { s, slots } = useParts$1(void 0, true);
2609
+ const { s, slots } = useParts$2(void 0, true);
1733
2610
  return /* @__PURE__ */ jsxs(DropdownMenu$1.CheckboxItem, {
1734
2611
  "data-slot": "dropdown-menu-checkbox-item",
1735
2612
  className: s.item({ class: [slots.item, className] }),
1736
2613
  ...props,
1737
2614
  children: [/* @__PURE__ */ jsx("span", {
1738
2615
  className: s.indicator({ class: slots.indicator }),
1739
- children: /* @__PURE__ */ jsx(DropdownMenu$1.ItemIndicator, { children: /* @__PURE__ */ jsx(CheckIcon, {}) })
2616
+ children: /* @__PURE__ */ jsx(DropdownMenu$1.ItemIndicator, { children: /* @__PURE__ */ jsx(CheckIcon$1, {}) })
1740
2617
  }), children]
1741
2618
  });
1742
2619
  }
1743
2620
  function DropdownMenuRadioItem({ className, children, ...props }) {
1744
- const { s, slots } = useParts$1(void 0, true);
2621
+ const { s, slots } = useParts$2(void 0, true);
1745
2622
  return /* @__PURE__ */ jsxs(DropdownMenu$1.RadioItem, {
1746
2623
  "data-slot": "dropdown-menu-radio-item",
1747
2624
  className: s.item({ class: [slots.item, className] }),
@@ -1753,7 +2630,7 @@ function DropdownMenuRadioItem({ className, children, ...props }) {
1753
2630
  });
1754
2631
  }
1755
2632
  function DropdownMenuLabel({ inset, className, ...props }) {
1756
- const { s, slots } = useParts$1(void 0, inset);
2633
+ const { s, slots } = useParts$2(void 0, inset);
1757
2634
  return /* @__PURE__ */ jsx(DropdownMenu$1.Label, {
1758
2635
  "data-slot": "dropdown-menu-label",
1759
2636
  className: s.label({ class: [slots.label, className] }),
@@ -1761,7 +2638,7 @@ function DropdownMenuLabel({ inset, className, ...props }) {
1761
2638
  });
1762
2639
  }
1763
2640
  function DropdownMenuSeparator({ className, ...props }) {
1764
- const { s, slots } = useParts$1();
2641
+ const { s, slots } = useParts$2();
1765
2642
  return /* @__PURE__ */ jsx(DropdownMenu$1.Separator, {
1766
2643
  "data-slot": "dropdown-menu-separator",
1767
2644
  className: s.separator({ class: [slots.separator, className] }),
@@ -1769,7 +2646,7 @@ function DropdownMenuSeparator({ className, ...props }) {
1769
2646
  });
1770
2647
  }
1771
2648
  function DropdownMenuShortcut({ className, ...props }) {
1772
- const { s, slots } = useParts$1();
2649
+ const { s, slots } = useParts$2();
1773
2650
  return /* @__PURE__ */ jsx("span", {
1774
2651
  "data-slot": "dropdown-menu-shortcut",
1775
2652
  className: s.shortcut({ class: [slots.shortcut, className] }),
@@ -1777,7 +2654,7 @@ function DropdownMenuShortcut({ className, ...props }) {
1777
2654
  });
1778
2655
  }
1779
2656
  function DropdownMenuSubTrigger({ icon, className, children, ...props }) {
1780
- const { s, slots } = useParts$1();
2657
+ const { s, slots } = useParts$2();
1781
2658
  return /* @__PURE__ */ jsxs(DropdownMenu$1.SubTrigger, {
1782
2659
  "data-slot": "dropdown-menu-sub-trigger",
1783
2660
  className: s.subTrigger({ class: [slots.subTrigger, className] }),
@@ -1788,47 +2665,331 @@ function DropdownMenuSubTrigger({ icon, className, children, ...props }) {
1788
2665
  "aria-hidden": "true",
1789
2666
  children: icon
1790
2667
  }),
1791
- children,
1792
- /* @__PURE__ */ jsx("span", {
1793
- className: "ml-auto flex text-faint-foreground",
1794
- children: /* @__PURE__ */ jsx(ChevronRightIcon, {})
2668
+ children,
2669
+ /* @__PURE__ */ jsx("span", {
2670
+ className: "ml-auto flex text-faint-foreground",
2671
+ children: /* @__PURE__ */ jsx(ChevronRightIcon, {})
2672
+ })
2673
+ ]
2674
+ });
2675
+ }
2676
+ function DropdownMenuSubContent({ sideOffset = 4, className, ...props }) {
2677
+ const { s, slots } = useParts$2();
2678
+ return /* @__PURE__ */ jsx(DropdownMenu$1.Portal, { children: /* @__PURE__ */ jsx(DropdownMenu$1.SubContent, {
2679
+ "data-slot": "dropdown-menu-sub-content",
2680
+ sideOffset,
2681
+ className: s.subContent({ class: [slots.subContent, className] }),
2682
+ ...props
2683
+ }) });
2684
+ }
2685
+ //#endregion
2686
+ //#region src/components/eyebrow/eyebrow.styles.ts
2687
+ const eyebrowStyles = tv({
2688
+ slots: { base: "font-mono text-caption uppercase tracking-[0.12em]" },
2689
+ variants: { tone: {
2690
+ muted: { base: "text-muted-foreground" },
2691
+ primary: { base: "text-primary" }
2692
+ } },
2693
+ defaultVariants: { tone: "muted" }
2694
+ });
2695
+ //#endregion
2696
+ //#region src/components/eyebrow/eyebrow.tsx
2697
+ /** Small uppercase label that sits above a heading. */
2698
+ function Eyebrow(inProps) {
2699
+ const [props, slots] = useComponentConfig("Eyebrow", inProps);
2700
+ const { tone, asChild, className, ...rest } = props;
2701
+ const s = eyebrowStyles({ tone });
2702
+ const Comp = asChild ? Slot.Root : "p";
2703
+ return /* @__PURE__ */ jsx(Comp, {
2704
+ "data-slot": "eyebrow",
2705
+ className: s.base({ class: [slots.base, className] }),
2706
+ ...rest
2707
+ });
2708
+ }
2709
+ //#endregion
2710
+ //#region src/components/file-upload/file-upload.styles.ts
2711
+ const fileUploadStyles = tv({ slots: {
2712
+ root: "grid gap-3",
2713
+ dropzone: [
2714
+ "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",
2715
+ themedBorder,
2716
+ transition,
2717
+ focusRing,
2718
+ "hover:border-primary/60 hover:bg-primary/4",
2719
+ "data-[dragging=true]:border-primary data-[dragging=true]:bg-primary/8",
2720
+ "disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-danger"
2721
+ ],
2722
+ icon: "flex size-10 items-center justify-center rounded-md border border-border bg-surface text-muted-foreground shadow-xs [&>svg]:size-5",
2723
+ title: "text-small font-medium text-foreground",
2724
+ highlight: "text-primary",
2725
+ hint: "text-caption text-faint-foreground",
2726
+ rejections: "grid gap-1 text-small font-medium text-danger",
2727
+ list: "grid gap-2",
2728
+ item: ["grid grid-cols-[auto_1fr_auto] items-center gap-3 rounded-md border-border bg-surface px-3 py-2.5", themedBorder],
2729
+ fileIcon: "flex size-8 items-center justify-center rounded-sm bg-muted text-muted-foreground [&>svg]:size-4",
2730
+ fileText: "grid min-w-0 gap-1",
2731
+ fileName: "truncate text-small font-medium text-foreground",
2732
+ fileMeta: "text-caption tabular-nums text-faint-foreground",
2733
+ fileError: "text-caption font-medium text-danger",
2734
+ progress: "h-1 overflow-hidden rounded-pill bg-muted",
2735
+ progressBar: "h-full rounded-pill bg-primary transition-[width] duration-(--glyph-duration-base)"
2736
+ } });
2737
+ //#endregion
2738
+ //#region src/components/file-upload/file-upload.tsx
2739
+ /** Formats bytes for people: 1 KB = 1024 bytes. */
2740
+ function formatBytes(bytes) {
2741
+ if (bytes < 1024) return `${bytes} B`;
2742
+ const units = [
2743
+ "KB",
2744
+ "MB",
2745
+ "GB",
2746
+ "TB"
2747
+ ];
2748
+ let value = bytes / 1024;
2749
+ let unit = 0;
2750
+ while (value >= 1024 && unit < units.length - 1) {
2751
+ value /= 1024;
2752
+ unit++;
2753
+ }
2754
+ return `${value >= 10 ? Math.round(value) : value.toFixed(1)} ${units[unit]}`;
2755
+ }
2756
+ /** Matches a file against an `accept` string like `"image/*,.pdf,application/zip"`. */
2757
+ function matchesAccept(file, accept) {
2758
+ if (!accept) return true;
2759
+ const name = file.name.toLowerCase();
2760
+ const type = file.type.toLowerCase();
2761
+ return accept.split(",").map((rule) => rule.trim().toLowerCase()).filter(Boolean).some((rule) => {
2762
+ if (rule.startsWith(".")) return name.endsWith(rule);
2763
+ if (rule.endsWith("/*")) return type.startsWith(rule.slice(0, -1));
2764
+ return type === rule;
2765
+ });
2766
+ }
2767
+ let counter = 0;
2768
+ const newId = () => `file-${Date.now().toString(36)}-${(counter++).toString(36)}`;
2769
+ function UploadIcon() {
2770
+ return /* @__PURE__ */ jsxs("svg", {
2771
+ viewBox: "0 0 24 24",
2772
+ fill: "none",
2773
+ stroke: "currentColor",
2774
+ strokeWidth: "2",
2775
+ strokeLinecap: "round",
2776
+ strokeLinejoin: "round",
2777
+ "aria-hidden": "true",
2778
+ 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" })]
2779
+ });
2780
+ }
2781
+ function FileIcon() {
2782
+ return /* @__PURE__ */ jsxs("svg", {
2783
+ viewBox: "0 0 24 24",
2784
+ fill: "none",
2785
+ stroke: "currentColor",
2786
+ strokeWidth: "2",
2787
+ strokeLinecap: "round",
2788
+ strokeLinejoin: "round",
2789
+ "aria-hidden": "true",
2790
+ 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" })]
2791
+ });
2792
+ }
2793
+ function XIcon$1() {
2794
+ return /* @__PURE__ */ jsx("svg", {
2795
+ viewBox: "0 0 24 24",
2796
+ fill: "none",
2797
+ stroke: "currentColor",
2798
+ strokeWidth: "2",
2799
+ strokeLinecap: "round",
2800
+ "aria-hidden": "true",
2801
+ children: /* @__PURE__ */ jsx("path", { d: "M18 6 6 18M6 6l12 12" })
2802
+ });
2803
+ }
2804
+ /**
2805
+ * Drag-and-drop or click to choose files, with type, size and count checks and a file
2806
+ * list. It does no uploading: you get `File` objects and can set `progress` and `error`
2807
+ * on each item while your own code uploads them.
2808
+ */
2809
+ function FileUpload(inProps) {
2810
+ const [props, slots] = useComponentConfig("FileUpload", useFieldControl(inProps));
2811
+ const { files: filesProp, defaultFiles = [], onFilesChange, onReject, accept, maxSize, maxFiles, multiple = true, disabled, label, hint, id, className, "aria-describedby": ariaDescribedBy, "aria-invalid": ariaInvalid } = props;
2812
+ const [files, setFiles] = useControllableState({
2813
+ value: filesProp,
2814
+ defaultValue: defaultFiles,
2815
+ onChange: onFilesChange
2816
+ });
2817
+ const [dragging, setDragging] = useState(false);
2818
+ const [rejections, setRejections] = useState([]);
2819
+ const inputRef = useRef(null);
2820
+ const hintId = useId();
2821
+ const rejectionsId = useId();
2822
+ const s = fileUploadStyles();
2823
+ const limit = multiple ? maxFiles ?? Number.POSITIVE_INFINITY : 1;
2824
+ const full = files.length >= limit;
2825
+ const addFiles = (incoming) => {
2826
+ const accepted = [];
2827
+ const rejected = [];
2828
+ let room = limit - (multiple ? files.length : 0);
2829
+ for (const file of incoming) if (!matchesAccept(file, accept)) rejected.push({
2830
+ file,
2831
+ reason: "wrong-type",
2832
+ message: `${file.name} isn't an allowed file type.`
2833
+ });
2834
+ else if (maxSize !== void 0 && file.size > maxSize) rejected.push({
2835
+ file,
2836
+ reason: "too-large",
2837
+ message: `${file.name} is too large (${formatBytes(file.size)}). The limit is ${formatBytes(maxSize)}.`
2838
+ });
2839
+ else if (room <= 0) rejected.push({
2840
+ file,
2841
+ reason: "too-many",
2842
+ message: `${file.name} wasn't added: the limit is ${limit} file${limit === 1 ? "" : "s"}.`
2843
+ });
2844
+ else {
2845
+ accepted.push({
2846
+ id: newId(),
2847
+ file
2848
+ });
2849
+ room--;
2850
+ }
2851
+ if (accepted.length > 0) setFiles(multiple ? [...files, ...accepted] : accepted);
2852
+ setRejections(rejected);
2853
+ if (rejected.length > 0) onReject?.(rejected);
2854
+ };
2855
+ const onDrop = (event) => {
2856
+ event.preventDefault();
2857
+ setDragging(false);
2858
+ if (disabled) return;
2859
+ addFiles(Array.from(event.dataTransfer.files));
2860
+ };
2861
+ const defaultHint = [
2862
+ accept ? `Accepted: ${accept.split(",").map((a) => a.trim()).join(", ")}` : null,
2863
+ maxSize !== void 0 ? `up to ${formatBytes(maxSize)} each` : null,
2864
+ multiple && maxFiles !== void 0 ? `max ${maxFiles} files` : null
2865
+ ].filter(Boolean).join(" · ");
2866
+ const describedBy = [
2867
+ ariaDescribedBy,
2868
+ hintId,
2869
+ rejections.length > 0 ? rejectionsId : void 0
2870
+ ].filter(Boolean).join(" ") || void 0;
2871
+ return /* @__PURE__ */ jsxs("div", {
2872
+ "data-slot": "file-upload",
2873
+ className: s.root({ class: [slots.root, className] }),
2874
+ children: [
2875
+ /* @__PURE__ */ jsxs("button", {
2876
+ type: "button",
2877
+ id,
2878
+ "data-dragging": dragging,
2879
+ disabled: disabled || full,
2880
+ "aria-describedby": describedBy,
2881
+ "aria-invalid": ariaInvalid,
2882
+ className: s.dropzone({ class: slots.dropzone }),
2883
+ onClick: () => inputRef.current?.click(),
2884
+ onDragEnter: (event) => {
2885
+ event.preventDefault();
2886
+ if (!disabled) setDragging(true);
2887
+ },
2888
+ onDragOver: (event) => event.preventDefault(),
2889
+ onDragLeave: (event) => {
2890
+ if (!event.currentTarget.contains(event.relatedTarget)) setDragging(false);
2891
+ },
2892
+ onDrop,
2893
+ children: [
2894
+ /* @__PURE__ */ jsx("span", {
2895
+ className: s.icon({ class: slots.icon }),
2896
+ children: /* @__PURE__ */ jsx(UploadIcon, {})
2897
+ }),
2898
+ /* @__PURE__ */ jsx("span", {
2899
+ className: s.title({ class: slots.title }),
2900
+ children: label ?? /* @__PURE__ */ jsxs(Fragment$1, { children: [
2901
+ "Drop ",
2902
+ multiple ? "files" : "a file",
2903
+ " here or",
2904
+ " ",
2905
+ /* @__PURE__ */ jsx("span", {
2906
+ className: s.highlight({ class: slots.highlight }),
2907
+ children: "browse"
2908
+ })
2909
+ ] })
2910
+ }),
2911
+ /* @__PURE__ */ jsx("span", {
2912
+ id: hintId,
2913
+ className: s.hint({ class: slots.hint }),
2914
+ children: full ? "File limit reached. Remove a file to add another." : hint ?? defaultHint
2915
+ })
2916
+ ]
2917
+ }),
2918
+ /* @__PURE__ */ jsx("input", {
2919
+ ref: inputRef,
2920
+ type: "file",
2921
+ tabIndex: -1,
2922
+ "aria-hidden": "true",
2923
+ className: "sr-only",
2924
+ accept,
2925
+ multiple,
2926
+ disabled,
2927
+ onChange: (event) => {
2928
+ addFiles(Array.from(event.target.files ?? []));
2929
+ event.target.value = "";
2930
+ }
2931
+ }),
2932
+ rejections.length > 0 && /* @__PURE__ */ jsx("ul", {
2933
+ id: rejectionsId,
2934
+ role: "alert",
2935
+ className: s.rejections({ class: slots.rejections }),
2936
+ children: rejections.map((r) => /* @__PURE__ */ jsx("li", { children: r.message }, `${r.file.name}-${r.reason}`))
2937
+ }),
2938
+ files.length > 0 && /* @__PURE__ */ jsx("ul", {
2939
+ className: s.list({ class: slots.list }),
2940
+ "aria-label": "Selected files",
2941
+ children: files.map((item) => /* @__PURE__ */ jsxs("li", {
2942
+ "data-slot": "file-upload-item",
2943
+ className: s.item({ class: slots.item }),
2944
+ children: [
2945
+ /* @__PURE__ */ jsx("span", {
2946
+ className: s.fileIcon({ class: slots.fileIcon }),
2947
+ children: /* @__PURE__ */ jsx(FileIcon, {})
2948
+ }),
2949
+ /* @__PURE__ */ jsxs("span", {
2950
+ className: s.fileText({ class: slots.fileText }),
2951
+ children: [
2952
+ /* @__PURE__ */ jsx("span", {
2953
+ className: s.fileName({ class: slots.fileName }),
2954
+ children: item.file.name
2955
+ }),
2956
+ item.error ? /* @__PURE__ */ jsx("span", {
2957
+ className: s.fileError({ class: slots.fileError }),
2958
+ children: item.error
2959
+ }) : /* @__PURE__ */ jsxs("span", {
2960
+ className: s.fileMeta({ class: slots.fileMeta }),
2961
+ children: [formatBytes(item.file.size), item.progress !== void 0 && item.progress < 100 && ` · ${Math.round(item.progress)}%`]
2962
+ }),
2963
+ item.progress !== void 0 && item.progress < 100 && !item.error && /* @__PURE__ */ jsx("span", {
2964
+ role: "progressbar",
2965
+ "aria-label": `Uploading ${item.file.name}`,
2966
+ "aria-valuemin": 0,
2967
+ "aria-valuemax": 100,
2968
+ "aria-valuenow": Math.round(item.progress),
2969
+ className: s.progress({ class: slots.progress }),
2970
+ children: /* @__PURE__ */ jsx("span", {
2971
+ className: s.progressBar({ class: slots.progressBar }),
2972
+ style: { width: `${Math.max(0, Math.min(100, item.progress))}%` }
2973
+ })
2974
+ })
2975
+ ]
2976
+ }),
2977
+ /* @__PURE__ */ jsx(IconButton, {
2978
+ size: "sm",
2979
+ icon: /* @__PURE__ */ jsx(XIcon$1, {}),
2980
+ "aria-label": `Remove ${item.file.name}`,
2981
+ disabled,
2982
+ onClick: () => {
2983
+ setFiles(files.filter((f) => f.id !== item.id));
2984
+ setRejections([]);
2985
+ }
2986
+ })
2987
+ ]
2988
+ }, item.id))
1795
2989
  })
1796
2990
  ]
1797
2991
  });
1798
2992
  }
1799
- function DropdownMenuSubContent({ sideOffset = 4, className, ...props }) {
1800
- const { s, slots } = useParts$1();
1801
- return /* @__PURE__ */ jsx(DropdownMenu$1.Portal, { children: /* @__PURE__ */ jsx(DropdownMenu$1.SubContent, {
1802
- "data-slot": "dropdown-menu-sub-content",
1803
- sideOffset,
1804
- className: s.subContent({ class: [slots.subContent, className] }),
1805
- ...props
1806
- }) });
1807
- }
1808
- //#endregion
1809
- //#region src/components/eyebrow/eyebrow.styles.ts
1810
- const eyebrowStyles = tv({
1811
- slots: { base: "font-mono text-caption uppercase tracking-[0.12em]" },
1812
- variants: { tone: {
1813
- muted: { base: "text-muted-foreground" },
1814
- primary: { base: "text-primary" }
1815
- } },
1816
- defaultVariants: { tone: "muted" }
1817
- });
1818
- //#endregion
1819
- //#region src/components/eyebrow/eyebrow.tsx
1820
- /** Small uppercase label that sits above a heading. */
1821
- function Eyebrow(inProps) {
1822
- const [props, slots] = useComponentConfig("Eyebrow", inProps);
1823
- const { tone, asChild, className, ...rest } = props;
1824
- const s = eyebrowStyles({ tone });
1825
- const Comp = asChild ? Slot.Root : "p";
1826
- return /* @__PURE__ */ jsx(Comp, {
1827
- "data-slot": "eyebrow",
1828
- className: s.base({ class: [slots.base, className] }),
1829
- ...rest
1830
- });
1831
- }
1832
2993
  //#endregion
1833
2994
  //#region src/components/grid/grid.tsx
1834
2995
  const colClasses = {
@@ -1984,6 +3145,130 @@ function Heading(inProps) {
1984
3145
  });
1985
3146
  }
1986
3147
  //#endregion
3148
+ //#region src/components/hover-card/hover-card.tsx
3149
+ const hoverCardStyles = tv({ slots: { content: [popover, "w-72 max-w-[calc(100vw-2rem)] p-4 text-small outline-none"] } });
3150
+ /**
3151
+ * A rich preview shown while hovering or focusing a link, such as a user or repository card.
3152
+ * Sighted mouse users only see it on hover; keep the same information reachable elsewhere.
3153
+ */
3154
+ const HoverCard = HoverCard$1.Root;
3155
+ const HoverCardTrigger = HoverCard$1.Trigger;
3156
+ function HoverCardContent(inProps) {
3157
+ const [props, slots] = useComponentConfig("HoverCard", inProps);
3158
+ const { sideOffset = 6, align = "center", className, ...rest } = props;
3159
+ return /* @__PURE__ */ jsx(HoverCard$1.Portal, { children: /* @__PURE__ */ jsx(HoverCard$1.Content, {
3160
+ "data-slot": "hover-card-content",
3161
+ sideOffset,
3162
+ align,
3163
+ className: hoverCardStyles().content({ class: [slots.content, className] }),
3164
+ ...rest
3165
+ }) });
3166
+ }
3167
+ //#endregion
3168
+ //#region src/components/input-otp/input-otp.styles.ts
3169
+ const inputOtpStyles = tv({
3170
+ slots: {
3171
+ root: "flex items-center gap-2 has-disabled:opacity-50",
3172
+ input: "disabled:cursor-not-allowed",
3173
+ group: "flex items-center",
3174
+ slot: [
3175
+ "relative flex items-center justify-center border-input bg-surface font-medium tabular-nums text-foreground shadow-xs",
3176
+ "border-y-(length:--glyph-border-width) border-r-(length:--glyph-border-width)",
3177
+ "first:rounded-l-md first:border-l-(length:--glyph-border-width) last:rounded-r-md",
3178
+ "data-[active=true]:z-10 data-[active=true]:border-ring data-[active=true]:ring-3 data-[active=true]:ring-ring/20",
3179
+ "aria-invalid:border-danger",
3180
+ transition
3181
+ ],
3182
+ caret: "pointer-events-none absolute inset-0 flex items-center justify-center",
3183
+ caretBar: "h-4 w-px animate-pulse bg-foreground",
3184
+ separator: "flex items-center text-faint-foreground [&>svg]:size-4"
3185
+ },
3186
+ variants: { size: {
3187
+ sm: { slot: "size-8 text-small" },
3188
+ md: { slot: "size-10 text-body" },
3189
+ lg: { slot: "size-12 text-h4" }
3190
+ } },
3191
+ defaultVariants: { size: "md" }
3192
+ });
3193
+ //#endregion
3194
+ //#region src/components/input-otp/input-otp.tsx
3195
+ const PartsContext = createContext(null);
3196
+ function useParts$1() {
3197
+ return useContext(PartsContext) ?? {
3198
+ s: inputOtpStyles(),
3199
+ slots: {},
3200
+ invalid: false
3201
+ };
3202
+ }
3203
+ /**
3204
+ * One-time code input: one box per character, paste support, and autofill from SMS on
3205
+ * mobile. Built on input-otp. Restrict characters with `pattern`, e.g. `REGEXP_ONLY_DIGITS`.
3206
+ */
3207
+ function InputOTP(inProps) {
3208
+ const [props, slots] = useComponentConfig("InputOTP", useFieldControl(inProps));
3209
+ const { length = 6, size, children, className, containerClassName, ...rest } = props;
3210
+ const s = inputOtpStyles({ size });
3211
+ const invalid = rest["aria-invalid"] === true || rest["aria-invalid"] === "true";
3212
+ return /* @__PURE__ */ jsx(PartsContext.Provider, {
3213
+ value: {
3214
+ s,
3215
+ slots,
3216
+ invalid
3217
+ },
3218
+ children: /* @__PURE__ */ jsx(OTPInput, {
3219
+ "data-slot": "input-otp",
3220
+ maxLength: length,
3221
+ autoComplete: "one-time-code",
3222
+ inputMode: "numeric",
3223
+ containerClassName: s.root({ class: [slots.root, containerClassName] }),
3224
+ className: s.input({ class: [slots.input, className] }),
3225
+ ...rest,
3226
+ children: children ?? /* @__PURE__ */ jsx(InputOTPGroup, { children: Array.from({ length }, (_, index) => /* @__PURE__ */ jsx(InputOTPSlot, { index }, index)) })
3227
+ })
3228
+ });
3229
+ }
3230
+ function InputOTPGroup({ className, ...props }) {
3231
+ const { s, slots } = useParts$1();
3232
+ return /* @__PURE__ */ jsx("div", {
3233
+ "data-slot": "input-otp-group",
3234
+ className: s.group({ class: [slots.group, className] }),
3235
+ ...props
3236
+ });
3237
+ }
3238
+ function InputOTPSlot({ index, className, ...props }) {
3239
+ const { s, slots, invalid } = useParts$1();
3240
+ const slot = useContext(OTPInputContext).slots[index];
3241
+ return /* @__PURE__ */ jsxs("div", {
3242
+ "data-slot": "input-otp-slot",
3243
+ "data-active": slot?.isActive ?? false,
3244
+ "aria-invalid": invalid || void 0,
3245
+ className: s.slot({ class: [slots.slot, className] }),
3246
+ ...props,
3247
+ children: [slot?.char ?? slot?.placeholderChar, slot?.hasFakeCaret && /* @__PURE__ */ jsx("div", {
3248
+ className: s.caret({ class: slots.caret }),
3249
+ children: /* @__PURE__ */ jsx("div", { className: s.caretBar({ class: slots.caretBar }) })
3250
+ })]
3251
+ });
3252
+ }
3253
+ function InputOTPSeparator({ className, ...props }) {
3254
+ const { s, slots } = useParts$1();
3255
+ return /* @__PURE__ */ jsx("div", {
3256
+ "data-slot": "input-otp-separator",
3257
+ "aria-hidden": "true",
3258
+ className: s.separator({ class: [slots.separator, className] }),
3259
+ ...props,
3260
+ children: /* @__PURE__ */ jsx("svg", {
3261
+ viewBox: "0 0 24 24",
3262
+ fill: "none",
3263
+ stroke: "currentColor",
3264
+ strokeWidth: "2",
3265
+ strokeLinecap: "round",
3266
+ "aria-hidden": "true",
3267
+ children: /* @__PURE__ */ jsx("path", { d: "M6 12h12" })
3268
+ })
3269
+ });
3270
+ }
3271
+ //#endregion
1987
3272
  //#region src/components/link/link.styles.ts
1988
3273
  const linkStyles = tv({
1989
3274
  slots: {
@@ -2064,6 +3349,393 @@ function Link(inProps) {
2064
3349
  });
2065
3350
  }
2066
3351
  //#endregion
3352
+ //#region src/components/modal/modal.styles.ts
3353
+ /** Modal is built from Dialog parts; these slots add Modal-specific classes on top. */
3354
+ const modalStyles = tv({ slots: {
3355
+ content: "",
3356
+ header: "",
3357
+ body: "grid gap-4",
3358
+ footer: ""
3359
+ } });
3360
+ //#endregion
3361
+ //#region src/components/modal/modal.tsx
3362
+ /**
3363
+ * The everyday modal in one component: title, description, body and footer as props.
3364
+ * For custom layouts use the Dialog parts; for yes/no decisions use `useConfirm()`.
3365
+ */
3366
+ function Modal(inProps) {
3367
+ const [props, slots] = useComponentConfig("Modal", inProps);
3368
+ const { open, defaultOpen, onOpenChange, title, description, trigger, footer, closeOnOverlayClick = true, onPointerDownOutside, className, children, ...rest } = props;
3369
+ const s = modalStyles();
3370
+ return /* @__PURE__ */ jsxs(Dialog, {
3371
+ ...open !== void 0 && { open },
3372
+ ...defaultOpen !== void 0 && { defaultOpen },
3373
+ ...onOpenChange && { onOpenChange },
3374
+ children: [trigger && /* @__PURE__ */ jsx(DialogTrigger, {
3375
+ asChild: true,
3376
+ children: trigger
3377
+ }), /* @__PURE__ */ jsxs(DialogContent, {
3378
+ "data-slot": "modal",
3379
+ className: s.content({ class: [slots.content, className] }),
3380
+ onPointerDownOutside: (event) => {
3381
+ onPointerDownOutside?.(event);
3382
+ if (!closeOnOverlayClick) event.preventDefault();
3383
+ },
3384
+ ...!description && { "aria-describedby": void 0 },
3385
+ ...rest,
3386
+ children: [
3387
+ /* @__PURE__ */ jsxs(DialogHeader, {
3388
+ className: s.header({ class: slots.header }),
3389
+ children: [/* @__PURE__ */ jsx(DialogTitle, { children: title }), description && /* @__PURE__ */ jsx(DialogDescription, { children: description })]
3390
+ }),
3391
+ children && /* @__PURE__ */ jsx(DialogBody, {
3392
+ className: s.body({ class: slots.body }),
3393
+ children
3394
+ }),
3395
+ footer && /* @__PURE__ */ jsx(DialogFooter, {
3396
+ className: s.footer({ class: slots.footer }),
3397
+ children: footer
3398
+ })
3399
+ ]
3400
+ })]
3401
+ });
3402
+ }
3403
+ /** Closes the surrounding Modal. Use with `asChild` around a button. */
3404
+ const ModalClose = DialogClose;
3405
+ //#endregion
3406
+ //#region src/components/navigation-menu/navigation-menu.styles.ts
3407
+ const topLevel = [
3408
+ "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",
3409
+ transition,
3410
+ focusRing,
3411
+ "hover:bg-muted hover:text-foreground data-[state=open]:bg-muted data-[state=open]:text-foreground",
3412
+ "data-active:text-foreground"
3413
+ ];
3414
+ const navigationMenuStyles = tv({ slots: {
3415
+ root: "relative z-10 flex max-w-max flex-1 items-center justify-center",
3416
+ list: "group flex flex-1 list-none items-center justify-center gap-1",
3417
+ item: "relative",
3418
+ trigger: topLevel,
3419
+ chevron: "size-3 text-faint-foreground transition-transform duration-(--glyph-duration-base) ease-standard group-data-[state=open]:rotate-180",
3420
+ content: "top-0 left-0 w-full p-2 animate-fade-in md:absolute md:w-auto",
3421
+ viewportWrapper: "absolute top-full left-0 flex justify-center",
3422
+ viewport: [
3423
+ "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",
3424
+ "md:w-(--radix-navigation-menu-viewport-width)",
3425
+ "transition-[width,height] duration-(--glyph-duration-base) ease-standard",
3426
+ themedBorder
3427
+ ],
3428
+ link: topLevel,
3429
+ card: [
3430
+ "flex select-none gap-3 rounded-md p-3 text-foreground no-underline outline-none",
3431
+ transition,
3432
+ focusRing,
3433
+ "hover:bg-muted focus-visible:bg-muted"
3434
+ ],
3435
+ 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",
3436
+ cardText: "grid min-w-0 gap-0.5",
3437
+ cardTitle: "text-small font-medium text-foreground",
3438
+ cardDescription: "text-small text-muted-foreground"
3439
+ } });
3440
+ //#endregion
3441
+ //#region src/components/navigation-menu/navigation-menu.tsx
3442
+ const s$2 = navigationMenuStyles();
3443
+ function useSlots$2() {
3444
+ return useComponentConfig("NavigationMenu", {})[1];
3445
+ }
3446
+ const ChevronDownIcon = ({ className }) => /* @__PURE__ */ jsx("svg", {
3447
+ xmlns: "http://www.w3.org/2000/svg",
3448
+ viewBox: "0 0 24 24",
3449
+ fill: "none",
3450
+ stroke: "currentColor",
3451
+ strokeWidth: "2",
3452
+ strokeLinecap: "round",
3453
+ strokeLinejoin: "round",
3454
+ "aria-hidden": "true",
3455
+ className,
3456
+ children: /* @__PURE__ */ jsx("path", { d: "m6 9 6 6 6-6" })
3457
+ });
3458
+ /**
3459
+ * Site navigation with dropdown panels (mega menus) for marketing headers.
3460
+ * Keyboard: Tab between items, arrows inside panels, Escape to close.
3461
+ */
3462
+ function NavigationMenu(inProps) {
3463
+ const [props, slots] = useComponentConfig("NavigationMenu", inProps);
3464
+ const { viewport = true, className, children, ...rest } = props;
3465
+ return /* @__PURE__ */ jsxs(NavigationMenu$1.Root, {
3466
+ "data-slot": "navigation-menu",
3467
+ className: s$2.root({ class: [slots.root, className] }),
3468
+ ...rest,
3469
+ children: [children, viewport && /* @__PURE__ */ jsx(NavigationMenuViewport, {})]
3470
+ });
3471
+ }
3472
+ function NavigationMenuList({ className, ...props }) {
3473
+ const slots = useSlots$2();
3474
+ return /* @__PURE__ */ jsx(NavigationMenu$1.List, {
3475
+ "data-slot": "navigation-menu-list",
3476
+ className: s$2.list({ class: [slots.list, className] }),
3477
+ ...props
3478
+ });
3479
+ }
3480
+ function NavigationMenuItem({ className, ...props }) {
3481
+ const slots = useSlots$2();
3482
+ return /* @__PURE__ */ jsx(NavigationMenu$1.Item, {
3483
+ "data-slot": "navigation-menu-item",
3484
+ className: s$2.item({ class: [slots.item, className] }),
3485
+ ...props
3486
+ });
3487
+ }
3488
+ function NavigationMenuTrigger({ className, children, ...props }) {
3489
+ const slots = useSlots$2();
3490
+ return /* @__PURE__ */ jsxs(NavigationMenu$1.Trigger, {
3491
+ "data-slot": "navigation-menu-trigger",
3492
+ className: s$2.trigger({ class: [slots.trigger, className] }),
3493
+ ...props,
3494
+ children: [children, /* @__PURE__ */ jsx(ChevronDownIcon, { className: s$2.chevron({ class: slots.chevron }) })]
3495
+ });
3496
+ }
3497
+ function NavigationMenuContent({ className, ...props }) {
3498
+ const slots = useSlots$2();
3499
+ return /* @__PURE__ */ jsx(NavigationMenu$1.Content, {
3500
+ "data-slot": "navigation-menu-content",
3501
+ className: s$2.content({ class: [slots.content, className] }),
3502
+ ...props
3503
+ });
3504
+ }
3505
+ function NavigationMenuViewport({ className, ...props }) {
3506
+ const slots = useSlots$2();
3507
+ return /* @__PURE__ */ jsx("div", {
3508
+ className: s$2.viewportWrapper({ class: slots.viewportWrapper }),
3509
+ children: /* @__PURE__ */ jsx(NavigationMenu$1.Viewport, {
3510
+ "data-slot": "navigation-menu-viewport",
3511
+ className: s$2.viewport({ class: [slots.viewport, className] }),
3512
+ ...props
3513
+ })
3514
+ });
3515
+ }
3516
+ /** A top-level link (no panel). Set `active` for the current page. */
3517
+ function NavigationMenuLink({ href, className, children, ...props }) {
3518
+ const slots = useSlots$2();
3519
+ const Link = useLinkComponent();
3520
+ const cls = s$2.link({ class: [slots.link, className] });
3521
+ if (href === void 0) return /* @__PURE__ */ jsx(NavigationMenu$1.Link, {
3522
+ "data-slot": "navigation-menu-link",
3523
+ className: cls,
3524
+ ...props,
3525
+ children
3526
+ });
3527
+ return /* @__PURE__ */ jsx(NavigationMenu$1.Link, {
3528
+ "data-slot": "navigation-menu-link",
3529
+ asChild: true,
3530
+ ...props,
3531
+ children: /* @__PURE__ */ jsx(Link, {
3532
+ href,
3533
+ className: cls,
3534
+ children
3535
+ })
3536
+ });
3537
+ }
3538
+ /** A link tile for mega-menu panels: icon, title and one line of description. */
3539
+ function NavigationMenuCard({ href, title, description, icon, className }) {
3540
+ const slots = useSlots$2();
3541
+ const Link = useLinkComponent();
3542
+ return /* @__PURE__ */ jsx(NavigationMenu$1.Link, {
3543
+ "data-slot": "navigation-menu-card",
3544
+ asChild: true,
3545
+ children: /* @__PURE__ */ jsxs(Link, {
3546
+ href,
3547
+ className: s$2.card({ class: [slots.card, className] }),
3548
+ children: [icon && /* @__PURE__ */ jsx("span", {
3549
+ className: s$2.cardIcon({ class: slots.cardIcon }),
3550
+ "aria-hidden": "true",
3551
+ children: icon
3552
+ }), /* @__PURE__ */ jsxs("span", {
3553
+ className: s$2.cardText({ class: slots.cardText }),
3554
+ children: [/* @__PURE__ */ jsx("span", {
3555
+ className: s$2.cardTitle({ class: slots.cardTitle }),
3556
+ children: title
3557
+ }), description && /* @__PURE__ */ jsx("span", {
3558
+ className: s$2.cardDescription({ class: slots.cardDescription }),
3559
+ children: description
3560
+ })]
3561
+ })]
3562
+ })
3563
+ });
3564
+ }
3565
+ //#endregion
3566
+ //#region src/components/number-input/number-input.styles.ts
3567
+ const numberInputStyles = tv({
3568
+ slots: {
3569
+ root: [
3570
+ ...fieldControl,
3571
+ "flex items-center gap-2 pl-3",
3572
+ "focus-within:border-ring focus-within:ring-3 focus-within:ring-ring/20",
3573
+ "data-invalid:focus-within:ring-danger/20",
3574
+ "has-[input:disabled]:cursor-not-allowed has-[input:disabled]:opacity-50"
3575
+ ],
3576
+ input: "h-full w-full min-w-0 bg-transparent tabular-nums text-foreground outline-none placeholder:text-faint-foreground disabled:cursor-not-allowed",
3577
+ adornment: "flex shrink-0 items-center text-faint-foreground [&>svg]:size-4",
3578
+ steppers: "flex h-full shrink-0 items-stretch border-l border-input",
3579
+ stepper: [
3580
+ "inline-flex w-8 cursor-pointer items-center justify-center text-muted-foreground hover:bg-muted hover:text-foreground",
3581
+ "disabled:pointer-events-none disabled:opacity-40 [&>svg]:size-3.5 last:rounded-r-[calc(var(--radius-md)-1px)]",
3582
+ focusRing
3583
+ ]
3584
+ },
3585
+ variants: { size: {
3586
+ sm: { root: "h-(--glyph-control-sm) text-small" },
3587
+ md: { root: "h-(--glyph-control-md) text-small" },
3588
+ lg: {
3589
+ root: "h-(--glyph-control-lg) text-body",
3590
+ stepper: "w-10"
3591
+ }
3592
+ } },
3593
+ defaultVariants: { size: "md" }
3594
+ });
3595
+ //#endregion
3596
+ //#region src/components/number-input/number-input.tsx
3597
+ function clamp(value, min, max) {
3598
+ return Math.min(max ?? Number.POSITIVE_INFINITY, Math.max(min ?? Number.NEGATIVE_INFINITY, value));
3599
+ }
3600
+ /** Parses user text leniently: keeps digits, one leading minus and the decimal point. */
3601
+ function parse(text) {
3602
+ const cleaned = text.replace(/[^\d.-]/g, "").replace(/(?!^)-/g, "");
3603
+ if (cleaned === "" || cleaned === "-" || cleaned === ".") return null;
3604
+ const n = Number(cleaned);
3605
+ return Number.isFinite(n) ? n : null;
3606
+ }
3607
+ /** Round away float noise from repeated steps (0.1 + 0.2). */
3608
+ function roundToStep(value, step) {
3609
+ const decimals = (String(step).split(".")[1] ?? "").length;
3610
+ return Number(value.toFixed(Math.min(decimals + 2, 10)));
3611
+ }
3612
+ /**
3613
+ * A number field with − / + steppers, arrow-key stepping, min/max clamping on blur, and
3614
+ * locale formatting when not focused. The value is a `number`, never a string.
3615
+ */
3616
+ function NumberInput(inProps) {
3617
+ const [props, slots] = useComponentConfig("NumberInput", useFieldControl(inProps));
3618
+ 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;
3619
+ const [value, setValue] = useControllableState({
3620
+ value: valueProp,
3621
+ defaultValue,
3622
+ onChange: onValueChange
3623
+ });
3624
+ const [draft, setDraft] = useState(null);
3625
+ const s = numberInputStyles({ size });
3626
+ const invalid = rest["aria-invalid"] === true || rest["aria-invalid"] === "true";
3627
+ const display = draft ?? (value === null || value === void 0 ? "" : formatOptions ? new Intl.NumberFormat(locale, formatOptions).format(value) : String(value));
3628
+ const commit = (next) => {
3629
+ setValue(next === null ? null : roundToStep(clamp(next, min, max), step));
3630
+ };
3631
+ const stepBy = (direction, multiplier = 1) => {
3632
+ const base = draft !== null ? parse(draft) : value;
3633
+ commit((base ?? min ?? 0) + direction * step * multiplier);
3634
+ setDraft(null);
3635
+ };
3636
+ const handleKeyDown = (event) => {
3637
+ onKeyDown?.(event);
3638
+ if (event.defaultPrevented || readOnly) return;
3639
+ const multiplier = event.shiftKey ? 10 : 1;
3640
+ if (event.key === "ArrowUp") {
3641
+ event.preventDefault();
3642
+ stepBy(1, multiplier);
3643
+ } else if (event.key === "ArrowDown") {
3644
+ event.preventDefault();
3645
+ stepBy(-1, multiplier);
3646
+ } else if (event.key === "Home" && min !== void 0) {
3647
+ event.preventDefault();
3648
+ commit(min);
3649
+ setDraft(null);
3650
+ } else if (event.key === "End" && max !== void 0) {
3651
+ event.preventDefault();
3652
+ commit(max);
3653
+ setDraft(null);
3654
+ } else if (event.key === "Enter" && draft !== null) {
3655
+ commit(parse(draft));
3656
+ setDraft(null);
3657
+ }
3658
+ };
3659
+ const atMin = value !== null && value !== void 0 && min !== void 0 && value <= min;
3660
+ const atMax = value !== null && value !== void 0 && max !== void 0 && value >= max;
3661
+ return /* @__PURE__ */ jsxs("div", {
3662
+ "data-slot": "number-input",
3663
+ "data-invalid": invalid || void 0,
3664
+ className: s.root({ class: [slots.root, className] }),
3665
+ children: [
3666
+ prefix && /* @__PURE__ */ jsx("span", {
3667
+ className: s.adornment({ class: slots.adornment }),
3668
+ children: prefix
3669
+ }),
3670
+ /* @__PURE__ */ jsx("input", {
3671
+ type: "text",
3672
+ inputMode: "decimal",
3673
+ role: "spinbutton",
3674
+ "aria-valuenow": value ?? void 0,
3675
+ "aria-valuemin": min,
3676
+ "aria-valuemax": max,
3677
+ autoComplete: "off",
3678
+ disabled,
3679
+ readOnly,
3680
+ value: display,
3681
+ className: s.input({ class: [slots.input, inputClassName] }),
3682
+ onFocus: (event) => {
3683
+ setDraft(value === null || value === void 0 ? "" : String(value));
3684
+ onFocus?.(event);
3685
+ },
3686
+ onChange: (event) => setDraft(event.target.value),
3687
+ onBlur: (event) => {
3688
+ if (draft !== null) commit(parse(draft));
3689
+ setDraft(null);
3690
+ onBlur?.(event);
3691
+ },
3692
+ onKeyDown: handleKeyDown,
3693
+ ...rest
3694
+ }),
3695
+ suffix && /* @__PURE__ */ jsx("span", {
3696
+ className: s.adornment({ class: slots.adornment }),
3697
+ children: suffix
3698
+ }),
3699
+ !hideSteppers && /* @__PURE__ */ jsxs("span", {
3700
+ className: s.steppers({ class: slots.steppers }),
3701
+ children: [/* @__PURE__ */ jsx("button", {
3702
+ type: "button",
3703
+ tabIndex: -1,
3704
+ "aria-label": "Decrease",
3705
+ disabled: disabled || readOnly || atMin,
3706
+ className: s.stepper({ class: slots.stepper }),
3707
+ onClick: () => stepBy(-1),
3708
+ children: /* @__PURE__ */ jsx("svg", {
3709
+ viewBox: "0 0 24 24",
3710
+ fill: "none",
3711
+ stroke: "currentColor",
3712
+ strokeWidth: "2",
3713
+ strokeLinecap: "round",
3714
+ "aria-hidden": "true",
3715
+ children: /* @__PURE__ */ jsx("path", { d: "M5 12h14" })
3716
+ })
3717
+ }), /* @__PURE__ */ jsx("button", {
3718
+ type: "button",
3719
+ tabIndex: -1,
3720
+ "aria-label": "Increase",
3721
+ disabled: disabled || readOnly || atMax,
3722
+ className: s.stepper({ class: slots.stepper }),
3723
+ onClick: () => stepBy(1),
3724
+ children: /* @__PURE__ */ jsx("svg", {
3725
+ viewBox: "0 0 24 24",
3726
+ fill: "none",
3727
+ stroke: "currentColor",
3728
+ strokeWidth: "2",
3729
+ strokeLinecap: "round",
3730
+ "aria-hidden": "true",
3731
+ children: /* @__PURE__ */ jsx("path", { d: "M12 5v14M5 12h14" })
3732
+ })
3733
+ })]
3734
+ })
3735
+ ]
3736
+ });
3737
+ }
3738
+ //#endregion
2067
3739
  //#region src/components/pagination/pagination.styles.ts
2068
3740
  const paginationStyles = tv({
2069
3741
  slots: {
@@ -2205,39 +3877,127 @@ function Pagination(inProps) {
2205
3877
  "aria-hidden": "true",
2206
3878
  children: "…"
2207
3879
  }, `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, {})) }),
3880
+ /* @__PURE__ */ jsx("li", { children: control(current + 1, "Next page", /* @__PURE__ */ jsx(ChevronRightIcon$2, {})) }),
2209
3881
  showEdges && /* @__PURE__ */ jsx("li", { children: control(pageCount, "Last page", /* @__PURE__ */ jsx(ChevronsRightIcon, {})) })
2210
3882
  ]
2211
3883
  })
2212
3884
  });
2213
3885
  }
2214
3886
  //#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 })
3887
+ //#region src/components/password-input/password-input.styles.ts
3888
+ const passwordInputStyles = tv({
3889
+ slots: {
3890
+ root: "grid gap-1.5",
3891
+ 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],
3892
+ meter: "flex items-center gap-2",
3893
+ bars: "grid flex-1 grid-cols-3 gap-1",
3894
+ bar: "h-1 rounded-pill bg-muted transition-colors duration-(--glyph-duration-base)",
3895
+ label: "w-14 text-right text-caption text-muted-foreground"
3896
+ },
3897
+ variants: { strength: {
3898
+ weak: { label: "text-danger" },
3899
+ fair: { label: "text-warning" },
3900
+ strong: { label: "text-success" }
3901
+ } }
3902
+ });
3903
+ //#endregion
3904
+ //#region src/components/password-input/password-input.tsx
3905
+ /**
3906
+ * A quick strength estimate from length and character variety. A hint for users,
3907
+ * not a security check: enforce real rules on the server.
3908
+ */
3909
+ function passwordStrength(password) {
3910
+ let score = 0;
3911
+ if (password.length >= 8) score++;
3912
+ if (password.length >= 12) score++;
3913
+ if (/[a-z]/.test(password) && /[A-Z]/.test(password)) score++;
3914
+ if (/\d/.test(password)) score++;
3915
+ if (/[^A-Za-z0-9]/.test(password)) score++;
3916
+ return {
3917
+ score,
3918
+ strength: score >= 4 ? "strong" : score >= 3 ? "fair" : "weak"
3919
+ };
3920
+ }
3921
+ const filled = {
3922
+ weak: 1,
3923
+ fair: 2,
3924
+ strong: 3
3925
+ };
3926
+ const barColor = {
3927
+ weak: "bg-danger",
3928
+ fair: "bg-warning",
3929
+ strong: "bg-success"
3930
+ };
3931
+ const labels = {
3932
+ weak: "Weak",
3933
+ fair: "Fair",
3934
+ strong: "Strong"
3935
+ };
3936
+ function EyeIcon({ off }) {
3937
+ return /* @__PURE__ */ jsx("svg", {
3938
+ viewBox: "0 0 24 24",
3939
+ fill: "none",
3940
+ stroke: "currentColor",
3941
+ strokeWidth: "2",
3942
+ strokeLinecap: "round",
3943
+ strokeLinejoin: "round",
3944
+ "aria-hidden": "true",
3945
+ 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", {
3946
+ cx: "12",
3947
+ cy: "12",
3948
+ r: "3"
3949
+ })] })
3950
+ });
3951
+ }
3952
+ /** A password field with a show/hide toggle and an optional strength meter. */
3953
+ function PasswordInput(inProps) {
3954
+ const [props, slots] = useComponentConfig("PasswordInput", inProps);
3955
+ const { showStrength = false, defaultVisible = false, value, defaultValue, onChange, className, ...rest } = props;
3956
+ const [visible, setVisible] = useState(defaultVisible);
3957
+ const [typed, setTyped] = useState(String(defaultValue ?? ""));
3958
+ const current = value !== void 0 ? String(value) : typed;
3959
+ const { strength } = passwordStrength(current);
3960
+ const s = passwordInputStyles({ strength });
3961
+ return /* @__PURE__ */ jsxs("div", {
3962
+ "data-slot": "password-input",
3963
+ className: s.root({ class: [slots.root, className] }),
3964
+ children: [/* @__PURE__ */ jsx(Input, {
3965
+ ...rest,
3966
+ ...value !== void 0 && { value },
3967
+ ...defaultValue !== void 0 && { defaultValue },
3968
+ type: visible ? "text" : "password",
3969
+ autoComplete: rest.autoComplete ?? "current-password",
3970
+ spellCheck: false,
3971
+ onChange: (event) => {
3972
+ setTyped(event.target.value);
3973
+ onChange?.(event);
3974
+ },
3975
+ suffix: /* @__PURE__ */ jsx("button", {
3976
+ type: "button",
3977
+ "aria-label": visible ? "Hide password" : "Show password",
3978
+ "aria-pressed": visible,
3979
+ disabled: rest.disabled,
3980
+ className: s.toggle({ class: slots.toggle }),
3981
+ onClick: () => setVisible((v) => !v),
3982
+ children: /* @__PURE__ */ jsx(EyeIcon, { off: visible })
3983
+ })
3984
+ }), showStrength && current.length > 0 && /* @__PURE__ */ jsxs("div", {
3985
+ className: s.meter({ class: slots.meter }),
3986
+ children: [/* @__PURE__ */ jsx("div", {
3987
+ className: s.bars({ class: slots.bars }),
3988
+ "aria-hidden": "true",
3989
+ children: [
3990
+ 1,
3991
+ 2,
3992
+ 3
3993
+ ].map((n) => /* @__PURE__ */ jsx("span", { className: s.bar({ class: [slots.bar, n <= filled[strength] && barColor[strength]] }) }, n))
3994
+ }), /* @__PURE__ */ jsx("span", {
3995
+ className: s.label({ class: slots.label }),
3996
+ "aria-live": "polite",
3997
+ children: labels[strength]
3998
+ })]
2239
3999
  })]
2240
- }) });
4000
+ });
2241
4001
  }
2242
4002
  //#endregion
2243
4003
  //#region src/components/progress/progress.styles.ts
@@ -2614,6 +4374,97 @@ function RadioGroupItem({ label, description, children, className, id, ...props
2614
4374
  });
2615
4375
  }
2616
4376
  //#endregion
4377
+ //#region src/components/resizable/resizable.styles.ts
4378
+ const resizableStyles = tv({ slots: {
4379
+ group: "flex h-full w-full data-[panel-group-direction=vertical]:flex-col",
4380
+ panel: "min-w-0",
4381
+ handle: [
4382
+ "relative flex w-px shrink-0 items-center justify-center bg-border outline-none",
4383
+ "transition-colors duration-(--glyph-duration-fast)",
4384
+ "after:absolute after:inset-y-0 after:left-1/2 after:w-2 after:-translate-x-1/2",
4385
+ "hover:bg-border-strong data-[resize-handle-state=drag]:bg-primary",
4386
+ "focus-visible:bg-primary focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-background",
4387
+ "data-[panel-group-direction=vertical]:h-px data-[panel-group-direction=vertical]:w-full",
4388
+ "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"
4389
+ ],
4390
+ 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"
4391
+ } });
4392
+ //#endregion
4393
+ //#region src/components/resizable/resizable.tsx
4394
+ const s$1 = resizableStyles();
4395
+ function useSlots$1() {
4396
+ return useComponentConfig("Resizable", {})[1];
4397
+ }
4398
+ /**
4399
+ * Panels separated by draggable, keyboard-accessible dividers, for editors and split views.
4400
+ * Set `direction` to "horizontal" or "vertical"; pass `autoSaveId` to remember sizes.
4401
+ */
4402
+ function ResizablePanelGroup({ className, ...props }) {
4403
+ const slots = useSlots$1();
4404
+ return /* @__PURE__ */ jsx(PanelGroup, {
4405
+ "data-slot": "resizable-group",
4406
+ className: s$1.group({ class: [slots.group, className] }),
4407
+ ...props
4408
+ });
4409
+ }
4410
+ function ResizablePanel({ className, ...props }) {
4411
+ const slots = useSlots$1();
4412
+ return /* @__PURE__ */ jsx(Panel, {
4413
+ "data-slot": "resizable-panel",
4414
+ className: s$1.panel({ class: [slots.panel, className] }),
4415
+ ...props
4416
+ });
4417
+ }
4418
+ function ResizableHandle({ withHandle, className, ...props }) {
4419
+ const slots = useSlots$1();
4420
+ return /* @__PURE__ */ jsx(PanelResizeHandle, {
4421
+ "data-slot": "resizable-handle",
4422
+ className: s$1.handle({ class: [slots.handle, className] }),
4423
+ ...props,
4424
+ children: withHandle && /* @__PURE__ */ jsx("div", {
4425
+ className: s$1.grip({ class: slots.grip }),
4426
+ "aria-hidden": "true",
4427
+ children: /* @__PURE__ */ jsxs("svg", {
4428
+ viewBox: "0 0 24 24",
4429
+ fill: "currentColor",
4430
+ "aria-hidden": "true",
4431
+ children: [
4432
+ /* @__PURE__ */ jsx("circle", {
4433
+ cx: "9",
4434
+ cy: "6",
4435
+ r: "1.5"
4436
+ }),
4437
+ /* @__PURE__ */ jsx("circle", {
4438
+ cx: "15",
4439
+ cy: "6",
4440
+ r: "1.5"
4441
+ }),
4442
+ /* @__PURE__ */ jsx("circle", {
4443
+ cx: "9",
4444
+ cy: "12",
4445
+ r: "1.5"
4446
+ }),
4447
+ /* @__PURE__ */ jsx("circle", {
4448
+ cx: "15",
4449
+ cy: "12",
4450
+ r: "1.5"
4451
+ }),
4452
+ /* @__PURE__ */ jsx("circle", {
4453
+ cx: "9",
4454
+ cy: "18",
4455
+ r: "1.5"
4456
+ }),
4457
+ /* @__PURE__ */ jsx("circle", {
4458
+ cx: "15",
4459
+ cy: "18",
4460
+ r: "1.5"
4461
+ })
4462
+ ]
4463
+ })
4464
+ })
4465
+ });
4466
+ }
4467
+ //#endregion
2617
4468
  //#region src/components/scroll-area/scroll-area.tsx
2618
4469
  const scrollAreaStyles = tv({ slots: {
2619
4470
  root: "relative overflow-hidden",
@@ -2734,7 +4585,7 @@ function SegmentedControl(inProps) {
2734
4585
  size,
2735
4586
  fullWidth
2736
4587
  });
2737
- return /* @__PURE__ */ jsx(ToggleGroup.Root, {
4588
+ return /* @__PURE__ */ jsx(ToggleGroup$1.Root, {
2738
4589
  type: "single",
2739
4590
  "data-slot": "segmented-control",
2740
4591
  ...value !== void 0 && { value },
@@ -2742,7 +4593,7 @@ function SegmentedControl(inProps) {
2742
4593
  onValueChange: (next) => next && onValueChange?.(next),
2743
4594
  className: s.root({ class: [slots.root, className] }),
2744
4595
  ...rest,
2745
- children: options.map((option) => /* @__PURE__ */ jsx(ToggleGroup.Item, {
4596
+ children: options.map((option) => /* @__PURE__ */ jsx(ToggleGroup$1.Item, {
2746
4597
  value: option.value,
2747
4598
  disabled: option.disabled,
2748
4599
  className: s.item({ class: slots.item }),
@@ -2794,7 +4645,7 @@ function Select(inProps) {
2794
4645
  className: s.trigger({ class: [slots.trigger, className] }),
2795
4646
  children: [/* @__PURE__ */ jsx(Select$1.Value, { placeholder }), /* @__PURE__ */ jsx(Select$1.Icon, {
2796
4647
  asChild: true,
2797
- children: /* @__PURE__ */ jsx(ChevronDownIcon, { className: s.icon({ class: slots.icon }) })
4648
+ children: /* @__PURE__ */ jsx(ChevronDownIcon$1, { className: s.icon({ class: slots.icon }) })
2798
4649
  })]
2799
4650
  }), /* @__PURE__ */ jsx(Select$1.Portal, { children: /* @__PURE__ */ jsx(Select$1.Content, {
2800
4651
  position: "popper",
@@ -2817,7 +4668,7 @@ function SelectItem({ className, children, ...props }) {
2817
4668
  ...props,
2818
4669
  children: [/* @__PURE__ */ jsx(Select$1.ItemText, { children }), /* @__PURE__ */ jsx(Select$1.ItemIndicator, {
2819
4670
  className: s.indicator({ class: slots.indicator }),
2820
- children: /* @__PURE__ */ jsx(CheckIcon$1, {})
4671
+ children: /* @__PURE__ */ jsx(CheckIcon$4, {})
2821
4672
  })]
2822
4673
  });
2823
4674
  }
@@ -2846,8 +4697,8 @@ function Separator(inProps) {
2846
4697
  //#region src/components/sheet/sheet.styles.ts
2847
4698
  const sheetStyles = tv({
2848
4699
  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"],
4700
+ overlay: "fixed inset-0 z-50 bg-overlay data-[state=open]:animate-fade-in data-[state=closed]:animate-fade-out",
4701
+ content: ["fixed z-50 flex flex-col gap-5 border-border bg-surface p-6 text-foreground shadow-lg outline-none"],
2851
4702
  close: [
2852
4703
  "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
4704
  transition,
@@ -2861,10 +4712,10 @@ const sheetStyles = tv({
2861
4712
  },
2862
4713
  variants: {
2863
4714
  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" }
4715
+ 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" },
4716
+ 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" },
4717
+ 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" },
4718
+ 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
4719
  },
2869
4720
  size: {
2870
4721
  sm: {},
@@ -3199,6 +5050,164 @@ function StatCard(inProps) {
3199
5050
  });
3200
5051
  }
3201
5052
  //#endregion
5053
+ //#region src/components/stepper/stepper.styles.ts
5054
+ const stepperStyles = tv({
5055
+ slots: {
5056
+ root: "flex w-full list-none p-0",
5057
+ step: "relative flex min-w-0",
5058
+ trigger: ["flex min-w-0 rounded-md text-left", focusRing],
5059
+ indicator: [
5060
+ "relative z-10 flex size-8 shrink-0 items-center justify-center rounded-pill text-small font-medium tabular-nums [&>svg]:size-4",
5061
+ themedBorder,
5062
+ transition
5063
+ ],
5064
+ connector: "absolute transition-colors duration-(--glyph-duration-base)",
5065
+ text: "grid min-w-0 gap-0.5",
5066
+ title: "text-small font-medium",
5067
+ description: "text-caption text-muted-foreground"
5068
+ },
5069
+ variants: {
5070
+ orientation: {
5071
+ horizontal: {
5072
+ root: "items-start",
5073
+ step: "flex-1 flex-col items-center text-center",
5074
+ trigger: "flex-col items-center gap-2 text-center",
5075
+ connector: "top-4 right-[calc(-50%+1.25rem)] left-[calc(50%+1.25rem)] h-px",
5076
+ text: "px-2"
5077
+ },
5078
+ vertical: {
5079
+ root: "flex-col",
5080
+ step: "gap-3 pb-7 last:pb-0",
5081
+ trigger: "items-start gap-3",
5082
+ connector: "top-9.5 bottom-1.5 left-4 w-px -translate-x-1/2",
5083
+ text: "pt-1.5"
5084
+ }
5085
+ },
5086
+ status: {
5087
+ complete: {
5088
+ indicator: "border-primary bg-primary text-primary-foreground",
5089
+ connector: "bg-primary",
5090
+ title: "text-foreground"
5091
+ },
5092
+ current: {
5093
+ indicator: "border-primary bg-surface text-primary ring-4 ring-primary/15",
5094
+ connector: "bg-border",
5095
+ title: "text-foreground"
5096
+ },
5097
+ upcoming: {
5098
+ indicator: "border-border bg-surface text-muted-foreground",
5099
+ connector: "bg-border",
5100
+ title: "text-muted-foreground"
5101
+ },
5102
+ error: {
5103
+ indicator: "border-danger bg-danger text-danger-foreground",
5104
+ connector: "bg-border",
5105
+ title: "text-danger"
5106
+ }
5107
+ },
5108
+ clickable: { true: { trigger: "cursor-pointer hover:[&_[data-slot=stepper-title]]:underline underline-offset-4" } }
5109
+ },
5110
+ defaultVariants: {
5111
+ orientation: "horizontal",
5112
+ status: "upcoming"
5113
+ }
5114
+ });
5115
+ //#endregion
5116
+ //#region src/components/stepper/stepper.tsx
5117
+ const statusText = {
5118
+ complete: "completed",
5119
+ current: "current step",
5120
+ upcoming: "not started",
5121
+ error: "needs attention"
5122
+ };
5123
+ const icon = {
5124
+ xmlns: "http://www.w3.org/2000/svg",
5125
+ viewBox: "0 0 24 24",
5126
+ fill: "none",
5127
+ stroke: "currentColor",
5128
+ strokeWidth: 2.5,
5129
+ strokeLinecap: "round",
5130
+ strokeLinejoin: "round"
5131
+ };
5132
+ const CheckIcon = () => /* @__PURE__ */ jsx("svg", {
5133
+ "aria-hidden": "true",
5134
+ ...icon,
5135
+ children: /* @__PURE__ */ jsx("path", { d: "M20 6 9 17l-5-5" })
5136
+ });
5137
+ const AlertIcon = () => /* @__PURE__ */ jsx("svg", {
5138
+ "aria-hidden": "true",
5139
+ ...icon,
5140
+ children: /* @__PURE__ */ jsx("path", { d: "M12 7v6M12 17h.01" })
5141
+ });
5142
+ function statusOf(step, index, current) {
5143
+ if (step.status) return step.status;
5144
+ if (index < current) return "complete";
5145
+ return index === current ? "current" : "upcoming";
5146
+ }
5147
+ /** Progress through a multi-step flow such as onboarding or checkout. */
5148
+ function Stepper(inProps) {
5149
+ const [props, slots] = useComponentConfig("Stepper", inProps);
5150
+ const { steps, current, orientation = "horizontal", onStepClick, className, "aria-label": ariaLabel = "Progress", ...rest } = props;
5151
+ const root = stepperStyles({ orientation });
5152
+ return /* @__PURE__ */ jsx("ol", {
5153
+ "data-slot": "stepper",
5154
+ "data-orientation": orientation,
5155
+ "aria-label": ariaLabel,
5156
+ className: root.root({ class: [slots.root, className] }),
5157
+ ...rest,
5158
+ children: steps.map((step, index) => {
5159
+ const status = statusOf(step, index, current);
5160
+ const clickable = Boolean(onStepClick) && status === "complete";
5161
+ const s = stepperStyles({
5162
+ orientation,
5163
+ status,
5164
+ clickable
5165
+ });
5166
+ const content = /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("span", {
5167
+ "data-slot": "stepper-indicator",
5168
+ className: s.indicator({ class: slots.indicator }),
5169
+ children: status === "complete" ? /* @__PURE__ */ jsx(CheckIcon, {}) : status === "error" ? /* @__PURE__ */ jsx(AlertIcon, {}) : index + 1
5170
+ }), /* @__PURE__ */ jsxs("span", {
5171
+ className: s.text({ class: slots.text }),
5172
+ children: [
5173
+ /* @__PURE__ */ jsx("span", {
5174
+ "data-slot": "stepper-title",
5175
+ className: s.title({ class: slots.title }),
5176
+ children: step.title
5177
+ }),
5178
+ step.description && /* @__PURE__ */ jsx("span", {
5179
+ className: s.description({ class: slots.description }),
5180
+ children: step.description
5181
+ }),
5182
+ /* @__PURE__ */ jsxs("span", {
5183
+ className: "sr-only",
5184
+ children: [", ", statusText[status]]
5185
+ })
5186
+ ]
5187
+ })] });
5188
+ return /* @__PURE__ */ jsxs("li", {
5189
+ "data-slot": "stepper-step",
5190
+ "data-status": status,
5191
+ "aria-current": status === "current" ? "step" : void 0,
5192
+ className: s.step({ class: slots.step }),
5193
+ children: [index < steps.length - 1 && /* @__PURE__ */ jsx("span", {
5194
+ "data-slot": "stepper-connector",
5195
+ "aria-hidden": "true",
5196
+ className: s.connector({ class: slots.connector })
5197
+ }), clickable ? /* @__PURE__ */ jsx("button", {
5198
+ type: "button",
5199
+ onClick: () => onStepClick?.(index),
5200
+ className: s.trigger({ class: slots.trigger }),
5201
+ children: content
5202
+ }) : /* @__PURE__ */ jsx("span", {
5203
+ className: s.trigger({ class: slots.trigger }),
5204
+ children: content
5205
+ })]
5206
+ }, index);
5207
+ })
5208
+ });
5209
+ }
5210
+ //#endregion
3202
5211
  //#region src/components/switch/switch.tsx
3203
5212
  const switchStyles = tv({
3204
5213
  slots: {
@@ -3305,6 +5314,170 @@ function TabsContent({ className, ...props }) {
3305
5314
  });
3306
5315
  }
3307
5316
  //#endregion
5317
+ //#region src/components/tag-input/tag-input.styles.ts
5318
+ const tagInputStyles = tv({
5319
+ slots: {
5320
+ root: "grid gap-1.5",
5321
+ frame: [
5322
+ ...fieldControl,
5323
+ "flex cursor-text flex-wrap items-center gap-1.5 px-2 py-1",
5324
+ "focus-within:border-ring focus-within:ring-3 focus-within:ring-ring/20",
5325
+ "data-invalid:focus-within:ring-danger/20",
5326
+ "has-[input:disabled]:cursor-not-allowed has-[input:disabled]:opacity-50"
5327
+ ],
5328
+ 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",
5329
+ tagLabel: "truncate",
5330
+ 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",
5331
+ input: "h-7 min-w-24 flex-1 bg-transparent px-1 text-foreground outline-none placeholder:text-faint-foreground disabled:cursor-not-allowed",
5332
+ message: "text-small font-medium text-danger"
5333
+ },
5334
+ variants: { size: {
5335
+ sm: { frame: "min-h-(--glyph-control-sm) text-small" },
5336
+ md: { frame: "min-h-(--glyph-control-md) text-small" },
5337
+ lg: { frame: "min-h-(--glyph-control-lg) text-body" }
5338
+ } },
5339
+ defaultVariants: { size: "md" }
5340
+ });
5341
+ //#endregion
5342
+ //#region src/components/tag-input/tag-input.tsx
5343
+ function XIcon() {
5344
+ return /* @__PURE__ */ jsx("svg", {
5345
+ viewBox: "0 0 24 24",
5346
+ fill: "none",
5347
+ stroke: "currentColor",
5348
+ strokeWidth: "2.5",
5349
+ strokeLinecap: "round",
5350
+ "aria-hidden": "true",
5351
+ children: /* @__PURE__ */ jsx("path", { d: "M18 6 6 18M6 6l12 12" })
5352
+ });
5353
+ }
5354
+ /**
5355
+ * Free-form multi-value input. Enter or a comma turns the text into a removable tag;
5356
+ * Backspace on an empty input removes the last one. Pasting a comma-separated list adds them all.
5357
+ */
5358
+ function TagInput(inProps) {
5359
+ const [props, slots] = useComponentConfig("TagInput", useFieldControl(inProps));
5360
+ 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;
5361
+ const [tags, setTags] = useControllableState({
5362
+ value: valueProp,
5363
+ defaultValue,
5364
+ onChange: onValueChange
5365
+ });
5366
+ const [draft, setDraft] = useState("");
5367
+ const [error, setError] = useState(null);
5368
+ const inputRef = useRef(null);
5369
+ const errorId = useId();
5370
+ const s = tagInputStyles({ size });
5371
+ const full = maxTags !== void 0 && tags.length >= maxTags;
5372
+ const invalid = Boolean(error) || ariaInvalid === true;
5373
+ const add = (raw) => {
5374
+ let next = [...tags];
5375
+ let problem = null;
5376
+ for (const candidate of raw.map((t) => t.trim()).filter(Boolean)) {
5377
+ if (maxTags !== void 0 && next.length >= maxTags) {
5378
+ problem = `You can add up to ${maxTags} tags.`;
5379
+ break;
5380
+ }
5381
+ if (!allowDuplicates && next.includes(candidate)) {
5382
+ problem = `“${candidate}” is already added.`;
5383
+ continue;
5384
+ }
5385
+ const verdict = validate?.(candidate, next) ?? true;
5386
+ if (verdict !== true) {
5387
+ problem = verdict;
5388
+ continue;
5389
+ }
5390
+ next = [...next, candidate];
5391
+ }
5392
+ if (next.length !== tags.length) setTags(next);
5393
+ setError(problem);
5394
+ return problem === null;
5395
+ };
5396
+ const commitDraft = () => {
5397
+ if (!draft.trim()) return;
5398
+ if (add([draft])) setDraft("");
5399
+ };
5400
+ const remove = (index) => {
5401
+ setTags(tags.filter((_, i) => i !== index));
5402
+ setError(null);
5403
+ inputRef.current?.focus();
5404
+ };
5405
+ const handleKeyDown = (event) => {
5406
+ if (event.key === "Enter" || separators.includes(event.key)) {
5407
+ if (event.key === "Enter" && !draft.trim()) return;
5408
+ event.preventDefault();
5409
+ commitDraft();
5410
+ } else if (event.key === "Backspace" && draft === "" && tags.length > 0) {
5411
+ event.preventDefault();
5412
+ remove(tags.length - 1);
5413
+ }
5414
+ };
5415
+ const handlePaste = (event) => {
5416
+ const text = event.clipboardData.getData("text");
5417
+ const pattern = new RegExp(`[${["\n", ...separators].map((s) => s.replace(/[-\\^\]]/g, "\\$&")).join("")}]`);
5418
+ if (!pattern.test(text)) return;
5419
+ event.preventDefault();
5420
+ add(text.split(pattern));
5421
+ };
5422
+ const describedBy = [ariaDescribedBy, error ? errorId : void 0].filter(Boolean).join(" ") || void 0;
5423
+ return /* @__PURE__ */ jsxs("div", {
5424
+ "data-slot": "tag-input",
5425
+ className: s.root({ class: [slots.root, className] }),
5426
+ children: [
5427
+ /* @__PURE__ */ jsxs("div", {
5428
+ "data-invalid": invalid || void 0,
5429
+ className: s.frame({ class: slots.frame }),
5430
+ onClick: () => inputRef.current?.focus(),
5431
+ children: [tags.map((tag, index) => /* @__PURE__ */ jsxs("span", {
5432
+ "data-slot": "tag",
5433
+ className: s.tag({ class: slots.tag }),
5434
+ children: [/* @__PURE__ */ jsx("span", {
5435
+ className: s.tagLabel({ class: slots.tagLabel }),
5436
+ children: tag
5437
+ }), !disabled && /* @__PURE__ */ jsx("button", {
5438
+ type: "button",
5439
+ "aria-label": `Remove ${tag}`,
5440
+ className: s.remove({ class: slots.remove }),
5441
+ onClick: (event) => {
5442
+ event.stopPropagation();
5443
+ remove(index);
5444
+ },
5445
+ children: /* @__PURE__ */ jsx(XIcon, {})
5446
+ })]
5447
+ }, `${tag}-${index}`)), /* @__PURE__ */ jsx("input", {
5448
+ ref: inputRef,
5449
+ id,
5450
+ value: draft,
5451
+ disabled: disabled || full,
5452
+ placeholder: full ? void 0 : tags.length === 0 ? placeholder : void 0,
5453
+ "aria-label": ariaLabel,
5454
+ "aria-describedby": describedBy,
5455
+ "aria-invalid": invalid || void 0,
5456
+ className: s.input({ class: slots.input }),
5457
+ onChange: (event) => {
5458
+ setDraft(event.target.value);
5459
+ if (error) setError(null);
5460
+ },
5461
+ onKeyDown: handleKeyDown,
5462
+ onPaste: handlePaste,
5463
+ onBlur: commitDraft
5464
+ })]
5465
+ }),
5466
+ error && /* @__PURE__ */ jsx("p", {
5467
+ id: errorId,
5468
+ role: "alert",
5469
+ className: s.message({ class: slots.message }),
5470
+ children: error
5471
+ }),
5472
+ name && tags.map((tag, index) => /* @__PURE__ */ jsx("input", {
5473
+ type: "hidden",
5474
+ name,
5475
+ value: tag
5476
+ }, `${tag}-${index}`))
5477
+ ]
5478
+ });
5479
+ }
5480
+ //#endregion
3308
5481
  //#region src/components/text/text.styles.ts
3309
5482
  const textStyles = tv({
3310
5483
  slots: { base: "" },
@@ -3373,6 +5546,87 @@ function Textarea(inProps) {
3373
5546
  });
3374
5547
  }
3375
5548
  //#endregion
5549
+ //#region src/components/timeline/timeline.styles.ts
5550
+ const timelineStyles = tv({
5551
+ slots: {
5552
+ root: "grid",
5553
+ item: "group/item relative grid grid-cols-[auto_1fr] gap-x-3",
5554
+ rail: "flex flex-col items-center",
5555
+ marker: ["z-10 flex size-6 shrink-0 items-center justify-center rounded-pill bg-surface [&>svg]:size-3.5", themedBorder],
5556
+ dot: "size-2 rounded-pill bg-current",
5557
+ connector: "my-1 w-px flex-1 bg-border group-last/item:hidden",
5558
+ content: "grid min-w-0 gap-0.5 pt-0.5 pb-6 group-last/item:pb-0",
5559
+ header: "flex flex-wrap items-baseline justify-between gap-x-3 gap-y-0.5",
5560
+ title: "text-small font-medium text-foreground",
5561
+ time: "font-mono text-caption text-faint-foreground tabular-nums",
5562
+ description: "text-small text-muted-foreground"
5563
+ },
5564
+ variants: { tone: {
5565
+ neutral: { marker: "border-border text-muted-foreground" },
5566
+ primary: { marker: "border-primary/40 text-[color-mix(in_oklab,var(--color-primary)_80%,var(--color-foreground))]" },
5567
+ info: { marker: "border-info/40 text-[color-mix(in_oklab,var(--color-info)_80%,var(--color-foreground))]" },
5568
+ success: { marker: "border-success/40 text-[color-mix(in_oklab,var(--color-success)_80%,var(--color-foreground))]" },
5569
+ warning: { marker: "border-warning/50 text-[color-mix(in_oklab,var(--color-warning)_80%,var(--color-foreground))]" },
5570
+ danger: { marker: "border-danger/40 text-[color-mix(in_oklab,var(--color-danger)_80%,var(--color-foreground))]" }
5571
+ } },
5572
+ defaultVariants: { tone: "neutral" }
5573
+ });
5574
+ //#endregion
5575
+ //#region src/components/timeline/timeline.tsx
5576
+ const TimelineContext = createContext({});
5577
+ /** A vertical list of events in order, for activity feeds, changelogs and order tracking. */
5578
+ function Timeline(inProps) {
5579
+ const [props, slots] = useComponentConfig("Timeline", inProps);
5580
+ const { items, className, children, ...rest } = props;
5581
+ const s = timelineStyles();
5582
+ return /* @__PURE__ */ jsx(TimelineContext.Provider, {
5583
+ value: slots,
5584
+ children: /* @__PURE__ */ jsx("ol", {
5585
+ "data-slot": "timeline",
5586
+ className: s.root({ class: [slots.root, className] }),
5587
+ ...rest,
5588
+ children: items ? items.map(({ id, description, ...item }, index) => /* @__PURE__ */ jsx(TimelineItem, {
5589
+ ...item,
5590
+ children: description
5591
+ }, id ?? index)) : children
5592
+ })
5593
+ });
5594
+ }
5595
+ function TimelineItem({ title, time, dateTime, icon, tone, className, children, ...props }) {
5596
+ const slots = useContext(TimelineContext);
5597
+ const s = timelineStyles({ tone });
5598
+ return /* @__PURE__ */ jsxs("li", {
5599
+ "data-slot": "timeline-item",
5600
+ "data-tone": tone ?? "neutral",
5601
+ className: s.item({ class: [slots.item, className] }),
5602
+ ...props,
5603
+ children: [/* @__PURE__ */ jsxs("div", {
5604
+ className: s.rail({ class: slots.rail }),
5605
+ "aria-hidden": "true",
5606
+ children: [/* @__PURE__ */ jsx("span", {
5607
+ className: s.marker({ class: slots.marker }),
5608
+ children: icon ?? /* @__PURE__ */ jsx("span", { className: s.dot({ class: slots.dot }) })
5609
+ }), /* @__PURE__ */ jsx("span", { className: s.connector({ class: slots.connector }) })]
5610
+ }), /* @__PURE__ */ jsxs("div", {
5611
+ className: s.content({ class: slots.content }),
5612
+ children: [/* @__PURE__ */ jsxs("div", {
5613
+ className: s.header({ class: slots.header }),
5614
+ children: [/* @__PURE__ */ jsx("p", {
5615
+ className: s.title({ class: slots.title }),
5616
+ children: title
5617
+ }), time && /* @__PURE__ */ jsx("time", {
5618
+ dateTime,
5619
+ className: s.time({ class: slots.time }),
5620
+ children: time
5621
+ })]
5622
+ }), children && /* @__PURE__ */ jsx("div", {
5623
+ className: s.description({ class: slots.description }),
5624
+ children
5625
+ })]
5626
+ })]
5627
+ });
5628
+ }
5629
+ //#endregion
3376
5630
  //#region src/components/toast/toast.tsx
3377
5631
  const toastStyles = tv({ slots: {
3378
5632
  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 +5695,87 @@ function Toaster(inProps) {
3441
5695
  });
3442
5696
  }
3443
5697
  //#endregion
5698
+ //#region src/components/toggle/toggle.styles.ts
5699
+ const toggleStyles = tv({
5700
+ slots: {
5701
+ base: [
5702
+ "inline-flex shrink-0 cursor-pointer select-none items-center justify-center gap-2 whitespace-nowrap rounded-md font-medium text-muted-foreground",
5703
+ transition,
5704
+ focusRing,
5705
+ "hover:bg-muted hover:text-foreground",
5706
+ "data-[state=on]:bg-muted data-[state=on]:text-foreground",
5707
+ "disabled:pointer-events-none disabled:opacity-50 [&_svg]:size-4 [&_svg]:shrink-0"
5708
+ ],
5709
+ group: "inline-flex items-center gap-1"
5710
+ },
5711
+ variants: {
5712
+ variant: {
5713
+ default: { base: "bg-transparent" },
5714
+ outline: { base: ["border-border bg-transparent shadow-xs hover:border-border-strong", themedBorder] }
5715
+ },
5716
+ size: {
5717
+ sm: { base: "h-(--glyph-control-sm) min-w-(--glyph-control-sm) px-2 text-caption" },
5718
+ md: { base: "h-(--glyph-control-md) min-w-(--glyph-control-md) px-2.5 text-small" },
5719
+ lg: { base: "h-(--glyph-control-lg) min-w-(--glyph-control-lg) px-3 text-small" }
5720
+ }
5721
+ },
5722
+ defaultVariants: {
5723
+ variant: "default",
5724
+ size: "md"
5725
+ }
5726
+ });
5727
+ //#endregion
5728
+ //#region src/components/toggle/toggle.tsx
5729
+ /**
5730
+ * A two-state button, e.g. Bold in a toolbar. Use Switch for settings that take effect
5731
+ * immediately, and Checkbox inside forms.
5732
+ */
5733
+ function Toggle(inProps) {
5734
+ const [props, slots] = useComponentConfig("Toggle", inProps);
5735
+ const { variant, size, className, ...rest } = props;
5736
+ return /* @__PURE__ */ jsx(Toggle$1.Root, {
5737
+ "data-slot": "toggle",
5738
+ className: toggleStyles({
5739
+ variant,
5740
+ size
5741
+ }).base({ class: [slots.base, className] }),
5742
+ ...rest
5743
+ });
5744
+ }
5745
+ const ToggleGroupContext = createContext({});
5746
+ /**
5747
+ * A set of toggles. `type="single"` behaves like a radio group (text alignment),
5748
+ * `type="multiple"` like checkboxes (bold, italic, underline). Arrow keys move between items.
5749
+ */
5750
+ function ToggleGroup(inProps) {
5751
+ const [props, slots] = useComponentConfig("Toggle", inProps);
5752
+ const { variant, size, className, ...rest } = props;
5753
+ return /* @__PURE__ */ jsx(ToggleGroupContext.Provider, {
5754
+ value: {
5755
+ variant,
5756
+ size
5757
+ },
5758
+ children: /* @__PURE__ */ jsx(ToggleGroup$1.Root, {
5759
+ "data-slot": "toggle-group",
5760
+ className: toggleStyles().group({ class: [slots.group, className] }),
5761
+ ...rest
5762
+ })
5763
+ });
5764
+ }
5765
+ function ToggleGroupItem({ variant, size, className, ...props }) {
5766
+ const group = useContext(ToggleGroupContext);
5767
+ const [, slots] = useComponentConfig("Toggle", {});
5768
+ const s = toggleStyles({
5769
+ variant: variant ?? group.variant,
5770
+ size: size ?? group.size
5771
+ });
5772
+ return /* @__PURE__ */ jsx(ToggleGroup$1.Item, {
5773
+ "data-slot": "toggle-group-item",
5774
+ className: s.base({ class: [slots.base, className] }),
5775
+ ...props
5776
+ });
5777
+ }
5778
+ //#endregion
3444
5779
  //#region src/components/tooltip/tooltip.tsx
3445
5780
  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
5781
  /** A short hint on hover or focus. The child must be focusable (a button or link). */
@@ -3463,6 +5798,231 @@ function Tooltip(inProps) {
3463
5798
  });
3464
5799
  }
3465
5800
  //#endregion
5801
+ //#region src/components/tree-view/tree-view.styles.ts
5802
+ const treeViewStyles = tv({
5803
+ slots: {
5804
+ root: "grid gap-px text-small",
5805
+ item: [
5806
+ "outline-none",
5807
+ "focus-visible:[&>[data-slot=tree-row]]:ring-2 focus-visible:[&>[data-slot=tree-row]]:ring-ring",
5808
+ "aria-selected:[&>[data-slot=tree-row]]:bg-muted aria-selected:[&>[data-slot=tree-row]]:text-foreground aria-selected:[&>[data-slot=tree-row]]:font-medium",
5809
+ "aria-disabled:[&>[data-slot=tree-row]]:pointer-events-none aria-disabled:[&>[data-slot=tree-row]]:opacity-50"
5810
+ ],
5811
+ row: [
5812
+ "group/row flex h-8 cursor-pointer select-none items-center gap-1.5 rounded-sm pr-2 text-muted-foreground",
5813
+ transition,
5814
+ "hover:bg-muted hover:text-foreground"
5815
+ ],
5816
+ chevron: "size-4 shrink-0 text-faint-foreground transition-transform duration-(--glyph-duration-fast) ease-standard group-data-[state=open]/row:rotate-90",
5817
+ spacer: "size-4 shrink-0",
5818
+ icon: "flex size-4 shrink-0 items-center justify-center text-faint-foreground [&>svg]:size-4",
5819
+ label: "min-w-0 flex-1 truncate",
5820
+ group: "grid gap-px"
5821
+ },
5822
+ variants: { size: {
5823
+ sm: { row: "h-7 text-caption" },
5824
+ md: {}
5825
+ } },
5826
+ defaultVariants: { size: "md" }
5827
+ });
5828
+ //#endregion
5829
+ //#region src/components/tree-view/tree-view.tsx
5830
+ function flattenVisible(nodes, expanded) {
5831
+ const out = [];
5832
+ const walk = (list, level, parentId) => {
5833
+ for (const node of list) {
5834
+ out.push({
5835
+ node,
5836
+ level,
5837
+ parentId
5838
+ });
5839
+ if (node.children?.length && expanded.has(node.id)) walk(node.children, level + 1, node.id);
5840
+ }
5841
+ };
5842
+ walk(nodes, 1, null);
5843
+ return out;
5844
+ }
5845
+ function textOf(node) {
5846
+ return (node.textValue ?? (typeof node.label === "string" ? node.label : "")).toLowerCase();
5847
+ }
5848
+ const NO_IDS = [];
5849
+ /**
5850
+ * An accessible tree for file browsers and nested navigation. Arrow keys move and
5851
+ * expand/collapse, Home/End jump, typing a letter finds the next match, Enter or Space selects.
5852
+ */
5853
+ function TreeView(inProps) {
5854
+ const [props, slots] = useComponentConfig("TreeView", inProps);
5855
+ const { nodes, expanded: expandedProp, defaultExpanded = NO_IDS, onExpandedChange, selected: selectedProp, defaultSelected = null, onSelect, size, className, ...rest } = props;
5856
+ const [expandedList, setExpandedList] = useControllableState({
5857
+ value: expandedProp,
5858
+ defaultValue: defaultExpanded,
5859
+ onChange: onExpandedChange
5860
+ });
5861
+ const [selected, setSelected] = useControllableState({
5862
+ value: selectedProp,
5863
+ defaultValue: defaultSelected
5864
+ });
5865
+ const expanded = useMemo(() => new Set(expandedList), [expandedList]);
5866
+ const visible = useMemo(() => flattenVisible(nodes, expanded), [nodes, expanded]);
5867
+ const [focusedId, setFocusedId] = useState(null);
5868
+ const refs = useRef(/* @__PURE__ */ new Map());
5869
+ const baseId = useId();
5870
+ const tabbableId = focusedId && visible.some((v) => v.node.id === focusedId) && focusedId || selected && visible.some((v) => v.node.id === selected) && selected || visible[0]?.node.id;
5871
+ const focus = useCallback((id) => {
5872
+ if (!id) return;
5873
+ setFocusedId(id);
5874
+ refs.current.get(id)?.focus();
5875
+ }, []);
5876
+ const toggle = useCallback((id, open) => {
5877
+ const isOpen = expanded.has(id);
5878
+ const next = open ?? !isOpen;
5879
+ if (next === isOpen) return;
5880
+ setExpandedList(next ? [...expandedList, id] : expandedList.filter((x) => x !== id));
5881
+ }, [
5882
+ expanded,
5883
+ expandedList,
5884
+ setExpandedList
5885
+ ]);
5886
+ const select = useCallback((node) => {
5887
+ if (node.disabled) return;
5888
+ setSelected(node.id);
5889
+ onSelect?.(node.id, node);
5890
+ }, [onSelect, setSelected]);
5891
+ const onKeyDown = (event) => {
5892
+ const index = visible.findIndex((v) => v.node.id === tabbableId);
5893
+ const current = visible[index];
5894
+ if (!current) return;
5895
+ const { node } = current;
5896
+ const hasChildren = Boolean(node.children?.length);
5897
+ const isOpen = expanded.has(node.id);
5898
+ let handled = true;
5899
+ switch (event.key) {
5900
+ case "ArrowDown":
5901
+ focus(visible[index + 1]?.node.id);
5902
+ break;
5903
+ case "ArrowUp":
5904
+ focus(visible[index - 1]?.node.id);
5905
+ break;
5906
+ case "ArrowRight":
5907
+ if (hasChildren && !isOpen) toggle(node.id, true);
5908
+ else if (hasChildren) focus(node.children?.[0]?.id);
5909
+ break;
5910
+ case "ArrowLeft":
5911
+ if (hasChildren && isOpen) toggle(node.id, false);
5912
+ else if (current.parentId) focus(current.parentId);
5913
+ break;
5914
+ case "Home":
5915
+ focus(visible[0]?.node.id);
5916
+ break;
5917
+ case "End":
5918
+ focus(visible.at(-1)?.node.id);
5919
+ break;
5920
+ case "Enter":
5921
+ case " ":
5922
+ select(node);
5923
+ break;
5924
+ default:
5925
+ handled = false;
5926
+ if (event.key.length === 1 && /\S/.test(event.key) && !event.metaKey && !event.ctrlKey) {
5927
+ const char = event.key.toLowerCase();
5928
+ const match = [...visible.slice(index + 1), ...visible.slice(0, index + 1)].find((v) => textOf(v.node).startsWith(char));
5929
+ if (match) {
5930
+ focus(match.node.id);
5931
+ handled = true;
5932
+ }
5933
+ }
5934
+ }
5935
+ if (handled) event.preventDefault();
5936
+ };
5937
+ const s = treeViewStyles({ size });
5938
+ /** Clicks bubble from nested items; only handle the item whose own row was clicked. */
5939
+ const onItemClick = (event, node, hasChildren) => {
5940
+ if (event.target.closest("[data-slot=tree-row]")?.parentElement !== event.currentTarget) return;
5941
+ focus(node.id);
5942
+ if (hasChildren) toggle(node.id);
5943
+ select(node);
5944
+ };
5945
+ const renderNodes = (list, level) => list.map((node, i) => {
5946
+ const hasChildren = Boolean(node.children?.length);
5947
+ const isOpen = hasChildren && expanded.has(node.id);
5948
+ return /* @__PURE__ */ jsxs("div", {
5949
+ ref: (el) => {
5950
+ if (el) refs.current.set(node.id, el);
5951
+ else refs.current.delete(node.id);
5952
+ },
5953
+ role: "treeitem",
5954
+ "data-slot": "tree-item",
5955
+ "aria-labelledby": `${baseId}-${node.id}`,
5956
+ "aria-level": level,
5957
+ "aria-setsize": list.length,
5958
+ "aria-posinset": i + 1,
5959
+ "aria-expanded": hasChildren ? isOpen : void 0,
5960
+ "aria-selected": selected === node.id,
5961
+ "aria-disabled": node.disabled || void 0,
5962
+ tabIndex: node.id === tabbableId ? 0 : -1,
5963
+ onFocus: (event) => {
5964
+ if (event.target === event.currentTarget) setFocusedId(node.id);
5965
+ },
5966
+ onClick: (event) => onItemClick(event, node, hasChildren),
5967
+ className: s.item({ class: slots.item }),
5968
+ children: [/* @__PURE__ */ jsxs("div", {
5969
+ "data-slot": "tree-row",
5970
+ "data-state": isOpen ? "open" : "closed",
5971
+ className: s.row({ class: slots.row }),
5972
+ style: { paddingInlineStart: `calc(${level - 1} * 1rem + 0.25rem)` },
5973
+ children: [
5974
+ hasChildren ? /* @__PURE__ */ jsx("svg", {
5975
+ "data-slot": "tree-chevron",
5976
+ viewBox: "0 0 24 24",
5977
+ fill: "none",
5978
+ stroke: "currentColor",
5979
+ strokeWidth: "2",
5980
+ strokeLinecap: "round",
5981
+ strokeLinejoin: "round",
5982
+ "aria-hidden": "true",
5983
+ className: s.chevron({ class: slots.chevron }),
5984
+ children: /* @__PURE__ */ jsx("path", { d: "m9 18 6-6-6-6" })
5985
+ }) : /* @__PURE__ */ jsx("span", { className: s.spacer({ class: slots.spacer }) }),
5986
+ node.icon && /* @__PURE__ */ jsx("span", {
5987
+ className: s.icon({ class: slots.icon }),
5988
+ "aria-hidden": "true",
5989
+ children: node.icon
5990
+ }),
5991
+ /* @__PURE__ */ jsx("span", {
5992
+ id: `${baseId}-${node.id}`,
5993
+ className: s.label({ class: slots.label }),
5994
+ children: node.label
5995
+ })
5996
+ ]
5997
+ }), isOpen && /* @__PURE__ */ jsx("div", {
5998
+ role: "group",
5999
+ className: s.group({ class: slots.group }),
6000
+ children: renderNodes(node.children ?? [], level + 1)
6001
+ })]
6002
+ }, node.id);
6003
+ });
6004
+ return /* @__PURE__ */ jsx("div", {
6005
+ role: "tree",
6006
+ "data-slot": "tree-view",
6007
+ onKeyDown,
6008
+ className: s.root({ class: [slots.root, className] }),
6009
+ ...rest,
6010
+ children: renderNodes(nodes, 1)
6011
+ });
6012
+ }
6013
+ //#endregion
6014
+ //#region src/components/visually-hidden/visually-hidden.tsx
6015
+ /**
6016
+ * Hides content visually while keeping it available to screen readers, e.g. a label for an
6017
+ * icon-only control or extra context in a table cell.
6018
+ */
6019
+ function VisuallyHidden(props) {
6020
+ return /* @__PURE__ */ jsx(VisuallyHidden$1.Root, {
6021
+ "data-slot": "visually-hidden",
6022
+ ...props
6023
+ });
6024
+ }
6025
+ //#endregion
3466
6026
  //#region src/hooks/use-media-query.ts
3467
6027
  /** Subscribes to a CSS media query. Returns `fallback` during SSR. */
3468
6028
  function useMediaQuery(query, fallback = false) {
@@ -3853,7 +6413,7 @@ function Navbar(inProps) {
3853
6413
  }), /* @__PURE__ */ jsx(Dialog$1.Close, {
3854
6414
  asChild: true,
3855
6415
  children: /* @__PURE__ */ jsx(IconButton, {
3856
- icon: /* @__PURE__ */ jsx(XIcon, {}),
6416
+ icon: /* @__PURE__ */ jsx(XIcon$2, {}),
3857
6417
  "aria-label": "Close menu"
3858
6418
  })
3859
6419
  })]
@@ -4132,13 +6692,6 @@ function GlyphProvider({ children, theme = glyph, defaultMode, storageKey, linkC
4132
6692
  });
4133
6693
  }
4134
6694
  //#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
6695
  //#region src/provider/theme-scope.tsx
4143
6696
  /** Renders a subtree with a different theme, e.g. to compare themes side by side. */
4144
6697
  function ThemeScope({ theme, mode, asChild, children, ...props }) {
@@ -4163,4 +6716,4 @@ function ThemeScope({ theme, mode, asChild, children, ...props }) {
4163
6716
  });
4164
6717
  }
4165
6718
  //#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 };
6719
+ 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, useLinkComponent, useMediaQuery, useScrolled };