@glyphui/ui 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/data-table.js +2 -2
- package/dist/{field-DXZD0l8w.js → field-CCecIzdq.js} +1 -1
- package/dist/{field-context-B8cYheXz.js → field-context-B6WOcK5m.js} +99 -99
- package/dist/form.js +2 -2
- package/dist/index.d.ts +2743 -93
- package/dist/index.js +2748 -111
- package/dist/{states-BxPjCUxz.js → states-Rp8wZ_jH.js} +1 -1
- package/package.json +4 -2
- package/src/components/accordion/accordion.styles.ts +41 -0
- package/src/components/accordion/accordion.tsx +86 -0
- package/src/components/accordion/index.ts +8 -0
- package/src/components/alert/alert-icons.tsx +66 -0
- package/src/components/alert/alert.styles.ts +57 -0
- package/src/components/alert/alert.tsx +86 -0
- package/src/components/alert/index.ts +2 -0
- package/src/components/alert-dialog/alert-dialog.styles.ts +24 -0
- package/src/components/alert-dialog/alert-dialog.tsx +118 -0
- package/src/components/alert-dialog/confirm.tsx +111 -0
- package/src/components/alert-dialog/index.ts +15 -0
- package/src/components/aspect-ratio/aspect-ratio.tsx +40 -0
- package/src/components/aspect-ratio/index.ts +1 -0
- package/src/components/badge/badge.styles.ts +1 -1
- package/src/components/banner/banner.styles.ts +40 -0
- package/src/components/banner/banner.tsx +101 -0
- package/src/components/banner/index.ts +2 -0
- package/src/components/blockquote/blockquote.tsx +59 -0
- package/src/components/blockquote/index.ts +1 -0
- package/src/components/breadcrumb/breadcrumb.styles.ts +20 -0
- package/src/components/breadcrumb/breadcrumb.tsx +135 -0
- package/src/components/breadcrumb/index.ts +12 -0
- package/src/components/button/button.tsx +11 -8
- package/src/components/code/code.styles.ts +33 -0
- package/src/components/code/code.tsx +96 -0
- package/src/components/code/index.ts +2 -0
- package/src/components/combobox/combobox.styles.ts +50 -0
- package/src/components/combobox/combobox.tsx +203 -0
- package/src/components/combobox/index.ts +2 -0
- package/src/components/command-menu/command-menu.styles.ts +41 -0
- package/src/components/command-menu/command-menu.tsx +217 -0
- package/src/components/command-menu/index.ts +14 -0
- package/src/components/description-list/description-list.styles.ts +31 -0
- package/src/components/description-list/description-list.tsx +56 -0
- package/src/components/description-list/index.ts +7 -0
- package/src/components/dialog/close-icon.tsx +22 -0
- package/src/components/dialog/dialog.styles.ts +41 -0
- package/src/components/dialog/dialog.tsx +111 -0
- package/src/components/dialog/index.ts +13 -0
- package/src/components/dropdown-menu/dropdown-menu.styles.ts +45 -0
- package/src/components/dropdown-menu/dropdown-menu.tsx +230 -0
- package/src/components/dropdown-menu/index.ts +19 -0
- package/src/components/grid/grid.tsx +144 -0
- package/src/components/grid/index.ts +1 -0
- package/src/components/link/index.ts +2 -0
- package/src/components/link/link.styles.ts +39 -0
- package/src/components/link/link.tsx +62 -0
- package/src/components/pagination/index.ts +3 -0
- package/src/components/pagination/pagination-range.ts +35 -0
- package/src/components/pagination/pagination.styles.ts +41 -0
- package/src/components/pagination/pagination.tsx +130 -0
- package/src/components/popover/index.ts +9 -0
- package/src/components/popover/popover.tsx +66 -0
- package/src/components/progress/index.ts +7 -0
- package/src/components/progress/progress.styles.ts +68 -0
- package/src/components/progress/progress.tsx +158 -0
- package/src/components/prose/index.ts +1 -0
- package/src/components/prose/prose.tsx +82 -0
- package/src/components/radio-group/index.ts +7 -0
- package/src/components/radio-group/radio-group.styles.ts +64 -0
- package/src/components/radio-group/radio-group.tsx +128 -0
- package/src/components/scroll-area/index.ts +1 -0
- package/src/components/scroll-area/scroll-area.tsx +68 -0
- package/src/components/sheet/index.ts +13 -0
- package/src/components/sheet/sheet.styles.ts +60 -0
- package/src/components/sheet/sheet.tsx +108 -0
- package/src/components/slider/index.ts +2 -0
- package/src/components/slider/slider.styles.ts +32 -0
- package/src/components/slider/slider.tsx +131 -0
- package/src/components/stat-card/index.ts +2 -0
- package/src/components/stat-card/stat-card.styles.ts +24 -0
- package/src/components/stat-card/stat-card.tsx +108 -0
- package/src/components/toast/index.ts +1 -0
- package/src/components/toast/toast.tsx +91 -0
- package/src/index.ts +25 -0
- package/src/provider/glyph-provider.tsx +16 -2
package/dist/index.js
CHANGED
|
@@ -1,13 +1,479 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { A as useGlyph, C as
|
|
3
|
-
import { _ as inputStyles, a as Table, c as TableCell, d as TableRow, f as tableStyles, g as fieldControl, h as Input, i as stateStyles, l as TableHead, m as skeletonStyles, n as ErrorState, o as TableBody, p as Skeleton, r as LoadingState, s as TableCaption, t as EmptyState, u as TableHeader, v as Checkbox, y as checkboxStyles } from "./states-
|
|
4
|
-
import { i as labelStyles, n as fieldStyles, r as Label, t as Field } from "./field-
|
|
2
|
+
import { A as useGlyph, C as MenuIcon, D as XIcon, E as SearchIcon, O as useComponentConfig, T as PanelLeftIcon, _ as CheckIcon$1, a as buttonStyles, b as ChevronRightIcon$1, c as tv, d as popover, f as themedBorder, i as IconButton, j as useLinkComponent, k as GlyphContext, l as twMergeConfig, n as useFieldControl, o as Spinner, p as transition, r as Button, s as spinnerStyles, t as FieldContext, u as focusRing, v as ChevronDownIcon, x as ChevronsUpDownIcon, y as ChevronLeftIcon } from "./field-context-B6WOcK5m.js";
|
|
3
|
+
import { _ as inputStyles, a as Table, c as TableCell, d as TableRow, f as tableStyles, g as fieldControl, h as Input, i as stateStyles, l as TableHead, m as skeletonStyles, n as ErrorState, o as TableBody, p as Skeleton, r as LoadingState, s as TableCaption, t as EmptyState, u as TableHeader, v as Checkbox, y as checkboxStyles } from "./states-Rp8wZ_jH.js";
|
|
4
|
+
import { i as labelStyles, n as fieldStyles, r as Label, t as Field } from "./field-CCecIzdq.js";
|
|
5
5
|
import { defineTheme, defineTheme as defineTheme$1, presets as presets$1, scopeSelector, themeToCss, themeToCss as themeToCss$1, tokenVar } from "@glyphui/tokens";
|
|
6
|
-
import { Avatar as Avatar$1, Dialog, Select as Select$1, Separator as Separator$1, Slot, Switch as Switch$1, Tabs as Tabs$1, ToggleGroup, Tooltip as Tooltip$1 } from "radix-ui";
|
|
7
|
-
import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
|
|
6
|
+
import { Accordion as Accordion$1, AlertDialog as AlertDialog$1, AspectRatio as AspectRatio$1, Avatar as Avatar$1, Dialog as Dialog$1, DropdownMenu as DropdownMenu$1, Popover as Popover$1, Progress as Progress$1, RadioGroup as RadioGroup$1, ScrollArea as ScrollArea$1, Select as Select$1, Separator as Separator$1, Slider as Slider$1, Slot, Switch as Switch$1, Tabs as Tabs$1, ToggleGroup, Tooltip as Tooltip$1 } from "radix-ui";
|
|
7
|
+
import { createContext, useCallback, useContext, useEffect, useId, useMemo, useRef, useState, useSyncExternalStore } from "react";
|
|
8
8
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
9
|
+
import { Command as Command$1 } from "cmdk";
|
|
10
|
+
import { Toaster as Toaster$1, toast } from "sonner";
|
|
9
11
|
import { clsx } from "clsx";
|
|
10
12
|
import { extendTailwindMerge } from "tailwind-merge";
|
|
13
|
+
//#region src/components/accordion/accordion.styles.ts
|
|
14
|
+
const accordionStyles = tv({
|
|
15
|
+
slots: {
|
|
16
|
+
root: "w-full",
|
|
17
|
+
item: "",
|
|
18
|
+
header: "flex",
|
|
19
|
+
trigger: [
|
|
20
|
+
"group flex flex-1 cursor-pointer items-center justify-between gap-4 rounded-xs py-4 text-left text-body font-medium text-foreground",
|
|
21
|
+
transition,
|
|
22
|
+
focusRing,
|
|
23
|
+
"hover:text-foreground/80 disabled:cursor-not-allowed disabled:opacity-50"
|
|
24
|
+
],
|
|
25
|
+
chevron: "size-4 shrink-0 text-faint-foreground transition-transform duration-(--glyph-duration-base) ease-standard group-data-[state=open]:rotate-180",
|
|
26
|
+
content: "overflow-hidden text-small text-muted-foreground",
|
|
27
|
+
contentInner: "pb-4 transition-[opacity,translate] duration-(--glyph-duration-base) ease-standard starting:-translate-y-1 starting:opacity-0"
|
|
28
|
+
},
|
|
29
|
+
variants: { variant: {
|
|
30
|
+
default: { item: "border-b border-border last:border-b-0" },
|
|
31
|
+
separated: {
|
|
32
|
+
root: "grid gap-2",
|
|
33
|
+
item: ["rounded-lg border-border bg-surface px-4 shadow-xs", themedBorder]
|
|
34
|
+
}
|
|
35
|
+
} },
|
|
36
|
+
defaultVariants: { variant: "default" }
|
|
37
|
+
});
|
|
38
|
+
//#endregion
|
|
39
|
+
//#region src/components/accordion/accordion.tsx
|
|
40
|
+
const AccordionContext = createContext(null);
|
|
41
|
+
function useParts$4() {
|
|
42
|
+
return useContext(AccordionContext) ?? {
|
|
43
|
+
s: accordionStyles(),
|
|
44
|
+
slots: {}
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Stacked sections that expand one at a time (`type="single"`, collapsible) or
|
|
49
|
+
* independently (`type="multiple"`). Good for FAQs and dense settings.
|
|
50
|
+
*/
|
|
51
|
+
function Accordion(inProps) {
|
|
52
|
+
const [props, slots] = useComponentConfig("Accordion", inProps);
|
|
53
|
+
const { variant, className, ...rest } = props;
|
|
54
|
+
const s = accordionStyles({ variant });
|
|
55
|
+
return /* @__PURE__ */ jsx(AccordionContext.Provider, {
|
|
56
|
+
value: {
|
|
57
|
+
s,
|
|
58
|
+
slots
|
|
59
|
+
},
|
|
60
|
+
children: /* @__PURE__ */ jsx(Accordion$1.Root, {
|
|
61
|
+
"data-slot": "accordion",
|
|
62
|
+
className: s.root({ class: [slots.root, className] }),
|
|
63
|
+
...rest
|
|
64
|
+
})
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
function AccordionItem({ className, ...props }) {
|
|
68
|
+
const { s, slots } = useParts$4();
|
|
69
|
+
return /* @__PURE__ */ jsx(Accordion$1.Item, {
|
|
70
|
+
"data-slot": "accordion-item",
|
|
71
|
+
className: s.item({ class: [slots.item, className] }),
|
|
72
|
+
...props
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
function AccordionTrigger({ className, children, ...props }) {
|
|
76
|
+
const { s, slots } = useParts$4();
|
|
77
|
+
return /* @__PURE__ */ jsx(Accordion$1.Header, {
|
|
78
|
+
className: s.header({ class: slots.header }),
|
|
79
|
+
children: /* @__PURE__ */ jsxs(Accordion$1.Trigger, {
|
|
80
|
+
"data-slot": "accordion-trigger",
|
|
81
|
+
className: s.trigger({ class: [slots.trigger, className] }),
|
|
82
|
+
...props,
|
|
83
|
+
children: [children, /* @__PURE__ */ jsx(ChevronDownIcon, { className: s.chevron({ class: slots.chevron }) })]
|
|
84
|
+
})
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
function AccordionContent({ className, children, ...props }) {
|
|
88
|
+
const { s, slots } = useParts$4();
|
|
89
|
+
return /* @__PURE__ */ jsx(Accordion$1.Content, {
|
|
90
|
+
"data-slot": "accordion-content",
|
|
91
|
+
className: s.content({ class: slots.content }),
|
|
92
|
+
...props,
|
|
93
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
94
|
+
className: s.contentInner({ class: [slots.contentInner, className] }),
|
|
95
|
+
children
|
|
96
|
+
})
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
//#endregion
|
|
100
|
+
//#region src/components/alert/alert.styles.ts
|
|
101
|
+
const alertStyles = tv({
|
|
102
|
+
slots: {
|
|
103
|
+
root: ["relative flex w-full items-start gap-3 rounded-md px-4 py-3 text-small", themedBorder],
|
|
104
|
+
icon: "mt-0.5 flex size-4 shrink-0 items-center justify-center [&>svg]:size-4",
|
|
105
|
+
content: "grid min-w-0 flex-1 gap-0.5",
|
|
106
|
+
title: "font-medium text-foreground",
|
|
107
|
+
description: "text-muted-foreground [&_a]:font-medium [&_a]:text-foreground [&_a]:underline [&_a]:underline-offset-2",
|
|
108
|
+
action: "flex shrink-0 items-center gap-2 self-center",
|
|
109
|
+
dismiss: "-my-1 -mr-2 shrink-0"
|
|
110
|
+
},
|
|
111
|
+
variants: {
|
|
112
|
+
tone: {
|
|
113
|
+
neutral: { icon: "text-muted-foreground" },
|
|
114
|
+
info: { icon: "text-[color-mix(in_oklab,var(--color-info)_80%,var(--color-foreground))]" },
|
|
115
|
+
success: { icon: "text-[color-mix(in_oklab,var(--color-success)_80%,var(--color-foreground))]" },
|
|
116
|
+
warning: { icon: "text-[color-mix(in_oklab,var(--color-warning)_80%,var(--color-foreground))]" },
|
|
117
|
+
danger: { icon: "text-[color-mix(in_oklab,var(--color-danger)_80%,var(--color-foreground))]" }
|
|
118
|
+
},
|
|
119
|
+
variant: {
|
|
120
|
+
soft: {},
|
|
121
|
+
outline: { root: "bg-surface" }
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
compoundVariants: [
|
|
125
|
+
{
|
|
126
|
+
variant: "soft",
|
|
127
|
+
tone: "neutral",
|
|
128
|
+
class: { root: "border-border bg-muted" }
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
variant: "soft",
|
|
132
|
+
tone: "info",
|
|
133
|
+
class: { root: "border-info/25 bg-info/8" }
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
variant: "soft",
|
|
137
|
+
tone: "success",
|
|
138
|
+
class: { root: "border-success/25 bg-success/8" }
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
variant: "soft",
|
|
142
|
+
tone: "warning",
|
|
143
|
+
class: { root: "border-warning/30 bg-warning/10" }
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
variant: "soft",
|
|
147
|
+
tone: "danger",
|
|
148
|
+
class: { root: "border-danger/25 bg-danger/8" }
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
variant: "outline",
|
|
152
|
+
tone: "neutral",
|
|
153
|
+
class: { root: "border-border-strong" }
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
variant: "outline",
|
|
157
|
+
tone: "info",
|
|
158
|
+
class: { root: "border-info/50" }
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
variant: "outline",
|
|
162
|
+
tone: "success",
|
|
163
|
+
class: { root: "border-success/50" }
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
variant: "outline",
|
|
167
|
+
tone: "warning",
|
|
168
|
+
class: { root: "border-warning/60" }
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
variant: "outline",
|
|
172
|
+
tone: "danger",
|
|
173
|
+
class: { root: "border-danger/50" }
|
|
174
|
+
}
|
|
175
|
+
],
|
|
176
|
+
defaultVariants: {
|
|
177
|
+
tone: "neutral",
|
|
178
|
+
variant: "soft"
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
//#endregion
|
|
182
|
+
//#region src/components/alert/alert-icons.tsx
|
|
183
|
+
function Icon({ children, ...props }) {
|
|
184
|
+
return /* @__PURE__ */ jsx("svg", {
|
|
185
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
186
|
+
width: "16",
|
|
187
|
+
height: "16",
|
|
188
|
+
viewBox: "0 0 24 24",
|
|
189
|
+
fill: "none",
|
|
190
|
+
stroke: "currentColor",
|
|
191
|
+
strokeWidth: "2",
|
|
192
|
+
strokeLinecap: "round",
|
|
193
|
+
strokeLinejoin: "round",
|
|
194
|
+
"aria-hidden": "true",
|
|
195
|
+
...props,
|
|
196
|
+
children
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
const InfoIcon = (p) => /* @__PURE__ */ jsxs(Icon, {
|
|
200
|
+
...p,
|
|
201
|
+
children: [/* @__PURE__ */ jsx("circle", {
|
|
202
|
+
cx: "12",
|
|
203
|
+
cy: "12",
|
|
204
|
+
r: "10"
|
|
205
|
+
}), /* @__PURE__ */ jsx("path", { d: "M12 16v-4M12 8h.01" })]
|
|
206
|
+
});
|
|
207
|
+
const SuccessIcon = (p) => /* @__PURE__ */ jsxs(Icon, {
|
|
208
|
+
...p,
|
|
209
|
+
children: [/* @__PURE__ */ jsx("circle", {
|
|
210
|
+
cx: "12",
|
|
211
|
+
cy: "12",
|
|
212
|
+
r: "10"
|
|
213
|
+
}), /* @__PURE__ */ jsx("path", { d: "m9 12 2 2 4-4" })]
|
|
214
|
+
});
|
|
215
|
+
const WarningIcon = (p) => /* @__PURE__ */ jsxs(Icon, {
|
|
216
|
+
...p,
|
|
217
|
+
children: [/* @__PURE__ */ jsx("path", { d: "m21.73 18-8-14a2 2 0 0 0-3.46 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3" }), /* @__PURE__ */ jsx("path", { d: "M12 9v4M12 17h.01" })]
|
|
218
|
+
});
|
|
219
|
+
const DangerIcon = (p) => /* @__PURE__ */ jsxs(Icon, {
|
|
220
|
+
...p,
|
|
221
|
+
children: [/* @__PURE__ */ jsx("circle", {
|
|
222
|
+
cx: "12",
|
|
223
|
+
cy: "12",
|
|
224
|
+
r: "10"
|
|
225
|
+
}), /* @__PURE__ */ jsx("path", { d: "m15 9-6 6M9 9l6 6" })]
|
|
226
|
+
});
|
|
227
|
+
const MegaphoneIcon = (p) => /* @__PURE__ */ jsxs(Icon, {
|
|
228
|
+
...p,
|
|
229
|
+
children: [/* @__PURE__ */ jsx("path", { d: "m3 11 18-5v12L3 14v-3z" }), /* @__PURE__ */ jsx("path", { d: "M11.6 16.8a3 3 0 1 1-5.8-1.6" })]
|
|
230
|
+
});
|
|
231
|
+
/** The default icon for each tone. */
|
|
232
|
+
const toneIcons = {
|
|
233
|
+
neutral: () => /* @__PURE__ */ jsx(InfoIcon, {}),
|
|
234
|
+
primary: () => /* @__PURE__ */ jsx(MegaphoneIcon, {}),
|
|
235
|
+
info: () => /* @__PURE__ */ jsx(InfoIcon, {}),
|
|
236
|
+
success: () => /* @__PURE__ */ jsx(SuccessIcon, {}),
|
|
237
|
+
warning: () => /* @__PURE__ */ jsx(WarningIcon, {}),
|
|
238
|
+
danger: () => /* @__PURE__ */ jsx(DangerIcon, {})
|
|
239
|
+
};
|
|
240
|
+
//#endregion
|
|
241
|
+
//#region src/components/alert/alert.tsx
|
|
242
|
+
/**
|
|
243
|
+
* An inline message about the content around it. Danger and warning alerts are announced
|
|
244
|
+
* immediately (`role="alert"`); other tones politely (`role="status"`).
|
|
245
|
+
*/
|
|
246
|
+
function Alert(inProps) {
|
|
247
|
+
const [props, slots] = useComponentConfig("Alert", inProps);
|
|
248
|
+
const { tone, variant, title, icon, action, onDismiss, dismissLabel = "Dismiss", className, children, ...rest } = props;
|
|
249
|
+
const resolvedTone = tone ?? "neutral";
|
|
250
|
+
const s = alertStyles({
|
|
251
|
+
tone,
|
|
252
|
+
variant
|
|
253
|
+
});
|
|
254
|
+
const iconNode = icon === false ? null : icon ?? toneIcons[resolvedTone]();
|
|
255
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
256
|
+
"data-slot": "alert",
|
|
257
|
+
"data-tone": resolvedTone,
|
|
258
|
+
role: resolvedTone === "danger" || resolvedTone === "warning" ? "alert" : "status",
|
|
259
|
+
className: s.root({ class: [slots.root, className] }),
|
|
260
|
+
...rest,
|
|
261
|
+
children: [
|
|
262
|
+
iconNode && /* @__PURE__ */ jsx("span", {
|
|
263
|
+
"data-slot": "alert-icon",
|
|
264
|
+
className: s.icon({ class: slots.icon }),
|
|
265
|
+
"aria-hidden": "true",
|
|
266
|
+
children: iconNode
|
|
267
|
+
}),
|
|
268
|
+
/* @__PURE__ */ jsxs("div", {
|
|
269
|
+
"data-slot": "alert-content",
|
|
270
|
+
className: s.content({ class: slots.content }),
|
|
271
|
+
children: [title && /* @__PURE__ */ jsx("p", {
|
|
272
|
+
"data-slot": "alert-title",
|
|
273
|
+
className: s.title({ class: slots.title }),
|
|
274
|
+
children: title
|
|
275
|
+
}), children && /* @__PURE__ */ jsx("div", {
|
|
276
|
+
"data-slot": "alert-description",
|
|
277
|
+
className: s.description({ class: slots.description }),
|
|
278
|
+
children
|
|
279
|
+
})]
|
|
280
|
+
}),
|
|
281
|
+
action && /* @__PURE__ */ jsx("div", {
|
|
282
|
+
"data-slot": "alert-action",
|
|
283
|
+
className: s.action({ class: slots.action }),
|
|
284
|
+
children: action
|
|
285
|
+
}),
|
|
286
|
+
onDismiss && /* @__PURE__ */ jsx(IconButton, {
|
|
287
|
+
size: "sm",
|
|
288
|
+
icon: /* @__PURE__ */ jsx(XIcon, {}),
|
|
289
|
+
"aria-label": dismissLabel,
|
|
290
|
+
onClick: onDismiss,
|
|
291
|
+
className: s.dismiss({ class: slots.dismiss })
|
|
292
|
+
})
|
|
293
|
+
]
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
//#endregion
|
|
297
|
+
//#region src/components/alert-dialog/alert-dialog.styles.ts
|
|
298
|
+
const alertDialogStyles = tv({ slots: {
|
|
299
|
+
overlay: "fixed inset-0 z-50 animate-fade-in bg-overlay",
|
|
300
|
+
content: [
|
|
301
|
+
"fixed top-1/2 left-1/2 z-50 grid w-[calc(100vw-2rem)] max-w-md -translate-x-1/2 -translate-y-1/2 gap-5",
|
|
302
|
+
"rounded-xl border-border bg-surface p-6 text-foreground shadow-lg outline-none animate-pop-in",
|
|
303
|
+
themedBorder
|
|
304
|
+
],
|
|
305
|
+
header: "flex flex-col gap-1.5",
|
|
306
|
+
title: "font-display text-h4 text-foreground",
|
|
307
|
+
description: "text-small text-muted-foreground",
|
|
308
|
+
footer: "flex flex-col-reverse gap-2 sm:flex-row sm:justify-end"
|
|
309
|
+
} });
|
|
310
|
+
//#endregion
|
|
311
|
+
//#region src/components/alert-dialog/alert-dialog.tsx
|
|
312
|
+
function useParts$3() {
|
|
313
|
+
const [, slots] = useComponentConfig("AlertDialog", {});
|
|
314
|
+
return {
|
|
315
|
+
s: alertDialogStyles(),
|
|
316
|
+
slots
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* A modal that interrupts to ask for a decision, e.g. confirming a destructive action.
|
|
321
|
+
* Unlike Dialog it can't be dismissed by clicking outside. For a one-line confirm, use `useConfirm()`.
|
|
322
|
+
*/
|
|
323
|
+
const AlertDialog = AlertDialog$1.Root;
|
|
324
|
+
const AlertDialogTrigger = AlertDialog$1.Trigger;
|
|
325
|
+
function AlertDialogContent(inProps) {
|
|
326
|
+
const [props, slots] = useComponentConfig("AlertDialog", inProps);
|
|
327
|
+
const { overlayClassName, className, ...rest } = props;
|
|
328
|
+
const s = alertDialogStyles();
|
|
329
|
+
return /* @__PURE__ */ jsxs(AlertDialog$1.Portal, { children: [/* @__PURE__ */ jsx(AlertDialog$1.Overlay, {
|
|
330
|
+
"data-slot": "alert-dialog-overlay",
|
|
331
|
+
className: s.overlay({ class: [slots.overlay, overlayClassName] })
|
|
332
|
+
}), /* @__PURE__ */ jsx(AlertDialog$1.Content, {
|
|
333
|
+
"data-slot": "alert-dialog-content",
|
|
334
|
+
className: s.content({ class: [slots.content, className] }),
|
|
335
|
+
...rest
|
|
336
|
+
})] });
|
|
337
|
+
}
|
|
338
|
+
function AlertDialogHeader({ className, ...props }) {
|
|
339
|
+
const { s, slots } = useParts$3();
|
|
340
|
+
return /* @__PURE__ */ jsx("div", {
|
|
341
|
+
"data-slot": "alert-dialog-header",
|
|
342
|
+
className: s.header({ class: [slots.header, className] }),
|
|
343
|
+
...props
|
|
344
|
+
});
|
|
345
|
+
}
|
|
346
|
+
function AlertDialogTitle({ className, ...props }) {
|
|
347
|
+
const { s, slots } = useParts$3();
|
|
348
|
+
return /* @__PURE__ */ jsx(AlertDialog$1.Title, {
|
|
349
|
+
"data-slot": "alert-dialog-title",
|
|
350
|
+
className: s.title({ class: [slots.title, className] }),
|
|
351
|
+
...props
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
function AlertDialogDescription({ className, ...props }) {
|
|
355
|
+
const { s, slots } = useParts$3();
|
|
356
|
+
return /* @__PURE__ */ jsx(AlertDialog$1.Description, {
|
|
357
|
+
"data-slot": "alert-dialog-description",
|
|
358
|
+
className: s.description({ class: [slots.description, className] }),
|
|
359
|
+
...props
|
|
360
|
+
});
|
|
361
|
+
}
|
|
362
|
+
function AlertDialogFooter({ className, ...props }) {
|
|
363
|
+
const { s, slots } = useParts$3();
|
|
364
|
+
return /* @__PURE__ */ jsx("div", {
|
|
365
|
+
"data-slot": "alert-dialog-footer",
|
|
366
|
+
className: s.footer({ class: [slots.footer, className] }),
|
|
367
|
+
...props
|
|
368
|
+
});
|
|
369
|
+
}
|
|
370
|
+
/** The confirming button. Closes the dialog. */
|
|
371
|
+
function AlertDialogAction({ tone = "default", ...props }) {
|
|
372
|
+
return /* @__PURE__ */ jsx(AlertDialog$1.Action, {
|
|
373
|
+
asChild: true,
|
|
374
|
+
children: /* @__PURE__ */ jsx(Button, {
|
|
375
|
+
"data-slot": "alert-dialog-action",
|
|
376
|
+
variant: tone === "danger" ? "danger" : "primary",
|
|
377
|
+
...props
|
|
378
|
+
})
|
|
379
|
+
});
|
|
380
|
+
}
|
|
381
|
+
/** The dismissing button. Receives focus when the dialog opens, so Enter never confirms by accident. */
|
|
382
|
+
function AlertDialogCancel(props) {
|
|
383
|
+
return /* @__PURE__ */ jsx(AlertDialog$1.Cancel, {
|
|
384
|
+
asChild: true,
|
|
385
|
+
children: /* @__PURE__ */ jsx(Button, {
|
|
386
|
+
"data-slot": "alert-dialog-cancel",
|
|
387
|
+
variant: "outline",
|
|
388
|
+
...props
|
|
389
|
+
})
|
|
390
|
+
});
|
|
391
|
+
}
|
|
392
|
+
//#endregion
|
|
393
|
+
//#region src/components/alert-dialog/confirm.tsx
|
|
394
|
+
const ConfirmContext = createContext(null);
|
|
395
|
+
/**
|
|
396
|
+
* Enables `useConfirm()` for everything inside. Renders one shared AlertDialog.
|
|
397
|
+
* Mount once near the root (inside GlyphProvider).
|
|
398
|
+
*/
|
|
399
|
+
function ConfirmProvider({ children }) {
|
|
400
|
+
const [pending, setPending] = useState(null);
|
|
401
|
+
const [open, setOpen] = useState(false);
|
|
402
|
+
const pendingRef = useRef(null);
|
|
403
|
+
const settle = useCallback((value) => {
|
|
404
|
+
pendingRef.current?.resolve(value);
|
|
405
|
+
pendingRef.current = null;
|
|
406
|
+
setOpen(false);
|
|
407
|
+
}, []);
|
|
408
|
+
const confirm = useCallback((options) => {
|
|
409
|
+
pendingRef.current?.resolve(false);
|
|
410
|
+
return new Promise((resolve) => {
|
|
411
|
+
const next = {
|
|
412
|
+
options,
|
|
413
|
+
resolve
|
|
414
|
+
};
|
|
415
|
+
pendingRef.current = next;
|
|
416
|
+
setPending(next);
|
|
417
|
+
setOpen(true);
|
|
418
|
+
});
|
|
419
|
+
}, []);
|
|
420
|
+
const value = useMemo(() => confirm, [confirm]);
|
|
421
|
+
const options = pending?.options;
|
|
422
|
+
const danger = options?.tone === "danger";
|
|
423
|
+
return /* @__PURE__ */ jsxs(ConfirmContext.Provider, {
|
|
424
|
+
value,
|
|
425
|
+
children: [children, /* @__PURE__ */ jsx(AlertDialog, {
|
|
426
|
+
open,
|
|
427
|
+
onOpenChange: (next) => !next && settle(false),
|
|
428
|
+
children: options && /* @__PURE__ */ jsxs(AlertDialogContent, { children: [/* @__PURE__ */ jsxs(AlertDialogHeader, { children: [/* @__PURE__ */ jsx(AlertDialogTitle, { children: options.title }), options.description && /* @__PURE__ */ jsx(AlertDialogDescription, { children: options.description })] }), /* @__PURE__ */ jsxs(AlertDialogFooter, { children: [/* @__PURE__ */ jsx(AlertDialogCancel, {
|
|
429
|
+
onClick: () => settle(false),
|
|
430
|
+
children: options.cancelLabel ?? "Cancel"
|
|
431
|
+
}), /* @__PURE__ */ jsx(AlertDialogAction, {
|
|
432
|
+
tone: options.tone,
|
|
433
|
+
onClick: () => settle(true),
|
|
434
|
+
children: options.confirmLabel ?? (danger ? "Delete" : "Confirm")
|
|
435
|
+
})] })] })
|
|
436
|
+
})]
|
|
437
|
+
});
|
|
438
|
+
}
|
|
439
|
+
/**
|
|
440
|
+
* Ask the user to confirm, in one line:
|
|
441
|
+
*
|
|
442
|
+
* ```tsx
|
|
443
|
+
* const confirm = useConfirm()
|
|
444
|
+
* if (await confirm({ title: 'Delete project?', tone: 'danger' })) await deleteProject()
|
|
445
|
+
* ```
|
|
446
|
+
*
|
|
447
|
+
* Resolves `true` when confirmed, `false` when cancelled or dismissed with Escape.
|
|
448
|
+
*/
|
|
449
|
+
function useConfirm() {
|
|
450
|
+
const confirm = useContext(ConfirmContext);
|
|
451
|
+
if (!confirm) throw new Error("useConfirm must be used inside <ConfirmProvider> (or <GlyphProvider>).");
|
|
452
|
+
return confirm;
|
|
453
|
+
}
|
|
454
|
+
//#endregion
|
|
455
|
+
//#region src/components/aspect-ratio/aspect-ratio.tsx
|
|
456
|
+
const aspectRatioStyles = tv({
|
|
457
|
+
slots: { base: "overflow-hidden [&>img]:size-full [&>img]:object-cover [&>video]:size-full [&>video]:object-cover" },
|
|
458
|
+
variants: {
|
|
459
|
+
rounded: { true: { base: "rounded-lg" } },
|
|
460
|
+
placeholder: { true: { base: "bg-muted" } }
|
|
461
|
+
}
|
|
462
|
+
});
|
|
463
|
+
/** Keeps media at a fixed width-to-height ratio, e.g. `ratio={16 / 9}`. Images inside cover the box. */
|
|
464
|
+
function AspectRatio(inProps) {
|
|
465
|
+
const [props, slots] = useComponentConfig("AspectRatio", inProps);
|
|
466
|
+
const { rounded, placeholder, className, ...rest } = props;
|
|
467
|
+
return /* @__PURE__ */ jsx(AspectRatio$1.Root, {
|
|
468
|
+
"data-slot": "aspect-ratio",
|
|
469
|
+
className: aspectRatioStyles({
|
|
470
|
+
rounded,
|
|
471
|
+
placeholder
|
|
472
|
+
}).base({ class: [slots.base, className] }),
|
|
473
|
+
...rest
|
|
474
|
+
});
|
|
475
|
+
}
|
|
476
|
+
//#endregion
|
|
11
477
|
//#region src/components/avatar/avatar.styles.ts
|
|
12
478
|
const avatarStyles = tv({
|
|
13
479
|
slots: {
|
|
@@ -117,7 +583,7 @@ const tones = {
|
|
|
117
583
|
const badgeStyles = tv({
|
|
118
584
|
slots: {
|
|
119
585
|
base: [
|
|
120
|
-
"inline-flex h-5.5 shrink-0 items-center gap-1.5 whitespace-nowrap rounded-pill border-transparent px-2",
|
|
586
|
+
"inline-flex h-5.5 w-fit shrink-0 items-center gap-1.5 whitespace-nowrap rounded-pill border-transparent px-2",
|
|
121
587
|
"text-caption tabular-nums",
|
|
122
588
|
themedBorder
|
|
123
589
|
],
|
|
@@ -171,6 +637,225 @@ function Badge(inProps) {
|
|
|
171
637
|
});
|
|
172
638
|
}
|
|
173
639
|
//#endregion
|
|
640
|
+
//#region src/components/banner/banner.styles.ts
|
|
641
|
+
const bannerStyles = tv({
|
|
642
|
+
slots: {
|
|
643
|
+
root: ["w-full border-b-(length:--glyph-border-width) text-small"],
|
|
644
|
+
inner: "mx-auto flex w-full max-w-7xl items-center gap-3 px-4 py-2.5 sm:px-6",
|
|
645
|
+
icon: "flex size-4 shrink-0 items-center justify-center [&>svg]:size-4",
|
|
646
|
+
content: "min-w-0 flex-1 [&_a]:font-medium [&_a]:underline [&_a]:underline-offset-2",
|
|
647
|
+
action: "flex shrink-0 items-center gap-2",
|
|
648
|
+
dismiss: "-my-1 -mr-2 shrink-0 text-current hover:bg-current/10 hover:text-current"
|
|
649
|
+
},
|
|
650
|
+
variants: { tone: {
|
|
651
|
+
neutral: {
|
|
652
|
+
root: "border-border bg-subtle text-foreground",
|
|
653
|
+
icon: "text-muted-foreground"
|
|
654
|
+
},
|
|
655
|
+
primary: { root: "border-primary bg-primary text-primary-foreground" },
|
|
656
|
+
info: { root: "border-info/25 bg-info/10 text-[color-mix(in_oklab,var(--color-info)_55%,var(--color-foreground))]" },
|
|
657
|
+
success: { root: "border-success/25 bg-success/10 text-[color-mix(in_oklab,var(--color-success)_55%,var(--color-foreground))]" },
|
|
658
|
+
warning: { root: "border-warning/30 bg-warning/14 text-[color-mix(in_oklab,var(--color-warning)_50%,var(--color-foreground))]" },
|
|
659
|
+
danger: { root: "border-danger/25 bg-danger/10 text-[color-mix(in_oklab,var(--color-danger)_55%,var(--color-foreground))]" }
|
|
660
|
+
} },
|
|
661
|
+
defaultVariants: { tone: "neutral" }
|
|
662
|
+
});
|
|
663
|
+
//#endregion
|
|
664
|
+
//#region src/components/banner/banner.tsx
|
|
665
|
+
function readDismissed(key) {
|
|
666
|
+
if (!key || typeof window === "undefined") return false;
|
|
667
|
+
try {
|
|
668
|
+
return window.localStorage.getItem(key) === "dismissed";
|
|
669
|
+
} catch {
|
|
670
|
+
return false;
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
/** A full-width announcement at the top of a page or section. */
|
|
674
|
+
function Banner(inProps) {
|
|
675
|
+
const [props, slots] = useComponentConfig("Banner", inProps);
|
|
676
|
+
const { tone, icon, action, dismissible = false, storageKey, onDismiss, dismissLabel = "Dismiss", className, children, ...rest } = props;
|
|
677
|
+
const [dismissed, setDismissed] = useState(() => readDismissed(storageKey));
|
|
678
|
+
if (dismissed) return null;
|
|
679
|
+
const resolvedTone = tone ?? "neutral";
|
|
680
|
+
const s = bannerStyles({ tone });
|
|
681
|
+
const iconNode = icon === false ? null : icon ?? toneIcons[resolvedTone]();
|
|
682
|
+
const dismiss = () => {
|
|
683
|
+
setDismissed(true);
|
|
684
|
+
if (storageKey) try {
|
|
685
|
+
window.localStorage.setItem(storageKey, "dismissed");
|
|
686
|
+
} catch {}
|
|
687
|
+
onDismiss?.();
|
|
688
|
+
};
|
|
689
|
+
return /* @__PURE__ */ jsx("section", {
|
|
690
|
+
"data-slot": "banner",
|
|
691
|
+
"data-tone": resolvedTone,
|
|
692
|
+
"aria-label": "Announcement",
|
|
693
|
+
className: s.root({ class: [slots.root, className] }),
|
|
694
|
+
...rest,
|
|
695
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
696
|
+
className: s.inner({ class: slots.inner }),
|
|
697
|
+
children: [
|
|
698
|
+
iconNode && /* @__PURE__ */ jsx("span", {
|
|
699
|
+
"data-slot": "banner-icon",
|
|
700
|
+
className: s.icon({ class: slots.icon }),
|
|
701
|
+
"aria-hidden": "true",
|
|
702
|
+
children: iconNode
|
|
703
|
+
}),
|
|
704
|
+
/* @__PURE__ */ jsx("div", {
|
|
705
|
+
"data-slot": "banner-content",
|
|
706
|
+
className: s.content({ class: slots.content }),
|
|
707
|
+
children
|
|
708
|
+
}),
|
|
709
|
+
action && /* @__PURE__ */ jsx("div", {
|
|
710
|
+
"data-slot": "banner-action",
|
|
711
|
+
className: s.action({ class: slots.action }),
|
|
712
|
+
children: action
|
|
713
|
+
}),
|
|
714
|
+
dismissible && /* @__PURE__ */ jsx(IconButton, {
|
|
715
|
+
size: "sm",
|
|
716
|
+
icon: /* @__PURE__ */ jsx(XIcon, {}),
|
|
717
|
+
"aria-label": dismissLabel,
|
|
718
|
+
onClick: dismiss,
|
|
719
|
+
className: s.dismiss({ class: slots.dismiss })
|
|
720
|
+
})
|
|
721
|
+
]
|
|
722
|
+
})
|
|
723
|
+
});
|
|
724
|
+
}
|
|
725
|
+
//#endregion
|
|
726
|
+
//#region src/components/blockquote/blockquote.tsx
|
|
727
|
+
const blockquoteStyles = tv({
|
|
728
|
+
slots: {
|
|
729
|
+
root: "grid gap-3 border-l-2 border-primary pl-5",
|
|
730
|
+
quote: "font-display text-pretty text-foreground",
|
|
731
|
+
caption: "text-small text-muted-foreground",
|
|
732
|
+
author: "font-medium text-foreground not-italic"
|
|
733
|
+
},
|
|
734
|
+
variants: { size: {
|
|
735
|
+
sm: { quote: "text-body" },
|
|
736
|
+
md: { quote: "text-lead" },
|
|
737
|
+
lg: { quote: "text-h3" }
|
|
738
|
+
} },
|
|
739
|
+
defaultVariants: { size: "md" }
|
|
740
|
+
});
|
|
741
|
+
/** A quotation with an optional attribution. */
|
|
742
|
+
function Blockquote(inProps) {
|
|
743
|
+
const [props, slots] = useComponentConfig("Blockquote", inProps);
|
|
744
|
+
const { author, source, citeUrl, size, className, children, ...rest } = props;
|
|
745
|
+
const s = blockquoteStyles({ size });
|
|
746
|
+
return /* @__PURE__ */ jsxs("figure", {
|
|
747
|
+
"data-slot": "blockquote",
|
|
748
|
+
className: s.root({ class: [slots.root, className] }),
|
|
749
|
+
...rest,
|
|
750
|
+
children: [/* @__PURE__ */ jsx("blockquote", {
|
|
751
|
+
cite: citeUrl,
|
|
752
|
+
className: s.quote({ class: slots.quote }),
|
|
753
|
+
children
|
|
754
|
+
}), (author || source) && /* @__PURE__ */ jsxs("figcaption", {
|
|
755
|
+
className: s.caption({ class: slots.caption }),
|
|
756
|
+
children: [
|
|
757
|
+
author && /* @__PURE__ */ jsx("cite", {
|
|
758
|
+
className: s.author({ class: slots.author }),
|
|
759
|
+
children: author
|
|
760
|
+
}),
|
|
761
|
+
author && source && ", ",
|
|
762
|
+
source
|
|
763
|
+
]
|
|
764
|
+
})]
|
|
765
|
+
});
|
|
766
|
+
}
|
|
767
|
+
//#endregion
|
|
768
|
+
//#region src/components/breadcrumb/breadcrumb.styles.ts
|
|
769
|
+
const breadcrumbStyles = tv({ slots: {
|
|
770
|
+
root: "min-w-0",
|
|
771
|
+
list: "flex flex-wrap items-center gap-1.5 text-small text-muted-foreground",
|
|
772
|
+
item: "inline-flex min-w-0 items-center gap-1.5",
|
|
773
|
+
link: [
|
|
774
|
+
"truncate rounded-xs hover:text-foreground",
|
|
775
|
+
transition,
|
|
776
|
+
focusRing
|
|
777
|
+
],
|
|
778
|
+
page: "truncate font-medium text-foreground",
|
|
779
|
+
separator: "flex items-center text-faint-foreground [&>svg]:size-3.5"
|
|
780
|
+
} });
|
|
781
|
+
//#endregion
|
|
782
|
+
//#region src/components/breadcrumb/breadcrumb.tsx
|
|
783
|
+
const s$2 = breadcrumbStyles();
|
|
784
|
+
function useSlots$2() {
|
|
785
|
+
return useComponentConfig("Breadcrumb", {})[1];
|
|
786
|
+
}
|
|
787
|
+
/** Shows where the current page sits in the hierarchy. */
|
|
788
|
+
function Breadcrumb({ items, separator, className, children, ...props }) {
|
|
789
|
+
const slots = useSlots$2();
|
|
790
|
+
return /* @__PURE__ */ jsx("nav", {
|
|
791
|
+
"aria-label": "Breadcrumb",
|
|
792
|
+
"data-slot": "breadcrumb",
|
|
793
|
+
className: s$2.root({ class: [slots.root, className] }),
|
|
794
|
+
...props,
|
|
795
|
+
children: items ? /* @__PURE__ */ jsx(BreadcrumbList, { children: items.map((item, index) => {
|
|
796
|
+
const last = index === items.length - 1;
|
|
797
|
+
return /* @__PURE__ */ jsxs(BreadcrumbItem, { children: [last || !item.href ? /* @__PURE__ */ jsx(BreadcrumbPage, {
|
|
798
|
+
"aria-current": last ? "page" : void 0,
|
|
799
|
+
children: item.label
|
|
800
|
+
}) : /* @__PURE__ */ jsx(BreadcrumbLink, {
|
|
801
|
+
href: item.href,
|
|
802
|
+
children: item.label
|
|
803
|
+
}), !last && /* @__PURE__ */ jsx(BreadcrumbSeparator, { children: separator })] }, index);
|
|
804
|
+
}) }) : children
|
|
805
|
+
});
|
|
806
|
+
}
|
|
807
|
+
function BreadcrumbList({ className, ...props }) {
|
|
808
|
+
const slots = useSlots$2();
|
|
809
|
+
return /* @__PURE__ */ jsx("ol", {
|
|
810
|
+
"data-slot": "breadcrumb-list",
|
|
811
|
+
className: s$2.list({ class: [slots.list, className] }),
|
|
812
|
+
...props
|
|
813
|
+
});
|
|
814
|
+
}
|
|
815
|
+
function BreadcrumbItem({ className, ...props }) {
|
|
816
|
+
const slots = useSlots$2();
|
|
817
|
+
return /* @__PURE__ */ jsx("li", {
|
|
818
|
+
"data-slot": "breadcrumb-item",
|
|
819
|
+
className: s$2.item({ class: [slots.item, className] }),
|
|
820
|
+
...props
|
|
821
|
+
});
|
|
822
|
+
}
|
|
823
|
+
function BreadcrumbLink({ href, className, children, asChild }) {
|
|
824
|
+
const Link = useLinkComponent();
|
|
825
|
+
const slots = useSlots$2();
|
|
826
|
+
const classes = s$2.link({ class: [slots.link, className] });
|
|
827
|
+
if (asChild) return /* @__PURE__ */ jsx(Slot.Root, {
|
|
828
|
+
"data-slot": "breadcrumb-link",
|
|
829
|
+
className: classes,
|
|
830
|
+
children
|
|
831
|
+
});
|
|
832
|
+
return /* @__PURE__ */ jsx(Link, {
|
|
833
|
+
href,
|
|
834
|
+
className: classes,
|
|
835
|
+
children
|
|
836
|
+
});
|
|
837
|
+
}
|
|
838
|
+
function BreadcrumbPage({ className, ...props }) {
|
|
839
|
+
const slots = useSlots$2();
|
|
840
|
+
return /* @__PURE__ */ jsx("span", {
|
|
841
|
+
"data-slot": "breadcrumb-page",
|
|
842
|
+
"aria-current": "page",
|
|
843
|
+
className: s$2.page({ class: [slots.page, className] }),
|
|
844
|
+
...props
|
|
845
|
+
});
|
|
846
|
+
}
|
|
847
|
+
function BreadcrumbSeparator({ className, children, ...props }) {
|
|
848
|
+
const slots = useSlots$2();
|
|
849
|
+
return /* @__PURE__ */ jsx("span", {
|
|
850
|
+
"data-slot": "breadcrumb-separator",
|
|
851
|
+
role: "presentation",
|
|
852
|
+
"aria-hidden": "true",
|
|
853
|
+
className: s$2.separator({ class: [slots.separator, className] }),
|
|
854
|
+
...props,
|
|
855
|
+
children: children ?? /* @__PURE__ */ jsx(ChevronRightIcon$1, {})
|
|
856
|
+
});
|
|
857
|
+
}
|
|
858
|
+
//#endregion
|
|
174
859
|
//#region src/components/card/card.styles.ts
|
|
175
860
|
const cardStyles = tv({
|
|
176
861
|
slots: {
|
|
@@ -277,98 +962,1698 @@ function CardFooter({ className, ...props }) {
|
|
|
277
962
|
});
|
|
278
963
|
}
|
|
279
964
|
//#endregion
|
|
280
|
-
//#region src/components/
|
|
281
|
-
const
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
965
|
+
//#region src/components/code/code.styles.ts
|
|
966
|
+
const codeStyles = tv({ slots: { base: "rounded-xs bg-muted px-[0.3em] py-[0.15em] font-mono text-[0.875em] text-foreground" } });
|
|
967
|
+
const codeBlockStyles = tv({
|
|
968
|
+
slots: {
|
|
969
|
+
root: ["relative min-w-0 overflow-hidden rounded-lg border-border bg-subtle", themedBorder],
|
|
970
|
+
header: "flex min-h-10 items-center justify-between gap-2 border-b border-border py-1 pr-1.5 pl-4",
|
|
971
|
+
title: "truncate font-mono text-caption text-faint-foreground",
|
|
972
|
+
copy: "shrink-0",
|
|
973
|
+
floatingCopy: "absolute top-2 right-2",
|
|
974
|
+
pre: "overflow-x-auto p-4 font-mono text-small leading-relaxed text-foreground"
|
|
975
|
+
},
|
|
976
|
+
variants: { wrap: { true: { pre: "whitespace-pre-wrap break-words" } } }
|
|
291
977
|
});
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
978
|
+
//#endregion
|
|
979
|
+
//#region src/components/code/code.tsx
|
|
980
|
+
/** Inline code within running text. */
|
|
981
|
+
function Code(inProps) {
|
|
982
|
+
const [{ className, ...rest }, slots] = useComponentConfig("Code", inProps);
|
|
983
|
+
return /* @__PURE__ */ jsx("code", {
|
|
984
|
+
"data-slot": "code",
|
|
985
|
+
className: codeStyles().base({ class: [slots.base, className] }),
|
|
986
|
+
...rest
|
|
987
|
+
});
|
|
988
|
+
}
|
|
989
|
+
const CopyIcon = () => /* @__PURE__ */ jsxs("svg", {
|
|
990
|
+
viewBox: "0 0 24 24",
|
|
991
|
+
fill: "none",
|
|
992
|
+
stroke: "currentColor",
|
|
993
|
+
strokeWidth: "2",
|
|
994
|
+
strokeLinecap: "round",
|
|
995
|
+
strokeLinejoin: "round",
|
|
996
|
+
"aria-hidden": "true",
|
|
997
|
+
children: [/* @__PURE__ */ jsx("rect", {
|
|
998
|
+
width: "14",
|
|
999
|
+
height: "14",
|
|
1000
|
+
x: "8",
|
|
1001
|
+
y: "8",
|
|
1002
|
+
rx: "2"
|
|
1003
|
+
}), /* @__PURE__ */ jsx("path", { d: "M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2" })]
|
|
1004
|
+
});
|
|
1005
|
+
/** A block of code with an optional file name and a copy button. No syntax highlighting is applied. */
|
|
1006
|
+
function CodeBlock(inProps) {
|
|
1007
|
+
const [props, slots] = useComponentConfig("CodeBlock", inProps);
|
|
1008
|
+
const { code, title, language, copyable = true, wrap, className, ...rest } = props;
|
|
1009
|
+
const [copied, setCopied] = useState(false);
|
|
1010
|
+
const timer = useRef(void 0);
|
|
1011
|
+
const s = codeBlockStyles({ wrap });
|
|
1012
|
+
const heading = title ?? language;
|
|
1013
|
+
useEffect(() => () => clearTimeout(timer.current), []);
|
|
1014
|
+
const copy = async () => {
|
|
1015
|
+
try {
|
|
1016
|
+
await navigator.clipboard.writeText(code);
|
|
1017
|
+
setCopied(true);
|
|
1018
|
+
clearTimeout(timer.current);
|
|
1019
|
+
timer.current = setTimeout(() => setCopied(false), 1600);
|
|
1020
|
+
} catch {}
|
|
1021
|
+
};
|
|
1022
|
+
const copyButton = copyable ? /* @__PURE__ */ jsx(IconButton, {
|
|
1023
|
+
size: "sm",
|
|
1024
|
+
icon: copied ? /* @__PURE__ */ jsx(CheckIcon$1, {}) : /* @__PURE__ */ jsx(CopyIcon, {}),
|
|
1025
|
+
"aria-label": copied ? "Copied" : "Copy code",
|
|
1026
|
+
onClick: copy,
|
|
1027
|
+
className: heading ? s.copy({ class: slots.copy }) : s.floatingCopy({ class: slots.floatingCopy })
|
|
1028
|
+
}) : null;
|
|
1029
|
+
return /* @__PURE__ */ jsxs("figure", {
|
|
1030
|
+
"data-slot": "code-block",
|
|
1031
|
+
className: s.root({ class: [slots.root, className] }),
|
|
1032
|
+
...rest,
|
|
1033
|
+
children: [heading ? /* @__PURE__ */ jsxs("figcaption", {
|
|
1034
|
+
className: s.header({ class: slots.header }),
|
|
1035
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
1036
|
+
className: s.title({ class: slots.title }),
|
|
1037
|
+
children: heading
|
|
1038
|
+
}), copyButton]
|
|
1039
|
+
}) : copyButton, /* @__PURE__ */ jsx("pre", {
|
|
1040
|
+
className: s.pre({ class: slots.pre }),
|
|
1041
|
+
children: /* @__PURE__ */ jsx("code", { children: code })
|
|
1042
|
+
})]
|
|
1043
|
+
});
|
|
1044
|
+
}
|
|
1045
|
+
//#endregion
|
|
1046
|
+
//#region src/hooks/use-controllable-state.ts
|
|
1047
|
+
/** State that can be controlled by a parent (`value` + `onChange`) or left uncontrolled. */
|
|
1048
|
+
function useControllableState({ value, defaultValue, onChange }) {
|
|
1049
|
+
const [internal, setInternal] = useState(defaultValue);
|
|
1050
|
+
const isControlled = value !== void 0;
|
|
1051
|
+
const current = isControlled ? value : internal;
|
|
1052
|
+
const onChangeRef = useRef(onChange);
|
|
1053
|
+
onChangeRef.current = onChange;
|
|
1054
|
+
return [current, useCallback((next) => {
|
|
1055
|
+
const resolved = typeof next === "function" ? next(current) : next;
|
|
1056
|
+
if (!isControlled) setInternal(resolved);
|
|
1057
|
+
onChangeRef.current?.(resolved);
|
|
1058
|
+
}, [current, isControlled])];
|
|
1059
|
+
}
|
|
1060
|
+
//#endregion
|
|
1061
|
+
//#region src/components/combobox/combobox.styles.ts
|
|
1062
|
+
const comboboxStyles = tv({
|
|
1063
|
+
slots: {
|
|
1064
|
+
trigger: [
|
|
1065
|
+
...fieldControl,
|
|
1066
|
+
"flex cursor-pointer items-center justify-between gap-2 px-3 text-left outline-none",
|
|
1067
|
+
"focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/20",
|
|
1068
|
+
"disabled:cursor-not-allowed disabled:opacity-50"
|
|
1069
|
+
],
|
|
1070
|
+
value: "flex min-w-0 flex-1 items-center gap-1 truncate",
|
|
1071
|
+
placeholder: "truncate text-faint-foreground",
|
|
1072
|
+
chip: "inline-flex h-5.5 max-w-40 shrink-0 items-center truncate rounded-pill bg-muted px-2 text-caption text-foreground",
|
|
1073
|
+
icon: "size-4 shrink-0 text-faint-foreground",
|
|
1074
|
+
content: [popover, "w-(--radix-popover-trigger-width) min-w-56 p-0"],
|
|
1075
|
+
search: "flex items-center gap-2 border-b border-border px-3 text-faint-foreground [&>svg]:size-4 [&>svg]:shrink-0",
|
|
1076
|
+
input: "h-10 w-full min-w-0 bg-transparent text-small text-foreground outline-none placeholder:text-faint-foreground",
|
|
1077
|
+
list: "max-h-72 overflow-y-auto overscroll-contain p-1",
|
|
1078
|
+
empty: "px-3 py-6 text-center text-small text-muted-foreground",
|
|
1079
|
+
item: ["relative flex cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-1.5 text-small text-foreground outline-none", "data-[selected=true]:bg-muted data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50"],
|
|
1080
|
+
itemText: "grid min-w-0 flex-1",
|
|
1081
|
+
itemDescription: "truncate text-caption text-faint-foreground",
|
|
1082
|
+
check: "size-4 shrink-0 text-primary"
|
|
1083
|
+
},
|
|
1084
|
+
variants: {
|
|
1085
|
+
size: {
|
|
1086
|
+
sm: { trigger: "min-h-(--glyph-control-sm) text-small" },
|
|
1087
|
+
md: { trigger: "min-h-(--glyph-control-md) text-small" },
|
|
1088
|
+
lg: { trigger: "min-h-(--glyph-control-lg) text-body" }
|
|
1089
|
+
},
|
|
1090
|
+
multiple: { true: {
|
|
1091
|
+
trigger: "py-1",
|
|
1092
|
+
value: "flex-wrap overflow-visible whitespace-normal"
|
|
1093
|
+
} }
|
|
1094
|
+
},
|
|
1095
|
+
defaultVariants: { size: "md" }
|
|
1096
|
+
});
|
|
1097
|
+
//#endregion
|
|
1098
|
+
//#region src/components/combobox/combobox.tsx
|
|
1099
|
+
function toArray$1(value) {
|
|
1100
|
+
if (value === void 0) return void 0;
|
|
1101
|
+
if (value === null) return [];
|
|
1102
|
+
return Array.isArray(value) ? [...value] : [value];
|
|
1103
|
+
}
|
|
1104
|
+
/**
|
|
1105
|
+
* A select with search, for long option lists. `multiple` allows several values, shown
|
|
1106
|
+
* as chips. The value type is inferred from `options`.
|
|
1107
|
+
*/
|
|
1108
|
+
function Combobox(inProps) {
|
|
1109
|
+
const [props, slots] = useComponentConfig("Combobox", useFieldControl(inProps));
|
|
1110
|
+
const { options, multiple = false, placeholder = "Select…", searchPlaceholder = "Search…", emptyText = "No results", maxChips = 3, size, disabled, required, name, id, className, contentClassName, "aria-label": ariaLabel, "aria-describedby": ariaDescribedBy, "aria-invalid": ariaInvalid } = props;
|
|
1111
|
+
const onValueChange = props.onValueChange;
|
|
1112
|
+
const [open, setOpen] = useState(false);
|
|
1113
|
+
const [selected, setSelected] = useControllableState({
|
|
1114
|
+
value: toArray$1(props.value),
|
|
1115
|
+
defaultValue: toArray$1(props.defaultValue) ?? [],
|
|
1116
|
+
onChange: (next) => onValueChange?.(multiple ? next : next[0] ?? null)
|
|
1117
|
+
});
|
|
1118
|
+
const byValue = useMemo(() => new Map(options.map((o) => [o.value, o])), [options]);
|
|
1119
|
+
const s = comboboxStyles({
|
|
1120
|
+
size,
|
|
1121
|
+
multiple
|
|
1122
|
+
});
|
|
1123
|
+
const choose = (value) => {
|
|
1124
|
+
if (multiple) {
|
|
1125
|
+
setSelected(selected.includes(value) ? selected.filter((v) => v !== value) : [...selected, value]);
|
|
1126
|
+
return;
|
|
1127
|
+
}
|
|
1128
|
+
setSelected(selected[0] === value ? [] : [value]);
|
|
1129
|
+
setOpen(false);
|
|
1130
|
+
};
|
|
1131
|
+
const labels = selected.map((v) => byValue.get(v)?.label ?? v);
|
|
1132
|
+
let display;
|
|
1133
|
+
if (labels.length === 0) display = /* @__PURE__ */ jsx("span", {
|
|
1134
|
+
className: s.placeholder({ class: slots.placeholder }),
|
|
1135
|
+
children: placeholder
|
|
1136
|
+
});
|
|
1137
|
+
else if (multiple) {
|
|
1138
|
+
const shown = labels.slice(0, maxChips);
|
|
1139
|
+
display = /* @__PURE__ */ jsxs(Fragment$1, { children: [shown.map((label, i) => /* @__PURE__ */ jsx("span", {
|
|
1140
|
+
className: s.chip({ class: slots.chip }),
|
|
1141
|
+
children: label
|
|
1142
|
+
}, selected[i])), labels.length > shown.length && /* @__PURE__ */ jsxs("span", {
|
|
1143
|
+
className: s.chip({ class: slots.chip }),
|
|
1144
|
+
children: ["+", labels.length - shown.length]
|
|
1145
|
+
})] });
|
|
1146
|
+
} else display = /* @__PURE__ */ jsx("span", {
|
|
1147
|
+
className: "truncate",
|
|
1148
|
+
children: labels[0]
|
|
1149
|
+
});
|
|
1150
|
+
return /* @__PURE__ */ jsxs(Popover$1.Root, {
|
|
1151
|
+
open,
|
|
1152
|
+
onOpenChange: setOpen,
|
|
1153
|
+
children: [
|
|
1154
|
+
/* @__PURE__ */ jsx(Popover$1.Trigger, {
|
|
1155
|
+
asChild: true,
|
|
1156
|
+
children: /* @__PURE__ */ jsxs("button", {
|
|
1157
|
+
type: "button",
|
|
1158
|
+
id,
|
|
1159
|
+
role: "combobox",
|
|
1160
|
+
"aria-haspopup": "listbox",
|
|
1161
|
+
"aria-expanded": open,
|
|
1162
|
+
"aria-label": ariaLabel,
|
|
1163
|
+
"aria-describedby": ariaDescribedBy,
|
|
1164
|
+
"aria-invalid": ariaInvalid,
|
|
1165
|
+
"aria-required": required,
|
|
1166
|
+
disabled,
|
|
1167
|
+
"data-slot": "combobox-trigger",
|
|
1168
|
+
className: s.trigger({ class: [slots.trigger, className] }),
|
|
1169
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
1170
|
+
className: s.value({ class: slots.value }),
|
|
1171
|
+
children: display
|
|
1172
|
+
}), /* @__PURE__ */ jsx(ChevronsUpDownIcon, { className: s.icon({ class: slots.icon }) })]
|
|
1173
|
+
})
|
|
1174
|
+
}),
|
|
1175
|
+
name && selected.map((value) => /* @__PURE__ */ jsx("input", {
|
|
1176
|
+
type: "hidden",
|
|
1177
|
+
name,
|
|
1178
|
+
value
|
|
1179
|
+
}, value)),
|
|
1180
|
+
/* @__PURE__ */ jsx(Popover$1.Portal, { children: /* @__PURE__ */ jsx(Popover$1.Content, {
|
|
1181
|
+
align: "start",
|
|
1182
|
+
sideOffset: 4,
|
|
1183
|
+
"data-slot": "combobox-content",
|
|
1184
|
+
className: s.content({ class: [slots.content, contentClassName] }),
|
|
1185
|
+
children: /* @__PURE__ */ jsxs(Command$1, {
|
|
1186
|
+
loop: true,
|
|
1187
|
+
label: ariaLabel ?? "Options",
|
|
1188
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
1189
|
+
className: s.search({ class: slots.search }),
|
|
1190
|
+
children: [/* @__PURE__ */ jsx(SearchIcon, {}), /* @__PURE__ */ jsx(Command$1.Input, {
|
|
1191
|
+
placeholder: searchPlaceholder,
|
|
1192
|
+
className: s.input({ class: slots.input })
|
|
1193
|
+
})]
|
|
1194
|
+
}), /* @__PURE__ */ jsxs(Command$1.List, {
|
|
1195
|
+
className: s.list({ class: slots.list }),
|
|
1196
|
+
children: [/* @__PURE__ */ jsx(Command$1.Empty, {
|
|
1197
|
+
className: s.empty({ class: slots.empty }),
|
|
1198
|
+
children: emptyText
|
|
1199
|
+
}), options.map((option) => {
|
|
1200
|
+
const checked = selected.includes(option.value);
|
|
1201
|
+
return /* @__PURE__ */ jsxs(Command$1.Item, {
|
|
1202
|
+
value: option.value,
|
|
1203
|
+
keywords: [option.label, ...option.keywords ?? []],
|
|
1204
|
+
disabled: option.disabled,
|
|
1205
|
+
onSelect: () => choose(option.value),
|
|
1206
|
+
"data-checked": checked || void 0,
|
|
1207
|
+
"aria-checked": checked,
|
|
1208
|
+
className: s.item({ class: slots.item }),
|
|
1209
|
+
children: [/* @__PURE__ */ jsxs("span", {
|
|
1210
|
+
className: s.itemText({ class: slots.itemText }),
|
|
1211
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
1212
|
+
className: "truncate",
|
|
1213
|
+
children: option.label
|
|
1214
|
+
}), option.description && /* @__PURE__ */ jsx("span", {
|
|
1215
|
+
className: s.itemDescription({ class: slots.itemDescription }),
|
|
1216
|
+
children: option.description
|
|
1217
|
+
})]
|
|
1218
|
+
}), checked && /* @__PURE__ */ jsx(CheckIcon$1, { className: s.check({ class: slots.check }) })]
|
|
1219
|
+
}, option.value);
|
|
1220
|
+
})]
|
|
1221
|
+
})]
|
|
1222
|
+
})
|
|
1223
|
+
}) })
|
|
1224
|
+
]
|
|
1225
|
+
});
|
|
1226
|
+
}
|
|
1227
|
+
//#endregion
|
|
1228
|
+
//#region src/components/kbd/kbd.tsx
|
|
1229
|
+
const kbdStyles = tv({ slots: { base: "inline-flex h-5 min-w-5 items-center justify-center rounded-xs border border-border bg-muted px-1 font-mono text-[0.6875rem] font-medium text-muted-foreground shadow-xs" } });
|
|
1230
|
+
/** A keyboard key, e.g. `<Kbd>⌘K</Kbd>`. */
|
|
1231
|
+
function Kbd(inProps) {
|
|
1232
|
+
const [{ className, ...rest }, slots] = useComponentConfig("Kbd", inProps);
|
|
1233
|
+
return /* @__PURE__ */ jsx("kbd", {
|
|
1234
|
+
"data-slot": "kbd",
|
|
1235
|
+
className: kbdStyles().base({ class: [slots.base, className] }),
|
|
1236
|
+
...rest
|
|
1237
|
+
});
|
|
1238
|
+
}
|
|
1239
|
+
//#endregion
|
|
1240
|
+
//#region src/components/command-menu/command-menu.styles.ts
|
|
1241
|
+
const commandMenuStyles = tv({ slots: {
|
|
1242
|
+
overlay: "fixed inset-0 z-50 animate-fade-in bg-overlay",
|
|
1243
|
+
content: ["fixed top-[12vh] left-1/2 z-50 w-[calc(100%-2rem)] max-w-xl -translate-x-1/2 overflow-hidden rounded-xl border-border bg-raised text-foreground shadow-lg outline-none animate-pop-in", themedBorder],
|
|
1244
|
+
root: "flex w-full flex-col overflow-hidden bg-raised text-foreground",
|
|
1245
|
+
search: "flex items-center gap-2.5 border-b border-border px-4 text-faint-foreground [&>svg]:size-4 [&>svg]:shrink-0",
|
|
1246
|
+
input: "h-12 w-full min-w-0 bg-transparent text-body text-foreground outline-none placeholder:text-faint-foreground",
|
|
1247
|
+
list: "max-h-[min(24rem,60vh)] overflow-y-auto overscroll-contain p-2",
|
|
1248
|
+
empty: "py-10 text-center text-small text-muted-foreground",
|
|
1249
|
+
group: [
|
|
1250
|
+
"overflow-hidden",
|
|
1251
|
+
"[&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:pt-2 [&_[cmdk-group-heading]]:pb-1",
|
|
1252
|
+
"[&_[cmdk-group-heading]]:font-mono [&_[cmdk-group-heading]]:text-caption [&_[cmdk-group-heading]]:uppercase",
|
|
1253
|
+
"[&_[cmdk-group-heading]]:tracking-[0.1em] [&_[cmdk-group-heading]]:text-faint-foreground"
|
|
1254
|
+
],
|
|
1255
|
+
item: ["relative flex h-10 cursor-pointer select-none items-center gap-3 rounded-md px-2.5 text-small text-foreground outline-none", "data-[selected=true]:bg-muted data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50"],
|
|
1256
|
+
itemIcon: "flex size-4 shrink-0 items-center justify-center text-muted-foreground [&>svg]:size-4",
|
|
1257
|
+
itemLabel: "min-w-0 flex-1 truncate",
|
|
1258
|
+
shortcut: "ml-auto flex shrink-0 items-center gap-1",
|
|
1259
|
+
separator: "-mx-2 my-1.5 h-px bg-border"
|
|
1260
|
+
} });
|
|
1261
|
+
//#endregion
|
|
1262
|
+
//#region src/components/command-menu/command-menu.tsx
|
|
1263
|
+
const s$1 = commandMenuStyles();
|
|
1264
|
+
const CommandMenuContext = createContext(null);
|
|
1265
|
+
function useSlots$1() {
|
|
1266
|
+
return useComponentConfig("CommandMenu", {})[1];
|
|
1267
|
+
}
|
|
1268
|
+
/**
|
|
1269
|
+
* A ⌘K command palette in a modal dialog: search, grouped actions, keyboard navigation.
|
|
1270
|
+
* Pair with `useCommandMenuShortcut(setOpen)` to open it from the keyboard.
|
|
1271
|
+
*/
|
|
1272
|
+
function CommandMenu(inProps) {
|
|
1273
|
+
const [props, slots] = useComponentConfig("CommandMenu", inProps);
|
|
1274
|
+
const { open: openProp, defaultOpen = false, onOpenChange, label = "Command menu", loop = true, filter, className, children } = props;
|
|
1275
|
+
const [open, setOpen] = useControllableState({
|
|
1276
|
+
value: openProp,
|
|
1277
|
+
defaultValue: defaultOpen,
|
|
1278
|
+
onChange: onOpenChange
|
|
1279
|
+
});
|
|
1280
|
+
return /* @__PURE__ */ jsx(Dialog$1.Root, {
|
|
1281
|
+
open,
|
|
1282
|
+
onOpenChange: setOpen,
|
|
1283
|
+
children: /* @__PURE__ */ jsxs(Dialog$1.Portal, { children: [/* @__PURE__ */ jsx(Dialog$1.Overlay, { className: s$1.overlay({ class: slots.overlay }) }), /* @__PURE__ */ jsxs(Dialog$1.Content, {
|
|
1284
|
+
"data-slot": "command-menu",
|
|
1285
|
+
"aria-describedby": void 0,
|
|
1286
|
+
className: s$1.content({ class: [slots.content, className] }),
|
|
1287
|
+
children: [/* @__PURE__ */ jsx(Dialog$1.Title, {
|
|
1288
|
+
className: "sr-only",
|
|
1289
|
+
children: label
|
|
1290
|
+
}), /* @__PURE__ */ jsx(CommandMenuContext.Provider, {
|
|
1291
|
+
value: { close: () => setOpen(false) },
|
|
1292
|
+
children: /* @__PURE__ */ jsx(Command, {
|
|
1293
|
+
label,
|
|
1294
|
+
loop,
|
|
1295
|
+
...filter && { filter },
|
|
1296
|
+
children
|
|
1297
|
+
})
|
|
1298
|
+
})]
|
|
1299
|
+
})] })
|
|
1300
|
+
});
|
|
1301
|
+
}
|
|
1302
|
+
/** The palette without a dialog, for inline search panels. */
|
|
1303
|
+
function Command({ className, ...props }) {
|
|
1304
|
+
const slots = useSlots$1();
|
|
1305
|
+
return /* @__PURE__ */ jsx(Command$1, {
|
|
1306
|
+
"data-slot": "command",
|
|
1307
|
+
className: s$1.root({ class: [slots.root, className] }),
|
|
1308
|
+
...props
|
|
1309
|
+
});
|
|
1310
|
+
}
|
|
1311
|
+
function CommandInput({ className, ...props }) {
|
|
1312
|
+
const slots = useSlots$1();
|
|
1313
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
1314
|
+
className: s$1.search({ class: slots.search }),
|
|
1315
|
+
children: [/* @__PURE__ */ jsx(SearchIcon, {}), /* @__PURE__ */ jsx(Command$1.Input, {
|
|
1316
|
+
"data-slot": "command-input",
|
|
1317
|
+
className: s$1.input({ class: [slots.input, className] }),
|
|
1318
|
+
...props
|
|
1319
|
+
})]
|
|
1320
|
+
});
|
|
1321
|
+
}
|
|
1322
|
+
function CommandList({ className, ...props }) {
|
|
1323
|
+
const slots = useSlots$1();
|
|
1324
|
+
return /* @__PURE__ */ jsx(Command$1.List, {
|
|
1325
|
+
"data-slot": "command-list",
|
|
1326
|
+
className: s$1.list({ class: [slots.list, className] }),
|
|
1327
|
+
...props
|
|
1328
|
+
});
|
|
1329
|
+
}
|
|
1330
|
+
function CommandEmpty({ className, children = "No results", ...props }) {
|
|
1331
|
+
const slots = useSlots$1();
|
|
1332
|
+
return /* @__PURE__ */ jsx(Command$1.Empty, {
|
|
1333
|
+
"data-slot": "command-empty",
|
|
1334
|
+
className: s$1.empty({ class: [slots.empty, className] }),
|
|
1335
|
+
...props,
|
|
1336
|
+
children
|
|
1337
|
+
});
|
|
1338
|
+
}
|
|
1339
|
+
function CommandGroup({ className, ...props }) {
|
|
1340
|
+
const slots = useSlots$1();
|
|
1341
|
+
return /* @__PURE__ */ jsx(Command$1.Group, {
|
|
1342
|
+
"data-slot": "command-group",
|
|
1343
|
+
className: s$1.group({ class: [slots.group, className] }),
|
|
1344
|
+
...props
|
|
1345
|
+
});
|
|
1346
|
+
}
|
|
1347
|
+
function CommandItem({ icon, shortcut, closeOnSelect = true, onSelect, className, children, ...props }) {
|
|
1348
|
+
const slots = useSlots$1();
|
|
1349
|
+
const menu = useContext(CommandMenuContext);
|
|
1350
|
+
const keys = shortcut === void 0 ? [] : typeof shortcut === "string" ? [shortcut] : shortcut;
|
|
1351
|
+
return /* @__PURE__ */ jsxs(Command$1.Item, {
|
|
1352
|
+
"data-slot": "command-item",
|
|
1353
|
+
onSelect: (value) => {
|
|
1354
|
+
onSelect?.(value);
|
|
1355
|
+
if (closeOnSelect) menu?.close();
|
|
1356
|
+
},
|
|
1357
|
+
className: s$1.item({ class: [slots.item, className] }),
|
|
1358
|
+
...props,
|
|
1359
|
+
children: [
|
|
1360
|
+
icon && /* @__PURE__ */ jsx("span", {
|
|
1361
|
+
className: s$1.itemIcon({ class: slots.itemIcon }),
|
|
1362
|
+
"aria-hidden": "true",
|
|
1363
|
+
children: icon
|
|
1364
|
+
}),
|
|
1365
|
+
/* @__PURE__ */ jsx("span", {
|
|
1366
|
+
className: s$1.itemLabel({ class: slots.itemLabel }),
|
|
1367
|
+
children
|
|
1368
|
+
}),
|
|
1369
|
+
keys.length > 0 && /* @__PURE__ */ jsx("span", {
|
|
1370
|
+
className: s$1.shortcut({ class: slots.shortcut }),
|
|
1371
|
+
"aria-hidden": "true",
|
|
1372
|
+
children: keys.map((key) => /* @__PURE__ */ jsx(Kbd, { children: key }, key))
|
|
1373
|
+
})
|
|
1374
|
+
]
|
|
1375
|
+
});
|
|
1376
|
+
}
|
|
1377
|
+
function CommandSeparator({ className, ...props }) {
|
|
1378
|
+
const slots = useSlots$1();
|
|
1379
|
+
return /* @__PURE__ */ jsx(Command$1.Separator, {
|
|
1380
|
+
"data-slot": "command-separator",
|
|
1381
|
+
className: s$1.separator({ class: [slots.separator, className] }),
|
|
1382
|
+
...props
|
|
1383
|
+
});
|
|
1384
|
+
}
|
|
1385
|
+
/** Toggles a command menu with ⌘K (macOS) or Ctrl+K. Pass another key to change it. */
|
|
1386
|
+
function useCommandMenuShortcut(setOpen, key = "k") {
|
|
1387
|
+
useEffect(() => {
|
|
1388
|
+
const onKeyDown = (event) => {
|
|
1389
|
+
if (event.key.toLowerCase() === key.toLowerCase() && (event.metaKey || event.ctrlKey)) {
|
|
1390
|
+
event.preventDefault();
|
|
1391
|
+
setOpen((open) => !open);
|
|
1392
|
+
}
|
|
1393
|
+
};
|
|
1394
|
+
document.addEventListener("keydown", onKeyDown);
|
|
1395
|
+
return () => document.removeEventListener("keydown", onKeyDown);
|
|
1396
|
+
}, [setOpen, key]);
|
|
1397
|
+
}
|
|
1398
|
+
//#endregion
|
|
1399
|
+
//#region src/components/container/container.tsx
|
|
1400
|
+
const containerStyles = tv({
|
|
1401
|
+
base: "mx-auto w-full px-4 sm:px-6",
|
|
1402
|
+
variants: { size: {
|
|
1403
|
+
sm: "max-w-2xl",
|
|
1404
|
+
md: "max-w-3xl",
|
|
1405
|
+
lg: "max-w-5xl",
|
|
1406
|
+
xl: "max-w-7xl",
|
|
1407
|
+
full: "max-w-none"
|
|
1408
|
+
} },
|
|
1409
|
+
defaultVariants: { size: "xl" }
|
|
1410
|
+
});
|
|
1411
|
+
/** Centers content at a readable max width with consistent side gutters. */
|
|
1412
|
+
function Container({ size, asChild, className, ...props }) {
|
|
1413
|
+
const Comp = asChild ? Slot.Root : "div";
|
|
1414
|
+
return /* @__PURE__ */ jsx(Comp, {
|
|
1415
|
+
"data-slot": "container",
|
|
1416
|
+
className: containerStyles({
|
|
1417
|
+
size,
|
|
1418
|
+
class: className
|
|
1419
|
+
}),
|
|
1420
|
+
...props
|
|
1421
|
+
});
|
|
1422
|
+
}
|
|
1423
|
+
//#endregion
|
|
1424
|
+
//#region src/components/description-list/description-list.styles.ts
|
|
1425
|
+
const descriptionListStyles = tv({
|
|
1426
|
+
slots: {
|
|
1427
|
+
root: "grid w-full",
|
|
1428
|
+
item: "grid min-w-0 gap-1",
|
|
1429
|
+
term: "text-small text-muted-foreground",
|
|
1430
|
+
details: "min-w-0 break-words text-small text-foreground"
|
|
1431
|
+
},
|
|
1432
|
+
variants: {
|
|
1433
|
+
layout: {
|
|
1434
|
+
stacked: { root: "gap-4" },
|
|
1435
|
+
inline: { item: "sm:grid-cols-[minmax(0,12rem)_1fr] sm:gap-4" }
|
|
1436
|
+
},
|
|
1437
|
+
dividers: {
|
|
1438
|
+
true: {
|
|
1439
|
+
root: "gap-0 divide-y divide-border",
|
|
1440
|
+
item: "py-3 first:pt-0 last:pb-0"
|
|
1441
|
+
},
|
|
1442
|
+
false: {}
|
|
1443
|
+
}
|
|
1444
|
+
},
|
|
1445
|
+
compoundVariants: [{
|
|
1446
|
+
layout: "inline",
|
|
1447
|
+
dividers: false,
|
|
1448
|
+
class: { root: "gap-3" }
|
|
1449
|
+
}],
|
|
1450
|
+
defaultVariants: {
|
|
1451
|
+
layout: "stacked",
|
|
1452
|
+
dividers: false
|
|
1453
|
+
}
|
|
1454
|
+
});
|
|
1455
|
+
//#endregion
|
|
1456
|
+
//#region src/components/description-list/description-list.tsx
|
|
1457
|
+
const DescriptionListContext = createContext(null);
|
|
1458
|
+
/**
|
|
1459
|
+
* Label–value pairs, such as account details or order metadata.
|
|
1460
|
+
* `layout="inline"` puts terms and details side by side from the `sm` breakpoint.
|
|
1461
|
+
*/
|
|
1462
|
+
function DescriptionList(inProps) {
|
|
1463
|
+
const [props, slots] = useComponentConfig("DescriptionList", inProps);
|
|
1464
|
+
const { layout, dividers, className, ...rest } = props;
|
|
1465
|
+
const s = descriptionListStyles({
|
|
1466
|
+
layout,
|
|
1467
|
+
dividers
|
|
1468
|
+
});
|
|
1469
|
+
return /* @__PURE__ */ jsx(DescriptionListContext.Provider, {
|
|
1470
|
+
value: {
|
|
1471
|
+
s,
|
|
1472
|
+
slots
|
|
1473
|
+
},
|
|
1474
|
+
children: /* @__PURE__ */ jsx("dl", {
|
|
1475
|
+
"data-slot": "description-list",
|
|
1476
|
+
className: s.root({ class: [slots.root, className] }),
|
|
1477
|
+
...rest
|
|
1478
|
+
})
|
|
1479
|
+
});
|
|
1480
|
+
}
|
|
1481
|
+
function DescriptionItem({ term, children, className, ...props }) {
|
|
1482
|
+
const ctx = useContext(DescriptionListContext);
|
|
1483
|
+
const s = ctx?.s ?? descriptionListStyles();
|
|
1484
|
+
const slots = ctx?.slots ?? {};
|
|
1485
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
1486
|
+
"data-slot": "description-item",
|
|
1487
|
+
className: s.item({ class: [slots.item, className] }),
|
|
1488
|
+
...props,
|
|
1489
|
+
children: [/* @__PURE__ */ jsx("dt", {
|
|
1490
|
+
"data-slot": "description-term",
|
|
1491
|
+
className: s.term({ class: slots.term }),
|
|
1492
|
+
children: term
|
|
1493
|
+
}), /* @__PURE__ */ jsx("dd", {
|
|
1494
|
+
"data-slot": "description-details",
|
|
1495
|
+
className: s.details({ class: slots.details }),
|
|
1496
|
+
children
|
|
1497
|
+
})]
|
|
1498
|
+
});
|
|
1499
|
+
}
|
|
1500
|
+
//#endregion
|
|
1501
|
+
//#region src/components/dialog/close-icon.tsx
|
|
1502
|
+
/** Local close icon so overlay components stay self-contained. */
|
|
1503
|
+
function CloseIcon(props) {
|
|
1504
|
+
return /* @__PURE__ */ jsx("svg", {
|
|
1505
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1506
|
+
width: "16",
|
|
1507
|
+
height: "16",
|
|
1508
|
+
viewBox: "0 0 24 24",
|
|
1509
|
+
fill: "none",
|
|
1510
|
+
stroke: "currentColor",
|
|
1511
|
+
strokeWidth: "2",
|
|
1512
|
+
strokeLinecap: "round",
|
|
1513
|
+
strokeLinejoin: "round",
|
|
1514
|
+
"aria-hidden": "true",
|
|
1515
|
+
...props,
|
|
1516
|
+
children: /* @__PURE__ */ jsx("path", { d: "M18 6 6 18M6 6l12 12" })
|
|
1517
|
+
});
|
|
1518
|
+
}
|
|
1519
|
+
//#endregion
|
|
1520
|
+
//#region src/components/dialog/dialog.styles.ts
|
|
1521
|
+
const dialogStyles = tv({
|
|
1522
|
+
slots: {
|
|
1523
|
+
overlay: "fixed inset-0 z-50 animate-fade-in bg-overlay",
|
|
1524
|
+
content: [
|
|
1525
|
+
"fixed top-1/2 left-1/2 z-50 grid max-h-[calc(100dvh-2rem)] w-[calc(100vw-2rem)] -translate-x-1/2 -translate-y-1/2 gap-5 overflow-y-auto",
|
|
1526
|
+
"rounded-xl border-border bg-surface p-6 text-foreground shadow-lg outline-none animate-pop-in",
|
|
1527
|
+
themedBorder
|
|
1528
|
+
],
|
|
1529
|
+
close: [
|
|
1530
|
+
"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",
|
|
1531
|
+
transition,
|
|
1532
|
+
focusRing
|
|
1533
|
+
],
|
|
1534
|
+
header: "flex flex-col gap-1.5 pr-8",
|
|
1535
|
+
title: "font-display text-h4 text-foreground",
|
|
1536
|
+
description: "text-small text-muted-foreground",
|
|
1537
|
+
body: "min-w-0 text-small text-foreground",
|
|
1538
|
+
footer: "flex flex-col-reverse gap-2 sm:flex-row sm:justify-end"
|
|
1539
|
+
},
|
|
1540
|
+
variants: { size: {
|
|
1541
|
+
sm: { content: "max-w-sm" },
|
|
1542
|
+
md: { content: "max-w-lg" },
|
|
1543
|
+
lg: { content: "max-w-2xl" },
|
|
1544
|
+
xl: { content: "max-w-4xl" }
|
|
1545
|
+
} },
|
|
1546
|
+
defaultVariants: { size: "md" }
|
|
1547
|
+
});
|
|
1548
|
+
//#endregion
|
|
1549
|
+
//#region src/components/dialog/dialog.tsx
|
|
1550
|
+
function useParts$2() {
|
|
1551
|
+
const [, slots] = useComponentConfig("Dialog", {});
|
|
1552
|
+
return {
|
|
1553
|
+
s: dialogStyles(),
|
|
1554
|
+
slots
|
|
1555
|
+
};
|
|
1556
|
+
}
|
|
1557
|
+
/** A modal window. Focus is trapped inside and returns to the trigger on close. */
|
|
1558
|
+
const Dialog = Dialog$1.Root;
|
|
1559
|
+
const DialogTrigger = Dialog$1.Trigger;
|
|
1560
|
+
const DialogClose = Dialog$1.Close;
|
|
1561
|
+
function DialogContent(inProps) {
|
|
1562
|
+
const [props, slots] = useComponentConfig("Dialog", inProps);
|
|
1563
|
+
const { size, showClose = true, overlayClassName, className, children, ...rest } = props;
|
|
1564
|
+
const s = dialogStyles({ size });
|
|
1565
|
+
return /* @__PURE__ */ jsxs(Dialog$1.Portal, { children: [/* @__PURE__ */ jsx(Dialog$1.Overlay, {
|
|
1566
|
+
"data-slot": "dialog-overlay",
|
|
1567
|
+
className: s.overlay({ class: [slots.overlay, overlayClassName] })
|
|
1568
|
+
}), /* @__PURE__ */ jsxs(Dialog$1.Content, {
|
|
1569
|
+
"data-slot": "dialog-content",
|
|
1570
|
+
className: s.content({ class: [slots.content, className] }),
|
|
1571
|
+
...rest,
|
|
1572
|
+
children: [children, showClose && /* @__PURE__ */ jsx(Dialog$1.Close, {
|
|
1573
|
+
"data-slot": "dialog-close",
|
|
1574
|
+
"aria-label": "Close",
|
|
1575
|
+
className: s.close({ class: slots.close }),
|
|
1576
|
+
children: /* @__PURE__ */ jsx(CloseIcon, {})
|
|
1577
|
+
})]
|
|
1578
|
+
})] });
|
|
1579
|
+
}
|
|
1580
|
+
function DialogHeader({ className, ...props }) {
|
|
1581
|
+
const { s, slots } = useParts$2();
|
|
1582
|
+
return /* @__PURE__ */ jsx("div", {
|
|
1583
|
+
"data-slot": "dialog-header",
|
|
1584
|
+
className: s.header({ class: [slots.header, className] }),
|
|
1585
|
+
...props
|
|
1586
|
+
});
|
|
1587
|
+
}
|
|
1588
|
+
function DialogTitle({ className, ...props }) {
|
|
1589
|
+
const { s, slots } = useParts$2();
|
|
1590
|
+
return /* @__PURE__ */ jsx(Dialog$1.Title, {
|
|
1591
|
+
"data-slot": "dialog-title",
|
|
1592
|
+
className: s.title({ class: [slots.title, className] }),
|
|
1593
|
+
...props
|
|
1594
|
+
});
|
|
1595
|
+
}
|
|
1596
|
+
function DialogDescription({ className, ...props }) {
|
|
1597
|
+
const { s, slots } = useParts$2();
|
|
1598
|
+
return /* @__PURE__ */ jsx(Dialog$1.Description, {
|
|
1599
|
+
"data-slot": "dialog-description",
|
|
1600
|
+
className: s.description({ class: [slots.description, className] }),
|
|
1601
|
+
...props
|
|
1602
|
+
});
|
|
1603
|
+
}
|
|
1604
|
+
function DialogBody({ className, ...props }) {
|
|
1605
|
+
const { s, slots } = useParts$2();
|
|
1606
|
+
return /* @__PURE__ */ jsx("div", {
|
|
1607
|
+
"data-slot": "dialog-body",
|
|
1608
|
+
className: s.body({ class: [slots.body, className] }),
|
|
1609
|
+
...props
|
|
1610
|
+
});
|
|
1611
|
+
}
|
|
1612
|
+
function DialogFooter({ className, ...props }) {
|
|
1613
|
+
const { s, slots } = useParts$2();
|
|
1614
|
+
return /* @__PURE__ */ jsx("div", {
|
|
1615
|
+
"data-slot": "dialog-footer",
|
|
1616
|
+
className: s.footer({ class: [slots.footer, className] }),
|
|
1617
|
+
...props
|
|
1618
|
+
});
|
|
1619
|
+
}
|
|
1620
|
+
//#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
|
+
//#region src/components/dropdown-menu/dropdown-menu.tsx
|
|
1656
|
+
function useParts$1(tone, inset) {
|
|
1657
|
+
const [, slots] = useComponentConfig("DropdownMenu", {});
|
|
1658
|
+
return {
|
|
1659
|
+
s: dropdownMenuStyles({
|
|
1660
|
+
tone,
|
|
1661
|
+
inset
|
|
1662
|
+
}),
|
|
1663
|
+
slots
|
|
1664
|
+
};
|
|
1665
|
+
}
|
|
1666
|
+
const svg = {
|
|
1667
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1668
|
+
viewBox: "0 0 24 24",
|
|
1669
|
+
fill: "none",
|
|
1670
|
+
stroke: "currentColor",
|
|
1671
|
+
strokeWidth: 2,
|
|
1672
|
+
strokeLinecap: "round",
|
|
1673
|
+
strokeLinejoin: "round"
|
|
1674
|
+
};
|
|
1675
|
+
const CheckIcon = () => /* @__PURE__ */ jsx("svg", {
|
|
1676
|
+
"aria-hidden": "true",
|
|
1677
|
+
...svg,
|
|
1678
|
+
children: /* @__PURE__ */ jsx("path", { d: "M20 6 9 17l-5-5" })
|
|
1679
|
+
});
|
|
1680
|
+
const DotIcon = () => /* @__PURE__ */ jsx("svg", {
|
|
1681
|
+
"aria-hidden": "true",
|
|
1682
|
+
...svg,
|
|
1683
|
+
children: /* @__PURE__ */ jsx("circle", {
|
|
1684
|
+
cx: "12",
|
|
1685
|
+
cy: "12",
|
|
1686
|
+
r: "4",
|
|
1687
|
+
fill: "currentColor"
|
|
1688
|
+
})
|
|
1689
|
+
});
|
|
1690
|
+
const ChevronRightIcon = () => /* @__PURE__ */ jsx("svg", {
|
|
1691
|
+
"aria-hidden": "true",
|
|
1692
|
+
...svg,
|
|
1693
|
+
children: /* @__PURE__ */ jsx("path", { d: "m9 18 6-6-6-6" })
|
|
1694
|
+
});
|
|
1695
|
+
/** A menu of actions opened from a button: row actions, account menus, "more" buttons. */
|
|
1696
|
+
const DropdownMenu = DropdownMenu$1.Root;
|
|
1697
|
+
const DropdownMenuTrigger = DropdownMenu$1.Trigger;
|
|
1698
|
+
const DropdownMenuGroup = DropdownMenu$1.Group;
|
|
1699
|
+
const DropdownMenuRadioGroup = DropdownMenu$1.RadioGroup;
|
|
1700
|
+
const DropdownMenuSub = DropdownMenu$1.Sub;
|
|
1701
|
+
function DropdownMenuContent(inProps) {
|
|
1702
|
+
const [props, slots] = useComponentConfig("DropdownMenu", inProps);
|
|
1703
|
+
const { sideOffset = 6, align = "start", className, ...rest } = props;
|
|
1704
|
+
const s = dropdownMenuStyles();
|
|
1705
|
+
return /* @__PURE__ */ jsx(DropdownMenu$1.Portal, { children: /* @__PURE__ */ jsx(DropdownMenu$1.Content, {
|
|
1706
|
+
"data-slot": "dropdown-menu-content",
|
|
1707
|
+
sideOffset,
|
|
1708
|
+
align,
|
|
1709
|
+
className: s.content({ class: [slots.content, className] }),
|
|
1710
|
+
...rest
|
|
1711
|
+
}) });
|
|
1712
|
+
}
|
|
1713
|
+
function DropdownMenuItem({ icon, shortcut, tone, inset, className, children, ...props }) {
|
|
1714
|
+
const { s, slots } = useParts$1(tone, inset);
|
|
1715
|
+
return /* @__PURE__ */ jsxs(DropdownMenu$1.Item, {
|
|
1716
|
+
"data-slot": "dropdown-menu-item",
|
|
1717
|
+
"data-tone": tone ?? "default",
|
|
1718
|
+
className: s.item({ class: [slots.item, className] }),
|
|
1719
|
+
...props,
|
|
1720
|
+
children: [
|
|
1721
|
+
icon && /* @__PURE__ */ jsx("span", {
|
|
1722
|
+
className: s.icon({ class: slots.icon }),
|
|
1723
|
+
"aria-hidden": "true",
|
|
1724
|
+
children: icon
|
|
1725
|
+
}),
|
|
1726
|
+
children,
|
|
1727
|
+
shortcut && /* @__PURE__ */ jsx(DropdownMenuShortcut, { children: shortcut })
|
|
1728
|
+
]
|
|
1729
|
+
});
|
|
1730
|
+
}
|
|
1731
|
+
function DropdownMenuCheckboxItem({ className, children, ...props }) {
|
|
1732
|
+
const { s, slots } = useParts$1(void 0, true);
|
|
1733
|
+
return /* @__PURE__ */ jsxs(DropdownMenu$1.CheckboxItem, {
|
|
1734
|
+
"data-slot": "dropdown-menu-checkbox-item",
|
|
1735
|
+
className: s.item({ class: [slots.item, className] }),
|
|
1736
|
+
...props,
|
|
1737
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
1738
|
+
className: s.indicator({ class: slots.indicator }),
|
|
1739
|
+
children: /* @__PURE__ */ jsx(DropdownMenu$1.ItemIndicator, { children: /* @__PURE__ */ jsx(CheckIcon, {}) })
|
|
1740
|
+
}), children]
|
|
1741
|
+
});
|
|
1742
|
+
}
|
|
1743
|
+
function DropdownMenuRadioItem({ className, children, ...props }) {
|
|
1744
|
+
const { s, slots } = useParts$1(void 0, true);
|
|
1745
|
+
return /* @__PURE__ */ jsxs(DropdownMenu$1.RadioItem, {
|
|
1746
|
+
"data-slot": "dropdown-menu-radio-item",
|
|
1747
|
+
className: s.item({ class: [slots.item, className] }),
|
|
1748
|
+
...props,
|
|
1749
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
1750
|
+
className: s.indicator({ class: slots.indicator }),
|
|
1751
|
+
children: /* @__PURE__ */ jsx(DropdownMenu$1.ItemIndicator, { children: /* @__PURE__ */ jsx(DotIcon, {}) })
|
|
1752
|
+
}), children]
|
|
1753
|
+
});
|
|
1754
|
+
}
|
|
1755
|
+
function DropdownMenuLabel({ inset, className, ...props }) {
|
|
1756
|
+
const { s, slots } = useParts$1(void 0, inset);
|
|
1757
|
+
return /* @__PURE__ */ jsx(DropdownMenu$1.Label, {
|
|
1758
|
+
"data-slot": "dropdown-menu-label",
|
|
1759
|
+
className: s.label({ class: [slots.label, className] }),
|
|
1760
|
+
...props
|
|
1761
|
+
});
|
|
1762
|
+
}
|
|
1763
|
+
function DropdownMenuSeparator({ className, ...props }) {
|
|
1764
|
+
const { s, slots } = useParts$1();
|
|
1765
|
+
return /* @__PURE__ */ jsx(DropdownMenu$1.Separator, {
|
|
1766
|
+
"data-slot": "dropdown-menu-separator",
|
|
1767
|
+
className: s.separator({ class: [slots.separator, className] }),
|
|
1768
|
+
...props
|
|
1769
|
+
});
|
|
1770
|
+
}
|
|
1771
|
+
function DropdownMenuShortcut({ className, ...props }) {
|
|
1772
|
+
const { s, slots } = useParts$1();
|
|
1773
|
+
return /* @__PURE__ */ jsx("span", {
|
|
1774
|
+
"data-slot": "dropdown-menu-shortcut",
|
|
1775
|
+
className: s.shortcut({ class: [slots.shortcut, className] }),
|
|
1776
|
+
...props
|
|
1777
|
+
});
|
|
1778
|
+
}
|
|
1779
|
+
function DropdownMenuSubTrigger({ icon, className, children, ...props }) {
|
|
1780
|
+
const { s, slots } = useParts$1();
|
|
1781
|
+
return /* @__PURE__ */ jsxs(DropdownMenu$1.SubTrigger, {
|
|
1782
|
+
"data-slot": "dropdown-menu-sub-trigger",
|
|
1783
|
+
className: s.subTrigger({ class: [slots.subTrigger, className] }),
|
|
1784
|
+
...props,
|
|
1785
|
+
children: [
|
|
1786
|
+
icon && /* @__PURE__ */ jsx("span", {
|
|
1787
|
+
className: s.icon({ class: slots.icon }),
|
|
1788
|
+
"aria-hidden": "true",
|
|
1789
|
+
children: icon
|
|
1790
|
+
}),
|
|
1791
|
+
children,
|
|
1792
|
+
/* @__PURE__ */ jsx("span", {
|
|
1793
|
+
className: "ml-auto flex text-faint-foreground",
|
|
1794
|
+
children: /* @__PURE__ */ jsx(ChevronRightIcon, {})
|
|
1795
|
+
})
|
|
1796
|
+
]
|
|
1797
|
+
});
|
|
1798
|
+
}
|
|
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
|
+
//#endregion
|
|
1833
|
+
//#region src/components/grid/grid.tsx
|
|
1834
|
+
const colClasses = {
|
|
1835
|
+
base: {
|
|
1836
|
+
1: "grid-cols-1",
|
|
1837
|
+
2: "grid-cols-2",
|
|
1838
|
+
3: "grid-cols-3",
|
|
1839
|
+
4: "grid-cols-4",
|
|
1840
|
+
5: "grid-cols-5",
|
|
1841
|
+
6: "grid-cols-6",
|
|
1842
|
+
7: "grid-cols-7",
|
|
1843
|
+
8: "grid-cols-8",
|
|
1844
|
+
9: "grid-cols-9",
|
|
1845
|
+
10: "grid-cols-10",
|
|
1846
|
+
11: "grid-cols-11",
|
|
1847
|
+
12: "grid-cols-12"
|
|
1848
|
+
},
|
|
1849
|
+
sm: {
|
|
1850
|
+
1: "sm:grid-cols-1",
|
|
1851
|
+
2: "sm:grid-cols-2",
|
|
1852
|
+
3: "sm:grid-cols-3",
|
|
1853
|
+
4: "sm:grid-cols-4",
|
|
1854
|
+
5: "sm:grid-cols-5",
|
|
1855
|
+
6: "sm:grid-cols-6",
|
|
1856
|
+
7: "sm:grid-cols-7",
|
|
1857
|
+
8: "sm:grid-cols-8",
|
|
1858
|
+
9: "sm:grid-cols-9",
|
|
1859
|
+
10: "sm:grid-cols-10",
|
|
1860
|
+
11: "sm:grid-cols-11",
|
|
1861
|
+
12: "sm:grid-cols-12"
|
|
1862
|
+
},
|
|
1863
|
+
md: {
|
|
1864
|
+
1: "md:grid-cols-1",
|
|
1865
|
+
2: "md:grid-cols-2",
|
|
1866
|
+
3: "md:grid-cols-3",
|
|
1867
|
+
4: "md:grid-cols-4",
|
|
1868
|
+
5: "md:grid-cols-5",
|
|
1869
|
+
6: "md:grid-cols-6",
|
|
1870
|
+
7: "md:grid-cols-7",
|
|
1871
|
+
8: "md:grid-cols-8",
|
|
1872
|
+
9: "md:grid-cols-9",
|
|
1873
|
+
10: "md:grid-cols-10",
|
|
1874
|
+
11: "md:grid-cols-11",
|
|
1875
|
+
12: "md:grid-cols-12"
|
|
1876
|
+
},
|
|
1877
|
+
lg: {
|
|
1878
|
+
1: "lg:grid-cols-1",
|
|
1879
|
+
2: "lg:grid-cols-2",
|
|
1880
|
+
3: "lg:grid-cols-3",
|
|
1881
|
+
4: "lg:grid-cols-4",
|
|
1882
|
+
5: "lg:grid-cols-5",
|
|
1883
|
+
6: "lg:grid-cols-6",
|
|
1884
|
+
7: "lg:grid-cols-7",
|
|
1885
|
+
8: "lg:grid-cols-8",
|
|
1886
|
+
9: "lg:grid-cols-9",
|
|
1887
|
+
10: "lg:grid-cols-10",
|
|
1888
|
+
11: "lg:grid-cols-11",
|
|
1889
|
+
12: "lg:grid-cols-12"
|
|
1890
|
+
},
|
|
1891
|
+
xl: {
|
|
1892
|
+
1: "xl:grid-cols-1",
|
|
1893
|
+
2: "xl:grid-cols-2",
|
|
1894
|
+
3: "xl:grid-cols-3",
|
|
1895
|
+
4: "xl:grid-cols-4",
|
|
1896
|
+
5: "xl:grid-cols-5",
|
|
1897
|
+
6: "xl:grid-cols-6",
|
|
1898
|
+
7: "xl:grid-cols-7",
|
|
1899
|
+
8: "xl:grid-cols-8",
|
|
1900
|
+
9: "xl:grid-cols-9",
|
|
1901
|
+
10: "xl:grid-cols-10",
|
|
1902
|
+
11: "xl:grid-cols-11",
|
|
1903
|
+
12: "xl:grid-cols-12"
|
|
1904
|
+
}
|
|
1905
|
+
};
|
|
1906
|
+
function colsToClasses(cols) {
|
|
1907
|
+
if (typeof cols === "number") return colClasses.base[cols];
|
|
1908
|
+
return Object.entries(cols).map(([bp, n]) => colClasses[bp][n]).join(" ");
|
|
1909
|
+
}
|
|
1910
|
+
const gridStyles = tv({
|
|
1911
|
+
slots: { base: "grid" },
|
|
1912
|
+
variants: {
|
|
1913
|
+
gap: {
|
|
1914
|
+
0: { base: "gap-0" },
|
|
1915
|
+
1: { base: "gap-1" },
|
|
1916
|
+
2: { base: "gap-2" },
|
|
1917
|
+
3: { base: "gap-3" },
|
|
1918
|
+
4: { base: "gap-4" },
|
|
1919
|
+
5: { base: "gap-5" },
|
|
1920
|
+
6: { base: "gap-6" },
|
|
1921
|
+
8: { base: "gap-8" },
|
|
1922
|
+
10: { base: "gap-10" },
|
|
1923
|
+
12: { base: "gap-12" }
|
|
1924
|
+
},
|
|
1925
|
+
align: {
|
|
1926
|
+
start: { base: "items-start" },
|
|
1927
|
+
center: { base: "items-center" },
|
|
1928
|
+
end: { base: "items-end" },
|
|
1929
|
+
stretch: { base: "items-stretch" }
|
|
1930
|
+
}
|
|
1931
|
+
},
|
|
1932
|
+
defaultVariants: { gap: 4 }
|
|
1933
|
+
});
|
|
1934
|
+
/** Responsive equal-width columns with spacing from the scale. */
|
|
1935
|
+
function Grid(inProps) {
|
|
1936
|
+
const [props, slots] = useComponentConfig("Grid", inProps);
|
|
1937
|
+
const { cols = 1, gap, align, asChild, className, ...rest } = props;
|
|
1938
|
+
const Comp = asChild ? Slot.Root : "div";
|
|
1939
|
+
return /* @__PURE__ */ jsx(Comp, {
|
|
1940
|
+
"data-slot": "grid",
|
|
1941
|
+
className: gridStyles({
|
|
1942
|
+
gap,
|
|
1943
|
+
align
|
|
1944
|
+
}).base({ class: [
|
|
1945
|
+
colsToClasses(cols),
|
|
1946
|
+
slots.base,
|
|
1947
|
+
className
|
|
1948
|
+
] }),
|
|
1949
|
+
...rest
|
|
1950
|
+
});
|
|
1951
|
+
}
|
|
1952
|
+
//#endregion
|
|
1953
|
+
//#region src/components/heading/heading.styles.ts
|
|
1954
|
+
const headingStyles = tv({
|
|
1955
|
+
slots: { base: "font-display text-balance text-foreground" },
|
|
1956
|
+
variants: { size: {
|
|
1957
|
+
display: { base: "text-display" },
|
|
1958
|
+
h1: { base: "text-h1" },
|
|
1959
|
+
h2: { base: "text-h2" },
|
|
1960
|
+
h3: { base: "text-h3" },
|
|
1961
|
+
h4: { base: "text-h4" }
|
|
1962
|
+
} }
|
|
1963
|
+
});
|
|
1964
|
+
//#endregion
|
|
1965
|
+
//#region src/components/heading/heading.tsx
|
|
1966
|
+
const sizeForLevel = {
|
|
1967
|
+
1: "h1",
|
|
1968
|
+
2: "h2",
|
|
1969
|
+
3: "h3",
|
|
1970
|
+
4: "h4",
|
|
1971
|
+
5: "h4",
|
|
1972
|
+
6: "h4"
|
|
1973
|
+
};
|
|
1974
|
+
/** A heading whose semantic level and visual size are set independently. */
|
|
1975
|
+
function Heading(inProps) {
|
|
1976
|
+
const [props, slots] = useComponentConfig("Heading", inProps);
|
|
1977
|
+
const { level = 2, size, asChild, className, ...rest } = props;
|
|
1978
|
+
const s = headingStyles({ size: size ?? sizeForLevel[level] });
|
|
1979
|
+
const Comp = asChild ? Slot.Root : `h${level}`;
|
|
1980
|
+
return /* @__PURE__ */ jsx(Comp, {
|
|
1981
|
+
"data-slot": "heading",
|
|
1982
|
+
className: s.base({ class: [slots.base, className] }),
|
|
1983
|
+
...rest
|
|
1984
|
+
});
|
|
1985
|
+
}
|
|
1986
|
+
//#endregion
|
|
1987
|
+
//#region src/components/link/link.styles.ts
|
|
1988
|
+
const linkStyles = tv({
|
|
1989
|
+
slots: {
|
|
1990
|
+
base: [
|
|
1991
|
+
"inline-flex items-baseline gap-1 rounded-xs font-medium",
|
|
1992
|
+
"bg-[linear-gradient(currentColor,currentColor)] bg-[position:0_100%] bg-no-repeat",
|
|
1993
|
+
"transition-[background-size,color] duration-(--glyph-duration-base) ease-standard",
|
|
1994
|
+
focusRing
|
|
1995
|
+
],
|
|
1996
|
+
icon: "size-3 shrink-0 self-center opacity-70"
|
|
1997
|
+
},
|
|
1998
|
+
variants: {
|
|
1999
|
+
tone: {
|
|
2000
|
+
default: { base: "text-foreground" },
|
|
2001
|
+
muted: { base: "text-muted-foreground hover:text-foreground" },
|
|
2002
|
+
primary: { base: "text-primary" }
|
|
2003
|
+
},
|
|
2004
|
+
underline: {
|
|
2005
|
+
hover: { base: "bg-[length:0%_1px] hover:bg-[length:100%_1px] focus-visible:bg-[length:100%_1px]" },
|
|
2006
|
+
always: { base: "bg-[length:100%_1px] hover:bg-[length:100%_2px]" },
|
|
2007
|
+
none: { base: "bg-none" }
|
|
2008
|
+
}
|
|
2009
|
+
},
|
|
2010
|
+
defaultVariants: {
|
|
2011
|
+
tone: "primary",
|
|
2012
|
+
underline: "hover"
|
|
2013
|
+
}
|
|
2014
|
+
});
|
|
2015
|
+
//#endregion
|
|
2016
|
+
//#region src/components/link/link.tsx
|
|
2017
|
+
const ExternalIcon = (props) => /* @__PURE__ */ jsx("svg", {
|
|
2018
|
+
viewBox: "0 0 24 24",
|
|
2019
|
+
fill: "none",
|
|
2020
|
+
stroke: "currentColor",
|
|
2021
|
+
strokeWidth: "2",
|
|
2022
|
+
strokeLinecap: "round",
|
|
2023
|
+
strokeLinejoin: "round",
|
|
2024
|
+
"aria-hidden": "true",
|
|
2025
|
+
...props,
|
|
2026
|
+
children: /* @__PURE__ */ jsx("path", { d: "M7 17 17 7M7 7h10v10" })
|
|
2027
|
+
});
|
|
2028
|
+
/**
|
|
2029
|
+
* A text link with an animated underline. Internal links go through the provider's
|
|
2030
|
+
* `linkComponent` (your router); external links render a plain `<a>`.
|
|
2031
|
+
*/
|
|
2032
|
+
function Link(inProps) {
|
|
2033
|
+
const [props, slots] = useComponentConfig("Link", inProps);
|
|
2034
|
+
const { href, external = false, tone, underline, className, children, ...rest } = props;
|
|
2035
|
+
const RouterLink = useLinkComponent();
|
|
2036
|
+
const s = linkStyles({
|
|
2037
|
+
tone,
|
|
2038
|
+
underline
|
|
2039
|
+
});
|
|
2040
|
+
const classes = s.base({ class: [slots.base, className] });
|
|
2041
|
+
if (external) return /* @__PURE__ */ jsxs("a", {
|
|
2042
|
+
"data-slot": "link",
|
|
2043
|
+
href,
|
|
2044
|
+
target: "_blank",
|
|
2045
|
+
rel: "noopener noreferrer",
|
|
2046
|
+
className: classes,
|
|
2047
|
+
...rest,
|
|
2048
|
+
children: [
|
|
2049
|
+
children,
|
|
2050
|
+
/* @__PURE__ */ jsx(ExternalIcon, { className: s.icon({ class: slots.icon }) }),
|
|
2051
|
+
" ",
|
|
2052
|
+
/* @__PURE__ */ jsx("span", {
|
|
2053
|
+
className: "sr-only",
|
|
2054
|
+
children: "(opens in a new tab)"
|
|
2055
|
+
})
|
|
2056
|
+
]
|
|
2057
|
+
});
|
|
2058
|
+
return /* @__PURE__ */ jsx(RouterLink, {
|
|
2059
|
+
"data-slot": "link",
|
|
2060
|
+
href,
|
|
2061
|
+
className: classes,
|
|
2062
|
+
...rest,
|
|
2063
|
+
children
|
|
2064
|
+
});
|
|
2065
|
+
}
|
|
2066
|
+
//#endregion
|
|
2067
|
+
//#region src/components/pagination/pagination.styles.ts
|
|
2068
|
+
const paginationStyles = tv({
|
|
2069
|
+
slots: {
|
|
2070
|
+
root: "flex",
|
|
2071
|
+
list: "flex flex-wrap items-center gap-1",
|
|
2072
|
+
item: [
|
|
2073
|
+
"inline-flex shrink-0 cursor-pointer select-none items-center justify-center rounded-md font-medium tabular-nums text-muted-foreground",
|
|
2074
|
+
transition,
|
|
2075
|
+
focusRing,
|
|
2076
|
+
"hover:bg-muted hover:text-foreground",
|
|
2077
|
+
"aria-[current=page]:bg-primary aria-[current=page]:text-primary-foreground aria-[current=page]:shadow-xs",
|
|
2078
|
+
"disabled:pointer-events-none disabled:opacity-40 aria-disabled:pointer-events-none aria-disabled:opacity-40",
|
|
2079
|
+
"[&>svg]:size-4"
|
|
2080
|
+
],
|
|
2081
|
+
ellipsis: "inline-flex items-center justify-center text-faint-foreground"
|
|
2082
|
+
},
|
|
2083
|
+
variants: { size: {
|
|
2084
|
+
sm: {
|
|
2085
|
+
item: "h-(--glyph-control-sm) min-w-(--glyph-control-sm) px-1.5 text-small",
|
|
2086
|
+
ellipsis: "h-(--glyph-control-sm) w-(--glyph-control-sm) text-small"
|
|
2087
|
+
},
|
|
2088
|
+
md: {
|
|
2089
|
+
item: "h-(--glyph-control-md) min-w-(--glyph-control-md) px-2 text-small",
|
|
2090
|
+
ellipsis: "h-(--glyph-control-md) w-(--glyph-control-md) text-small"
|
|
2091
|
+
}
|
|
2092
|
+
} },
|
|
2093
|
+
defaultVariants: { size: "md" }
|
|
2094
|
+
});
|
|
2095
|
+
//#endregion
|
|
2096
|
+
//#region src/components/pagination/pagination-range.ts
|
|
2097
|
+
/**
|
|
2098
|
+
* The page numbers to show, with `'ellipsis'` for gaps. Always includes the first and
|
|
2099
|
+
* last page and `siblingCount` pages on each side of the current one, and keeps the
|
|
2100
|
+
* number of items constant so the control doesn't jump in width.
|
|
2101
|
+
*
|
|
2102
|
+
* `paginationRange(6, 20)` → `[1, 'ellipsis', 5, 6, 7, 'ellipsis', 20]`
|
|
2103
|
+
*/
|
|
2104
|
+
function paginationRange(page, pageCount, siblingCount = 1) {
|
|
2105
|
+
const count = Math.max(0, Math.floor(pageCount));
|
|
2106
|
+
if (count === 0) return [];
|
|
2107
|
+
const current = Math.min(Math.max(1, Math.floor(page)), count);
|
|
2108
|
+
if (count <= siblingCount * 2 + 5) return range(1, count);
|
|
2109
|
+
const left = Math.max(current - siblingCount, 1);
|
|
2110
|
+
const right = Math.min(current + siblingCount, count);
|
|
2111
|
+
const showLeftGap = left > 2;
|
|
2112
|
+
const showRightGap = right < count - 1;
|
|
2113
|
+
const edge = 3 + siblingCount * 2;
|
|
2114
|
+
if (!showLeftGap && showRightGap) return [
|
|
2115
|
+
...range(1, edge),
|
|
2116
|
+
"ellipsis",
|
|
2117
|
+
count
|
|
2118
|
+
];
|
|
2119
|
+
if (showLeftGap && !showRightGap) return [
|
|
2120
|
+
1,
|
|
2121
|
+
"ellipsis",
|
|
2122
|
+
...range(count - edge + 1, count)
|
|
2123
|
+
];
|
|
2124
|
+
return [
|
|
2125
|
+
1,
|
|
2126
|
+
"ellipsis",
|
|
2127
|
+
...range(left, right),
|
|
2128
|
+
"ellipsis",
|
|
2129
|
+
count
|
|
2130
|
+
];
|
|
2131
|
+
}
|
|
2132
|
+
function range(from, to) {
|
|
2133
|
+
return Array.from({ length: to - from + 1 }, (_, i) => from + i);
|
|
2134
|
+
}
|
|
2135
|
+
//#endregion
|
|
2136
|
+
//#region src/components/pagination/pagination.tsx
|
|
2137
|
+
const ChevronsLeftIcon = () => /* @__PURE__ */ jsx("svg", {
|
|
2138
|
+
viewBox: "0 0 24 24",
|
|
2139
|
+
fill: "none",
|
|
2140
|
+
stroke: "currentColor",
|
|
2141
|
+
strokeWidth: "2",
|
|
2142
|
+
strokeLinecap: "round",
|
|
2143
|
+
strokeLinejoin: "round",
|
|
2144
|
+
"aria-hidden": "true",
|
|
2145
|
+
children: /* @__PURE__ */ jsx("path", { d: "m11 17-5-5 5-5M18 17l-5-5 5-5" })
|
|
2146
|
+
});
|
|
2147
|
+
const ChevronsRightIcon = () => /* @__PURE__ */ jsx("svg", {
|
|
2148
|
+
viewBox: "0 0 24 24",
|
|
2149
|
+
fill: "none",
|
|
2150
|
+
stroke: "currentColor",
|
|
2151
|
+
strokeWidth: "2",
|
|
2152
|
+
strokeLinecap: "round",
|
|
2153
|
+
strokeLinejoin: "round",
|
|
2154
|
+
"aria-hidden": "true",
|
|
2155
|
+
children: /* @__PURE__ */ jsx("path", { d: "m6 17 5-5-5-5M13 17l5-5-5-5" })
|
|
2156
|
+
});
|
|
2157
|
+
/** Page navigation for long lists. Controlled: you own `page`. */
|
|
2158
|
+
function Pagination(inProps) {
|
|
2159
|
+
const [props, slots] = useComponentConfig("Pagination", inProps);
|
|
2160
|
+
const { page, pageCount, onPageChange, getHref, siblingCount = 1, showEdges = true, size, className, ...rest } = props;
|
|
2161
|
+
const Link = useLinkComponent();
|
|
2162
|
+
const s = paginationStyles({ size });
|
|
2163
|
+
const itemClass = s.item({ class: slots.item });
|
|
2164
|
+
const current = Math.min(Math.max(1, page), Math.max(1, pageCount));
|
|
2165
|
+
const control = (target, label, content, options = {}) => {
|
|
2166
|
+
const disabled = target < 1 || target > pageCount || target === current && !options.current;
|
|
2167
|
+
const shared = {
|
|
2168
|
+
"aria-label": label,
|
|
2169
|
+
"aria-current": options.current ? "page" : void 0,
|
|
2170
|
+
className: itemClass
|
|
2171
|
+
};
|
|
2172
|
+
if (getHref) {
|
|
2173
|
+
if (disabled) return /* @__PURE__ */ jsx("span", {
|
|
2174
|
+
"aria-disabled": "true",
|
|
2175
|
+
...shared,
|
|
2176
|
+
children: content
|
|
2177
|
+
});
|
|
2178
|
+
return /* @__PURE__ */ jsx(Link, {
|
|
2179
|
+
href: getHref(target),
|
|
2180
|
+
onClick: () => onPageChange?.(target),
|
|
2181
|
+
...shared,
|
|
2182
|
+
children: content
|
|
2183
|
+
});
|
|
2184
|
+
}
|
|
2185
|
+
return /* @__PURE__ */ jsx("button", {
|
|
2186
|
+
type: "button",
|
|
2187
|
+
disabled,
|
|
2188
|
+
onClick: () => onPageChange?.(target),
|
|
2189
|
+
...shared,
|
|
2190
|
+
children: content
|
|
2191
|
+
});
|
|
2192
|
+
};
|
|
2193
|
+
return /* @__PURE__ */ jsx("nav", {
|
|
2194
|
+
"aria-label": "Pagination",
|
|
2195
|
+
"data-slot": "pagination",
|
|
2196
|
+
className: s.root({ class: [slots.root, className] }),
|
|
2197
|
+
...rest,
|
|
2198
|
+
children: /* @__PURE__ */ jsxs("ul", {
|
|
2199
|
+
className: s.list({ class: slots.list }),
|
|
2200
|
+
children: [
|
|
2201
|
+
showEdges && /* @__PURE__ */ jsx("li", { children: control(1, "First page", /* @__PURE__ */ jsx(ChevronsLeftIcon, {})) }),
|
|
2202
|
+
/* @__PURE__ */ jsx("li", { children: control(current - 1, "Previous page", /* @__PURE__ */ jsx(ChevronLeftIcon, {})) }),
|
|
2203
|
+
paginationRange(current, pageCount, siblingCount).map((item, index) => item === "ellipsis" ? /* @__PURE__ */ jsx("li", {
|
|
2204
|
+
className: s.ellipsis({ class: slots.ellipsis }),
|
|
2205
|
+
"aria-hidden": "true",
|
|
2206
|
+
children: "…"
|
|
2207
|
+
}, `gap-${index}`) : /* @__PURE__ */ jsx("li", { children: control(item, `Page ${item}`, item, { current: item === current }) }, item)),
|
|
2208
|
+
/* @__PURE__ */ jsx("li", { children: control(current + 1, "Next page", /* @__PURE__ */ jsx(ChevronRightIcon$1, {})) }),
|
|
2209
|
+
showEdges && /* @__PURE__ */ jsx("li", { children: control(pageCount, "Last page", /* @__PURE__ */ jsx(ChevronsRightIcon, {})) })
|
|
2210
|
+
]
|
|
2211
|
+
})
|
|
2212
|
+
});
|
|
2213
|
+
}
|
|
2214
|
+
//#endregion
|
|
2215
|
+
//#region src/components/popover/popover.tsx
|
|
2216
|
+
const popoverStyles = tv({ slots: {
|
|
2217
|
+
content: [popover, "w-72 max-w-[calc(100vw-2rem)] overflow-visible p-4 text-small outline-none"],
|
|
2218
|
+
arrow: "fill-raised"
|
|
2219
|
+
} });
|
|
2220
|
+
/** Floating content anchored to a trigger: quick settings, details, small forms. */
|
|
2221
|
+
const Popover = Popover$1.Root;
|
|
2222
|
+
const PopoverTrigger = Popover$1.Trigger;
|
|
2223
|
+
const PopoverAnchor = Popover$1.Anchor;
|
|
2224
|
+
const PopoverClose = Popover$1.Close;
|
|
2225
|
+
function PopoverContent(inProps) {
|
|
2226
|
+
const [props, slots] = useComponentConfig("Popover", inProps);
|
|
2227
|
+
const { showArrow = false, sideOffset = 6, align = "center", className, children, ...rest } = props;
|
|
2228
|
+
const s = popoverStyles();
|
|
2229
|
+
return /* @__PURE__ */ jsx(Popover$1.Portal, { children: /* @__PURE__ */ jsxs(Popover$1.Content, {
|
|
2230
|
+
"data-slot": "popover-content",
|
|
2231
|
+
sideOffset,
|
|
2232
|
+
align,
|
|
2233
|
+
className: s.content({ class: [slots.content, className] }),
|
|
2234
|
+
...rest,
|
|
2235
|
+
children: [children, showArrow && /* @__PURE__ */ jsx(Popover$1.Arrow, {
|
|
2236
|
+
width: 12,
|
|
2237
|
+
height: 6,
|
|
2238
|
+
className: s.arrow({ class: slots.arrow })
|
|
2239
|
+
})]
|
|
2240
|
+
}) });
|
|
2241
|
+
}
|
|
2242
|
+
//#endregion
|
|
2243
|
+
//#region src/components/progress/progress.styles.ts
|
|
2244
|
+
const progressStyles = tv({
|
|
2245
|
+
slots: {
|
|
2246
|
+
root: "grid w-full gap-1.5",
|
|
2247
|
+
header: "flex items-baseline justify-between gap-3 text-small",
|
|
2248
|
+
label: "font-medium text-foreground",
|
|
2249
|
+
value: "tabular-nums text-muted-foreground",
|
|
2250
|
+
track: "relative w-full overflow-hidden rounded-pill bg-muted",
|
|
2251
|
+
indicator: ["h-full w-full rounded-pill transition-transform duration-(--glyph-duration-slow) ease-standard", "data-[state=indeterminate]:w-1/3 data-[state=indeterminate]:animate-pulse"]
|
|
2252
|
+
},
|
|
2253
|
+
variants: {
|
|
2254
|
+
size: {
|
|
2255
|
+
sm: { track: "h-1" },
|
|
2256
|
+
md: { track: "h-2" },
|
|
2257
|
+
lg: { track: "h-3" }
|
|
2258
|
+
},
|
|
2259
|
+
tone: {
|
|
2260
|
+
primary: { indicator: "bg-primary" },
|
|
2261
|
+
neutral: { indicator: "bg-foreground" },
|
|
2262
|
+
success: { indicator: "bg-success" },
|
|
2263
|
+
warning: { indicator: "bg-warning" },
|
|
2264
|
+
danger: { indicator: "bg-danger" }
|
|
2265
|
+
}
|
|
2266
|
+
},
|
|
2267
|
+
defaultVariants: {
|
|
2268
|
+
size: "md",
|
|
2269
|
+
tone: "primary"
|
|
2270
|
+
}
|
|
2271
|
+
});
|
|
2272
|
+
const progressCircleStyles = tv({
|
|
2273
|
+
slots: {
|
|
2274
|
+
root: "relative inline-flex shrink-0 items-center justify-center",
|
|
2275
|
+
svg: "size-full -rotate-90",
|
|
2276
|
+
track: "stroke-muted",
|
|
2277
|
+
indicator: "stroke-current transition-[stroke-dashoffset] duration-(--glyph-duration-slow) ease-standard",
|
|
2278
|
+
value: "absolute font-medium tabular-nums text-foreground"
|
|
2279
|
+
},
|
|
2280
|
+
variants: {
|
|
2281
|
+
size: {
|
|
2282
|
+
sm: {
|
|
2283
|
+
root: "size-6",
|
|
2284
|
+
value: "hidden"
|
|
2285
|
+
},
|
|
2286
|
+
md: {
|
|
2287
|
+
root: "size-10",
|
|
2288
|
+
value: "text-[0.625rem]"
|
|
2289
|
+
},
|
|
2290
|
+
lg: {
|
|
2291
|
+
root: "size-16",
|
|
2292
|
+
value: "text-small"
|
|
2293
|
+
}
|
|
2294
|
+
},
|
|
2295
|
+
tone: {
|
|
2296
|
+
primary: { indicator: "text-primary" },
|
|
2297
|
+
neutral: { indicator: "text-foreground" },
|
|
2298
|
+
success: { indicator: "text-success" },
|
|
2299
|
+
warning: { indicator: "text-warning" },
|
|
2300
|
+
danger: { indicator: "text-danger" }
|
|
2301
|
+
}
|
|
2302
|
+
},
|
|
2303
|
+
defaultVariants: {
|
|
2304
|
+
size: "md",
|
|
2305
|
+
tone: "primary"
|
|
2306
|
+
}
|
|
2307
|
+
});
|
|
2308
|
+
//#endregion
|
|
2309
|
+
//#region src/components/progress/progress.tsx
|
|
2310
|
+
function clampPercent(value, max) {
|
|
2311
|
+
if (max <= 0) return 0;
|
|
2312
|
+
return Math.min(100, Math.max(0, value / max * 100));
|
|
2313
|
+
}
|
|
2314
|
+
const defaultFormat = (value, max) => `${Math.round(clampPercent(value, max))}%`;
|
|
2315
|
+
/** A horizontal bar showing how far a task has progressed. */
|
|
2316
|
+
function Progress(inProps) {
|
|
2317
|
+
const [props, slots] = useComponentConfig("Progress", inProps);
|
|
2318
|
+
const { value = null, max = 100, label, showValue = false, formatValue = defaultFormat, size, tone, className, "aria-label": ariaLabel, ...rest } = props;
|
|
2319
|
+
const labelId = useId();
|
|
2320
|
+
const s = progressStyles({
|
|
2321
|
+
size,
|
|
2322
|
+
tone
|
|
2323
|
+
});
|
|
2324
|
+
const determinate = typeof value === "number";
|
|
2325
|
+
const percent = determinate ? clampPercent(value, max) : 0;
|
|
2326
|
+
const valueText = determinate ? formatValue(value, max) : void 0;
|
|
2327
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
2328
|
+
"data-slot": "progress",
|
|
2329
|
+
className: s.root({ class: [slots.root, className] }),
|
|
2330
|
+
...rest,
|
|
2331
|
+
children: [(label || showValue && valueText) && /* @__PURE__ */ jsxs("div", {
|
|
2332
|
+
"data-slot": "progress-header",
|
|
2333
|
+
className: s.header({ class: slots.header }),
|
|
2334
|
+
children: [label && /* @__PURE__ */ jsx("span", {
|
|
2335
|
+
id: labelId,
|
|
2336
|
+
className: s.label({ class: slots.label }),
|
|
2337
|
+
children: label
|
|
2338
|
+
}), showValue && valueText && /* @__PURE__ */ jsx("span", {
|
|
2339
|
+
className: s.value({ class: slots.value }),
|
|
2340
|
+
"aria-hidden": "true",
|
|
2341
|
+
children: valueText
|
|
2342
|
+
})]
|
|
2343
|
+
}), /* @__PURE__ */ jsx(Progress$1.Root, {
|
|
2344
|
+
"data-slot": "progress-track",
|
|
2345
|
+
value: determinate ? Math.min(Math.max(value, 0), max) : null,
|
|
2346
|
+
max,
|
|
2347
|
+
getValueLabel: (v, m) => formatValue(v, m),
|
|
2348
|
+
"aria-labelledby": label ? labelId : void 0,
|
|
2349
|
+
"aria-label": label ? void 0 : ariaLabel,
|
|
2350
|
+
className: s.track({ class: slots.track }),
|
|
2351
|
+
children: /* @__PURE__ */ jsx(Progress$1.Indicator, {
|
|
2352
|
+
"data-slot": "progress-indicator",
|
|
2353
|
+
className: s.indicator({ class: slots.indicator }),
|
|
2354
|
+
style: determinate ? { transform: `translateX(-${100 - percent}%)` } : void 0
|
|
2355
|
+
})
|
|
2356
|
+
})]
|
|
2357
|
+
});
|
|
2358
|
+
}
|
|
2359
|
+
const RADIUS = 16;
|
|
2360
|
+
const CIRCUMFERENCE = 2 * Math.PI * RADIUS;
|
|
2361
|
+
/** A compact ring for progress or a share of a total. */
|
|
2362
|
+
function ProgressCircle(inProps) {
|
|
2363
|
+
const [props, slots] = useComponentConfig("ProgressCircle", inProps);
|
|
2364
|
+
const { value, max = 100, showValue = false, formatValue = defaultFormat, size, tone, className, ...rest } = props;
|
|
2365
|
+
const s = progressCircleStyles({
|
|
2366
|
+
size,
|
|
2367
|
+
tone
|
|
2368
|
+
});
|
|
2369
|
+
const percent = clampPercent(value, max);
|
|
2370
|
+
const valueText = formatValue(value, max);
|
|
2371
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
2372
|
+
"data-slot": "progress-circle",
|
|
2373
|
+
role: "progressbar",
|
|
2374
|
+
"aria-valuemin": 0,
|
|
2375
|
+
"aria-valuemax": max,
|
|
2376
|
+
"aria-valuenow": Math.min(Math.max(value, 0), max),
|
|
2377
|
+
"aria-valuetext": valueText,
|
|
2378
|
+
className: s.root({ class: [slots.root, className] }),
|
|
2379
|
+
...rest,
|
|
2380
|
+
children: [/* @__PURE__ */ jsxs("svg", {
|
|
2381
|
+
viewBox: "0 0 40 40",
|
|
2382
|
+
className: s.svg({ class: slots.svg }),
|
|
2383
|
+
"aria-hidden": "true",
|
|
2384
|
+
children: [/* @__PURE__ */ jsx("circle", {
|
|
2385
|
+
cx: "20",
|
|
2386
|
+
cy: "20",
|
|
2387
|
+
r: RADIUS,
|
|
2388
|
+
fill: "none",
|
|
2389
|
+
strokeWidth: "4",
|
|
2390
|
+
className: s.track({ class: slots.track })
|
|
2391
|
+
}), /* @__PURE__ */ jsx("circle", {
|
|
2392
|
+
cx: "20",
|
|
2393
|
+
cy: "20",
|
|
2394
|
+
r: RADIUS,
|
|
2395
|
+
fill: "none",
|
|
2396
|
+
strokeWidth: "4",
|
|
2397
|
+
strokeLinecap: "round",
|
|
2398
|
+
strokeDasharray: CIRCUMFERENCE,
|
|
2399
|
+
strokeDashoffset: CIRCUMFERENCE * (1 - percent / 100),
|
|
2400
|
+
className: s.indicator({ class: slots.indicator })
|
|
2401
|
+
})]
|
|
2402
|
+
}), showValue && /* @__PURE__ */ jsx("span", {
|
|
2403
|
+
className: s.value({ class: slots.value }),
|
|
2404
|
+
"aria-hidden": "true",
|
|
2405
|
+
children: valueText
|
|
2406
|
+
})]
|
|
302
2407
|
});
|
|
303
2408
|
}
|
|
304
2409
|
//#endregion
|
|
305
|
-
//#region src/components/
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
2410
|
+
//#region src/components/prose/prose.tsx
|
|
2411
|
+
/**
|
|
2412
|
+
* Element styles for long-form content. Every value comes from theme tokens, so articles
|
|
2413
|
+
* pick up the theme's display font, type scale, colors and radius.
|
|
2414
|
+
*/
|
|
2415
|
+
const proseStyles = tv({
|
|
2416
|
+
slots: { base: [
|
|
2417
|
+
"text-foreground [&>:first-child]:mt-0 [&>:last-child]:mb-0",
|
|
2418
|
+
"[&_h1]:mt-[1.4em] [&_h1]:mb-[0.5em] [&_h1]:font-display [&_h1]:text-h1 [&_h1]:text-balance",
|
|
2419
|
+
"[&_h2]:mt-[1.6em] [&_h2]:mb-[0.5em] [&_h2]:font-display [&_h2]:text-h2 [&_h2]:text-balance",
|
|
2420
|
+
"[&_h3]:mt-[1.5em] [&_h3]:mb-[0.4em] [&_h3]:font-display [&_h3]:text-h3 [&_h3]:text-balance",
|
|
2421
|
+
"[&_h4]:mt-[1.4em] [&_h4]:mb-[0.4em] [&_h4]:font-display [&_h4]:text-h4",
|
|
2422
|
+
"[&_p]:my-[1em] [&_p]:text-pretty",
|
|
2423
|
+
"[&_strong]:font-semibold [&_strong]:text-foreground",
|
|
2424
|
+
"[&_a]:font-medium [&_a]:text-primary [&_a]:underline [&_a]:decoration-primary/40 [&_a]:underline-offset-4 [&_a:hover]:decoration-primary",
|
|
2425
|
+
"[&_ul]:my-[1em] [&_ul]:list-disc [&_ul]:pl-[1.5em] [&_ol]:my-[1em] [&_ol]:list-decimal [&_ol]:pl-[1.5em]",
|
|
2426
|
+
"[&_li]:my-[0.35em] [&_li]:pl-[0.25em] [&_li::marker]:text-faint-foreground",
|
|
2427
|
+
"[&_blockquote]:my-[1.5em] [&_blockquote]:border-l-2 [&_blockquote]:border-primary [&_blockquote]:pl-[1em] [&_blockquote]:font-display [&_blockquote]:text-muted-foreground",
|
|
2428
|
+
"[&_:not(pre)>code]:rounded-xs [&_:not(pre)>code]:bg-muted [&_:not(pre)>code]:px-[0.3em] [&_:not(pre)>code]:py-[0.15em] [&_:not(pre)>code]:font-mono [&_:not(pre)>code]:text-[0.875em]",
|
|
2429
|
+
"[&_pre]:my-[1.5em] [&_pre]:overflow-x-auto [&_pre]:rounded-lg [&_pre]:border [&_pre]:border-border [&_pre]:bg-subtle [&_pre]:p-4 [&_pre]:font-mono [&_pre]:text-small [&_pre]:leading-relaxed",
|
|
2430
|
+
"[&_hr]:my-[2em] [&_hr]:border-border",
|
|
2431
|
+
"[&_img]:my-[1.5em] [&_img]:max-w-full [&_img]:rounded-lg",
|
|
2432
|
+
"[&_figure]:my-[1.75em] [&_figure_img]:my-0 [&_figcaption]:mt-2 [&_figcaption]:text-small [&_figcaption]:text-faint-foreground",
|
|
2433
|
+
"[&_table]:my-[1.5em] [&_table]:w-full [&_table]:border-collapse [&_table]:text-small [&_table]:tabular-nums",
|
|
2434
|
+
"[&_th]:border-b [&_th]:border-border-strong [&_th]:px-3 [&_th]:py-2 [&_th]:text-left [&_th]:font-medium",
|
|
2435
|
+
"[&_td]:border-b [&_td]:border-border [&_td]:px-3 [&_td]:py-2 [&_td]:align-top"
|
|
2436
|
+
] },
|
|
2437
|
+
variants: {
|
|
2438
|
+
size: {
|
|
2439
|
+
sm: { base: "text-small [&_blockquote]:text-body" },
|
|
2440
|
+
md: { base: "text-body [&_blockquote]:text-lead" },
|
|
2441
|
+
lg: { base: "text-lead [&_blockquote]:text-h4" }
|
|
2442
|
+
},
|
|
2443
|
+
fullWidth: {
|
|
2444
|
+
true: { base: "max-w-none" },
|
|
2445
|
+
false: { base: "max-w-prose" }
|
|
2446
|
+
}
|
|
2447
|
+
},
|
|
2448
|
+
defaultVariants: {
|
|
2449
|
+
size: "md",
|
|
2450
|
+
fullWidth: false
|
|
2451
|
+
}
|
|
313
2452
|
});
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
const
|
|
320
|
-
const
|
|
321
|
-
const Comp = asChild ? Slot.Root : "
|
|
2453
|
+
/**
|
|
2454
|
+
* Styles raw HTML or MDX (headings, lists, links, quotes, code, tables, images) from theme
|
|
2455
|
+
* tokens. Wrap rendered Markdown or CMS content in it.
|
|
2456
|
+
*/
|
|
2457
|
+
function Prose(inProps) {
|
|
2458
|
+
const [props, slots] = useComponentConfig("Prose", inProps);
|
|
2459
|
+
const { size, fullWidth, asChild, className, ...rest } = props;
|
|
2460
|
+
const Comp = asChild ? Slot.Root : "div";
|
|
322
2461
|
return /* @__PURE__ */ jsx(Comp, {
|
|
323
|
-
"data-slot": "
|
|
324
|
-
className:
|
|
2462
|
+
"data-slot": "prose",
|
|
2463
|
+
className: proseStyles({
|
|
2464
|
+
size,
|
|
2465
|
+
fullWidth
|
|
2466
|
+
}).base({ class: [slots.base, className] }),
|
|
325
2467
|
...rest
|
|
326
2468
|
});
|
|
327
2469
|
}
|
|
328
2470
|
//#endregion
|
|
329
|
-
//#region src/components/
|
|
330
|
-
const
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
2471
|
+
//#region src/components/radio-group/radio-group.styles.ts
|
|
2472
|
+
const control = [
|
|
2473
|
+
"mt-0.5 inline-flex size-4 shrink-0 items-center justify-center rounded-pill border-input bg-surface shadow-xs",
|
|
2474
|
+
themedBorder,
|
|
2475
|
+
transition
|
|
2476
|
+
];
|
|
2477
|
+
const radioGroupStyles = tv({
|
|
2478
|
+
slots: {
|
|
2479
|
+
root: "",
|
|
2480
|
+
option: "flex items-start gap-2.5",
|
|
2481
|
+
control: [
|
|
2482
|
+
...control,
|
|
2483
|
+
focusRing,
|
|
2484
|
+
"peer cursor-pointer hover:border-border-strong aria-invalid:border-danger",
|
|
2485
|
+
"data-[state=checked]:border-primary disabled:cursor-not-allowed disabled:opacity-50"
|
|
2486
|
+
],
|
|
2487
|
+
indicator: "flex size-full items-center justify-center after:block after:size-2 after:rounded-pill after:bg-primary",
|
|
2488
|
+
text: "grid gap-0.5",
|
|
2489
|
+
label: "cursor-pointer text-small font-medium text-foreground peer-disabled:cursor-not-allowed peer-disabled:opacity-60",
|
|
2490
|
+
description: "text-small text-faint-foreground",
|
|
2491
|
+
card: [
|
|
2492
|
+
"group relative flex w-full cursor-pointer items-start gap-3 rounded-lg border-border bg-surface p-4 text-left shadow-xs",
|
|
2493
|
+
themedBorder,
|
|
2494
|
+
transition,
|
|
2495
|
+
focusRing,
|
|
2496
|
+
"hover:border-border-strong",
|
|
2497
|
+
"data-[state=checked]:border-primary data-[state=checked]:ring-1 data-[state=checked]:ring-primary",
|
|
2498
|
+
"disabled:cursor-not-allowed disabled:opacity-50"
|
|
2499
|
+
],
|
|
2500
|
+
cardControl: [...control, "group-data-[state=checked]:border-primary"]
|
|
2501
|
+
},
|
|
2502
|
+
variants: {
|
|
2503
|
+
orientation: {
|
|
2504
|
+
vertical: { root: "grid gap-3" },
|
|
2505
|
+
horizontal: { root: "flex flex-wrap gap-x-5 gap-y-3" }
|
|
2506
|
+
},
|
|
2507
|
+
variant: {
|
|
2508
|
+
default: {},
|
|
2509
|
+
card: {}
|
|
2510
|
+
}
|
|
2511
|
+
},
|
|
2512
|
+
compoundVariants: [{
|
|
2513
|
+
variant: "card",
|
|
2514
|
+
orientation: "horizontal",
|
|
2515
|
+
class: { root: "grid grid-cols-[repeat(auto-fit,minmax(12rem,1fr))] gap-3" }
|
|
2516
|
+
}],
|
|
2517
|
+
defaultVariants: {
|
|
2518
|
+
orientation: "vertical",
|
|
2519
|
+
variant: "default"
|
|
2520
|
+
}
|
|
339
2521
|
});
|
|
340
2522
|
//#endregion
|
|
341
|
-
//#region src/components/
|
|
342
|
-
const
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
}
|
|
350
|
-
/**
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
const
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
2523
|
+
//#region src/components/radio-group/radio-group.tsx
|
|
2524
|
+
const RadioGroupContext = createContext(null);
|
|
2525
|
+
function useRadioGroupContext() {
|
|
2526
|
+
return useContext(RadioGroupContext) ?? {
|
|
2527
|
+
s: radioGroupStyles(),
|
|
2528
|
+
slots: {},
|
|
2529
|
+
variant: "default"
|
|
2530
|
+
};
|
|
2531
|
+
}
|
|
2532
|
+
/**
|
|
2533
|
+
* Pick exactly one option from a short visible list. `variant="card"` turns each option
|
|
2534
|
+
* into a bordered card with a title and description.
|
|
2535
|
+
*/
|
|
2536
|
+
function RadioGroup(inProps) {
|
|
2537
|
+
const [props, slots] = useComponentConfig("RadioGroup", useFieldControl(inProps));
|
|
2538
|
+
const { variant = "default", orientation = "vertical", onValueChange, className, ...rest } = props;
|
|
2539
|
+
const s = radioGroupStyles({
|
|
2540
|
+
variant,
|
|
2541
|
+
orientation
|
|
2542
|
+
});
|
|
2543
|
+
return /* @__PURE__ */ jsx(RadioGroupContext.Provider, {
|
|
2544
|
+
value: {
|
|
2545
|
+
s,
|
|
2546
|
+
slots,
|
|
2547
|
+
variant
|
|
2548
|
+
},
|
|
2549
|
+
children: /* @__PURE__ */ jsx(RadioGroup$1.Root, {
|
|
2550
|
+
"data-slot": "radio-group",
|
|
2551
|
+
"data-variant": variant,
|
|
2552
|
+
orientation,
|
|
2553
|
+
...onValueChange && { onValueChange: (value) => onValueChange(value) },
|
|
2554
|
+
className: s.root({ class: [slots.root, className] }),
|
|
2555
|
+
...rest
|
|
2556
|
+
})
|
|
2557
|
+
});
|
|
2558
|
+
}
|
|
2559
|
+
function RadioGroupItem({ label, description, children, className, id, ...props }) {
|
|
2560
|
+
const { s, slots, variant } = useRadioGroupContext();
|
|
2561
|
+
const generated = useId();
|
|
2562
|
+
const itemId = id ?? generated;
|
|
2563
|
+
const descriptionId = description ? `${itemId}-description` : void 0;
|
|
2564
|
+
if (variant === "card") return /* @__PURE__ */ jsxs(RadioGroup$1.Item, {
|
|
2565
|
+
id: itemId,
|
|
2566
|
+
"data-slot": "radio-group-card",
|
|
2567
|
+
"aria-describedby": descriptionId,
|
|
2568
|
+
className: s.card({ class: [slots.card, className] }),
|
|
2569
|
+
...props,
|
|
2570
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
2571
|
+
className: s.cardControl({ class: slots.cardControl }),
|
|
2572
|
+
"aria-hidden": "true",
|
|
2573
|
+
children: /* @__PURE__ */ jsx(RadioGroup$1.Indicator, { className: s.indicator({ class: slots.indicator }) })
|
|
2574
|
+
}), /* @__PURE__ */ jsxs("span", {
|
|
2575
|
+
className: s.text({ class: slots.text }),
|
|
2576
|
+
children: [
|
|
2577
|
+
label && /* @__PURE__ */ jsx("span", {
|
|
2578
|
+
className: s.label({ class: slots.label }),
|
|
2579
|
+
children: label
|
|
2580
|
+
}),
|
|
2581
|
+
description && /* @__PURE__ */ jsx("span", {
|
|
2582
|
+
id: descriptionId,
|
|
2583
|
+
className: s.description({ class: slots.description }),
|
|
2584
|
+
children: description
|
|
2585
|
+
}),
|
|
2586
|
+
children
|
|
2587
|
+
]
|
|
2588
|
+
})]
|
|
2589
|
+
});
|
|
2590
|
+
const control = /* @__PURE__ */ jsx(RadioGroup$1.Item, {
|
|
2591
|
+
id: itemId,
|
|
2592
|
+
"data-slot": "radio-group-item",
|
|
2593
|
+
"aria-describedby": descriptionId,
|
|
2594
|
+
className: s.control({ class: [slots.control, !label && className] }),
|
|
2595
|
+
...props,
|
|
2596
|
+
children: /* @__PURE__ */ jsx(RadioGroup$1.Indicator, { className: s.indicator({ class: slots.indicator }) })
|
|
2597
|
+
});
|
|
2598
|
+
if (!label) return control;
|
|
2599
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
2600
|
+
"data-slot": "radio-group-option",
|
|
2601
|
+
className: s.option({ class: [slots.option, className] }),
|
|
2602
|
+
children: [control, /* @__PURE__ */ jsxs("span", {
|
|
2603
|
+
className: s.text({ class: slots.text }),
|
|
2604
|
+
children: [/* @__PURE__ */ jsx("label", {
|
|
2605
|
+
htmlFor: itemId,
|
|
2606
|
+
className: s.label({ class: slots.label }),
|
|
2607
|
+
children: label
|
|
2608
|
+
}), description && /* @__PURE__ */ jsx("span", {
|
|
2609
|
+
id: descriptionId,
|
|
2610
|
+
className: s.description({ class: slots.description }),
|
|
2611
|
+
children: description
|
|
2612
|
+
})]
|
|
2613
|
+
})]
|
|
360
2614
|
});
|
|
361
2615
|
}
|
|
362
2616
|
//#endregion
|
|
363
|
-
//#region src/components/
|
|
364
|
-
const
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
"data-
|
|
370
|
-
|
|
371
|
-
|
|
2617
|
+
//#region src/components/scroll-area/scroll-area.tsx
|
|
2618
|
+
const scrollAreaStyles = tv({ slots: {
|
|
2619
|
+
root: "relative overflow-hidden",
|
|
2620
|
+
viewport: ["size-full rounded-[inherit]", focusRing],
|
|
2621
|
+
scrollbar: [
|
|
2622
|
+
"flex touch-none select-none p-px transition-colors duration-(--glyph-duration-fast)",
|
|
2623
|
+
"data-[orientation=vertical]:h-full data-[orientation=vertical]:w-2.5 data-[orientation=vertical]:border-l data-[orientation=vertical]:border-l-transparent",
|
|
2624
|
+
"data-[orientation=horizontal]:h-2.5 data-[orientation=horizontal]:flex-col data-[orientation=horizontal]:border-t data-[orientation=horizontal]:border-t-transparent"
|
|
2625
|
+
],
|
|
2626
|
+
thumb: "relative flex-1 rounded-pill bg-border-strong hover:bg-faint-foreground",
|
|
2627
|
+
corner: "bg-transparent"
|
|
2628
|
+
} });
|
|
2629
|
+
/**
|
|
2630
|
+
* A scrollable region with slim, theme-colored scrollbars. Give it a height (or width)
|
|
2631
|
+
* with `className`, e.g. `h-72`.
|
|
2632
|
+
*/
|
|
2633
|
+
function ScrollArea(inProps) {
|
|
2634
|
+
const [props, slots] = useComponentConfig("ScrollArea", inProps);
|
|
2635
|
+
const { orientation = "vertical", viewportClassName, className, children, ...rest } = props;
|
|
2636
|
+
const s = scrollAreaStyles();
|
|
2637
|
+
const bar = (o) => /* @__PURE__ */ jsx(ScrollArea$1.Scrollbar, {
|
|
2638
|
+
"data-slot": "scroll-area-scrollbar",
|
|
2639
|
+
orientation: o,
|
|
2640
|
+
className: s.scrollbar({ class: slots.scrollbar }),
|
|
2641
|
+
children: /* @__PURE__ */ jsx(ScrollArea$1.Thumb, { className: s.thumb({ class: slots.thumb }) })
|
|
2642
|
+
});
|
|
2643
|
+
return /* @__PURE__ */ jsxs(ScrollArea$1.Root, {
|
|
2644
|
+
"data-slot": "scroll-area",
|
|
2645
|
+
className: s.root({ class: [slots.root, className] }),
|
|
2646
|
+
...rest,
|
|
2647
|
+
children: [
|
|
2648
|
+
/* @__PURE__ */ jsx(ScrollArea$1.Viewport, {
|
|
2649
|
+
"data-slot": "scroll-area-viewport",
|
|
2650
|
+
className: s.viewport({ class: [slots.viewport, viewportClassName] }),
|
|
2651
|
+
children
|
|
2652
|
+
}),
|
|
2653
|
+
orientation !== "horizontal" && bar("vertical"),
|
|
2654
|
+
orientation !== "vertical" && bar("horizontal"),
|
|
2655
|
+
/* @__PURE__ */ jsx(ScrollArea$1.Corner, { className: s.corner({ class: slots.corner }) })
|
|
2656
|
+
]
|
|
372
2657
|
});
|
|
373
2658
|
}
|
|
374
2659
|
//#endregion
|
|
@@ -532,7 +2817,7 @@ function SelectItem({ className, children, ...props }) {
|
|
|
532
2817
|
...props,
|
|
533
2818
|
children: [/* @__PURE__ */ jsx(Select$1.ItemText, { children }), /* @__PURE__ */ jsx(Select$1.ItemIndicator, {
|
|
534
2819
|
className: s.indicator({ class: slots.indicator }),
|
|
535
|
-
children: /* @__PURE__ */ jsx(CheckIcon, {})
|
|
2820
|
+
children: /* @__PURE__ */ jsx(CheckIcon$1, {})
|
|
536
2821
|
})]
|
|
537
2822
|
});
|
|
538
2823
|
}
|
|
@@ -558,6 +2843,217 @@ function Separator(inProps) {
|
|
|
558
2843
|
});
|
|
559
2844
|
}
|
|
560
2845
|
//#endregion
|
|
2846
|
+
//#region src/components/sheet/sheet.styles.ts
|
|
2847
|
+
const sheetStyles = tv({
|
|
2848
|
+
slots: {
|
|
2849
|
+
overlay: "fixed inset-0 z-50 animate-fade-in bg-overlay",
|
|
2850
|
+
content: ["fixed z-50 flex flex-col gap-5 border-border bg-surface p-6 text-foreground shadow-lg outline-none", "transition-[translate] duration-(--glyph-duration-slow) ease-standard"],
|
|
2851
|
+
close: [
|
|
2852
|
+
"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
|
+
transition,
|
|
2854
|
+
focusRing
|
|
2855
|
+
],
|
|
2856
|
+
header: "flex flex-col gap-1.5 pr-8",
|
|
2857
|
+
title: "font-display text-h4 text-foreground",
|
|
2858
|
+
description: "text-small text-muted-foreground",
|
|
2859
|
+
body: "-mx-6 min-h-0 flex-1 overflow-y-auto px-6 text-small",
|
|
2860
|
+
footer: "mt-auto flex flex-col-reverse gap-2 sm:flex-row sm:justify-end"
|
|
2861
|
+
},
|
|
2862
|
+
variants: {
|
|
2863
|
+
side: {
|
|
2864
|
+
right: { content: "inset-y-0 right-0 h-full w-full border-l-(length:--glyph-border-width) starting:translate-x-full" },
|
|
2865
|
+
left: { content: "inset-y-0 left-0 h-full w-full border-r-(length:--glyph-border-width) starting:-translate-x-full" },
|
|
2866
|
+
top: { content: "inset-x-0 top-0 max-h-[85dvh] border-b-(length:--glyph-border-width) starting:-translate-y-full" },
|
|
2867
|
+
bottom: { content: "inset-x-0 bottom-0 max-h-[85dvh] rounded-t-xl border-t-(length:--glyph-border-width) starting:translate-y-full" }
|
|
2868
|
+
},
|
|
2869
|
+
size: {
|
|
2870
|
+
sm: {},
|
|
2871
|
+
md: {},
|
|
2872
|
+
lg: {},
|
|
2873
|
+
xl: {}
|
|
2874
|
+
}
|
|
2875
|
+
},
|
|
2876
|
+
compoundVariants: [
|
|
2877
|
+
{
|
|
2878
|
+
side: ["left", "right"],
|
|
2879
|
+
size: "sm",
|
|
2880
|
+
class: { content: "sm:max-w-sm" }
|
|
2881
|
+
},
|
|
2882
|
+
{
|
|
2883
|
+
side: ["left", "right"],
|
|
2884
|
+
size: "md",
|
|
2885
|
+
class: { content: "sm:max-w-md" }
|
|
2886
|
+
},
|
|
2887
|
+
{
|
|
2888
|
+
side: ["left", "right"],
|
|
2889
|
+
size: "lg",
|
|
2890
|
+
class: { content: "sm:max-w-xl" }
|
|
2891
|
+
},
|
|
2892
|
+
{
|
|
2893
|
+
side: ["left", "right"],
|
|
2894
|
+
size: "xl",
|
|
2895
|
+
class: { content: "sm:max-w-3xl" }
|
|
2896
|
+
}
|
|
2897
|
+
],
|
|
2898
|
+
defaultVariants: {
|
|
2899
|
+
side: "right",
|
|
2900
|
+
size: "md"
|
|
2901
|
+
}
|
|
2902
|
+
});
|
|
2903
|
+
//#endregion
|
|
2904
|
+
//#region src/components/sheet/sheet.tsx
|
|
2905
|
+
function useParts() {
|
|
2906
|
+
const [, slots] = useComponentConfig("Sheet", {});
|
|
2907
|
+
return {
|
|
2908
|
+
s: sheetStyles(),
|
|
2909
|
+
slots
|
|
2910
|
+
};
|
|
2911
|
+
}
|
|
2912
|
+
/** A panel that slides in from an edge: filters, details, settings, mobile navigation. */
|
|
2913
|
+
const Sheet = Dialog$1.Root;
|
|
2914
|
+
const SheetTrigger = Dialog$1.Trigger;
|
|
2915
|
+
const SheetClose = Dialog$1.Close;
|
|
2916
|
+
function SheetContent(inProps) {
|
|
2917
|
+
const [props, slots] = useComponentConfig("Sheet", inProps);
|
|
2918
|
+
const { side, size, showClose = true, overlayClassName, className, children, ...rest } = props;
|
|
2919
|
+
const s = sheetStyles({
|
|
2920
|
+
side,
|
|
2921
|
+
size
|
|
2922
|
+
});
|
|
2923
|
+
return /* @__PURE__ */ jsxs(Dialog$1.Portal, { children: [/* @__PURE__ */ jsx(Dialog$1.Overlay, {
|
|
2924
|
+
"data-slot": "sheet-overlay",
|
|
2925
|
+
className: s.overlay({ class: [slots.overlay, overlayClassName] })
|
|
2926
|
+
}), /* @__PURE__ */ jsxs(Dialog$1.Content, {
|
|
2927
|
+
"data-slot": "sheet-content",
|
|
2928
|
+
"data-side": side ?? "right",
|
|
2929
|
+
className: s.content({ class: [slots.content, className] }),
|
|
2930
|
+
...rest,
|
|
2931
|
+
children: [children, showClose && /* @__PURE__ */ jsx(Dialog$1.Close, {
|
|
2932
|
+
"data-slot": "sheet-close",
|
|
2933
|
+
"aria-label": "Close",
|
|
2934
|
+
className: s.close({ class: slots.close }),
|
|
2935
|
+
children: /* @__PURE__ */ jsx(CloseIcon, {})
|
|
2936
|
+
})]
|
|
2937
|
+
})] });
|
|
2938
|
+
}
|
|
2939
|
+
function SheetHeader({ className, ...props }) {
|
|
2940
|
+
const { s, slots } = useParts();
|
|
2941
|
+
return /* @__PURE__ */ jsx("div", {
|
|
2942
|
+
"data-slot": "sheet-header",
|
|
2943
|
+
className: s.header({ class: [slots.header, className] }),
|
|
2944
|
+
...props
|
|
2945
|
+
});
|
|
2946
|
+
}
|
|
2947
|
+
function SheetTitle({ className, ...props }) {
|
|
2948
|
+
const { s, slots } = useParts();
|
|
2949
|
+
return /* @__PURE__ */ jsx(Dialog$1.Title, {
|
|
2950
|
+
"data-slot": "sheet-title",
|
|
2951
|
+
className: s.title({ class: [slots.title, className] }),
|
|
2952
|
+
...props
|
|
2953
|
+
});
|
|
2954
|
+
}
|
|
2955
|
+
function SheetDescription({ className, ...props }) {
|
|
2956
|
+
const { s, slots } = useParts();
|
|
2957
|
+
return /* @__PURE__ */ jsx(Dialog$1.Description, {
|
|
2958
|
+
"data-slot": "sheet-description",
|
|
2959
|
+
className: s.description({ class: [slots.description, className] }),
|
|
2960
|
+
...props
|
|
2961
|
+
});
|
|
2962
|
+
}
|
|
2963
|
+
function SheetBody({ className, ...props }) {
|
|
2964
|
+
const { s, slots } = useParts();
|
|
2965
|
+
return /* @__PURE__ */ jsx("div", {
|
|
2966
|
+
"data-slot": "sheet-body",
|
|
2967
|
+
className: s.body({ class: [slots.body, className] }),
|
|
2968
|
+
...props
|
|
2969
|
+
});
|
|
2970
|
+
}
|
|
2971
|
+
function SheetFooter({ className, ...props }) {
|
|
2972
|
+
const { s, slots } = useParts();
|
|
2973
|
+
return /* @__PURE__ */ jsx("div", {
|
|
2974
|
+
"data-slot": "sheet-footer",
|
|
2975
|
+
className: s.footer({ class: [slots.footer, className] }),
|
|
2976
|
+
...props
|
|
2977
|
+
});
|
|
2978
|
+
}
|
|
2979
|
+
//#endregion
|
|
2980
|
+
//#region src/components/slider/slider.styles.ts
|
|
2981
|
+
const sliderStyles = tv({
|
|
2982
|
+
slots: {
|
|
2983
|
+
wrapper: "grid w-full gap-1.5",
|
|
2984
|
+
root: "relative flex h-5 w-full touch-none select-none items-center data-disabled:cursor-not-allowed data-disabled:opacity-50",
|
|
2985
|
+
track: "relative h-1.5 w-full grow overflow-hidden rounded-pill bg-muted",
|
|
2986
|
+
range: "absolute h-full bg-primary",
|
|
2987
|
+
thumb: [
|
|
2988
|
+
"relative block size-4 cursor-grab rounded-pill border-2 border-primary bg-background shadow-sm outline-none active:cursor-grabbing",
|
|
2989
|
+
"transition-[box-shadow] duration-(--glyph-duration-fast) ease-standard",
|
|
2990
|
+
"hover:ring-4 hover:ring-ring/15 focus-visible:ring-4 focus-visible:ring-ring/30",
|
|
2991
|
+
"data-disabled:cursor-not-allowed"
|
|
2992
|
+
],
|
|
2993
|
+
value: "pointer-events-none absolute bottom-full left-1/2 mb-2 -translate-x-1/2 whitespace-nowrap rounded-xs bg-secondary px-1.5 py-0.5 font-mono text-caption text-secondary-foreground tabular-nums",
|
|
2994
|
+
marks: "relative h-4 w-full",
|
|
2995
|
+
mark: "absolute top-0 -translate-x-1/2 text-caption text-faint-foreground tabular-nums"
|
|
2996
|
+
},
|
|
2997
|
+
variants: { showValue: { true: { wrapper: "pt-7" } } }
|
|
2998
|
+
});
|
|
2999
|
+
//#endregion
|
|
3000
|
+
//#region src/components/slider/slider.tsx
|
|
3001
|
+
const toArray = (value) => value === void 0 ? void 0 : typeof value === "number" ? [value] : [...value];
|
|
3002
|
+
/** Choose a number, or a range with two thumbs, by dragging or with arrow keys. */
|
|
3003
|
+
function Slider(inProps) {
|
|
3004
|
+
const [props, slots] = useComponentConfig("Slider", useFieldControl(inProps));
|
|
3005
|
+
const { value, defaultValue, onValueChange, onValueCommit, min = 0, max = 100, step = 1, minStepsBetweenThumbs, marks, showValue = false, disabled, name, id, className, thumbLabels = ["Minimum", "Maximum"], "aria-label": ariaLabel, "aria-describedby": ariaDescribedBy, "aria-invalid": ariaInvalid } = props;
|
|
3006
|
+
const isRange = Array.isArray(value ?? defaultValue);
|
|
3007
|
+
const fromArray = (next) => isRange ? [next[0], next[1]] : next[0];
|
|
3008
|
+
const current = toArray(value) ?? toArray(defaultValue) ?? [min];
|
|
3009
|
+
const s = sliderStyles({ showValue: Boolean(showValue) });
|
|
3010
|
+
const format = typeof showValue === "function" ? showValue : (n) => n;
|
|
3011
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
3012
|
+
"data-slot": "slider",
|
|
3013
|
+
className: s.wrapper({ class: [slots.wrapper, className] }),
|
|
3014
|
+
children: [/* @__PURE__ */ jsxs(Slider$1.Root, {
|
|
3015
|
+
className: s.root({ class: slots.root }),
|
|
3016
|
+
min,
|
|
3017
|
+
max,
|
|
3018
|
+
step,
|
|
3019
|
+
disabled,
|
|
3020
|
+
name,
|
|
3021
|
+
...minStepsBetweenThumbs !== void 0 && { minStepsBetweenThumbs },
|
|
3022
|
+
...value !== void 0 && { value: toArray(value) },
|
|
3023
|
+
...defaultValue !== void 0 && { defaultValue: toArray(defaultValue) },
|
|
3024
|
+
...onValueChange && { onValueChange: (next) => onValueChange(fromArray(next)) },
|
|
3025
|
+
...onValueCommit && { onValueCommit: (next) => onValueCommit(fromArray(next)) },
|
|
3026
|
+
children: [/* @__PURE__ */ jsx(Slider$1.Track, {
|
|
3027
|
+
className: s.track({ class: slots.track }),
|
|
3028
|
+
children: /* @__PURE__ */ jsx(Slider$1.Range, { className: s.range({ class: slots.range }) })
|
|
3029
|
+
}), current.map((thumbValue, index) => /* @__PURE__ */ jsx(Slider$1.Thumb, {
|
|
3030
|
+
id: index === 0 ? id : void 0,
|
|
3031
|
+
"aria-label": isRange ? thumbLabels[index] : ariaLabel,
|
|
3032
|
+
"aria-describedby": ariaDescribedBy,
|
|
3033
|
+
"aria-invalid": ariaInvalid,
|
|
3034
|
+
className: s.thumb({ class: slots.thumb }),
|
|
3035
|
+
children: showValue && /* @__PURE__ */ jsx("span", {
|
|
3036
|
+
className: s.value({ class: slots.value }),
|
|
3037
|
+
"aria-hidden": "true",
|
|
3038
|
+
children: format(thumbValue)
|
|
3039
|
+
})
|
|
3040
|
+
}, index))]
|
|
3041
|
+
}), marks && marks.length > 0 && /* @__PURE__ */ jsx("div", {
|
|
3042
|
+
className: s.marks({ class: slots.marks }),
|
|
3043
|
+
"aria-hidden": "true",
|
|
3044
|
+
children: marks.map((mark) => {
|
|
3045
|
+
const m = typeof mark === "number" ? { value: mark } : mark;
|
|
3046
|
+
const percent = (m.value - min) / (max - min || 1) * 100;
|
|
3047
|
+
return /* @__PURE__ */ jsx("span", {
|
|
3048
|
+
className: s.mark({ class: slots.mark }),
|
|
3049
|
+
style: { left: `${percent}%` },
|
|
3050
|
+
children: m.label ?? m.value
|
|
3051
|
+
}, m.value);
|
|
3052
|
+
})
|
|
3053
|
+
})]
|
|
3054
|
+
});
|
|
3055
|
+
}
|
|
3056
|
+
//#endregion
|
|
561
3057
|
//#region src/components/stack/stack.tsx
|
|
562
3058
|
const stackStyles = tv({
|
|
563
3059
|
base: "flex",
|
|
@@ -615,6 +3111,94 @@ function Stack({ direction, gap, align, justify, wrap, asChild, className, ...pr
|
|
|
615
3111
|
});
|
|
616
3112
|
}
|
|
617
3113
|
//#endregion
|
|
3114
|
+
//#region src/components/stat-card/stat-card.styles.ts
|
|
3115
|
+
const statCardStyles = tv({ slots: {
|
|
3116
|
+
root: "gap-2",
|
|
3117
|
+
header: "flex items-center justify-between gap-2",
|
|
3118
|
+
label: "text-small text-muted-foreground",
|
|
3119
|
+
icon: "flex size-8 shrink-0 items-center justify-center rounded-md bg-muted text-muted-foreground [&>svg]:size-4",
|
|
3120
|
+
valueRow: "flex flex-wrap items-baseline gap-x-2 gap-y-1",
|
|
3121
|
+
value: "font-display text-h2 tabular-nums text-foreground",
|
|
3122
|
+
delta: "gap-1 [&>svg]:size-3",
|
|
3123
|
+
description: "text-small text-faint-foreground",
|
|
3124
|
+
chart: "mt-1 min-w-0 text-primary"
|
|
3125
|
+
} });
|
|
3126
|
+
//#endregion
|
|
3127
|
+
//#region src/components/stat-card/stat-card.tsx
|
|
3128
|
+
const ArrowUp = () => /* @__PURE__ */ jsx("svg", {
|
|
3129
|
+
viewBox: "0 0 24 24",
|
|
3130
|
+
fill: "none",
|
|
3131
|
+
stroke: "currentColor",
|
|
3132
|
+
strokeWidth: "2.5",
|
|
3133
|
+
strokeLinecap: "round",
|
|
3134
|
+
strokeLinejoin: "round",
|
|
3135
|
+
"aria-hidden": "true",
|
|
3136
|
+
children: /* @__PURE__ */ jsx("path", { d: "M7 17 17 7M8 7h9v9" })
|
|
3137
|
+
});
|
|
3138
|
+
const ArrowDown = () => /* @__PURE__ */ jsx("svg", {
|
|
3139
|
+
viewBox: "0 0 24 24",
|
|
3140
|
+
fill: "none",
|
|
3141
|
+
stroke: "currentColor",
|
|
3142
|
+
strokeWidth: "2.5",
|
|
3143
|
+
strokeLinecap: "round",
|
|
3144
|
+
strokeLinejoin: "round",
|
|
3145
|
+
"aria-hidden": "true",
|
|
3146
|
+
children: /* @__PURE__ */ jsx("path", { d: "M7 7l10 10M17 8v9H8" })
|
|
3147
|
+
});
|
|
3148
|
+
function deltaTone(trend, invert) {
|
|
3149
|
+
if (trend === "neutral") return "neutral";
|
|
3150
|
+
return trend === "up" !== invert ? "success" : "danger";
|
|
3151
|
+
}
|
|
3152
|
+
/** A key metric with its label, change versus the last period, and an optional chart. */
|
|
3153
|
+
function StatCard(inProps) {
|
|
3154
|
+
const [props, slots] = useComponentConfig("StatCard", inProps);
|
|
3155
|
+
const { label, value, delta, trend = "neutral", invertTrend = false, icon, description, chart, className, ...cardProps } = props;
|
|
3156
|
+
const s = statCardStyles();
|
|
3157
|
+
return /* @__PURE__ */ jsxs(Card, {
|
|
3158
|
+
"data-slot": "stat-card",
|
|
3159
|
+
className: s.root({ class: [slots.root, className] }),
|
|
3160
|
+
...cardProps,
|
|
3161
|
+
children: [
|
|
3162
|
+
/* @__PURE__ */ jsxs("div", {
|
|
3163
|
+
className: s.header({ class: slots.header }),
|
|
3164
|
+
children: [/* @__PURE__ */ jsx("p", {
|
|
3165
|
+
className: s.label({ class: slots.label }),
|
|
3166
|
+
children: label
|
|
3167
|
+
}), icon && /* @__PURE__ */ jsx("span", {
|
|
3168
|
+
className: s.icon({ class: slots.icon }),
|
|
3169
|
+
"aria-hidden": "true",
|
|
3170
|
+
children: icon
|
|
3171
|
+
})]
|
|
3172
|
+
}),
|
|
3173
|
+
/* @__PURE__ */ jsxs("div", {
|
|
3174
|
+
className: s.valueRow({ class: slots.valueRow }),
|
|
3175
|
+
children: [/* @__PURE__ */ jsx("p", {
|
|
3176
|
+
"data-slot": "stat-card-value",
|
|
3177
|
+
className: s.value({ class: slots.value }),
|
|
3178
|
+
children: value
|
|
3179
|
+
}), delta !== void 0 && /* @__PURE__ */ jsxs(Badge, {
|
|
3180
|
+
"data-trend": trend,
|
|
3181
|
+
tone: deltaTone(trend, invertTrend),
|
|
3182
|
+
className: s.delta({ class: slots.delta }),
|
|
3183
|
+
children: [
|
|
3184
|
+
trend === "up" && /* @__PURE__ */ jsx(ArrowUp, {}),
|
|
3185
|
+
trend === "down" && /* @__PURE__ */ jsx(ArrowDown, {}),
|
|
3186
|
+
delta
|
|
3187
|
+
]
|
|
3188
|
+
})]
|
|
3189
|
+
}),
|
|
3190
|
+
description && /* @__PURE__ */ jsx("p", {
|
|
3191
|
+
className: s.description({ class: slots.description }),
|
|
3192
|
+
children: description
|
|
3193
|
+
}),
|
|
3194
|
+
chart && /* @__PURE__ */ jsx("div", {
|
|
3195
|
+
className: s.chart({ class: slots.chart }),
|
|
3196
|
+
children: chart
|
|
3197
|
+
})
|
|
3198
|
+
]
|
|
3199
|
+
});
|
|
3200
|
+
}
|
|
3201
|
+
//#endregion
|
|
618
3202
|
//#region src/components/switch/switch.tsx
|
|
619
3203
|
const switchStyles = tv({
|
|
620
3204
|
slots: {
|
|
@@ -789,6 +3373,74 @@ function Textarea(inProps) {
|
|
|
789
3373
|
});
|
|
790
3374
|
}
|
|
791
3375
|
//#endregion
|
|
3376
|
+
//#region src/components/toast/toast.tsx
|
|
3377
|
+
const toastStyles = tv({ slots: {
|
|
3378
|
+
toast: ["group flex w-(--width) items-start gap-3 rounded-lg border-border bg-raised p-4 text-small text-foreground shadow-lg", themedBorder],
|
|
3379
|
+
content: "flex min-w-0 flex-1 flex-col gap-0.5",
|
|
3380
|
+
title: "font-medium text-foreground",
|
|
3381
|
+
description: "text-muted-foreground",
|
|
3382
|
+
icon: "mt-0.5 flex size-4 shrink-0 items-center justify-center [&>svg]:size-4",
|
|
3383
|
+
actionButton: [
|
|
3384
|
+
"inline-flex h-7 shrink-0 cursor-pointer items-center rounded-sm bg-primary px-2.5 text-caption font-medium text-primary-foreground hover:bg-primary/88",
|
|
3385
|
+
transition,
|
|
3386
|
+
focusRing
|
|
3387
|
+
],
|
|
3388
|
+
cancelButton: [
|
|
3389
|
+
"inline-flex h-7 shrink-0 cursor-pointer items-center rounded-sm bg-muted px-2.5 text-caption font-medium text-muted-foreground hover:text-foreground",
|
|
3390
|
+
transition,
|
|
3391
|
+
focusRing
|
|
3392
|
+
],
|
|
3393
|
+
closeButton: [
|
|
3394
|
+
"absolute -top-2 -left-2 flex size-5 cursor-pointer items-center justify-center rounded-pill border-border bg-raised text-muted-foreground shadow-xs hover:text-foreground [&>svg]:size-3",
|
|
3395
|
+
themedBorder,
|
|
3396
|
+
focusRing
|
|
3397
|
+
],
|
|
3398
|
+
success: "[&_[data-icon]]:text-success",
|
|
3399
|
+
error: "[&_[data-icon]]:text-danger",
|
|
3400
|
+
warning: "[&_[data-icon]]:text-warning",
|
|
3401
|
+
info: "[&_[data-icon]]:text-info",
|
|
3402
|
+
loading: "[&_[data-icon]]:text-muted-foreground"
|
|
3403
|
+
} });
|
|
3404
|
+
/**
|
|
3405
|
+
* Renders toasts sent with `toast()`. Mount once near the root. Styled entirely by the
|
|
3406
|
+
* theme's tokens, so it follows the theme and color mode automatically.
|
|
3407
|
+
*
|
|
3408
|
+
* ```tsx
|
|
3409
|
+
* toast.success('Saved')
|
|
3410
|
+
* toast.promise(save(), { loading: 'Saving…', success: 'Saved', error: 'Couldn’t save' })
|
|
3411
|
+
* ```
|
|
3412
|
+
*/
|
|
3413
|
+
function Toaster(inProps) {
|
|
3414
|
+
const [props, slots] = useComponentConfig("Toast", inProps);
|
|
3415
|
+
const { toastOptions, position = "bottom-right", ...rest } = props;
|
|
3416
|
+
const s = toastStyles();
|
|
3417
|
+
const classNames = toastOptions?.classNames ?? {};
|
|
3418
|
+
return /* @__PURE__ */ jsx(Toaster$1, {
|
|
3419
|
+
position,
|
|
3420
|
+
gap: 10,
|
|
3421
|
+
...rest,
|
|
3422
|
+
toastOptions: {
|
|
3423
|
+
...toastOptions,
|
|
3424
|
+
unstyled: true,
|
|
3425
|
+
classNames: {
|
|
3426
|
+
toast: s.toast({ class: [slots.toast, classNames.toast] }),
|
|
3427
|
+
content: s.content({ class: [slots.content, classNames.content] }),
|
|
3428
|
+
title: s.title({ class: [slots.title, classNames.title] }),
|
|
3429
|
+
description: s.description({ class: [slots.description, classNames.description] }),
|
|
3430
|
+
icon: s.icon({ class: [slots.icon, classNames.icon] }),
|
|
3431
|
+
actionButton: s.actionButton({ class: [slots.actionButton, classNames.actionButton] }),
|
|
3432
|
+
cancelButton: s.cancelButton({ class: [slots.cancelButton, classNames.cancelButton] }),
|
|
3433
|
+
closeButton: s.closeButton({ class: [slots.closeButton, classNames.closeButton] }),
|
|
3434
|
+
success: s.success({ class: [slots.success, classNames.success] }),
|
|
3435
|
+
error: s.error({ class: [slots.error, classNames.error] }),
|
|
3436
|
+
warning: s.warning({ class: [slots.warning, classNames.warning] }),
|
|
3437
|
+
info: s.info({ class: [slots.info, classNames.info] }),
|
|
3438
|
+
loading: s.loading({ class: [slots.loading, classNames.loading] })
|
|
3439
|
+
}
|
|
3440
|
+
}
|
|
3441
|
+
});
|
|
3442
|
+
}
|
|
3443
|
+
//#endregion
|
|
792
3444
|
//#region src/components/tooltip/tooltip.tsx
|
|
793
3445
|
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" } });
|
|
794
3446
|
/** A short hint on hover or focus. The child must be focusable (a button or link). */
|
|
@@ -811,21 +3463,6 @@ function Tooltip(inProps) {
|
|
|
811
3463
|
});
|
|
812
3464
|
}
|
|
813
3465
|
//#endregion
|
|
814
|
-
//#region src/hooks/use-controllable-state.ts
|
|
815
|
-
/** State that can be controlled by a parent (`value` + `onChange`) or left uncontrolled. */
|
|
816
|
-
function useControllableState({ value, defaultValue, onChange }) {
|
|
817
|
-
const [internal, setInternal] = useState(defaultValue);
|
|
818
|
-
const isControlled = value !== void 0;
|
|
819
|
-
const current = isControlled ? value : internal;
|
|
820
|
-
const onChangeRef = useRef(onChange);
|
|
821
|
-
onChangeRef.current = onChange;
|
|
822
|
-
return [current, useCallback((next) => {
|
|
823
|
-
const resolved = typeof next === "function" ? next(current) : next;
|
|
824
|
-
if (!isControlled) setInternal(resolved);
|
|
825
|
-
onChangeRef.current?.(resolved);
|
|
826
|
-
}, [current, isControlled])];
|
|
827
|
-
}
|
|
828
|
-
//#endregion
|
|
829
3466
|
//#region src/hooks/use-media-query.ts
|
|
830
3467
|
/** Subscribes to a CSS media query. Returns `fallback` during SSR. */
|
|
831
3468
|
function useMediaQuery(query, fallback = false) {
|
|
@@ -1121,13 +3758,13 @@ function AppShell(inProps) {
|
|
|
1121
3758
|
className: s.sidebar({ class: slots.sidebar }),
|
|
1122
3759
|
children: sidebar
|
|
1123
3760
|
}),
|
|
1124
|
-
/* @__PURE__ */ jsx(Dialog.Root, {
|
|
3761
|
+
/* @__PURE__ */ jsx(Dialog$1.Root, {
|
|
1125
3762
|
open: mobileOpen,
|
|
1126
3763
|
onOpenChange: setMobileOpen,
|
|
1127
|
-
children: /* @__PURE__ */ jsxs(Dialog.Portal, { children: [/* @__PURE__ */ jsx(Dialog.Overlay, { className: s.overlay({ class: slots.overlay }) }), /* @__PURE__ */ jsxs(Dialog.Content, {
|
|
3764
|
+
children: /* @__PURE__ */ jsxs(Dialog$1.Portal, { children: [/* @__PURE__ */ jsx(Dialog$1.Overlay, { className: s.overlay({ class: slots.overlay }) }), /* @__PURE__ */ jsxs(Dialog$1.Content, {
|
|
1128
3765
|
className: s.drawer({ class: slots.drawer }),
|
|
1129
3766
|
"aria-describedby": void 0,
|
|
1130
|
-
children: [/* @__PURE__ */ jsx(Dialog.Title, {
|
|
3767
|
+
children: [/* @__PURE__ */ jsx(Dialog$1.Title, {
|
|
1131
3768
|
className: "sr-only",
|
|
1132
3769
|
children: "Navigation"
|
|
1133
3770
|
}), /* @__PURE__ */ jsx(AppShellContext.Provider, {
|
|
@@ -1191,29 +3828,29 @@ function Navbar(inProps) {
|
|
|
1191
3828
|
className: s.actions({ class: slots.actions }),
|
|
1192
3829
|
children: actions
|
|
1193
3830
|
}),
|
|
1194
|
-
/* @__PURE__ */ jsxs(Dialog.Root, {
|
|
3831
|
+
/* @__PURE__ */ jsxs(Dialog$1.Root, {
|
|
1195
3832
|
open,
|
|
1196
3833
|
onOpenChange: setOpen,
|
|
1197
|
-
children: [/* @__PURE__ */ jsx(Dialog.Trigger, {
|
|
3834
|
+
children: [/* @__PURE__ */ jsx(Dialog$1.Trigger, {
|
|
1198
3835
|
asChild: true,
|
|
1199
3836
|
children: /* @__PURE__ */ jsx(IconButton, {
|
|
1200
3837
|
icon: /* @__PURE__ */ jsx(MenuIcon, {}),
|
|
1201
3838
|
"aria-label": "Open menu",
|
|
1202
3839
|
className: s.menuButton({ class: slots.menuButton })
|
|
1203
3840
|
})
|
|
1204
|
-
}), /* @__PURE__ */ jsxs(Dialog.Portal, { children: [/* @__PURE__ */ jsx(Dialog.Overlay, { className: s.overlay({ class: slots.overlay }) }), /* @__PURE__ */ jsxs(Dialog.Content, {
|
|
3841
|
+
}), /* @__PURE__ */ jsxs(Dialog$1.Portal, { children: [/* @__PURE__ */ jsx(Dialog$1.Overlay, { className: s.overlay({ class: slots.overlay }) }), /* @__PURE__ */ jsxs(Dialog$1.Content, {
|
|
1205
3842
|
className: s.panel({ class: slots.panel }),
|
|
1206
3843
|
"aria-describedby": void 0,
|
|
1207
3844
|
children: [
|
|
1208
3845
|
/* @__PURE__ */ jsxs("div", {
|
|
1209
3846
|
className: s.panelHeader({ class: slots.panelHeader }),
|
|
1210
|
-
children: [/* @__PURE__ */ jsx(Dialog.Title, {
|
|
3847
|
+
children: [/* @__PURE__ */ jsx(Dialog$1.Title, {
|
|
1211
3848
|
asChild: true,
|
|
1212
3849
|
children: /* @__PURE__ */ jsx("div", {
|
|
1213
3850
|
className: s.brand({ class: slots.brand }),
|
|
1214
3851
|
children: brand
|
|
1215
3852
|
})
|
|
1216
|
-
}), /* @__PURE__ */ jsx(Dialog.Close, {
|
|
3853
|
+
}), /* @__PURE__ */ jsx(Dialog$1.Close, {
|
|
1217
3854
|
asChild: true,
|
|
1218
3855
|
children: /* @__PURE__ */ jsx(IconButton, {
|
|
1219
3856
|
icon: /* @__PURE__ */ jsx(XIcon, {}),
|
|
@@ -1476,8 +4113,8 @@ function ThemeStyle({ theme, selector }) {
|
|
|
1476
4113
|
}
|
|
1477
4114
|
//#endregion
|
|
1478
4115
|
//#region src/provider/glyph-provider.tsx
|
|
1479
|
-
/** Provides the theme, color mode and
|
|
1480
|
-
function GlyphProvider({ children, theme = glyph, defaultMode, storageKey, linkComponent = "a" }) {
|
|
4116
|
+
/** Provides the theme, color mode, tooltips, `useConfirm()` and (optionally) toasts. Render once at the root. */
|
|
4117
|
+
function GlyphProvider({ children, theme = glyph, defaultMode, storageKey, linkComponent = "a", toaster = false }) {
|
|
1481
4118
|
const value = useMemo(() => ({
|
|
1482
4119
|
theme,
|
|
1483
4120
|
linkComponent
|
|
@@ -1489,7 +4126,7 @@ function GlyphProvider({ children, theme = glyph, defaultMode, storageKey, linkC
|
|
|
1489
4126
|
value,
|
|
1490
4127
|
children: [/* @__PURE__ */ jsx(ThemeStyle, { theme }), /* @__PURE__ */ jsx(Tooltip$1.Provider, {
|
|
1491
4128
|
delayDuration: 300,
|
|
1492
|
-
children
|
|
4129
|
+
children: /* @__PURE__ */ jsxs(ConfirmProvider, { children: [children, toaster && /* @__PURE__ */ jsx(Toaster, { ...toaster === true ? {} : toaster })] })
|
|
1493
4130
|
})]
|
|
1494
4131
|
})
|
|
1495
4132
|
});
|
|
@@ -1526,4 +4163,4 @@ function ThemeScope({ theme, mode, asChild, children, ...props }) {
|
|
|
1526
4163
|
});
|
|
1527
4164
|
}
|
|
1528
4165
|
//#endregion
|
|
1529
|
-
export { AppShell, Async, Avatar, AvatarGroup, Badge, Button, Card, CardBody, CardDescription, CardFooter, CardHeader, CardTitle, Checkbox, ColorModeProvider, ColorModeScript, Container, EmptyState, ErrorState, Eyebrow, Field, FieldContext, GlyphProvider, Heading, IconButton, Input, Kbd, Label, LoadingState, Navbar, PageHeader, Section, SegmentedControl, Select, SelectItem, Separator, Sidebar, SidebarContent, SidebarFooter, SidebarHeader, SidebarItem, SidebarSection, SidebarTrigger, Skeleton, Spinner, Stack, Switch, Table, TableBody, TableCaption, TableCell, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Text, Textarea, ThemeScope, Tooltip, appShellStyles, avatarStyles, badgeStyles, brutalist, buttonStyles, cardStyles, checkboxStyles, cn, containerStyles, defineTheme, editorial, eyebrowStyles, fieldControl, fieldStyles, getColorModeScript, glyph, headingStyles, inputStyles, kbdStyles, labelStyles, navbarStyles, pageHeaderStyles, playful, presets, sectionStyles, segmentedControlStyles, selectStyles, separatorStyles, sidebarStyles, skeletonStyles, spinnerStyles, stackStyles, stateStyles, switchStyles, tableStyles, tabsStyles, textStyles, textareaStyles, themeToCss, tokenVar, tooltipStyles, tv, useAppShell, useAsync, useColorMode, useComponentConfig, useControllableState, useFieldControl, useGlyph, useLinkComponent, useMediaQuery, useScrolled };
|
|
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 };
|