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