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