@nextlyhq/ui 0.0.2-alpha.6 → 0.0.2-alpha.60
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 +102 -24
- package/dist/color.cjs +193 -0
- package/dist/color.cjs.map +1 -0
- package/dist/color.d.cts +251 -0
- package/dist/color.d.ts +251 -0
- package/dist/color.mjs +179 -0
- package/dist/color.mjs.map +1 -0
- package/dist/index.cjs +3164 -1102
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1220 -315
- package/dist/index.d.ts +1220 -315
- package/dist/index.mjs +2887 -839
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +2 -0
- package/dist/styles.scoped.css +2 -0
- package/dist/tailwind-preset.cjs +153 -0
- package/dist/tailwind-preset.cjs.map +1 -0
- package/dist/tailwind-preset.d.cts +120 -0
- package/dist/tailwind-preset.d.ts +120 -0
- package/dist/tailwind-preset.mjs +148 -0
- package/dist/tailwind-preset.mjs.map +1 -0
- package/dist/theme.css +1117 -0
- package/dist/utils.cjs +13 -0
- package/dist/utils.cjs.map +1 -0
- package/dist/utils.d.cts +19 -0
- package/dist/utils.d.ts +19 -0
- package/dist/utils.mjs +11 -0
- package/dist/utils.mjs.map +1 -0
- package/docs/plugin-ui-authoring.md +230 -0
- package/package.json +77 -17
package/dist/index.mjs
CHANGED
|
@@ -1,55 +1,56 @@
|
|
|
1
|
-
|
|
2
|
-
import { cva } from 'class-variance-authority';
|
|
3
|
-
import * as React5 from 'react';
|
|
4
|
-
import { forwardRef, createContext, useContext } from 'react';
|
|
5
|
-
import { clsx } from 'clsx';
|
|
6
|
-
import { twMerge } from 'tailwind-merge';
|
|
7
|
-
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
8
|
-
import { Root as Root$3 } from '@radix-ui/react-label';
|
|
9
|
-
import * as SeparatorPrimitive from '@radix-ui/react-separator';
|
|
10
|
-
import * as CheckboxPrimitive from '@radix-ui/react-checkbox';
|
|
11
|
-
import { Minus, Check, ChevronDown, X, ChevronRight, Circle, Search, Loader2, ChevronUp, XCircle, AlertTriangle, AlertCircle, CheckCircle2, FileQuestion, ChevronsLeft, ChevronLeft, ChevronsRight } from 'lucide-react';
|
|
12
|
-
import * as RadioGroupPrimitive from '@radix-ui/react-radio-group';
|
|
13
|
-
import { Root as Root$4, Thumb } from '@radix-ui/react-switch';
|
|
14
|
-
import * as CollapsiblePrimitive from '@radix-ui/react-collapsible';
|
|
15
|
-
import * as AccordionPrimitive from '@radix-ui/react-accordion';
|
|
16
|
-
import { Root, Image, Fallback } from '@radix-ui/react-avatar';
|
|
17
|
-
import { List, Trigger, Content, Root as Root$1 } from '@radix-ui/react-tabs';
|
|
18
|
-
import { Content as Content$1, Root as Root$2, Provider, Trigger as Trigger$1 } from '@radix-ui/react-tooltip';
|
|
19
|
-
import * as PopoverPrimitive from '@radix-ui/react-popover';
|
|
20
|
-
import * as DialogPrimitive from '@radix-ui/react-dialog';
|
|
21
|
-
import * as AlertDialogPrimitive from '@radix-ui/react-alert-dialog';
|
|
22
|
-
import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';
|
|
23
|
-
import * as SelectPrimitive from '@radix-ui/react-select';
|
|
24
|
-
import { Command as Command$1 } from 'cmdk';
|
|
25
|
-
import { Toaster as Toaster$1 } from 'sonner';
|
|
26
|
-
export { toast } from 'sonner';
|
|
1
|
+
"use client";
|
|
27
2
|
|
|
28
3
|
// src/components/button.tsx
|
|
4
|
+
import { Slot } from "@radix-ui/react-slot";
|
|
5
|
+
import { cva } from "class-variance-authority";
|
|
6
|
+
import * as React from "react";
|
|
7
|
+
import { forwardRef } from "react";
|
|
8
|
+
|
|
9
|
+
// src/lib/utils.ts
|
|
10
|
+
import { clsx } from "clsx";
|
|
11
|
+
import { twMerge } from "tailwind-merge";
|
|
29
12
|
function cn(...inputs) {
|
|
30
13
|
return twMerge(clsx(inputs));
|
|
31
14
|
}
|
|
15
|
+
|
|
16
|
+
// src/components/button.tsx
|
|
17
|
+
import { jsx } from "react/jsx-runtime";
|
|
32
18
|
var buttonVariants = cva(
|
|
33
|
-
"inline-flex items-center justify-center whitespace-nowrap rounded-
|
|
19
|
+
"inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium cursor-pointer transition-all duration-150 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-0 disabled:pointer-events-none disabled:opacity-50 disabled:cursor-not-allowed active:scale-[0.98] [&_svg]:text-current",
|
|
34
20
|
{
|
|
35
21
|
variants: {
|
|
36
22
|
variant: {
|
|
37
23
|
default: "bg-primary text-primary-foreground border border-transparent hover:opacity-90",
|
|
38
24
|
primary: "bg-primary text-primary-foreground border border-transparent hover:opacity-90",
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
25
|
+
// Solid fill uses the emphasis token so on-color text stays AA in dark
|
|
26
|
+
// mode (the base token is the readable text color, too light here).
|
|
27
|
+
// Hover darkens to a deeper shade rather than opacity-90, which would
|
|
28
|
+
// composite the fill toward the page and drop the label under 4.5:1.
|
|
29
|
+
// One step, not two: the label is white in light mode and black in
|
|
30
|
+
// dark, so mixing the fill toward black moves it away from the label in
|
|
31
|
+
// one mode and into it in the other. `-600` clears both (5.92:1 light,
|
|
32
|
+
// 5.67:1 dark); `-700` reads at 3.70:1 against the dark label.
|
|
33
|
+
destructive: "bg-destructive-solid text-destructive-foreground border border-transparent hover:bg-destructive-600",
|
|
34
|
+
// border-border is the decorative separator token, and it is the right
|
|
35
|
+
// one here: a button is identified by its label and fill, so its edge
|
|
36
|
+
// carries no meaning on its own, unlike border-input, which is the
|
|
37
|
+
// token for controls identified by their boundary (that token is now
|
|
38
|
+
// below 1.4.11's 3:1 in light mode; see contrast/accepted.ts). It is
|
|
39
|
+
// still used in preference to a faint primary alpha, which reads as a
|
|
40
|
+
// tint of the brand colour rather than as an edge.
|
|
41
|
+
outline: "border border-border text-foreground hover-unified bg-background",
|
|
42
|
+
secondary: "bg-background border border-border text-foreground hover:bg-primary/5",
|
|
42
43
|
ghost: "text-foreground border border-transparent hover-unified",
|
|
43
44
|
link: "text-primary border border-transparent underline-offset-4 hover:underline"
|
|
44
45
|
},
|
|
45
46
|
size: {
|
|
46
|
-
default: "h-
|
|
47
|
-
sm: "h-
|
|
48
|
-
md: "h-
|
|
49
|
-
lg: "h-
|
|
50
|
-
icon: "h-
|
|
51
|
-
"icon-sm": "h-
|
|
52
|
-
"icon-lg": "h-
|
|
47
|
+
default: "h-[var(--nx-control-height)] px-6 py-2",
|
|
48
|
+
sm: "h-[var(--nx-control-height-md)] px-4 text-sm",
|
|
49
|
+
md: "h-[var(--nx-control-height)] px-6 text-sm",
|
|
50
|
+
lg: "h-[var(--nx-control-height-lg)] px-8 text-base",
|
|
51
|
+
icon: "h-[var(--nx-control-height)] w-[var(--nx-control-height)] p-0",
|
|
52
|
+
"icon-sm": "h-[var(--nx-control-height-md)] w-[var(--nx-control-height-md)] p-0",
|
|
53
|
+
"icon-lg": "h-[var(--nx-control-height-lg)] w-[var(--nx-control-height-lg)] p-0"
|
|
53
54
|
}
|
|
54
55
|
},
|
|
55
56
|
defaultVariants: {
|
|
@@ -68,7 +69,7 @@ var Button = forwardRef(
|
|
|
68
69
|
...props
|
|
69
70
|
}, ref) => {
|
|
70
71
|
const Comp = asChild ? Slot : "button";
|
|
71
|
-
const hasMultipleChildren =
|
|
72
|
+
const hasMultipleChildren = React.Children.count(children) > 1;
|
|
72
73
|
return /* @__PURE__ */ jsx(
|
|
73
74
|
Comp,
|
|
74
75
|
{
|
|
@@ -85,14 +86,30 @@ var Button = forwardRef(
|
|
|
85
86
|
}
|
|
86
87
|
);
|
|
87
88
|
Button.displayName = "Button";
|
|
88
|
-
|
|
89
|
-
|
|
89
|
+
|
|
90
|
+
// src/components/input.tsx
|
|
91
|
+
import { cva as cva2 } from "class-variance-authority";
|
|
92
|
+
import { forwardRef as forwardRef2 } from "react";
|
|
93
|
+
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
94
|
+
var inputVariants = cva2(
|
|
95
|
+
// `text-foreground` is explicit rather than inherited. Tailwind's preflight
|
|
96
|
+
// sets `color: inherit` on form controls, so without it the typed value takes
|
|
97
|
+
// whatever colour an ancestor happens to carry -- muted inside a
|
|
98
|
+
// `text-muted-foreground` block, red inside a `text-destructive` one. Select
|
|
99
|
+
// and Textarea have always pinned it; Input was the one control that did not,
|
|
100
|
+
// and callers were compensating by putting the token on a wrapper.
|
|
101
|
+
"file:text-foreground text-foreground placeholder:text-muted-foreground placeholder:opacity-50 selection:bg-primary selection:text-primary-foreground w-full min-w-0 rounded-md border border-input bg-background text-sm transition-all duration-150 outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 focus:ring-0 focus:ring-offset-0 focus:outline-none focus:border-primary! focus-visible:border-primary! aria-invalid:border-destructive aria-invalid:focus:border-destructive! data-[invalid=true]:border-destructive data-[invalid=true]:focus:border-destructive!",
|
|
90
102
|
{
|
|
91
103
|
variants: {
|
|
92
104
|
size: {
|
|
93
|
-
sm
|
|
94
|
-
|
|
95
|
-
|
|
105
|
+
// `-md` rather than `-sm`, so that a small input is the same height as
|
|
106
|
+
// a small button standing beside it in a toolbar or a filter row.
|
|
107
|
+
// Button's `sm` has always used this step; an input reading `-sm` made
|
|
108
|
+
// `size="sm"` mean 36px on one control and 32px on another, and a form
|
|
109
|
+
// row mixing them sat 4px out of line.
|
|
110
|
+
sm: "h-[var(--nx-control-height-md)] px-2.5 py-2 text-sm",
|
|
111
|
+
default: "h-[var(--nx-control-height)] px-3 py-2.5 text-sm",
|
|
112
|
+
lg: "h-[var(--nx-control-height-lg)] px-4 py-3 text-base"
|
|
96
113
|
}
|
|
97
114
|
},
|
|
98
115
|
defaultVariants: {
|
|
@@ -100,9 +117,9 @@ var inputVariants = cva(
|
|
|
100
117
|
}
|
|
101
118
|
}
|
|
102
119
|
);
|
|
103
|
-
var Input =
|
|
120
|
+
var Input = forwardRef2(
|
|
104
121
|
({ className, type, size, ...props }, ref) => {
|
|
105
|
-
return /* @__PURE__ */
|
|
122
|
+
return /* @__PURE__ */ jsx2(
|
|
106
123
|
"input",
|
|
107
124
|
{
|
|
108
125
|
type,
|
|
@@ -115,14 +132,20 @@ var Input = forwardRef(
|
|
|
115
132
|
}
|
|
116
133
|
);
|
|
117
134
|
Input.displayName = "Input";
|
|
118
|
-
|
|
119
|
-
|
|
135
|
+
|
|
136
|
+
// src/components/textarea.tsx
|
|
137
|
+
import { forwardRef as forwardRef3 } from "react";
|
|
138
|
+
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
139
|
+
var Textarea = forwardRef3(({ className, ...props }, ref) => {
|
|
140
|
+
return /* @__PURE__ */ jsx3(
|
|
120
141
|
"textarea",
|
|
121
142
|
{
|
|
122
143
|
"data-slot": "textarea",
|
|
123
144
|
className: cn(
|
|
124
|
-
|
|
125
|
-
|
|
145
|
+
// hover:border-primary (full strength) keeps the hover boundary more
|
|
146
|
+
// visible than the resting border-input, not a fainter alpha of it.
|
|
147
|
+
"flex min-h-[80px] w-full rounded-md border border-input bg-background px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground placeholder:opacity-50 transition-all duration-200 focus:border-primary! focus-visible:border-primary! focus:outline-none hover:border-primary disabled:cursor-not-allowed disabled:opacity-50 disabled:bg-primary/5 resize-y",
|
|
148
|
+
"aria-invalid:border-destructive aria-invalid:focus:border-destructive!",
|
|
126
149
|
className
|
|
127
150
|
),
|
|
128
151
|
ref,
|
|
@@ -131,9 +154,13 @@ var Textarea = forwardRef(({ className, ...props }, ref) => {
|
|
|
131
154
|
);
|
|
132
155
|
});
|
|
133
156
|
Textarea.displayName = "Textarea";
|
|
157
|
+
|
|
158
|
+
// src/components/label.tsx
|
|
159
|
+
import { Root as LabelRoot } from "@radix-ui/react-label";
|
|
160
|
+
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
134
161
|
function Label({ className, ...props }) {
|
|
135
|
-
return /* @__PURE__ */
|
|
136
|
-
|
|
162
|
+
return /* @__PURE__ */ jsx4(
|
|
163
|
+
LabelRoot,
|
|
137
164
|
{
|
|
138
165
|
"data-slot": "label",
|
|
139
166
|
className: cn(
|
|
@@ -144,17 +171,135 @@ function Label({ className, ...props }) {
|
|
|
144
171
|
}
|
|
145
172
|
);
|
|
146
173
|
}
|
|
147
|
-
|
|
148
|
-
|
|
174
|
+
|
|
175
|
+
// src/components/form-label-with-tooltip.tsx
|
|
176
|
+
import { Info } from "lucide-react";
|
|
177
|
+
import * as React2 from "react";
|
|
178
|
+
|
|
179
|
+
// src/components/tooltip.tsx
|
|
180
|
+
import {
|
|
181
|
+
Provider,
|
|
182
|
+
Root,
|
|
183
|
+
Trigger,
|
|
184
|
+
Portal,
|
|
185
|
+
Content
|
|
186
|
+
} from "@radix-ui/react-tooltip";
|
|
187
|
+
import { forwardRef as forwardRef4 } from "react";
|
|
188
|
+
|
|
189
|
+
// src/providers/portal-provider.tsx
|
|
190
|
+
import { createContext, useContext } from "react";
|
|
191
|
+
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
192
|
+
var PortalContext = createContext({ container: null });
|
|
193
|
+
function PortalProvider({ container, children }) {
|
|
194
|
+
return /* @__PURE__ */ jsx5(PortalContext.Provider, { value: { container }, children });
|
|
195
|
+
}
|
|
196
|
+
function usePortalContainer() {
|
|
197
|
+
const { container } = useContext(PortalContext);
|
|
198
|
+
return container ?? void 0;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// src/components/tooltip.tsx
|
|
202
|
+
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
203
|
+
var TooltipProvider = Provider;
|
|
204
|
+
var Tooltip = Root;
|
|
205
|
+
var TooltipTrigger = Trigger;
|
|
206
|
+
var TooltipContent = forwardRef4(({ className, sideOffset = 4, ...props }, ref) => {
|
|
207
|
+
const portalContainer = usePortalContainer();
|
|
208
|
+
return (
|
|
209
|
+
// Portalled for the same reason as every other overlay here, plus one
|
|
210
|
+
// specific to the tooltip: the positioner measures against the nearest
|
|
211
|
+
// containing block, and it counts `container-type` as one while the
|
|
212
|
+
// browser does not. Left inline under a `@container` element, the content
|
|
213
|
+
// is offset by that element's own position. Portalling lifts it out of any
|
|
214
|
+
// such ancestor, so the two agree again.
|
|
215
|
+
/* @__PURE__ */ jsx6(Portal, { container: portalContainer, children: /* @__PURE__ */ jsx6(
|
|
216
|
+
Content,
|
|
217
|
+
{
|
|
218
|
+
ref,
|
|
219
|
+
sideOffset,
|
|
220
|
+
"data-slot": "tooltip-content",
|
|
221
|
+
className: cn(
|
|
222
|
+
"z-50 overflow-hidden rounded-lg px-3 py-1.5 text-xs shadow-lg border border-border bg-popover text-popover-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
|
223
|
+
className
|
|
224
|
+
),
|
|
225
|
+
...props
|
|
226
|
+
}
|
|
227
|
+
) })
|
|
228
|
+
);
|
|
229
|
+
});
|
|
230
|
+
TooltipContent.displayName = Content.displayName;
|
|
231
|
+
|
|
232
|
+
// src/components/form-label-with-tooltip.tsx
|
|
233
|
+
import { jsx as jsx7, jsxs } from "react/jsx-runtime";
|
|
234
|
+
var FormLabelWithTooltip = React2.forwardRef(
|
|
235
|
+
({
|
|
236
|
+
className,
|
|
237
|
+
labelClassName,
|
|
238
|
+
tooltipClassName,
|
|
239
|
+
label,
|
|
240
|
+
description,
|
|
241
|
+
required,
|
|
242
|
+
...props
|
|
243
|
+
}, ref) => {
|
|
244
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("flex items-center gap-2", className), children: [
|
|
245
|
+
/* @__PURE__ */ jsxs(Label, { ref, className: labelClassName, ...props, children: [
|
|
246
|
+
label,
|
|
247
|
+
required && /* @__PURE__ */ jsx7("span", { className: "text-destructive ml-1", children: "*" })
|
|
248
|
+
] }),
|
|
249
|
+
description && /* @__PURE__ */ jsx7(TooltipProvider, { children: /* @__PURE__ */ jsxs(Tooltip, { delayDuration: 200, children: [
|
|
250
|
+
/* @__PURE__ */ jsxs(
|
|
251
|
+
TooltipTrigger,
|
|
252
|
+
{
|
|
253
|
+
type: "button",
|
|
254
|
+
tabIndex: -1,
|
|
255
|
+
className: "shrink-0 text-muted-foreground hover:text-foreground focus:outline-none focus:text-foreground transition-colors cursor-help",
|
|
256
|
+
children: [
|
|
257
|
+
/* @__PURE__ */ jsx7(Info, { className: "h-3.5 w-3.5" }),
|
|
258
|
+
/* @__PURE__ */ jsx7("span", { className: "sr-only", children: "Toggle description" })
|
|
259
|
+
]
|
|
260
|
+
}
|
|
261
|
+
),
|
|
262
|
+
/* @__PURE__ */ jsx7(
|
|
263
|
+
TooltipContent,
|
|
264
|
+
{
|
|
265
|
+
side: "right",
|
|
266
|
+
className: cn(
|
|
267
|
+
"max-w-[250px] text-xs break-words relative z-[100] shadow-md border border-border bg-primary text-primary-foreground px-3 py-2 rounded-lg",
|
|
268
|
+
tooltipClassName
|
|
269
|
+
),
|
|
270
|
+
children: description
|
|
271
|
+
}
|
|
272
|
+
)
|
|
273
|
+
] }) })
|
|
274
|
+
] });
|
|
275
|
+
}
|
|
276
|
+
);
|
|
277
|
+
FormLabelWithTooltip.displayName = "FormLabelWithTooltip";
|
|
278
|
+
|
|
279
|
+
// src/components/badge.tsx
|
|
280
|
+
import { cva as cva3 } from "class-variance-authority";
|
|
281
|
+
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
282
|
+
var badgeVariants = cva3(
|
|
283
|
+
"inline-flex items-center rounded-sm px-2.5 py-0.5 h-[22px] text-xs font-medium transition-colors",
|
|
149
284
|
{
|
|
150
285
|
variants: {
|
|
151
286
|
variant: {
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
287
|
+
// Clear, legible chip in both modes (was bg-primary/5 at ~5% opacity,
|
|
288
|
+
// which was nearly invisible on dark backgrounds).
|
|
289
|
+
default: "bg-muted text-foreground",
|
|
290
|
+
primary: "bg-primary/10 text-primary dark:bg-primary/20",
|
|
291
|
+
success: "bg-success-100 text-success-700 dark:bg-success-900 dark:text-success-100",
|
|
292
|
+
warning: "bg-warning-100 text-warning-700 dark:bg-warning-900 dark:text-warning-100",
|
|
293
|
+
destructive: "bg-destructive-100 text-destructive-700 dark:bg-destructive-900 dark:text-destructive-100",
|
|
294
|
+
/*
|
|
295
|
+
* The border colour is NOT important-marked. The base sets no border
|
|
296
|
+
* colour, so nothing inside this component competes for it — the only
|
|
297
|
+
* thing a mark could win against is the caller's own class. Seven
|
|
298
|
+
* outline badges pass one, including a status pill whose comment gives
|
|
299
|
+
* a 3:1 contrast reason for the colour it asks for, and every one of
|
|
300
|
+
* them was being overridden without any sign that it had been.
|
|
301
|
+
*/
|
|
302
|
+
outline: "border border-border bg-transparent text-foreground dark:text-muted-foreground dark:border-border"
|
|
158
303
|
}
|
|
159
304
|
},
|
|
160
305
|
defaultVariants: {
|
|
@@ -163,7 +308,7 @@ var badgeVariants = cva(
|
|
|
163
308
|
}
|
|
164
309
|
);
|
|
165
310
|
function Badge({ className, variant = "default", ...props }) {
|
|
166
|
-
return /* @__PURE__ */
|
|
311
|
+
return /* @__PURE__ */ jsx8(
|
|
167
312
|
"div",
|
|
168
313
|
{
|
|
169
314
|
"data-slot": `badge.${variant}`,
|
|
@@ -172,8 +317,13 @@ function Badge({ className, variant = "default", ...props }) {
|
|
|
172
317
|
}
|
|
173
318
|
);
|
|
174
319
|
}
|
|
175
|
-
|
|
176
|
-
|
|
320
|
+
|
|
321
|
+
// src/components/card.tsx
|
|
322
|
+
import { cva as cva4 } from "class-variance-authority";
|
|
323
|
+
import { forwardRef as forwardRef6 } from "react";
|
|
324
|
+
import { jsx as jsx9 } from "react/jsx-runtime";
|
|
325
|
+
var cardVariants = cva4(
|
|
326
|
+
"bg-card text-foreground rounded-lg border border-border transition-all duration-200",
|
|
177
327
|
{
|
|
178
328
|
variants: {
|
|
179
329
|
variant: {
|
|
@@ -187,9 +337,9 @@ var cardVariants = cva(
|
|
|
187
337
|
}
|
|
188
338
|
}
|
|
189
339
|
);
|
|
190
|
-
var Card =
|
|
340
|
+
var Card = forwardRef6(
|
|
191
341
|
({ className, variant, ...props }, ref) => {
|
|
192
|
-
return /* @__PURE__ */
|
|
342
|
+
return /* @__PURE__ */ jsx9(
|
|
193
343
|
"div",
|
|
194
344
|
{
|
|
195
345
|
ref,
|
|
@@ -201,16 +351,23 @@ var Card = forwardRef(
|
|
|
201
351
|
}
|
|
202
352
|
);
|
|
203
353
|
Card.displayName = "Card";
|
|
204
|
-
var CardHeader =
|
|
354
|
+
var CardHeader = forwardRef6(
|
|
205
355
|
({ className, noBorder = false, ...props }, ref) => {
|
|
206
|
-
return /* @__PURE__ */
|
|
356
|
+
return /* @__PURE__ */ jsx9(
|
|
207
357
|
"div",
|
|
208
358
|
{
|
|
209
359
|
ref,
|
|
210
360
|
"data-slot": "card-header",
|
|
211
361
|
className: cn(
|
|
212
|
-
|
|
213
|
-
|
|
362
|
+
// Mirrors CardFooter: a header that carries its own tint runs the full
|
|
363
|
+
// width of the card, so at a nonzero --radius it would paint square
|
|
364
|
+
// across the card's curved top corners. `inherit` takes the parent's
|
|
365
|
+
// computed radius rather than restating a step. It only helps when the
|
|
366
|
+
// header is a direct child of the card; a header nested inside another
|
|
367
|
+
// wrapper inherits that wrapper's radius instead, and such a card needs
|
|
368
|
+
// `overflow-hidden` to clip the fill.
|
|
369
|
+
"flex flex-col rounded-t-[inherit] p-4",
|
|
370
|
+
!noBorder && "border-b border-border",
|
|
214
371
|
className
|
|
215
372
|
),
|
|
216
373
|
...props
|
|
@@ -219,9 +376,9 @@ var CardHeader = forwardRef(
|
|
|
219
376
|
}
|
|
220
377
|
);
|
|
221
378
|
CardHeader.displayName = "CardHeader";
|
|
222
|
-
var CardTitle =
|
|
379
|
+
var CardTitle = forwardRef6(
|
|
223
380
|
({ className, ...props }, ref) => {
|
|
224
|
-
return /* @__PURE__ */
|
|
381
|
+
return /* @__PURE__ */ jsx9(
|
|
225
382
|
"h3",
|
|
226
383
|
{
|
|
227
384
|
ref,
|
|
@@ -233,9 +390,9 @@ var CardTitle = forwardRef(
|
|
|
233
390
|
}
|
|
234
391
|
);
|
|
235
392
|
CardTitle.displayName = "CardTitle";
|
|
236
|
-
var CardDescription =
|
|
393
|
+
var CardDescription = forwardRef6(
|
|
237
394
|
({ className, ...props }, ref) => {
|
|
238
|
-
return /* @__PURE__ */
|
|
395
|
+
return /* @__PURE__ */ jsx9(
|
|
239
396
|
"p",
|
|
240
397
|
{
|
|
241
398
|
ref,
|
|
@@ -247,9 +404,9 @@ var CardDescription = forwardRef(
|
|
|
247
404
|
}
|
|
248
405
|
);
|
|
249
406
|
CardDescription.displayName = "CardDescription";
|
|
250
|
-
var CardAction =
|
|
407
|
+
var CardAction = forwardRef6(
|
|
251
408
|
({ className, ...props }, ref) => {
|
|
252
|
-
return /* @__PURE__ */
|
|
409
|
+
return /* @__PURE__ */ jsx9(
|
|
253
410
|
"div",
|
|
254
411
|
{
|
|
255
412
|
ref,
|
|
@@ -261,9 +418,9 @@ var CardAction = forwardRef(
|
|
|
261
418
|
}
|
|
262
419
|
);
|
|
263
420
|
CardAction.displayName = "CardAction";
|
|
264
|
-
var CardContent =
|
|
421
|
+
var CardContent = forwardRef6(
|
|
265
422
|
({ className, ...props }, ref) => {
|
|
266
|
-
return /* @__PURE__ */
|
|
423
|
+
return /* @__PURE__ */ jsx9(
|
|
267
424
|
"div",
|
|
268
425
|
{
|
|
269
426
|
ref,
|
|
@@ -275,15 +432,21 @@ var CardContent = forwardRef(
|
|
|
275
432
|
}
|
|
276
433
|
);
|
|
277
434
|
CardContent.displayName = "CardContent";
|
|
278
|
-
var CardFooter =
|
|
435
|
+
var CardFooter = forwardRef6(
|
|
279
436
|
({ className, ...props }, ref) => {
|
|
280
|
-
return /* @__PURE__ */
|
|
437
|
+
return /* @__PURE__ */ jsx9(
|
|
281
438
|
"div",
|
|
282
439
|
{
|
|
283
440
|
ref,
|
|
284
441
|
"data-slot": "card-footer",
|
|
285
442
|
className: cn(
|
|
286
|
-
|
|
443
|
+
// The footer's tint runs the full width of the card, so at a nonzero
|
|
444
|
+
// --radius it would paint square across the card's curved bottom
|
|
445
|
+
// corners. `inherit` takes the card's own computed radius rather than
|
|
446
|
+
// restating a step, so a card whose radius is overridden stays
|
|
447
|
+
// matched, and it can never disagree with the card at any --radius,
|
|
448
|
+
// including the shipped 0 where `rounded-lg` is 0.
|
|
449
|
+
"flex items-center px-6 py-4 border-t border-border bg-primary/5 rounded-b-[inherit]",
|
|
287
450
|
className
|
|
288
451
|
),
|
|
289
452
|
...props
|
|
@@ -292,15 +455,93 @@ var CardFooter = forwardRef(
|
|
|
292
455
|
}
|
|
293
456
|
);
|
|
294
457
|
CardFooter.displayName = "CardFooter";
|
|
295
|
-
|
|
296
|
-
|
|
458
|
+
|
|
459
|
+
// src/components/layout.tsx
|
|
460
|
+
import { forwardRef as forwardRef7 } from "react";
|
|
461
|
+
import { jsx as jsx10, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
462
|
+
var GAP = {
|
|
463
|
+
0: "gap-0",
|
|
464
|
+
1: "gap-1",
|
|
465
|
+
2: "gap-2",
|
|
466
|
+
3: "gap-3",
|
|
467
|
+
4: "gap-4",
|
|
468
|
+
6: "gap-6",
|
|
469
|
+
8: "gap-8"
|
|
470
|
+
};
|
|
471
|
+
var COLS = {
|
|
472
|
+
1: "grid-cols-1",
|
|
473
|
+
2: "grid-cols-2",
|
|
474
|
+
3: "grid-cols-3",
|
|
475
|
+
4: "grid-cols-4",
|
|
476
|
+
6: "grid-cols-6"
|
|
477
|
+
};
|
|
478
|
+
var RESPONSIVE_COLS = {
|
|
479
|
+
1: "grid-cols-1",
|
|
480
|
+
2: "grid-cols-1 @2xl:grid-cols-2",
|
|
481
|
+
3: "grid-cols-1 @2xl:grid-cols-3",
|
|
482
|
+
4: "grid-cols-1 @2xl:grid-cols-4",
|
|
483
|
+
6: "grid-cols-1 @2xl:grid-cols-6"
|
|
484
|
+
};
|
|
485
|
+
var Stack = forwardRef7(
|
|
486
|
+
({ direction = "col", gap = 4, className, ...props }, ref) => /* @__PURE__ */ jsx10(
|
|
487
|
+
"div",
|
|
488
|
+
{
|
|
489
|
+
ref,
|
|
490
|
+
className: cn(
|
|
491
|
+
"flex",
|
|
492
|
+
direction === "col" ? "flex-col" : "flex-row",
|
|
493
|
+
GAP[gap],
|
|
494
|
+
className
|
|
495
|
+
),
|
|
496
|
+
...props
|
|
497
|
+
}
|
|
498
|
+
)
|
|
499
|
+
);
|
|
500
|
+
Stack.displayName = "Stack";
|
|
501
|
+
var Grid = forwardRef7(
|
|
502
|
+
({ cols = 2, gap = 4, responsive = false, className, children, ...rest }, ref) => {
|
|
503
|
+
if (!responsive) {
|
|
504
|
+
return /* @__PURE__ */ jsx10(
|
|
505
|
+
"div",
|
|
506
|
+
{
|
|
507
|
+
ref,
|
|
508
|
+
className: cn("grid", COLS[cols], GAP[gap], className),
|
|
509
|
+
...rest,
|
|
510
|
+
children
|
|
511
|
+
}
|
|
512
|
+
);
|
|
513
|
+
}
|
|
514
|
+
return /* @__PURE__ */ jsx10("div", { ref, className: cn("@container", className), ...rest, children: /* @__PURE__ */ jsx10("div", { className: cn("grid", RESPONSIVE_COLS[cols], GAP[gap]), children }) });
|
|
515
|
+
}
|
|
516
|
+
);
|
|
517
|
+
Grid.displayName = "Grid";
|
|
518
|
+
var Stat = forwardRef7(
|
|
519
|
+
({ label, value, className, ...props }, ref) => /* @__PURE__ */ jsxs2("div", { ref, className: cn("flex flex-col gap-1", className), ...props, children: [
|
|
520
|
+
/* @__PURE__ */ jsx10("span", { className: "text-sm text-muted-foreground", children: label }),
|
|
521
|
+
/* @__PURE__ */ jsx10("span", { className: "text-2xl font-semibold text-foreground", children: value })
|
|
522
|
+
] })
|
|
523
|
+
);
|
|
524
|
+
Stat.displayName = "Stat";
|
|
525
|
+
|
|
526
|
+
// src/components/alert.tsx
|
|
527
|
+
import { cva as cva5 } from "class-variance-authority";
|
|
528
|
+
import { forwardRef as forwardRef8 } from "react";
|
|
529
|
+
import { jsx as jsx11 } from "react/jsx-runtime";
|
|
530
|
+
var alertVariants = cva5(
|
|
531
|
+
"relative flex items-start gap-3 rounded-md border border-border p-4 text-sm transition-colors duration-150",
|
|
297
532
|
{
|
|
298
533
|
variants: {
|
|
299
534
|
variant: {
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
535
|
+
// text-primary is mode-correct (dark ink on light in light mode, light
|
|
536
|
+
// ink on dark in dark mode); the previous dark text override rendered
|
|
537
|
+
// dark slate on the dark tint at about 1:1.
|
|
538
|
+
info: "bg-primary/5 text-primary",
|
|
539
|
+
// dark:border-l-* re-asserts the strong base accent on the left after
|
|
540
|
+
// the dark:border-*-900 all-sides rule, so the meaningful accent stays
|
|
541
|
+
// visible in dark mode instead of collapsing to the faint -900 shade.
|
|
542
|
+
success: "border-success-200 bg-success-50 text-success-900 border-l-4 border-l-success dark:border-success-900 dark:border-l-success dark:bg-success-950 dark:text-success-100",
|
|
543
|
+
warning: "border-warning-200 bg-warning-50 text-warning-900 border-l-4 border-l-warning dark:border-warning-900 dark:border-l-warning dark:bg-warning-950 dark:text-warning-100",
|
|
544
|
+
destructive: "border-destructive-200 bg-destructive-50 text-destructive-900 border-l-4 border-l-destructive dark:border-destructive-900 dark:border-l-destructive dark:bg-destructive-950 dark:text-destructive-100"
|
|
304
545
|
}
|
|
305
546
|
},
|
|
306
547
|
defaultVariants: {
|
|
@@ -308,9 +549,9 @@ var alertVariants = cva(
|
|
|
308
549
|
}
|
|
309
550
|
}
|
|
310
551
|
);
|
|
311
|
-
var Alert =
|
|
552
|
+
var Alert = forwardRef8(
|
|
312
553
|
({ className, variant = "info", role = "alert", ...props }, ref) => {
|
|
313
|
-
return /* @__PURE__ */
|
|
554
|
+
return /* @__PURE__ */ jsx11(
|
|
314
555
|
"div",
|
|
315
556
|
{
|
|
316
557
|
ref,
|
|
@@ -323,9 +564,9 @@ var Alert = forwardRef(
|
|
|
323
564
|
}
|
|
324
565
|
);
|
|
325
566
|
Alert.displayName = "Alert";
|
|
326
|
-
var AlertTitle =
|
|
567
|
+
var AlertTitle = forwardRef8(
|
|
327
568
|
({ className, ...props }, ref) => {
|
|
328
|
-
return /* @__PURE__ */
|
|
569
|
+
return /* @__PURE__ */ jsx11(
|
|
329
570
|
"h5",
|
|
330
571
|
{
|
|
331
572
|
ref,
|
|
@@ -340,9 +581,9 @@ var AlertTitle = forwardRef(
|
|
|
340
581
|
}
|
|
341
582
|
);
|
|
342
583
|
AlertTitle.displayName = "AlertTitle";
|
|
343
|
-
var AlertDescription =
|
|
584
|
+
var AlertDescription = forwardRef8(
|
|
344
585
|
({ className, ...props }, ref) => {
|
|
345
|
-
return /* @__PURE__ */
|
|
586
|
+
return /* @__PURE__ */ jsx11(
|
|
346
587
|
"div",
|
|
347
588
|
{
|
|
348
589
|
ref,
|
|
@@ -354,13 +595,17 @@ var AlertDescription = forwardRef(
|
|
|
354
595
|
}
|
|
355
596
|
);
|
|
356
597
|
AlertDescription.displayName = "AlertDescription";
|
|
598
|
+
|
|
599
|
+
// src/components/separator.tsx
|
|
600
|
+
import * as SeparatorPrimitive from "@radix-ui/react-separator";
|
|
601
|
+
import { jsx as jsx12 } from "react/jsx-runtime";
|
|
357
602
|
function Separator({
|
|
358
603
|
className,
|
|
359
604
|
orientation = "horizontal",
|
|
360
605
|
decorative = true,
|
|
361
606
|
...props
|
|
362
607
|
}) {
|
|
363
|
-
return /* @__PURE__ */
|
|
608
|
+
return /* @__PURE__ */ jsx12(
|
|
364
609
|
SeparatorPrimitive.Root,
|
|
365
610
|
{
|
|
366
611
|
"data-slot": "separator",
|
|
@@ -374,16 +619,20 @@ function Separator({
|
|
|
374
619
|
}
|
|
375
620
|
);
|
|
376
621
|
}
|
|
377
|
-
|
|
622
|
+
|
|
623
|
+
// src/components/skeleton.tsx
|
|
624
|
+
import * as React3 from "react";
|
|
625
|
+
import { jsx as jsx13 } from "react/jsx-runtime";
|
|
626
|
+
var Skeleton = React3.forwardRef(
|
|
378
627
|
({ className, ...props }, ref) => {
|
|
379
|
-
return /* @__PURE__ */
|
|
628
|
+
return /* @__PURE__ */ jsx13(
|
|
380
629
|
"div",
|
|
381
630
|
{
|
|
382
631
|
ref,
|
|
383
632
|
"data-slot": "skeleton",
|
|
384
633
|
"aria-hidden": "true",
|
|
385
634
|
className: cn(
|
|
386
|
-
"bg-primary/5 animate-pulse rounded-
|
|
635
|
+
"bg-primary/5 animate-pulse rounded-md motion-reduce:animate-none",
|
|
387
636
|
className
|
|
388
637
|
),
|
|
389
638
|
...props
|
|
@@ -392,11 +641,16 @@ var Skeleton = React5.forwardRef(
|
|
|
392
641
|
}
|
|
393
642
|
);
|
|
394
643
|
Skeleton.displayName = "Skeleton";
|
|
395
|
-
|
|
644
|
+
|
|
645
|
+
// src/components/progress.tsx
|
|
646
|
+
import { cva as cva6 } from "class-variance-authority";
|
|
647
|
+
import * as React4 from "react";
|
|
648
|
+
import { jsx as jsx14 } from "react/jsx-runtime";
|
|
649
|
+
var progressVariants = cva6("h-full rounded-none transition-all", {
|
|
396
650
|
variants: {
|
|
397
651
|
variant: {
|
|
398
652
|
default: "bg-primary-500",
|
|
399
|
-
success: "bg-
|
|
653
|
+
success: "bg-success-500",
|
|
400
654
|
error: "bg-destructive"
|
|
401
655
|
}
|
|
402
656
|
},
|
|
@@ -404,7 +658,7 @@ var progressVariants = cva("h-full rounded-none transition-all", {
|
|
|
404
658
|
variant: "default"
|
|
405
659
|
}
|
|
406
660
|
});
|
|
407
|
-
var Progress =
|
|
661
|
+
var Progress = React4.forwardRef(
|
|
408
662
|
({
|
|
409
663
|
value,
|
|
410
664
|
max = 100,
|
|
@@ -415,7 +669,7 @@ var Progress = React5.forwardRef(
|
|
|
415
669
|
}, ref) => {
|
|
416
670
|
const clampedValue = Math.min(Math.max(0, value), max);
|
|
417
671
|
const percentage = clampedValue / max * 100;
|
|
418
|
-
return /* @__PURE__ */
|
|
672
|
+
return /* @__PURE__ */ jsx14(
|
|
419
673
|
"div",
|
|
420
674
|
{
|
|
421
675
|
ref,
|
|
@@ -425,11 +679,11 @@ var Progress = React5.forwardRef(
|
|
|
425
679
|
"aria-valuemax": max,
|
|
426
680
|
"aria-label": ariaLabel || `Progress: ${Math.round(percentage)}%`,
|
|
427
681
|
className: cn(
|
|
428
|
-
"relative h-2 w-full overflow-hidden rounded-
|
|
682
|
+
"relative h-2 w-full overflow-hidden rounded-full bg-accent",
|
|
429
683
|
className
|
|
430
684
|
),
|
|
431
685
|
...props,
|
|
432
|
-
children: /* @__PURE__ */
|
|
686
|
+
children: /* @__PURE__ */ jsx14(
|
|
433
687
|
"div",
|
|
434
688
|
{
|
|
435
689
|
className: cn(progressVariants({ variant })),
|
|
@@ -444,28 +698,44 @@ var Progress = React5.forwardRef(
|
|
|
444
698
|
}
|
|
445
699
|
);
|
|
446
700
|
Progress.displayName = "Progress";
|
|
447
|
-
|
|
701
|
+
|
|
702
|
+
// src/components/checkbox.tsx
|
|
703
|
+
import * as CheckboxPrimitive from "@radix-ui/react-checkbox";
|
|
704
|
+
import { Check, Minus } from "lucide-react";
|
|
705
|
+
import { forwardRef as forwardRef11 } from "react";
|
|
706
|
+
import { jsx as jsx15 } from "react/jsx-runtime";
|
|
707
|
+
var Checkbox = forwardRef11(({ className, indeterminate, ...props }, ref) => /* @__PURE__ */ jsx15(
|
|
448
708
|
CheckboxPrimitive.Root,
|
|
449
709
|
{
|
|
450
710
|
ref,
|
|
451
711
|
"data-slot": "checkbox",
|
|
452
712
|
className: cn(
|
|
453
|
-
|
|
713
|
+
// Resting border uses border-control-border, NOT border-input. An
|
|
714
|
+
// unchecked box has no label, value or focus ring to identify it -- the
|
|
715
|
+
// border is the whole control -- so it is held to 1.4.11's 3:1, which
|
|
716
|
+
// border-input deliberately no longer meets. The checked state switches
|
|
717
|
+
// to border-primary below, keeping the two states distinct.
|
|
718
|
+
"peer relative h-4 w-4 shrink-0 rounded-sm border border-control-border ring-offset-background before:absolute before:left-1/2 before:top-1/2 before:h-6 before:w-6 before:-translate-x-1/2 before:-translate-y-1/2 before:content-[''] focus:border-primary! focus-visible:border-primary! focus:outline-none focus-visible:outline-none aria-invalid:border-destructive aria-invalid:focus:border-destructive! aria-invalid:focus-visible:border-destructive! disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground data-[state=checked]:border-primary data-[state=indeterminate]:bg-primary data-[state=indeterminate]:text-primary-foreground data-[state=indeterminate]:border-primary transition-all duration-200",
|
|
454
719
|
className
|
|
455
720
|
),
|
|
456
721
|
...props,
|
|
457
|
-
children: /* @__PURE__ */
|
|
722
|
+
children: /* @__PURE__ */ jsx15(
|
|
458
723
|
CheckboxPrimitive.Indicator,
|
|
459
724
|
{
|
|
460
725
|
className: cn("flex items-center justify-center text-current"),
|
|
461
|
-
children: indeterminate ? /* @__PURE__ */
|
|
726
|
+
children: indeterminate ? /* @__PURE__ */ jsx15(Minus, { className: "h-3 w-3" }) : /* @__PURE__ */ jsx15(Check, { className: "h-3 w-3" })
|
|
462
727
|
}
|
|
463
728
|
)
|
|
464
729
|
}
|
|
465
730
|
));
|
|
466
731
|
Checkbox.displayName = "Checkbox";
|
|
467
|
-
|
|
468
|
-
|
|
732
|
+
|
|
733
|
+
// src/components/radio-group.tsx
|
|
734
|
+
import * as RadioGroupPrimitive from "@radix-ui/react-radio-group";
|
|
735
|
+
import { forwardRef as forwardRef12 } from "react";
|
|
736
|
+
import { jsx as jsx16 } from "react/jsx-runtime";
|
|
737
|
+
var RadioGroup = forwardRef12(({ className, ...props }, ref) => {
|
|
738
|
+
return /* @__PURE__ */ jsx16(
|
|
469
739
|
RadioGroupPrimitive.Root,
|
|
470
740
|
{
|
|
471
741
|
className: cn("grid gap-2", className),
|
|
@@ -476,52 +746,92 @@ var RadioGroup = forwardRef(({ className, ...props }, ref) => {
|
|
|
476
746
|
);
|
|
477
747
|
});
|
|
478
748
|
RadioGroup.displayName = "RadioGroup";
|
|
479
|
-
var RadioGroupItem =
|
|
480
|
-
return /* @__PURE__ */
|
|
749
|
+
var RadioGroupItem = forwardRef12(({ className, ...props }, ref) => {
|
|
750
|
+
return /* @__PURE__ */ jsx16(
|
|
481
751
|
RadioGroupPrimitive.Item,
|
|
482
752
|
{
|
|
483
753
|
ref,
|
|
484
754
|
"data-slot": "radio-group-item",
|
|
485
755
|
className: cn(
|
|
486
|
-
|
|
756
|
+
// Unchecked outline uses primary/40 (clearly visible) instead of primary/5
|
|
757
|
+
// (~5% opacity, effectively invisible); hover strengthens above the resting state.
|
|
758
|
+
// Resting border uses border-control-border, NOT border-input. An
|
|
759
|
+
// unchecked radio is only its ring, with nothing else to identify it,
|
|
760
|
+
// so it is held to 1.4.11's 3:1 -- which border-input deliberately no
|
|
761
|
+
// longer meets. The checked state switches to border-primary below.
|
|
762
|
+
// rounded-full is fixed rather than derived from --radius: the circle is
|
|
763
|
+
// what tells the user only one option can be chosen. The thick checked
|
|
764
|
+
// border leaves a background-coloured core, and because the border's
|
|
765
|
+
// inner edge is curved too that core reads as a round dot.
|
|
766
|
+
"peer h-4 w-4 shrink-0 rounded-full border border-control-border bg-background cursor-pointer transition-all duration-150 focus:border-primary! focus-visible:border-primary! focus:outline-none focus-visible:outline-none aria-invalid:border-destructive aria-invalid:focus:border-destructive! aria-invalid:focus-visible:border-destructive! disabled:cursor-not-allowed disabled:opacity-50 hover:border-primary/70 data-[state=checked]:border-primary data-[state=checked]:border-[5px]",
|
|
487
767
|
className
|
|
488
768
|
),
|
|
489
769
|
...props,
|
|
490
|
-
children: /* @__PURE__ */
|
|
770
|
+
children: /* @__PURE__ */ jsx16(RadioGroupPrimitive.Indicator, { className: "block size-full rounded-full" })
|
|
491
771
|
}
|
|
492
772
|
);
|
|
493
773
|
});
|
|
494
774
|
RadioGroupItem.displayName = "RadioGroupItem";
|
|
775
|
+
|
|
776
|
+
// src/components/switch.tsx
|
|
777
|
+
import {
|
|
778
|
+
Root as SwitchRoot,
|
|
779
|
+
Thumb as SwitchThumb
|
|
780
|
+
} from "@radix-ui/react-switch";
|
|
781
|
+
import { jsx as jsx17 } from "react/jsx-runtime";
|
|
495
782
|
function Switch({ className, ...props }) {
|
|
496
|
-
return /* @__PURE__ */
|
|
497
|
-
|
|
783
|
+
return /* @__PURE__ */ jsx17(
|
|
784
|
+
SwitchRoot,
|
|
498
785
|
{
|
|
499
786
|
"data-slot": "switch",
|
|
500
787
|
className: cn(
|
|
501
|
-
"peer inline-flex h-[1.15rem] w-8 shrink-0 items-center rounded-
|
|
502
|
-
"data-[state=checked]:bg-primary data-[state=checked]
|
|
503
|
-
|
|
788
|
+
"peer inline-flex h-[1.15rem] w-8 shrink-0 items-center rounded-full border border-border transition-all outline-none focus-visible:border-primary aria-invalid:border-destructive aria-invalid:focus-visible:border-destructive! disabled:cursor-not-allowed disabled:opacity-50",
|
|
789
|
+
"data-[state=checked]:bg-primary data-[state=checked]:border-primary!",
|
|
790
|
+
// An unchecked switch is a track and a thumb and nothing else -- no
|
|
791
|
+
// label inside it, no value, no glyph -- so 1.4.11 applies to both the
|
|
792
|
+
// track against the page and the thumb against the track. `bg-input`
|
|
793
|
+
// cannot serve here: it is the FIELD border weight, deliberately below
|
|
794
|
+
// the minimum, and at that value the pill and its thumb both vanish
|
|
795
|
+
// into a light page. The control token is the same answer used for the
|
|
796
|
+
// checkbox and radio boundary, for the same reason.
|
|
797
|
+
// At full strength in both modes. A `/80` here read as a softening of
|
|
798
|
+
// the dark track and was in fact a removal of the guarantee the token
|
|
799
|
+
// carries: composited over the surfaces the switch renders on it
|
|
800
|
+
// measures 3.02 on the page, 2.94 on a card, 2.85 on a popover or the
|
|
801
|
+
// sidebar and 2.65 on muted, so three of the four fall under the 3:1
|
|
802
|
+
// this token exists to hold. Opaque, the same four are 4.23, 4.01,
|
|
803
|
+
// 3.79 and 3.40.
|
|
804
|
+
"data-[state=unchecked]:bg-control-border data-[state=unchecked]:border-control-border",
|
|
504
805
|
className
|
|
505
806
|
),
|
|
506
807
|
...props,
|
|
507
|
-
children: /* @__PURE__ */
|
|
508
|
-
|
|
808
|
+
children: /* @__PURE__ */ jsx17(
|
|
809
|
+
SwitchThumb,
|
|
509
810
|
{
|
|
510
811
|
"data-slot": "switch-thumb",
|
|
511
812
|
className: cn(
|
|
512
|
-
"bg-background dark:data-[state=unchecked]:bg-foreground dark:data-[state=checked]:bg-primary-foreground pointer-events-none block size-4 rounded-
|
|
813
|
+
"bg-background dark:data-[state=unchecked]:bg-foreground dark:data-[state=checked]:bg-primary-foreground pointer-events-none block size-4 rounded-full ring-0 transition-transform data-[state=checked]:translate-x-[calc(100%-2px)] data-[state=unchecked]:translate-x-0"
|
|
513
814
|
)
|
|
514
815
|
}
|
|
515
816
|
)
|
|
516
817
|
}
|
|
517
818
|
);
|
|
518
819
|
}
|
|
820
|
+
|
|
821
|
+
// src/components/collapsible.tsx
|
|
822
|
+
import * as CollapsiblePrimitive from "@radix-ui/react-collapsible";
|
|
519
823
|
var Collapsible = CollapsiblePrimitive.Root;
|
|
520
824
|
var CollapsibleTrigger2 = CollapsiblePrimitive.CollapsibleTrigger;
|
|
521
825
|
var CollapsibleContent2 = CollapsiblePrimitive.CollapsibleContent;
|
|
826
|
+
|
|
827
|
+
// src/components/accordion.tsx
|
|
828
|
+
import * as AccordionPrimitive from "@radix-ui/react-accordion";
|
|
829
|
+
import { ChevronDown } from "lucide-react";
|
|
830
|
+
import { forwardRef as forwardRef13 } from "react";
|
|
831
|
+
import { jsx as jsx18, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
522
832
|
var Accordion = AccordionPrimitive.Root;
|
|
523
|
-
var AccordionItem =
|
|
524
|
-
({ className, ...props }, ref) => /* @__PURE__ */
|
|
833
|
+
var AccordionItem = forwardRef13(
|
|
834
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx18(
|
|
525
835
|
AccordionPrimitive.Item,
|
|
526
836
|
{
|
|
527
837
|
ref,
|
|
@@ -532,8 +842,8 @@ var AccordionItem = forwardRef(
|
|
|
532
842
|
)
|
|
533
843
|
);
|
|
534
844
|
AccordionItem.displayName = "AccordionItem";
|
|
535
|
-
var AccordionTrigger =
|
|
536
|
-
({ className, children, ...props }, ref) => /* @__PURE__ */
|
|
845
|
+
var AccordionTrigger = forwardRef13(
|
|
846
|
+
({ className, children, ...props }, ref) => /* @__PURE__ */ jsx18(AccordionPrimitive.Header, { className: "flex", "data-slot": "accordion-header", children: /* @__PURE__ */ jsxs3(
|
|
537
847
|
AccordionPrimitive.Trigger,
|
|
538
848
|
{
|
|
539
849
|
ref,
|
|
@@ -545,27 +855,37 @@ var AccordionTrigger = forwardRef(
|
|
|
545
855
|
...props,
|
|
546
856
|
children: [
|
|
547
857
|
children,
|
|
548
|
-
/* @__PURE__ */
|
|
858
|
+
/* @__PURE__ */ jsx18(ChevronDown, { className: "h-4 w-4 shrink-0 transition-transform duration-150 will-change-transform" })
|
|
549
859
|
]
|
|
550
860
|
}
|
|
551
861
|
) })
|
|
552
862
|
);
|
|
553
863
|
AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName;
|
|
554
|
-
var AccordionContent =
|
|
555
|
-
({ className, children, ...props }, ref) => /* @__PURE__ */
|
|
864
|
+
var AccordionContent = forwardRef13(
|
|
865
|
+
({ className, children, ...props }, ref) => /* @__PURE__ */ jsx18(
|
|
556
866
|
AccordionPrimitive.Content,
|
|
557
867
|
{
|
|
558
868
|
ref,
|
|
559
869
|
"data-slot": "accordion-content",
|
|
560
|
-
className: "overflow-hidden text-sm transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down",
|
|
870
|
+
className: "overflow-hidden text-sm transition-all will-change-[height] transform-[translateZ(0)] data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down",
|
|
561
871
|
...props,
|
|
562
|
-
children: /* @__PURE__ */
|
|
872
|
+
children: /* @__PURE__ */ jsx18("div", { className: cn("pb-4 pt-0", className), children })
|
|
563
873
|
}
|
|
564
874
|
)
|
|
565
875
|
);
|
|
566
876
|
AccordionContent.displayName = AccordionPrimitive.Content.displayName;
|
|
567
|
-
|
|
568
|
-
|
|
877
|
+
|
|
878
|
+
// src/components/avatar.tsx
|
|
879
|
+
import {
|
|
880
|
+
Root as AvatarRoot,
|
|
881
|
+
Image as AvatarImagePrimitive,
|
|
882
|
+
Fallback as AvatarFallbackPrimitive
|
|
883
|
+
} from "@radix-ui/react-avatar";
|
|
884
|
+
import { cva as cva7 } from "class-variance-authority";
|
|
885
|
+
import { createContext as createContext2, forwardRef as forwardRef14, useContext as useContext2 } from "react";
|
|
886
|
+
import { jsx as jsx19 } from "react/jsx-runtime";
|
|
887
|
+
var avatarVariants = cva7(
|
|
888
|
+
"relative inline-flex shrink-0 overflow-hidden rounded-full items-center justify-center bg-primary/5 text-muted-foreground",
|
|
569
889
|
{
|
|
570
890
|
variants: {
|
|
571
891
|
size: {
|
|
@@ -593,11 +913,11 @@ var fallbackTextSizeMap = {
|
|
|
593
913
|
"2xl": "text-2xl"
|
|
594
914
|
// 24px for 80px avatar
|
|
595
915
|
};
|
|
596
|
-
var AvatarSizeContext =
|
|
597
|
-
var Avatar =
|
|
916
|
+
var AvatarSizeContext = createContext2("md");
|
|
917
|
+
var Avatar = forwardRef14(
|
|
598
918
|
({ className, size = "md", ...props }, ref) => {
|
|
599
|
-
return /* @__PURE__ */
|
|
600
|
-
|
|
919
|
+
return /* @__PURE__ */ jsx19(AvatarSizeContext.Provider, { value: size, children: /* @__PURE__ */ jsx19(
|
|
920
|
+
AvatarRoot,
|
|
601
921
|
{
|
|
602
922
|
ref,
|
|
603
923
|
"data-slot": "avatar",
|
|
@@ -608,10 +928,10 @@ var Avatar = forwardRef(
|
|
|
608
928
|
}
|
|
609
929
|
);
|
|
610
930
|
Avatar.displayName = "Avatar";
|
|
611
|
-
var AvatarImage =
|
|
931
|
+
var AvatarImage = forwardRef14(
|
|
612
932
|
({ className, ...props }, ref) => {
|
|
613
|
-
return /* @__PURE__ */
|
|
614
|
-
|
|
933
|
+
return /* @__PURE__ */ jsx19(
|
|
934
|
+
AvatarImagePrimitive,
|
|
615
935
|
{
|
|
616
936
|
ref,
|
|
617
937
|
"data-slot": "avatar-image",
|
|
@@ -622,17 +942,17 @@ var AvatarImage = forwardRef(
|
|
|
622
942
|
}
|
|
623
943
|
);
|
|
624
944
|
AvatarImage.displayName = "AvatarImage";
|
|
625
|
-
var AvatarFallback =
|
|
945
|
+
var AvatarFallback = forwardRef14(
|
|
626
946
|
({ className, children, ...props }, ref) => {
|
|
627
|
-
const size =
|
|
947
|
+
const size = useContext2(AvatarSizeContext) || "md";
|
|
628
948
|
const textSize = fallbackTextSizeMap[size];
|
|
629
|
-
return /* @__PURE__ */
|
|
630
|
-
|
|
949
|
+
return /* @__PURE__ */ jsx19(
|
|
950
|
+
AvatarFallbackPrimitive,
|
|
631
951
|
{
|
|
632
952
|
ref,
|
|
633
953
|
"data-slot": "avatar-fallback",
|
|
634
954
|
className: cn(
|
|
635
|
-
"bg-primary/5 text-muted-foreground flex size-full items-center justify-center rounded-
|
|
955
|
+
"bg-primary/5 text-muted-foreground flex size-full items-center justify-center rounded-full font-medium",
|
|
636
956
|
textSize,
|
|
637
957
|
className
|
|
638
958
|
),
|
|
@@ -643,83 +963,113 @@ var AvatarFallback = forwardRef(
|
|
|
643
963
|
}
|
|
644
964
|
);
|
|
645
965
|
AvatarFallback.displayName = "AvatarFallback";
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
966
|
+
|
|
967
|
+
// src/components/tabs.tsx
|
|
968
|
+
import { Root as Root7, List, Trigger as Trigger3, Content as Content3 } from "@radix-ui/react-tabs";
|
|
969
|
+
import { cva as cva8 } from "class-variance-authority";
|
|
970
|
+
import { forwardRef as forwardRef15 } from "react";
|
|
971
|
+
import { jsx as jsx20 } from "react/jsx-runtime";
|
|
972
|
+
var Tabs = Root7;
|
|
973
|
+
var TABS_LIST_VARIANTS = {
|
|
974
|
+
default: "h-10",
|
|
975
|
+
ghost: "h-8 bg-transparent"
|
|
976
|
+
};
|
|
977
|
+
var tabsListVariants = cva8(
|
|
978
|
+
// Square corners: underline tabs, so the list never draws a rounded surface.
|
|
979
|
+
// `gap-1` and `p-0` are invariant across the variants, so they belong here —
|
|
980
|
+
// repeating them in each arm gives any future adjustment two sites to change
|
|
981
|
+
// and one to forget.
|
|
982
|
+
//
|
|
983
|
+
// The rail the triggers sit on, and it is load-bearing rather than
|
|
984
|
+
// decoration. Each trigger draws a 2px border on its trailing edge and pulls
|
|
985
|
+
// itself half a step onto this one: with no rail here, that pull put a 2px
|
|
986
|
+
// line onto whatever followed the strip in the document, and above a rounded
|
|
987
|
+
// panel that is the corner curve — a straight bar crossing an 8px arc. The
|
|
988
|
+
// rail also gives an inactive tab somewhere to be inactive, which is what
|
|
989
|
+
// makes the active one read as selected rather than as the only tab.
|
|
990
|
+
//
|
|
991
|
+
// Which edge is the trailing one depends on orientation, so the rail follows
|
|
992
|
+
// it. Radix stamps `data-orientation` on the list and on every trigger, so
|
|
993
|
+
// both halves read the same source and cannot disagree about the axis. A
|
|
994
|
+
// fixed bottom rail draws a horizontal line beneath a vertical list.
|
|
995
|
+
"inline-flex items-center justify-center gap-1 rounded-none border-b border-border p-0 text-muted-foreground data-[orientation=vertical]:flex-col data-[orientation=vertical]:items-stretch data-[orientation=vertical]:border-b-0 data-[orientation=vertical]:border-r",
|
|
996
|
+
{
|
|
997
|
+
variants: { variant: TABS_LIST_VARIANTS },
|
|
998
|
+
defaultVariants: { variant: "default" }
|
|
999
|
+
}
|
|
660
1000
|
);
|
|
1001
|
+
var TabsList = forwardRef15(({ className, variant, ...props }, ref) => /* @__PURE__ */ jsx20(
|
|
1002
|
+
List,
|
|
1003
|
+
{
|
|
1004
|
+
ref,
|
|
1005
|
+
"data-slot": "tabs-list",
|
|
1006
|
+
className: cn(tabsListVariants({ variant }), className),
|
|
1007
|
+
...props
|
|
1008
|
+
}
|
|
1009
|
+
));
|
|
661
1010
|
TabsList.displayName = List.displayName;
|
|
662
|
-
var
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
1011
|
+
var TABS_TRIGGER_SIZES = {
|
|
1012
|
+
default: "text-sm",
|
|
1013
|
+
sm: "text-xs"
|
|
1014
|
+
};
|
|
1015
|
+
var tabsTriggerVariants = cva8(
|
|
1016
|
+
// Square corners: the active state is a 2px border on the trailing edge that
|
|
1017
|
+
// has to run the full length of the trigger and stay flush with its ends.
|
|
1018
|
+
//
|
|
1019
|
+
// The active colour is NOT important-marked. Nothing inside this component
|
|
1020
|
+
// competes for it — the inactive arm is mutually exclusive with the active
|
|
1021
|
+
// one — so the only thing an `!` could win against is a caller's class, which
|
|
1022
|
+
// is precisely what a theme supplies. Marking it made the one line under
|
|
1023
|
+
// every selected tab the one line a theme could not restyle, and the failure
|
|
1024
|
+
// read as "the theme did not apply here" rather than as an opt-out.
|
|
1025
|
+
//
|
|
1026
|
+
// The trailing edge is the bottom when the strip is horizontal and the right
|
|
1027
|
+
// when it is vertical, so the indicator, the half-step pull onto the rail and
|
|
1028
|
+
// the active colour all switch axis together off the same `data-orientation`
|
|
1029
|
+
// the list reads. Switching only some of them puts the selection affordance
|
|
1030
|
+
// on one axis and the line it sits on the other.
|
|
1031
|
+
"inline-flex items-center justify-center whitespace-nowrap rounded-none bg-transparent px-4 py-2 font-medium cursor-pointer transition-all duration-200 border-b-2 relative -mb-0.5 data-[state=active]:border-b-primary data-[state=active]:text-primary data-[state=inactive]:border-transparent data-[state=inactive]:text-muted-foreground hover:text-primary hover:border-primary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 disabled:cursor-not-allowed data-[orientation=vertical]:border-b-0 data-[orientation=vertical]:mb-0 data-[orientation=vertical]:border-r-2 data-[orientation=vertical]:-mr-0.5 data-[orientation=vertical]:data-[state=active]:border-r-primary",
|
|
1032
|
+
{
|
|
1033
|
+
variants: { size: TABS_TRIGGER_SIZES },
|
|
1034
|
+
defaultVariants: { size: "default" }
|
|
1035
|
+
}
|
|
675
1036
|
);
|
|
676
|
-
TabsTrigger
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
1037
|
+
var TabsTrigger = forwardRef15(({ className, size, ...props }, ref) => /* @__PURE__ */ jsx20(
|
|
1038
|
+
Trigger3,
|
|
1039
|
+
{
|
|
1040
|
+
ref,
|
|
1041
|
+
"data-slot": "tabs-trigger",
|
|
1042
|
+
className: cn(tabsTriggerVariants({ size }), className),
|
|
1043
|
+
...props
|
|
1044
|
+
}
|
|
1045
|
+
));
|
|
1046
|
+
TabsTrigger.displayName = Trigger3.displayName;
|
|
1047
|
+
var TabsContent = forwardRef15(
|
|
1048
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx20(
|
|
1049
|
+
Content3,
|
|
680
1050
|
{
|
|
681
1051
|
ref,
|
|
682
1052
|
"data-slot": "tabs-content",
|
|
683
1053
|
className: cn(
|
|
684
|
-
"mt-2 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring
|
|
1054
|
+
"mt-2 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
|
685
1055
|
className
|
|
686
1056
|
),
|
|
687
1057
|
...props
|
|
688
1058
|
}
|
|
689
1059
|
)
|
|
690
1060
|
);
|
|
691
|
-
TabsContent.displayName =
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
{
|
|
698
|
-
ref,
|
|
699
|
-
sideOffset,
|
|
700
|
-
"data-slot": "tooltip-content",
|
|
701
|
-
className: cn(
|
|
702
|
-
"z-50 overflow-hidden rounded-none px-3 py-1.5 text-xs shadow-lg border border-primary/5 bg-popover text-popover-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
|
703
|
-
className
|
|
704
|
-
),
|
|
705
|
-
...props
|
|
706
|
-
}
|
|
707
|
-
));
|
|
708
|
-
TooltipContent.displayName = Content$1.displayName;
|
|
709
|
-
var PortalContext = createContext({ container: null });
|
|
710
|
-
function PortalProvider({ container, children }) {
|
|
711
|
-
return /* @__PURE__ */ jsx(PortalContext.Provider, { value: { container }, children });
|
|
712
|
-
}
|
|
713
|
-
function usePortalContainer() {
|
|
714
|
-
const { container } = useContext(PortalContext);
|
|
715
|
-
return container ?? void 0;
|
|
716
|
-
}
|
|
1061
|
+
TabsContent.displayName = Content3.displayName;
|
|
1062
|
+
|
|
1063
|
+
// src/components/popover.tsx
|
|
1064
|
+
import * as PopoverPrimitive from "@radix-ui/react-popover";
|
|
1065
|
+
import * as React5 from "react";
|
|
1066
|
+
import { jsx as jsx21 } from "react/jsx-runtime";
|
|
717
1067
|
var Popover = PopoverPrimitive.Root;
|
|
718
1068
|
var PopoverTrigger = PopoverPrimitive.Trigger;
|
|
719
1069
|
var PopoverAnchor = PopoverPrimitive.Anchor;
|
|
720
1070
|
var PopoverContent = React5.forwardRef(({ className, align = "center", sideOffset = 4, ...props }, ref) => {
|
|
721
1071
|
const portalContainer = usePortalContainer();
|
|
722
|
-
return /* @__PURE__ */
|
|
1072
|
+
return /* @__PURE__ */ jsx21(PopoverPrimitive.Portal, { container: portalContainer, children: /* @__PURE__ */ jsx21(
|
|
723
1073
|
PopoverPrimitive.Content,
|
|
724
1074
|
{
|
|
725
1075
|
ref,
|
|
@@ -727,7 +1077,7 @@ var PopoverContent = React5.forwardRef(({ className, align = "center", sideOffse
|
|
|
727
1077
|
sideOffset,
|
|
728
1078
|
"data-slot": "popover-content",
|
|
729
1079
|
className: cn(
|
|
730
|
-
"z-[100] w-72 rounded-
|
|
1080
|
+
"z-[100] w-72 rounded-lg border border-border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-popover-content-transform-origin]",
|
|
731
1081
|
className
|
|
732
1082
|
),
|
|
733
1083
|
...props
|
|
@@ -735,24 +1085,36 @@ var PopoverContent = React5.forwardRef(({ className, align = "center", sideOffse
|
|
|
735
1085
|
) });
|
|
736
1086
|
});
|
|
737
1087
|
PopoverContent.displayName = PopoverPrimitive.Content.displayName;
|
|
1088
|
+
|
|
1089
|
+
// src/components/dialog.tsx
|
|
1090
|
+
import * as DialogPrimitive from "@radix-ui/react-dialog";
|
|
1091
|
+
import { cva as cva9 } from "class-variance-authority";
|
|
1092
|
+
import { X } from "lucide-react";
|
|
1093
|
+
import { forwardRef as forwardRef17 } from "react";
|
|
1094
|
+
import { jsx as jsx22, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
738
1095
|
var Dialog = DialogPrimitive.Root;
|
|
739
1096
|
var DialogTrigger = DialogPrimitive.Trigger;
|
|
740
1097
|
var DialogPortal = DialogPrimitive.Portal;
|
|
741
1098
|
var DialogClose = DialogPrimitive.Close;
|
|
742
|
-
var DialogOverlay =
|
|
1099
|
+
var DialogOverlay = forwardRef17(({ className, ...props }, ref) => /* @__PURE__ */ jsx22(
|
|
743
1100
|
DialogPrimitive.Overlay,
|
|
744
1101
|
{
|
|
745
1102
|
ref,
|
|
746
1103
|
"data-slot": "dialog-overlay",
|
|
747
1104
|
className: cn(
|
|
748
|
-
|
|
1105
|
+
// A modal scrim, from the `--nx-overlay` token rather than a surface
|
|
1106
|
+
// token. A black wash is the point — painting it from `background` would
|
|
1107
|
+
// make it a white veil in light mode — but the alpha still has to differ
|
|
1108
|
+
// per mode, because what it composites over is white in one and mid-tone
|
|
1109
|
+
// in the other.
|
|
1110
|
+
"fixed inset-0 z-50 bg-overlay backdrop-blur-sm transition-opacity duration-150 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
749
1111
|
className
|
|
750
1112
|
),
|
|
751
1113
|
...props
|
|
752
1114
|
}
|
|
753
1115
|
));
|
|
754
1116
|
DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
|
|
755
|
-
var dialogContentVariants =
|
|
1117
|
+
var dialogContentVariants = cva9("", {
|
|
756
1118
|
variants: {
|
|
757
1119
|
size: {
|
|
758
1120
|
sm: "max-w-sm",
|
|
@@ -766,31 +1128,31 @@ var dialogContentVariants = cva("", {
|
|
|
766
1128
|
size: "md"
|
|
767
1129
|
}
|
|
768
1130
|
});
|
|
769
|
-
var DialogContent =
|
|
1131
|
+
var DialogContent = forwardRef17(({ className, children, size, ...props }, ref) => {
|
|
770
1132
|
const portalContainer = usePortalContainer();
|
|
771
|
-
return /* @__PURE__ */
|
|
772
|
-
/* @__PURE__ */
|
|
773
|
-
/* @__PURE__ */
|
|
1133
|
+
return /* @__PURE__ */ jsxs4(DialogPortal, { container: portalContainer, children: [
|
|
1134
|
+
/* @__PURE__ */ jsx22(DialogOverlay, {}),
|
|
1135
|
+
/* @__PURE__ */ jsxs4(
|
|
774
1136
|
DialogPrimitive.Content,
|
|
775
1137
|
{
|
|
776
1138
|
ref,
|
|
777
1139
|
"data-slot": "dialog-content",
|
|
778
1140
|
className: cn(
|
|
779
|
-
"fixed left-[50%] top-[50%] z-[51] grid w-full translate-x-[-50%] translate-y-[-50%] gap-4 border border-
|
|
1141
|
+
"fixed left-[50%] top-[50%] z-[51] grid w-full translate-x-[-50%] translate-y-[-50%] gap-4 border border-border bg-background p-6 shadow-xl rounded-lg duration-150 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%]",
|
|
780
1142
|
dialogContentVariants({ size }),
|
|
781
1143
|
className
|
|
782
1144
|
),
|
|
783
1145
|
...props,
|
|
784
1146
|
children: [
|
|
785
1147
|
children,
|
|
786
|
-
/* @__PURE__ */
|
|
1148
|
+
/* @__PURE__ */ jsxs4(
|
|
787
1149
|
DialogPrimitive.Close,
|
|
788
1150
|
{
|
|
789
1151
|
"data-slot": "dialog-close",
|
|
790
|
-
className: "absolute right-4 top-4 rounded-
|
|
1152
|
+
className: "absolute right-4 top-4 rounded-md p-1 text-muted-foreground cursor-pointer transition-colors duration-150 hover-unified focus:outline-none focus:ring-2 focus:ring-ring disabled:pointer-events-none disabled:cursor-not-allowed",
|
|
791
1153
|
children: [
|
|
792
|
-
/* @__PURE__ */
|
|
793
|
-
/* @__PURE__ */
|
|
1154
|
+
/* @__PURE__ */ jsx22(X, { className: "h-4 w-4" }),
|
|
1155
|
+
/* @__PURE__ */ jsx22("span", { className: "sr-only", children: "Close" })
|
|
794
1156
|
]
|
|
795
1157
|
}
|
|
796
1158
|
)
|
|
@@ -800,8 +1162,8 @@ var DialogContent = forwardRef(({ className, children, size, ...props }, ref) =>
|
|
|
800
1162
|
] });
|
|
801
1163
|
});
|
|
802
1164
|
DialogContent.displayName = DialogPrimitive.Content.displayName;
|
|
803
|
-
var DialogHeader =
|
|
804
|
-
({ className, ...props }, ref) => /* @__PURE__ */
|
|
1165
|
+
var DialogHeader = forwardRef17(
|
|
1166
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx22(
|
|
805
1167
|
"div",
|
|
806
1168
|
{
|
|
807
1169
|
ref,
|
|
@@ -814,8 +1176,8 @@ var DialogHeader = forwardRef(
|
|
|
814
1176
|
)
|
|
815
1177
|
);
|
|
816
1178
|
DialogHeader.displayName = "DialogHeader";
|
|
817
|
-
var DialogFooter =
|
|
818
|
-
({ className, ...props }, ref) => /* @__PURE__ */
|
|
1179
|
+
var DialogFooter = forwardRef17(
|
|
1180
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx22(
|
|
819
1181
|
"div",
|
|
820
1182
|
{
|
|
821
1183
|
ref,
|
|
@@ -828,7 +1190,7 @@ var DialogFooter = forwardRef(
|
|
|
828
1190
|
)
|
|
829
1191
|
);
|
|
830
1192
|
DialogFooter.displayName = "DialogFooter";
|
|
831
|
-
var DialogTitle =
|
|
1193
|
+
var DialogTitle = forwardRef17(({ className, ...props }, ref) => /* @__PURE__ */ jsx22(
|
|
832
1194
|
DialogPrimitive.Title,
|
|
833
1195
|
{
|
|
834
1196
|
ref,
|
|
@@ -840,7 +1202,7 @@ var DialogTitle = forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ j
|
|
|
840
1202
|
}
|
|
841
1203
|
));
|
|
842
1204
|
DialogTitle.displayName = DialogPrimitive.Title.displayName;
|
|
843
|
-
var DialogDescription =
|
|
1205
|
+
var DialogDescription = forwardRef17(({ className, ...props }, ref) => /* @__PURE__ */ jsx22(
|
|
844
1206
|
DialogPrimitive.Description,
|
|
845
1207
|
{
|
|
846
1208
|
ref,
|
|
@@ -849,31 +1211,43 @@ var DialogDescription = forwardRef(({ className, ...props }, ref) => /* @__PURE_
|
|
|
849
1211
|
}
|
|
850
1212
|
));
|
|
851
1213
|
DialogDescription.displayName = DialogPrimitive.Description.displayName;
|
|
1214
|
+
|
|
1215
|
+
// src/components/alert-dialog.tsx
|
|
1216
|
+
import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog";
|
|
1217
|
+
import {
|
|
1218
|
+
forwardRef as forwardRef18
|
|
1219
|
+
} from "react";
|
|
1220
|
+
import { jsx as jsx23, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
852
1221
|
var AlertDialog = AlertDialogPrimitive.Root;
|
|
853
1222
|
var AlertDialogTrigger = AlertDialogPrimitive.Trigger;
|
|
854
1223
|
var AlertDialogPortal = AlertDialogPrimitive.Portal;
|
|
855
|
-
var AlertDialogOverlay =
|
|
1224
|
+
var AlertDialogOverlay = forwardRef18(({ className, ...props }, ref) => /* @__PURE__ */ jsx23(
|
|
856
1225
|
AlertDialogPrimitive.Overlay,
|
|
857
1226
|
{
|
|
858
1227
|
ref,
|
|
859
1228
|
className: cn(
|
|
860
|
-
|
|
1229
|
+
// A modal scrim, from the `--nx-overlay` token rather than a surface
|
|
1230
|
+
// token. A black wash is the point — painting it from `background` would
|
|
1231
|
+
// make it a white veil in light mode — but the alpha still has to differ
|
|
1232
|
+
// per mode, because what it composites over is white in one and mid-tone
|
|
1233
|
+
// in the other.
|
|
1234
|
+
"fixed inset-0 z-50 bg-overlay backdrop-blur-sm transition-opacity duration-150 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
861
1235
|
className
|
|
862
1236
|
),
|
|
863
1237
|
...props
|
|
864
1238
|
}
|
|
865
1239
|
));
|
|
866
1240
|
AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName;
|
|
867
|
-
var AlertDialogContent =
|
|
1241
|
+
var AlertDialogContent = forwardRef18(({ className, ...props }, ref) => {
|
|
868
1242
|
const portalContainer = usePortalContainer();
|
|
869
|
-
return /* @__PURE__ */
|
|
870
|
-
/* @__PURE__ */
|
|
871
|
-
/* @__PURE__ */
|
|
1243
|
+
return /* @__PURE__ */ jsxs5(AlertDialogPortal, { container: portalContainer, children: [
|
|
1244
|
+
/* @__PURE__ */ jsx23(AlertDialogOverlay, {}),
|
|
1245
|
+
/* @__PURE__ */ jsx23(
|
|
872
1246
|
AlertDialogPrimitive.Content,
|
|
873
1247
|
{
|
|
874
1248
|
ref,
|
|
875
1249
|
className: cn(
|
|
876
|
-
"fixed left-[50%] top-[50%] z-[51] grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border border-
|
|
1250
|
+
"fixed left-[50%] top-[50%] z-[51] grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border border-border bg-background p-6 shadow-xl rounded-lg duration-150 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%]",
|
|
877
1251
|
className
|
|
878
1252
|
),
|
|
879
1253
|
...props
|
|
@@ -882,8 +1256,8 @@ var AlertDialogContent = forwardRef(({ className, ...props }, ref) => {
|
|
|
882
1256
|
] });
|
|
883
1257
|
});
|
|
884
1258
|
AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName;
|
|
885
|
-
var AlertDialogHeader =
|
|
886
|
-
({ className, ...props }, ref) => /* @__PURE__ */
|
|
1259
|
+
var AlertDialogHeader = forwardRef18(
|
|
1260
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx23(
|
|
887
1261
|
"div",
|
|
888
1262
|
{
|
|
889
1263
|
ref,
|
|
@@ -896,8 +1270,8 @@ var AlertDialogHeader = forwardRef(
|
|
|
896
1270
|
)
|
|
897
1271
|
);
|
|
898
1272
|
AlertDialogHeader.displayName = "AlertDialogHeader";
|
|
899
|
-
var AlertDialogFooter =
|
|
900
|
-
({ className, ...props }, ref) => /* @__PURE__ */
|
|
1273
|
+
var AlertDialogFooter = forwardRef18(
|
|
1274
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx23(
|
|
901
1275
|
"div",
|
|
902
1276
|
{
|
|
903
1277
|
ref,
|
|
@@ -910,7 +1284,7 @@ var AlertDialogFooter = forwardRef(
|
|
|
910
1284
|
)
|
|
911
1285
|
);
|
|
912
1286
|
AlertDialogFooter.displayName = "AlertDialogFooter";
|
|
913
|
-
var AlertDialogTitle =
|
|
1287
|
+
var AlertDialogTitle = forwardRef18(({ className, ...props }, ref) => /* @__PURE__ */ jsx23(
|
|
914
1288
|
AlertDialogPrimitive.Title,
|
|
915
1289
|
{
|
|
916
1290
|
ref,
|
|
@@ -922,7 +1296,7 @@ var AlertDialogTitle = forwardRef(({ className, ...props }, ref) => /* @__PURE__
|
|
|
922
1296
|
}
|
|
923
1297
|
));
|
|
924
1298
|
AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName;
|
|
925
|
-
var AlertDialogDescription =
|
|
1299
|
+
var AlertDialogDescription = forwardRef18(({ className, ...props }, ref) => /* @__PURE__ */ jsx23(
|
|
926
1300
|
AlertDialogPrimitive.Description,
|
|
927
1301
|
{
|
|
928
1302
|
ref,
|
|
@@ -931,7 +1305,7 @@ var AlertDialogDescription = forwardRef(({ className, ...props }, ref) => /* @__
|
|
|
931
1305
|
}
|
|
932
1306
|
));
|
|
933
1307
|
AlertDialogDescription.displayName = AlertDialogPrimitive.Description.displayName;
|
|
934
|
-
var AlertDialogAction =
|
|
1308
|
+
var AlertDialogAction = forwardRef18(({ className, children, ...props }, ref) => /* @__PURE__ */ jsx23(
|
|
935
1309
|
AlertDialogPrimitive.Action,
|
|
936
1310
|
{
|
|
937
1311
|
ref,
|
|
@@ -941,7 +1315,7 @@ var AlertDialogAction = forwardRef(({ className, children, ...props }, ref) => /
|
|
|
941
1315
|
}
|
|
942
1316
|
));
|
|
943
1317
|
AlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName;
|
|
944
|
-
var AlertDialogCancel =
|
|
1318
|
+
var AlertDialogCancel = forwardRef18(({ className, children, ...props }, ref) => /* @__PURE__ */ jsx23(
|
|
945
1319
|
AlertDialogPrimitive.Cancel,
|
|
946
1320
|
{
|
|
947
1321
|
ref,
|
|
@@ -955,50 +1329,58 @@ var AlertDialogCancel = forwardRef(({ className, children, ...props }, ref) => /
|
|
|
955
1329
|
}
|
|
956
1330
|
));
|
|
957
1331
|
AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName;
|
|
1332
|
+
|
|
1333
|
+
// src/components/dropdown-menu.tsx
|
|
1334
|
+
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
|
|
1335
|
+
import { Check as Check2, ChevronRight, Circle } from "lucide-react";
|
|
1336
|
+
import * as React6 from "react";
|
|
1337
|
+
import { jsx as jsx24, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
958
1338
|
var DropdownMenu = DropdownMenuPrimitive.Root;
|
|
959
1339
|
var DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;
|
|
960
1340
|
var DropdownMenuGroup = DropdownMenuPrimitive.Group;
|
|
961
1341
|
var DropdownMenuPortal = DropdownMenuPrimitive.Portal;
|
|
962
1342
|
var DropdownMenuSub = DropdownMenuPrimitive.Sub;
|
|
963
1343
|
var DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup;
|
|
964
|
-
var
|
|
1344
|
+
var menuItemBase = "cursor-pointer transition-colors data-[highlighted]:bg-muted data-[highlighted]:text-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50";
|
|
1345
|
+
var DropdownMenuSubTrigger = React6.forwardRef(({ className, inset, children, ...props }, ref) => /* @__PURE__ */ jsxs6(
|
|
965
1346
|
DropdownMenuPrimitive.SubTrigger,
|
|
966
1347
|
{
|
|
967
1348
|
ref,
|
|
968
1349
|
className: cn(
|
|
969
|
-
"flex
|
|
1350
|
+
"flex select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none data-[state=open]:bg-muted data-[state=open]:text-foreground [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
|
1351
|
+
menuItemBase,
|
|
970
1352
|
inset && "pl-8",
|
|
971
1353
|
className
|
|
972
1354
|
),
|
|
973
1355
|
...props,
|
|
974
1356
|
children: [
|
|
975
1357
|
children,
|
|
976
|
-
/* @__PURE__ */
|
|
1358
|
+
/* @__PURE__ */ jsx24(ChevronRight, { className: "ml-auto" })
|
|
977
1359
|
]
|
|
978
1360
|
}
|
|
979
1361
|
));
|
|
980
1362
|
DropdownMenuSubTrigger.displayName = DropdownMenuPrimitive.SubTrigger.displayName;
|
|
981
|
-
var DropdownMenuSubContent =
|
|
1363
|
+
var DropdownMenuSubContent = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx24(
|
|
982
1364
|
DropdownMenuPrimitive.SubContent,
|
|
983
1365
|
{
|
|
984
1366
|
ref,
|
|
985
1367
|
className: cn(
|
|
986
|
-
"z-50 min-w-[8rem] overflow-hidden rounded-
|
|
1368
|
+
"z-50 min-w-[8rem] overflow-hidden rounded-lg border border-border bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-dropdown-menu-content-transform-origin]",
|
|
987
1369
|
className
|
|
988
1370
|
),
|
|
989
1371
|
...props
|
|
990
1372
|
}
|
|
991
1373
|
));
|
|
992
1374
|
DropdownMenuSubContent.displayName = DropdownMenuPrimitive.SubContent.displayName;
|
|
993
|
-
var DropdownMenuContent =
|
|
1375
|
+
var DropdownMenuContent = React6.forwardRef(({ className, sideOffset = 4, ...props }, ref) => {
|
|
994
1376
|
const portalContainer = usePortalContainer();
|
|
995
|
-
return /* @__PURE__ */
|
|
1377
|
+
return /* @__PURE__ */ jsx24(DropdownMenuPrimitive.Portal, { container: portalContainer, children: /* @__PURE__ */ jsx24(
|
|
996
1378
|
DropdownMenuPrimitive.Content,
|
|
997
1379
|
{
|
|
998
1380
|
ref,
|
|
999
1381
|
sideOffset,
|
|
1000
1382
|
className: cn(
|
|
1001
|
-
"z-50 max-h-[var(--radix-dropdown-menu-content-available-height)] min-w-[8rem] overflow-y-auto overflow-x-hidden rounded-
|
|
1383
|
+
"z-50 max-h-[var(--radix-dropdown-menu-content-available-height)] min-w-[8rem] overflow-y-auto overflow-x-hidden rounded-lg border border-border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-dropdown-menu-content-transform-origin]",
|
|
1002
1384
|
className
|
|
1003
1385
|
),
|
|
1004
1386
|
...props
|
|
@@ -1006,12 +1388,13 @@ var DropdownMenuContent = React5.forwardRef(({ className, sideOffset = 4, ...pro
|
|
|
1006
1388
|
) });
|
|
1007
1389
|
});
|
|
1008
1390
|
DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName;
|
|
1009
|
-
var DropdownMenuItem =
|
|
1391
|
+
var DropdownMenuItem = React6.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ jsx24(
|
|
1010
1392
|
DropdownMenuPrimitive.Item,
|
|
1011
1393
|
{
|
|
1012
1394
|
ref,
|
|
1013
1395
|
className: cn(
|
|
1014
|
-
"relative flex
|
|
1396
|
+
"relative flex select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
|
1397
|
+
menuItemBase,
|
|
1015
1398
|
inset && "pl-8",
|
|
1016
1399
|
className
|
|
1017
1400
|
),
|
|
@@ -1019,40 +1402,42 @@ var DropdownMenuItem = React5.forwardRef(({ className, inset, ...props }, ref) =
|
|
|
1019
1402
|
}
|
|
1020
1403
|
));
|
|
1021
1404
|
DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName;
|
|
1022
|
-
var DropdownMenuCheckboxItem =
|
|
1405
|
+
var DropdownMenuCheckboxItem = React6.forwardRef(({ className, children, checked, ...props }, ref) => /* @__PURE__ */ jsxs6(
|
|
1023
1406
|
DropdownMenuPrimitive.CheckboxItem,
|
|
1024
1407
|
{
|
|
1025
1408
|
ref,
|
|
1026
1409
|
className: cn(
|
|
1027
|
-
"relative flex
|
|
1410
|
+
"relative flex select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none",
|
|
1411
|
+
menuItemBase,
|
|
1028
1412
|
className
|
|
1029
1413
|
),
|
|
1030
1414
|
checked,
|
|
1031
1415
|
...props,
|
|
1032
1416
|
children: [
|
|
1033
|
-
/* @__PURE__ */
|
|
1417
|
+
/* @__PURE__ */ jsx24("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsx24(DropdownMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx24(Check2, { className: "h-4 w-4" }) }) }),
|
|
1034
1418
|
children
|
|
1035
1419
|
]
|
|
1036
1420
|
}
|
|
1037
1421
|
));
|
|
1038
1422
|
DropdownMenuCheckboxItem.displayName = DropdownMenuPrimitive.CheckboxItem.displayName;
|
|
1039
|
-
var DropdownMenuRadioItem =
|
|
1423
|
+
var DropdownMenuRadioItem = React6.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs6(
|
|
1040
1424
|
DropdownMenuPrimitive.RadioItem,
|
|
1041
1425
|
{
|
|
1042
1426
|
ref,
|
|
1043
1427
|
className: cn(
|
|
1044
|
-
"relative flex
|
|
1428
|
+
"relative flex select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none",
|
|
1429
|
+
menuItemBase,
|
|
1045
1430
|
className
|
|
1046
1431
|
),
|
|
1047
1432
|
...props,
|
|
1048
1433
|
children: [
|
|
1049
|
-
/* @__PURE__ */
|
|
1434
|
+
/* @__PURE__ */ jsx24("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsx24(DropdownMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx24(Circle, { className: "h-2 w-2 fill-current" }) }) }),
|
|
1050
1435
|
children
|
|
1051
1436
|
]
|
|
1052
1437
|
}
|
|
1053
1438
|
));
|
|
1054
1439
|
DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName;
|
|
1055
|
-
var DropdownMenuLabel =
|
|
1440
|
+
var DropdownMenuLabel = React6.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ jsx24(
|
|
1056
1441
|
DropdownMenuPrimitive.Label,
|
|
1057
1442
|
{
|
|
1058
1443
|
ref,
|
|
@@ -1065,7 +1450,7 @@ var DropdownMenuLabel = React5.forwardRef(({ className, inset, ...props }, ref)
|
|
|
1065
1450
|
}
|
|
1066
1451
|
));
|
|
1067
1452
|
DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName;
|
|
1068
|
-
var DropdownMenuSeparator =
|
|
1453
|
+
var DropdownMenuSeparator = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx24(
|
|
1069
1454
|
DropdownMenuPrimitive.Separator,
|
|
1070
1455
|
{
|
|
1071
1456
|
ref,
|
|
@@ -1074,8 +1459,8 @@ var DropdownMenuSeparator = React5.forwardRef(({ className, ...props }, ref) =>
|
|
|
1074
1459
|
}
|
|
1075
1460
|
));
|
|
1076
1461
|
DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName;
|
|
1077
|
-
var DropdownMenuShortcut =
|
|
1078
|
-
return /* @__PURE__ */
|
|
1462
|
+
var DropdownMenuShortcut = React6.forwardRef(({ className, ...props }, ref) => {
|
|
1463
|
+
return /* @__PURE__ */ jsx24(
|
|
1079
1464
|
"span",
|
|
1080
1465
|
{
|
|
1081
1466
|
ref,
|
|
@@ -1085,27 +1470,39 @@ var DropdownMenuShortcut = React5.forwardRef(({ className, ...props }, ref) => {
|
|
|
1085
1470
|
);
|
|
1086
1471
|
});
|
|
1087
1472
|
DropdownMenuShortcut.displayName = "DropdownMenuShortcut";
|
|
1473
|
+
|
|
1474
|
+
// src/components/select.tsx
|
|
1475
|
+
import * as SelectPrimitive from "@radix-ui/react-select";
|
|
1476
|
+
import { cva as cva10 } from "class-variance-authority";
|
|
1477
|
+
import { Check as Check3, ChevronDown as ChevronDown2, ChevronUp } from "lucide-react";
|
|
1478
|
+
import { forwardRef as forwardRef20 } from "react";
|
|
1479
|
+
import { jsx as jsx25, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1088
1480
|
function Select({ ...props }) {
|
|
1089
|
-
return /* @__PURE__ */
|
|
1481
|
+
return /* @__PURE__ */ jsx25(SelectPrimitive.Root, { "data-slot": "select", ...props });
|
|
1090
1482
|
}
|
|
1091
1483
|
function SelectGroup({
|
|
1092
1484
|
...props
|
|
1093
1485
|
}) {
|
|
1094
|
-
return /* @__PURE__ */
|
|
1486
|
+
return /* @__PURE__ */ jsx25(SelectPrimitive.Group, { "data-slot": "select-group", ...props });
|
|
1095
1487
|
}
|
|
1096
1488
|
function SelectValue({
|
|
1097
1489
|
...props
|
|
1098
1490
|
}) {
|
|
1099
|
-
return /* @__PURE__ */
|
|
1491
|
+
return /* @__PURE__ */ jsx25(SelectPrimitive.Value, { "data-slot": "select-value", ...props });
|
|
1100
1492
|
}
|
|
1101
|
-
var selectTriggerVariants =
|
|
1102
|
-
|
|
1493
|
+
var selectTriggerVariants = cva10(
|
|
1494
|
+
// hover:border-primary (full strength) keeps the hover boundary more visible
|
|
1495
|
+
// than the resting border-input, not a fainter alpha of it.
|
|
1496
|
+
"flex w-full items-center justify-between gap-2 rounded-md border border-input bg-background px-3 text-sm text-foreground cursor-pointer transition-all duration-150 focus:border-primary! focus-visible:border-primary! focus:outline-none hover:border-primary disabled:cursor-not-allowed disabled:opacity-50 disabled:bg-primary/5 data-[placeholder]:text-muted-foreground aria-[invalid=true]:border-destructive aria-[invalid=true]:focus:border-destructive! [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg]:size-4",
|
|
1103
1497
|
{
|
|
1104
1498
|
variants: {
|
|
1105
1499
|
size: {
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1500
|
+
// `-md`, matching Button and Input: one height for one size name. A
|
|
1501
|
+
// select sitting beside a small button in a filter row is the case that
|
|
1502
|
+
// makes a 4px difference visible.
|
|
1503
|
+
sm: "h-[var(--nx-control-height-md)] text-sm",
|
|
1504
|
+
default: "h-[var(--nx-control-height)] text-sm",
|
|
1505
|
+
lg: "h-[var(--nx-control-height-lg)] text-base"
|
|
1109
1506
|
}
|
|
1110
1507
|
},
|
|
1111
1508
|
defaultVariants: {
|
|
@@ -1113,8 +1510,8 @@ var selectTriggerVariants = cva(
|
|
|
1113
1510
|
}
|
|
1114
1511
|
}
|
|
1115
1512
|
);
|
|
1116
|
-
var SelectTrigger =
|
|
1117
|
-
return /* @__PURE__ */
|
|
1513
|
+
var SelectTrigger = forwardRef20(({ className, size, children, ...props }, ref) => {
|
|
1514
|
+
return /* @__PURE__ */ jsxs7(
|
|
1118
1515
|
SelectPrimitive.Trigger,
|
|
1119
1516
|
{
|
|
1120
1517
|
ref,
|
|
@@ -1123,7 +1520,7 @@ var SelectTrigger = forwardRef(({ className, size, children, ...props }, ref) =>
|
|
|
1123
1520
|
...props,
|
|
1124
1521
|
children: [
|
|
1125
1522
|
children,
|
|
1126
|
-
/* @__PURE__ */
|
|
1523
|
+
/* @__PURE__ */ jsx25(SelectPrimitive.Icon, { asChild: true, children: /* @__PURE__ */ jsx25(ChevronDown2, { className: "size-4 opacity-50" }) })
|
|
1127
1524
|
]
|
|
1128
1525
|
}
|
|
1129
1526
|
);
|
|
@@ -1136,20 +1533,20 @@ function SelectContent({
|
|
|
1136
1533
|
...props
|
|
1137
1534
|
}) {
|
|
1138
1535
|
const portalContainer = usePortalContainer();
|
|
1139
|
-
return /* @__PURE__ */
|
|
1536
|
+
return /* @__PURE__ */ jsx25(SelectPrimitive.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxs7(
|
|
1140
1537
|
SelectPrimitive.Content,
|
|
1141
1538
|
{
|
|
1142
1539
|
"data-slot": "select-content",
|
|
1143
1540
|
className: cn(
|
|
1144
|
-
"bg-popover text-popover-foreground border border-
|
|
1541
|
+
"bg-popover text-popover-foreground border border-border shadow-none rounded-lg z-9999 max-h-(--radix-select-content-available-height) min-w-32 overflow-hidden data-[state=open]:animate-zoom-in-95 data-[state=closed]:animate-zoom-out-95 data-[side=bottom]:animate-slide-in-from-top-2 data-[side=left]:animate-slide-in-from-right-2 data-[side=right]:animate-slide-in-from-left-2 data-[side=top]:animate-slide-in-from-bottom-2",
|
|
1145
1542
|
position === "popper" && "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
|
|
1146
1543
|
className
|
|
1147
1544
|
),
|
|
1148
1545
|
position,
|
|
1149
1546
|
...props,
|
|
1150
1547
|
children: [
|
|
1151
|
-
/* @__PURE__ */
|
|
1152
|
-
/* @__PURE__ */
|
|
1548
|
+
/* @__PURE__ */ jsx25(SelectScrollUpButton, {}),
|
|
1549
|
+
/* @__PURE__ */ jsx25(
|
|
1153
1550
|
SelectPrimitive.Viewport,
|
|
1154
1551
|
{
|
|
1155
1552
|
className: cn(
|
|
@@ -1159,7 +1556,7 @@ function SelectContent({
|
|
|
1159
1556
|
children
|
|
1160
1557
|
}
|
|
1161
1558
|
),
|
|
1162
|
-
/* @__PURE__ */
|
|
1559
|
+
/* @__PURE__ */ jsx25(SelectScrollDownButton, {})
|
|
1163
1560
|
]
|
|
1164
1561
|
}
|
|
1165
1562
|
) });
|
|
@@ -1168,7 +1565,7 @@ function SelectLabel({
|
|
|
1168
1565
|
className,
|
|
1169
1566
|
...props
|
|
1170
1567
|
}) {
|
|
1171
|
-
return /* @__PURE__ */
|
|
1568
|
+
return /* @__PURE__ */ jsx25(
|
|
1172
1569
|
SelectPrimitive.Label,
|
|
1173
1570
|
{
|
|
1174
1571
|
"data-slot": "select-label",
|
|
@@ -1182,18 +1579,18 @@ function SelectItem({
|
|
|
1182
1579
|
children,
|
|
1183
1580
|
...props
|
|
1184
1581
|
}) {
|
|
1185
|
-
return /* @__PURE__ */
|
|
1582
|
+
return /* @__PURE__ */ jsxs7(
|
|
1186
1583
|
SelectPrimitive.Item,
|
|
1187
1584
|
{
|
|
1188
1585
|
"data-slot": "select-item",
|
|
1189
1586
|
className: cn(
|
|
1190
|
-
"relative flex w-full cursor-pointer items-center gap-2 rounded-
|
|
1587
|
+
"relative flex w-full cursor-pointer items-center gap-2 rounded-sm py-2 pr-8 pl-2 text-sm text-foreground outline-none select-none transition-colors hover-unified focus:bg-primary/5 focus:text-primary data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg]:size-4",
|
|
1191
1588
|
className
|
|
1192
1589
|
),
|
|
1193
1590
|
...props,
|
|
1194
1591
|
children: [
|
|
1195
|
-
/* @__PURE__ */
|
|
1196
|
-
/* @__PURE__ */
|
|
1592
|
+
/* @__PURE__ */ jsx25("span", { className: "absolute right-2 flex size-3.5 items-center justify-center", children: /* @__PURE__ */ jsx25(SelectPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx25(Check3, { className: "size-4" }) }) }),
|
|
1593
|
+
/* @__PURE__ */ jsx25(SelectPrimitive.ItemText, { children })
|
|
1197
1594
|
]
|
|
1198
1595
|
}
|
|
1199
1596
|
);
|
|
@@ -1202,7 +1599,7 @@ function SelectSeparator({
|
|
|
1202
1599
|
className,
|
|
1203
1600
|
...props
|
|
1204
1601
|
}) {
|
|
1205
|
-
return /* @__PURE__ */
|
|
1602
|
+
return /* @__PURE__ */ jsx25(
|
|
1206
1603
|
SelectPrimitive.Separator,
|
|
1207
1604
|
{
|
|
1208
1605
|
"data-slot": "select-separator",
|
|
@@ -1215,7 +1612,7 @@ function SelectScrollUpButton({
|
|
|
1215
1612
|
className,
|
|
1216
1613
|
...props
|
|
1217
1614
|
}) {
|
|
1218
|
-
return /* @__PURE__ */
|
|
1615
|
+
return /* @__PURE__ */ jsx25(
|
|
1219
1616
|
SelectPrimitive.ScrollUpButton,
|
|
1220
1617
|
{
|
|
1221
1618
|
"data-slot": "select-scroll-up-button",
|
|
@@ -1224,7 +1621,7 @@ function SelectScrollUpButton({
|
|
|
1224
1621
|
className
|
|
1225
1622
|
),
|
|
1226
1623
|
...props,
|
|
1227
|
-
children: /* @__PURE__ */
|
|
1624
|
+
children: /* @__PURE__ */ jsx25(ChevronUp, { className: "size-4" })
|
|
1228
1625
|
}
|
|
1229
1626
|
);
|
|
1230
1627
|
}
|
|
@@ -1232,7 +1629,7 @@ function SelectScrollDownButton({
|
|
|
1232
1629
|
className,
|
|
1233
1630
|
...props
|
|
1234
1631
|
}) {
|
|
1235
|
-
return /* @__PURE__ */
|
|
1632
|
+
return /* @__PURE__ */ jsx25(
|
|
1236
1633
|
SelectPrimitive.ScrollDownButton,
|
|
1237
1634
|
{
|
|
1238
1635
|
"data-slot": "select-scroll-down-button",
|
|
@@ -1241,19 +1638,32 @@ function SelectScrollDownButton({
|
|
|
1241
1638
|
className
|
|
1242
1639
|
),
|
|
1243
1640
|
...props,
|
|
1244
|
-
children: /* @__PURE__ */
|
|
1641
|
+
children: /* @__PURE__ */ jsx25(ChevronDown2, { className: "size-4" })
|
|
1245
1642
|
}
|
|
1246
1643
|
);
|
|
1247
1644
|
}
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1645
|
+
|
|
1646
|
+
// src/components/sheet.tsx
|
|
1647
|
+
import * as DialogPrimitive2 from "@radix-ui/react-dialog";
|
|
1648
|
+
import { cva as cva11 } from "class-variance-authority";
|
|
1649
|
+
import * as React7 from "react";
|
|
1650
|
+
import { jsx as jsx26, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1651
|
+
var SheetModalContext = React7.createContext(true);
|
|
1652
|
+
var Sheet = ({ modal = true, children, ...props }) => /* @__PURE__ */ jsx26(SheetModalContext.Provider, { value: modal, children: /* @__PURE__ */ jsx26(DialogPrimitive2.Root, { modal, ...props, children }) });
|
|
1653
|
+
Sheet.displayName = "Sheet";
|
|
1654
|
+
var SheetTrigger = DialogPrimitive2.Trigger;
|
|
1655
|
+
var SheetClose = DialogPrimitive2.Close;
|
|
1656
|
+
var SheetPortal = DialogPrimitive2.Portal;
|
|
1657
|
+
var SheetOverlay = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx26(
|
|
1658
|
+
DialogPrimitive2.Overlay,
|
|
1254
1659
|
{
|
|
1255
1660
|
className: cn(
|
|
1256
|
-
|
|
1661
|
+
// A modal scrim, from the `--nx-overlay` token rather than a surface
|
|
1662
|
+
// token. A black wash is the point — painting it from `background` would
|
|
1663
|
+
// make it a white veil in light mode — but the alpha still has to differ
|
|
1664
|
+
// per mode, because what it composites over is white in one and mid-tone
|
|
1665
|
+
// in the other.
|
|
1666
|
+
"fixed inset-0 z-50 bg-overlay backdrop-blur-sm",
|
|
1257
1667
|
"data-[state=open]:animate-in data-[state=closed]:animate-out",
|
|
1258
1668
|
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
1259
1669
|
className
|
|
@@ -1262,16 +1672,16 @@ var SheetOverlay = React5.forwardRef(({ className, ...props }, ref) => /* @__PUR
|
|
|
1262
1672
|
ref
|
|
1263
1673
|
}
|
|
1264
1674
|
));
|
|
1265
|
-
SheetOverlay.displayName =
|
|
1266
|
-
var sheetVariants =
|
|
1675
|
+
SheetOverlay.displayName = DialogPrimitive2.Overlay.displayName;
|
|
1676
|
+
var sheetVariants = cva11(
|
|
1267
1677
|
"fixed z-50 gap-4 bg-background p-6 shadow-lg will-change-transform transition ease-in-out data-[state=closed]:duration-150 data-[state=open]:duration-150 data-[state=open]:animate-in data-[state=closed]:animate-out",
|
|
1268
1678
|
{
|
|
1269
1679
|
variants: {
|
|
1270
1680
|
side: {
|
|
1271
|
-
top: "inset-x-0 top-0 border-b border-
|
|
1272
|
-
bottom: "inset-x-0 bottom-0 border-t border-
|
|
1273
|
-
left: "inset-y-0 left-0 h-full w-3/4 border-r border-
|
|
1274
|
-
right: "inset-y-0 right-0 h-full w-3/4 border-l border-
|
|
1681
|
+
top: "inset-x-0 top-0 border-b border-border data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top",
|
|
1682
|
+
bottom: "inset-x-0 bottom-0 border-t border-border data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom",
|
|
1683
|
+
left: "inset-y-0 left-0 h-full w-3/4 border-r border-border data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm",
|
|
1684
|
+
right: "inset-y-0 right-0 h-full w-3/4 border-l border-border data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm"
|
|
1275
1685
|
}
|
|
1276
1686
|
},
|
|
1277
1687
|
defaultVariants: {
|
|
@@ -1279,12 +1689,13 @@ var sheetVariants = cva(
|
|
|
1279
1689
|
}
|
|
1280
1690
|
}
|
|
1281
1691
|
);
|
|
1282
|
-
var SheetContent =
|
|
1692
|
+
var SheetContent = React7.forwardRef(({ side = "right", className, children, ...props }, ref) => {
|
|
1283
1693
|
const portalContainer = usePortalContainer();
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
/* @__PURE__ */
|
|
1287
|
-
|
|
1694
|
+
const modal = React7.useContext(SheetModalContext);
|
|
1695
|
+
return /* @__PURE__ */ jsxs8(SheetPortal, { container: portalContainer, children: [
|
|
1696
|
+
modal ? /* @__PURE__ */ jsx26(SheetOverlay, {}) : null,
|
|
1697
|
+
/* @__PURE__ */ jsx26(
|
|
1698
|
+
DialogPrimitive2.Content,
|
|
1288
1699
|
{
|
|
1289
1700
|
ref,
|
|
1290
1701
|
"data-slot": "sheet-content",
|
|
@@ -1295,11 +1706,11 @@ var SheetContent = React5.forwardRef(({ side = "right", className, children, ...
|
|
|
1295
1706
|
)
|
|
1296
1707
|
] });
|
|
1297
1708
|
});
|
|
1298
|
-
SheetContent.displayName =
|
|
1709
|
+
SheetContent.displayName = DialogPrimitive2.Content.displayName;
|
|
1299
1710
|
var SheetHeader = ({
|
|
1300
1711
|
className,
|
|
1301
1712
|
...props
|
|
1302
|
-
}) => /* @__PURE__ */
|
|
1713
|
+
}) => /* @__PURE__ */ jsx26(
|
|
1303
1714
|
"div",
|
|
1304
1715
|
{
|
|
1305
1716
|
className: cn(
|
|
@@ -1313,7 +1724,7 @@ SheetHeader.displayName = "SheetHeader";
|
|
|
1313
1724
|
var SheetFooter = ({
|
|
1314
1725
|
className,
|
|
1315
1726
|
...props
|
|
1316
|
-
}) => /* @__PURE__ */
|
|
1727
|
+
}) => /* @__PURE__ */ jsx26(
|
|
1317
1728
|
"div",
|
|
1318
1729
|
{
|
|
1319
1730
|
className: cn(
|
|
@@ -1324,31 +1735,38 @@ var SheetFooter = ({
|
|
|
1324
1735
|
}
|
|
1325
1736
|
);
|
|
1326
1737
|
SheetFooter.displayName = "SheetFooter";
|
|
1327
|
-
var SheetTitle =
|
|
1328
|
-
|
|
1738
|
+
var SheetTitle = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx26(
|
|
1739
|
+
DialogPrimitive2.Title,
|
|
1329
1740
|
{
|
|
1330
1741
|
ref,
|
|
1331
1742
|
className: cn("text-lg font-semibold text-foreground", className),
|
|
1332
1743
|
...props
|
|
1333
1744
|
}
|
|
1334
1745
|
));
|
|
1335
|
-
SheetTitle.displayName =
|
|
1336
|
-
var SheetDescription =
|
|
1337
|
-
|
|
1746
|
+
SheetTitle.displayName = DialogPrimitive2.Title.displayName;
|
|
1747
|
+
var SheetDescription = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx26(
|
|
1748
|
+
DialogPrimitive2.Description,
|
|
1338
1749
|
{
|
|
1339
1750
|
ref,
|
|
1340
1751
|
className: cn("text-sm text-muted-foreground", className),
|
|
1341
1752
|
...props
|
|
1342
1753
|
}
|
|
1343
1754
|
));
|
|
1344
|
-
SheetDescription.displayName =
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1755
|
+
SheetDescription.displayName = DialogPrimitive2.Description.displayName;
|
|
1756
|
+
|
|
1757
|
+
// src/components/command.tsx
|
|
1758
|
+
import * as DialogPrimitive3 from "@radix-ui/react-dialog";
|
|
1759
|
+
import { Command as CommandPrimitive, defaultFilter } from "cmdk";
|
|
1760
|
+
import { Search } from "lucide-react";
|
|
1761
|
+
import { forwardRef as forwardRef22 } from "react";
|
|
1762
|
+
import { jsx as jsx27, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
1763
|
+
var Command = forwardRef22(
|
|
1764
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx27(
|
|
1765
|
+
CommandPrimitive,
|
|
1348
1766
|
{
|
|
1349
1767
|
ref,
|
|
1350
1768
|
className: cn(
|
|
1351
|
-
"flex h-full w-full flex-col overflow-hidden rounded-
|
|
1769
|
+
"flex h-full w-full flex-col overflow-hidden rounded-lg bg-background text-foreground",
|
|
1352
1770
|
className
|
|
1353
1771
|
),
|
|
1354
1772
|
...props
|
|
@@ -1356,12 +1774,17 @@ var Command = forwardRef(
|
|
|
1356
1774
|
)
|
|
1357
1775
|
);
|
|
1358
1776
|
Command.displayName = "Command";
|
|
1359
|
-
var CommandDialogOverlay =
|
|
1360
|
-
|
|
1777
|
+
var CommandDialogOverlay = forwardRef22(({ className, ...props }, ref) => /* @__PURE__ */ jsx27(
|
|
1778
|
+
DialogPrimitive3.Overlay,
|
|
1361
1779
|
{
|
|
1362
1780
|
ref,
|
|
1363
1781
|
className: cn(
|
|
1364
|
-
|
|
1782
|
+
// A modal scrim, from the `--nx-overlay` token rather than a surface
|
|
1783
|
+
// token. A black wash is the point — painting it from `background` would
|
|
1784
|
+
// make it a white veil in light mode — but the alpha still has to differ
|
|
1785
|
+
// per mode, because what it composites over is white in one and mid-tone
|
|
1786
|
+
// in the other.
|
|
1787
|
+
"fixed inset-0 z-[99] bg-overlay backdrop-blur-sm",
|
|
1365
1788
|
"data-[state=open]:animate-in data-[state=closed]:animate-out",
|
|
1366
1789
|
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
1367
1790
|
"transition-opacity duration-200",
|
|
@@ -1371,13 +1794,19 @@ var CommandDialogOverlay = forwardRef(({ className, ...props }, ref) => /* @__PU
|
|
|
1371
1794
|
}
|
|
1372
1795
|
));
|
|
1373
1796
|
CommandDialogOverlay.displayName = "CommandDialogOverlay";
|
|
1374
|
-
var CommandDialog = ({
|
|
1797
|
+
var CommandDialog = ({
|
|
1798
|
+
children,
|
|
1799
|
+
commandProps,
|
|
1800
|
+
contentProps,
|
|
1801
|
+
...props
|
|
1802
|
+
}) => {
|
|
1375
1803
|
const portalContainer = usePortalContainer();
|
|
1376
|
-
return /* @__PURE__ */
|
|
1377
|
-
/* @__PURE__ */
|
|
1378
|
-
/* @__PURE__ */
|
|
1379
|
-
|
|
1804
|
+
return /* @__PURE__ */ jsx27(DialogPrimitive3.Root, { ...props, children: /* @__PURE__ */ jsxs9(DialogPrimitive3.Portal, { container: portalContainer, children: [
|
|
1805
|
+
/* @__PURE__ */ jsx27(CommandDialogOverlay, {}),
|
|
1806
|
+
/* @__PURE__ */ jsx27(
|
|
1807
|
+
DialogPrimitive3.Content,
|
|
1380
1808
|
{
|
|
1809
|
+
...contentProps,
|
|
1381
1810
|
"data-slot": "command-content",
|
|
1382
1811
|
className: cn(
|
|
1383
1812
|
// Position
|
|
@@ -1395,7 +1824,7 @@ var CommandDialog = ({ children, ...props }) => {
|
|
|
1395
1824
|
"m-4 sm:m-0",
|
|
1396
1825
|
// 16px margin on mobile, no margin on desktop
|
|
1397
1826
|
// Visual
|
|
1398
|
-
"overflow-hidden rounded-
|
|
1827
|
+
"overflow-hidden rounded-lg border border-border bg-background shadow-xl",
|
|
1399
1828
|
// Animation
|
|
1400
1829
|
"duration-200",
|
|
1401
1830
|
"data-[state=open]:animate-in data-[state=closed]:animate-out",
|
|
@@ -1403,20 +1832,32 @@ var CommandDialog = ({ children, ...props }) => {
|
|
|
1403
1832
|
"data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
|
|
1404
1833
|
"data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-top-[48%]"
|
|
1405
1834
|
),
|
|
1406
|
-
children: /* @__PURE__ */
|
|
1835
|
+
children: /* @__PURE__ */ jsx27(
|
|
1836
|
+
Command,
|
|
1837
|
+
{
|
|
1838
|
+
...commandProps,
|
|
1839
|
+
className: cn(
|
|
1840
|
+
"[&_[cmdk-group-heading]]:px-3 [&_[cmdk-group-heading]]:py-2 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-semibold [&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group-heading]]:uppercase [&_[cmdk-group-heading]]:tracking-wide [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-group]]:mb-2 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-3 [&_[cmdk-item]]:py-2 [&_[cmdk-item]_svg]:h-4 [&_[cmdk-item]_svg]:w-4",
|
|
1841
|
+
// Merged rather than overridden: a caller passing `className` for its own reason
|
|
1842
|
+
// would otherwise silently drop every layout rule this dialog depends on.
|
|
1843
|
+
commandProps?.className
|
|
1844
|
+
),
|
|
1845
|
+
children
|
|
1846
|
+
}
|
|
1847
|
+
)
|
|
1407
1848
|
}
|
|
1408
1849
|
)
|
|
1409
1850
|
] }) });
|
|
1410
1851
|
};
|
|
1411
|
-
var CommandInput =
|
|
1852
|
+
var CommandInput = forwardRef22(({ className, ...props }, ref) => /* @__PURE__ */ jsxs9(
|
|
1412
1853
|
"div",
|
|
1413
1854
|
{
|
|
1414
|
-
className: "flex items-center border-b border-
|
|
1855
|
+
className: "flex items-center border-b border-border px-4",
|
|
1415
1856
|
"cmdk-input-wrapper": "",
|
|
1416
1857
|
children: [
|
|
1417
|
-
/* @__PURE__ */
|
|
1418
|
-
/* @__PURE__ */
|
|
1419
|
-
|
|
1858
|
+
/* @__PURE__ */ jsx27(Search, { className: "mr-3 h-5 w-5 shrink-0 text-muted-foreground" }),
|
|
1859
|
+
/* @__PURE__ */ jsx27(
|
|
1860
|
+
CommandPrimitive.Input,
|
|
1420
1861
|
{
|
|
1421
1862
|
ref,
|
|
1422
1863
|
className: cn(
|
|
@@ -1440,8 +1881,8 @@ var CommandInput = forwardRef(({ className, ...props }, ref) => /* @__PURE__ */
|
|
|
1440
1881
|
}
|
|
1441
1882
|
));
|
|
1442
1883
|
CommandInput.displayName = "CommandInput";
|
|
1443
|
-
var CommandList =
|
|
1444
|
-
|
|
1884
|
+
var CommandList = forwardRef22(({ className, ...props }, ref) => /* @__PURE__ */ jsx27(
|
|
1885
|
+
CommandPrimitive.List,
|
|
1445
1886
|
{
|
|
1446
1887
|
ref,
|
|
1447
1888
|
className: cn(
|
|
@@ -1455,8 +1896,8 @@ var CommandList = forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ j
|
|
|
1455
1896
|
}
|
|
1456
1897
|
));
|
|
1457
1898
|
CommandList.displayName = "CommandList";
|
|
1458
|
-
var CommandEmpty =
|
|
1459
|
-
|
|
1899
|
+
var CommandEmpty = forwardRef22((props, ref) => /* @__PURE__ */ jsx27(
|
|
1900
|
+
CommandPrimitive.Empty,
|
|
1460
1901
|
{
|
|
1461
1902
|
ref,
|
|
1462
1903
|
className: "py-8 px-4 text-center text-sm text-muted-foreground",
|
|
@@ -1464,8 +1905,8 @@ var CommandEmpty = forwardRef((props, ref) => /* @__PURE__ */ jsx(
|
|
|
1464
1905
|
}
|
|
1465
1906
|
));
|
|
1466
1907
|
CommandEmpty.displayName = "CommandEmpty";
|
|
1467
|
-
var CommandGroup =
|
|
1468
|
-
|
|
1908
|
+
var CommandGroup = forwardRef22(({ className, ...props }, ref) => /* @__PURE__ */ jsx27(
|
|
1909
|
+
CommandPrimitive.Group,
|
|
1469
1910
|
{
|
|
1470
1911
|
ref,
|
|
1471
1912
|
className: cn(
|
|
@@ -1479,8 +1920,8 @@ var CommandGroup = forwardRef(({ className, ...props }, ref) => /* @__PURE__ */
|
|
|
1479
1920
|
}
|
|
1480
1921
|
));
|
|
1481
1922
|
CommandGroup.displayName = "CommandGroup";
|
|
1482
|
-
var CommandSeparator =
|
|
1483
|
-
|
|
1923
|
+
var CommandSeparator = forwardRef22(({ className, ...props }, ref) => /* @__PURE__ */ jsx27(
|
|
1924
|
+
CommandPrimitive.Separator,
|
|
1484
1925
|
{
|
|
1485
1926
|
ref,
|
|
1486
1927
|
className: cn("h-px bg-border my-2", className),
|
|
@@ -1488,8 +1929,8 @@ var CommandSeparator = forwardRef(({ className, ...props }, ref) => /* @__PURE__
|
|
|
1488
1929
|
}
|
|
1489
1930
|
));
|
|
1490
1931
|
CommandSeparator.displayName = "CommandSeparator";
|
|
1491
|
-
var CommandItem =
|
|
1492
|
-
|
|
1932
|
+
var CommandItem = forwardRef22(({ className, ...props }, ref) => /* @__PURE__ */ jsx27(
|
|
1933
|
+
CommandPrimitive.Item,
|
|
1493
1934
|
{
|
|
1494
1935
|
ref,
|
|
1495
1936
|
className: cn(
|
|
@@ -1501,7 +1942,7 @@ var CommandItem = forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ j
|
|
|
1501
1942
|
// Spacing
|
|
1502
1943
|
"px-3 py-2.5",
|
|
1503
1944
|
// Visual
|
|
1504
|
-
"rounded-
|
|
1945
|
+
"rounded-sm text-base sm:text-sm outline-none",
|
|
1505
1946
|
// Transitions
|
|
1506
1947
|
"transition-all duration-200 ease-(--ease-premium)",
|
|
1507
1948
|
// Hover state - shared dashboard hover treatment
|
|
@@ -1517,9 +1958,9 @@ var CommandItem = forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ j
|
|
|
1517
1958
|
}
|
|
1518
1959
|
));
|
|
1519
1960
|
CommandItem.displayName = "CommandItem";
|
|
1520
|
-
var CommandShortcut =
|
|
1961
|
+
var CommandShortcut = forwardRef22(
|
|
1521
1962
|
({ className, ...props }, ref) => {
|
|
1522
|
-
return /* @__PURE__ */
|
|
1963
|
+
return /* @__PURE__ */ jsx27(
|
|
1523
1964
|
"span",
|
|
1524
1965
|
{
|
|
1525
1966
|
ref,
|
|
@@ -1530,7 +1971,7 @@ var CommandShortcut = forwardRef(
|
|
|
1530
1971
|
"text-xs font-mono",
|
|
1531
1972
|
// Visual
|
|
1532
1973
|
"text-muted-foreground bg-primary/5",
|
|
1533
|
-
"border border-
|
|
1974
|
+
"border border-border rounded-md",
|
|
1534
1975
|
// Spacing
|
|
1535
1976
|
"px-1.5 py-0.5",
|
|
1536
1977
|
className
|
|
@@ -1541,7 +1982,14 @@ var CommandShortcut = forwardRef(
|
|
|
1541
1982
|
}
|
|
1542
1983
|
);
|
|
1543
1984
|
CommandShortcut.displayName = "CommandShortcut";
|
|
1544
|
-
var
|
|
1985
|
+
var commandDefaultFilter = defaultFilter;
|
|
1986
|
+
|
|
1987
|
+
// src/components/spinner.tsx
|
|
1988
|
+
import { cva as cva12 } from "class-variance-authority";
|
|
1989
|
+
import { Loader2 } from "lucide-react";
|
|
1990
|
+
import { forwardRef as forwardRef23 } from "react";
|
|
1991
|
+
import { jsx as jsx28 } from "react/jsx-runtime";
|
|
1992
|
+
var spinnerVariants = cva12("animate-spin motion-reduce:animate-none", {
|
|
1545
1993
|
variants: {
|
|
1546
1994
|
size: {
|
|
1547
1995
|
sm: "h-4 w-4",
|
|
@@ -1553,9 +2001,9 @@ var spinnerVariants = cva("animate-spin motion-reduce:animate-none", {
|
|
|
1553
2001
|
size: "md"
|
|
1554
2002
|
}
|
|
1555
2003
|
});
|
|
1556
|
-
var Spinner =
|
|
2004
|
+
var Spinner = forwardRef23(
|
|
1557
2005
|
({ size = "md", className, "aria-label": ariaLabel = "Loading", ...props }, ref) => {
|
|
1558
|
-
return /* @__PURE__ */
|
|
2006
|
+
return /* @__PURE__ */ jsx28(
|
|
1559
2007
|
Loader2,
|
|
1560
2008
|
{
|
|
1561
2009
|
ref,
|
|
@@ -1568,12 +2016,23 @@ var Spinner = forwardRef(
|
|
|
1568
2016
|
}
|
|
1569
2017
|
);
|
|
1570
2018
|
Spinner.displayName = "Spinner";
|
|
2019
|
+
|
|
2020
|
+
// src/components/toaster.tsx
|
|
2021
|
+
import {
|
|
2022
|
+
CheckCircle2,
|
|
2023
|
+
AlertCircle,
|
|
2024
|
+
AlertTriangle,
|
|
2025
|
+
XCircle,
|
|
2026
|
+
Loader2 as Loader22
|
|
2027
|
+
} from "lucide-react";
|
|
2028
|
+
import { toast, Toaster as Sonner } from "sonner";
|
|
2029
|
+
import { jsx as jsx29 } from "react/jsx-runtime";
|
|
1571
2030
|
function Toaster({ theme = "system", ...props }) {
|
|
1572
|
-
return /* @__PURE__ */
|
|
1573
|
-
|
|
2031
|
+
return /* @__PURE__ */ jsx29(
|
|
2032
|
+
Sonner,
|
|
1574
2033
|
{
|
|
1575
2034
|
theme,
|
|
1576
|
-
className: "toaster group
|
|
2035
|
+
className: "toaster group bg-transparent! overflow-visible! z-[9999]!",
|
|
1577
2036
|
"data-slot": "toaster",
|
|
1578
2037
|
toastOptions: {
|
|
1579
2038
|
classNames: {
|
|
@@ -1581,23 +2040,27 @@ function Toaster({ theme = "system", ...props }) {
|
|
|
1581
2040
|
}
|
|
1582
2041
|
},
|
|
1583
2042
|
icons: {
|
|
1584
|
-
success: /* @__PURE__ */
|
|
1585
|
-
info: /* @__PURE__ */
|
|
1586
|
-
warning: /* @__PURE__ */
|
|
1587
|
-
error: /* @__PURE__ */
|
|
1588
|
-
loading: /* @__PURE__ */
|
|
2043
|
+
success: /* @__PURE__ */ jsx29(CheckCircle2, { className: "h-4 w-4" }),
|
|
2044
|
+
info: /* @__PURE__ */ jsx29(AlertCircle, { className: "h-4 w-4" }),
|
|
2045
|
+
warning: /* @__PURE__ */ jsx29(AlertTriangle, { className: "h-4 w-4" }),
|
|
2046
|
+
error: /* @__PURE__ */ jsx29(XCircle, { className: "h-4 w-4" }),
|
|
2047
|
+
loading: /* @__PURE__ */ jsx29(Loader22, { className: "h-4 w-4 animate-spin" })
|
|
1589
2048
|
},
|
|
1590
2049
|
style: {
|
|
1591
|
-
"--normal-bg": "
|
|
1592
|
-
"--normal-text": "
|
|
1593
|
-
"--normal-border": "
|
|
2050
|
+
"--normal-bg": "var(--nx-popover)",
|
|
2051
|
+
"--normal-text": "var(--nx-popover-foreground)",
|
|
2052
|
+
"--normal-border": "var(--nx-border)",
|
|
1594
2053
|
"--border-radius": "0px"
|
|
1595
2054
|
},
|
|
1596
2055
|
...props
|
|
1597
2056
|
}
|
|
1598
2057
|
);
|
|
1599
2058
|
}
|
|
1600
|
-
|
|
2059
|
+
|
|
2060
|
+
// src/components/table.tsx
|
|
2061
|
+
import * as React8 from "react";
|
|
2062
|
+
import { jsx as jsx30 } from "react/jsx-runtime";
|
|
2063
|
+
var Table = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx30("div", { className: "relative w-full overflow-auto", children: /* @__PURE__ */ jsx30(
|
|
1601
2064
|
"table",
|
|
1602
2065
|
{
|
|
1603
2066
|
ref,
|
|
@@ -1606,9 +2069,16 @@ var Table = React5.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */
|
|
|
1606
2069
|
}
|
|
1607
2070
|
) }));
|
|
1608
2071
|
Table.displayName = "Table";
|
|
1609
|
-
var TableHeader =
|
|
2072
|
+
var TableHeader = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx30(
|
|
2073
|
+
"thead",
|
|
2074
|
+
{
|
|
2075
|
+
ref,
|
|
2076
|
+
className: cn("[&_tr]:border-b border-border", className),
|
|
2077
|
+
...props
|
|
2078
|
+
}
|
|
2079
|
+
));
|
|
1610
2080
|
TableHeader.displayName = "TableHeader";
|
|
1611
|
-
var TableBody =
|
|
2081
|
+
var TableBody = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx30(
|
|
1612
2082
|
"tbody",
|
|
1613
2083
|
{
|
|
1614
2084
|
ref,
|
|
@@ -1617,28 +2087,31 @@ var TableBody = React5.forwardRef(({ className, ...props }, ref) => /* @__PURE__
|
|
|
1617
2087
|
}
|
|
1618
2088
|
));
|
|
1619
2089
|
TableBody.displayName = "TableBody";
|
|
1620
|
-
var TableFooter =
|
|
2090
|
+
var TableFooter = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx30(
|
|
1621
2091
|
"tfoot",
|
|
1622
2092
|
{
|
|
1623
2093
|
ref,
|
|
1624
|
-
className: cn(
|
|
2094
|
+
className: cn(
|
|
2095
|
+
"border-t border-border font-medium [&>tr]:last:border-b-0",
|
|
2096
|
+
className
|
|
2097
|
+
),
|
|
1625
2098
|
...props
|
|
1626
2099
|
}
|
|
1627
2100
|
));
|
|
1628
2101
|
TableFooter.displayName = "TableFooter";
|
|
1629
|
-
var TableRow =
|
|
2102
|
+
var TableRow = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx30(
|
|
1630
2103
|
"tr",
|
|
1631
2104
|
{
|
|
1632
2105
|
ref,
|
|
1633
2106
|
className: cn(
|
|
1634
|
-
"border-b border-
|
|
2107
|
+
"border-b border-border transition-colors data-[state=selected]:bg-primary/5",
|
|
1635
2108
|
className
|
|
1636
2109
|
),
|
|
1637
2110
|
...props
|
|
1638
2111
|
}
|
|
1639
2112
|
));
|
|
1640
2113
|
TableRow.displayName = "TableRow";
|
|
1641
|
-
var TableHead =
|
|
2114
|
+
var TableHead = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx30(
|
|
1642
2115
|
"th",
|
|
1643
2116
|
{
|
|
1644
2117
|
ref,
|
|
@@ -1650,7 +2123,7 @@ var TableHead = React5.forwardRef(({ className, ...props }, ref) => /* @__PURE__
|
|
|
1650
2123
|
}
|
|
1651
2124
|
));
|
|
1652
2125
|
TableHead.displayName = "TableHead";
|
|
1653
|
-
var TableCell =
|
|
2126
|
+
var TableCell = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx30(
|
|
1654
2127
|
"td",
|
|
1655
2128
|
{
|
|
1656
2129
|
ref,
|
|
@@ -1662,7 +2135,7 @@ var TableCell = React5.forwardRef(({ className, ...props }, ref) => /* @__PURE__
|
|
|
1662
2135
|
}
|
|
1663
2136
|
));
|
|
1664
2137
|
TableCell.displayName = "TableCell";
|
|
1665
|
-
var TableCaption =
|
|
2138
|
+
var TableCaption = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx30(
|
|
1666
2139
|
"caption",
|
|
1667
2140
|
{
|
|
1668
2141
|
ref,
|
|
@@ -1671,6 +2144,10 @@ var TableCaption = React5.forwardRef(({ className, ...props }, ref) => /* @__PUR
|
|
|
1671
2144
|
}
|
|
1672
2145
|
));
|
|
1673
2146
|
TableCaption.displayName = "TableCaption";
|
|
2147
|
+
|
|
2148
|
+
// src/components/table-search.tsx
|
|
2149
|
+
import { Search as Search2, Loader2 as Loader23, X as X2 } from "lucide-react";
|
|
2150
|
+
import { jsx as jsx31, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1674
2151
|
function TableSearch({
|
|
1675
2152
|
value,
|
|
1676
2153
|
onChange,
|
|
@@ -1679,9 +2156,9 @@ function TableSearch({
|
|
|
1679
2156
|
isLoading = false,
|
|
1680
2157
|
inputRef
|
|
1681
2158
|
}) {
|
|
1682
|
-
return /* @__PURE__ */
|
|
1683
|
-
/* @__PURE__ */
|
|
1684
|
-
/* @__PURE__ */
|
|
2159
|
+
return /* @__PURE__ */ jsxs10("div", { className: "relative w-full max-w-lg", children: [
|
|
2160
|
+
/* @__PURE__ */ jsx31(Search2, { className: "absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" }),
|
|
2161
|
+
/* @__PURE__ */ jsx31(
|
|
1685
2162
|
"input",
|
|
1686
2163
|
{
|
|
1687
2164
|
ref: inputRef,
|
|
@@ -1690,541 +2167,2112 @@ function TableSearch({
|
|
|
1690
2167
|
value,
|
|
1691
2168
|
onChange: (e) => onChange(e.target.value),
|
|
1692
2169
|
"aria-busy": isLoading,
|
|
1693
|
-
className: "h-10 w-full rounded-
|
|
2170
|
+
className: "h-10 w-full rounded-md border border-input bg-background pl-10 pr-10 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 transition-all"
|
|
1694
2171
|
}
|
|
1695
2172
|
),
|
|
1696
|
-
(value || isLoading) && /* @__PURE__ */
|
|
1697
|
-
isLoading && /* @__PURE__ */
|
|
1698
|
-
value && /* @__PURE__ */
|
|
2173
|
+
(value || isLoading) && /* @__PURE__ */ jsxs10("div", { className: "absolute right-3 top-1/2 -translate-y-1/2 flex items-center gap-2", children: [
|
|
2174
|
+
isLoading && /* @__PURE__ */ jsx31(Loader23, { className: "w-3.5 h-3.5 text-primary animate-spin" }),
|
|
2175
|
+
value && /* @__PURE__ */ jsx31(
|
|
1699
2176
|
"button",
|
|
1700
2177
|
{
|
|
1701
2178
|
type: "button",
|
|
1702
2179
|
onClick: onClear,
|
|
1703
|
-
className: "text-muted-foreground
|
|
2180
|
+
className: "text-muted-foreground hover:text-foreground transition-colors p-0.5 rounded-md hover:bg-primary/5",
|
|
1704
2181
|
"aria-label": "Clear search",
|
|
1705
|
-
children: /* @__PURE__ */
|
|
2182
|
+
children: /* @__PURE__ */ jsx31(X2, { className: "w-3.5 h-3.5" })
|
|
1706
2183
|
}
|
|
1707
2184
|
)
|
|
1708
2185
|
] })
|
|
1709
2186
|
] });
|
|
1710
2187
|
}
|
|
2188
|
+
|
|
2189
|
+
// src/components/table-states.tsx
|
|
2190
|
+
import { AlertCircle as AlertCircle2, Loader2 as Loader24, FileQuestion } from "lucide-react";
|
|
2191
|
+
import { jsx as jsx32, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
1711
2192
|
function TableError({
|
|
1712
2193
|
message = "An error occurred. Please try again."
|
|
1713
2194
|
}) {
|
|
1714
|
-
return /* @__PURE__ */
|
|
1715
|
-
/* @__PURE__ */
|
|
1716
|
-
/* @__PURE__ */
|
|
2195
|
+
return /* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-2", children: [
|
|
2196
|
+
/* @__PURE__ */ jsx32(AlertCircle2, { className: "w-4 h-4 shrink-0" }),
|
|
2197
|
+
/* @__PURE__ */ jsx32("span", { children: message })
|
|
1717
2198
|
] });
|
|
1718
2199
|
}
|
|
1719
2200
|
function TableLoading() {
|
|
1720
|
-
return /* @__PURE__ */
|
|
1721
|
-
/* @__PURE__ */
|
|
1722
|
-
/* @__PURE__ */
|
|
2201
|
+
return /* @__PURE__ */ jsxs11("div", { className: "flex flex-col items-center justify-center gap-4 p-12 text-muted-foreground", children: [
|
|
2202
|
+
/* @__PURE__ */ jsx32(Loader24, { className: "w-8 h-8 animate-spin text-primary/80" }),
|
|
2203
|
+
/* @__PURE__ */ jsx32("span", { className: "text-sm font-medium", children: "Loading data..." })
|
|
1723
2204
|
] });
|
|
1724
2205
|
}
|
|
1725
2206
|
function TableEmpty({ message = "No records found" }) {
|
|
1726
|
-
return /* @__PURE__ */
|
|
1727
|
-
/* @__PURE__ */
|
|
1728
|
-
/* @__PURE__ */
|
|
1729
|
-
] });
|
|
1730
|
-
}
|
|
1731
|
-
function renderPageNumbers(currentPage, totalPages, maxVisiblePages, onPageChange) {
|
|
1732
|
-
const getBtnClass = (active) => `flex h-8 w-8 items-center justify-center border-y border-primary/5 border-r border-primary/5 text-xs z-10 -ml-px transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring ${active ? "!bg-primary !text-primary-foreground !border-primary z-20" : "!bg-background !border-primary/5 hover-muted disabled:opacity-50"}`;
|
|
1733
|
-
if (totalPages <= maxVisiblePages) {
|
|
1734
|
-
return Array.from({ length: totalPages }).map((_, i) => /* @__PURE__ */ jsx(
|
|
1735
|
-
"button",
|
|
1736
|
-
{
|
|
1737
|
-
onClick: () => onPageChange(i),
|
|
1738
|
-
"aria-label": `Go to page ${i + 1}`,
|
|
1739
|
-
"aria-current": currentPage === i ? "page" : void 0,
|
|
1740
|
-
className: getBtnClass(currentPage === i),
|
|
1741
|
-
children: i + 1
|
|
1742
|
-
},
|
|
1743
|
-
`page-${i}`
|
|
1744
|
-
));
|
|
1745
|
-
}
|
|
1746
|
-
const pages = [];
|
|
1747
|
-
const startPage = Math.max(0, currentPage - Math.floor(maxVisiblePages / 2));
|
|
1748
|
-
const endPage = Math.min(totalPages - 1, startPage + maxVisiblePages - 1);
|
|
1749
|
-
if (startPage > 0) {
|
|
1750
|
-
pages.push(
|
|
1751
|
-
/* @__PURE__ */ jsx(
|
|
1752
|
-
"button",
|
|
1753
|
-
{
|
|
1754
|
-
onClick: () => onPageChange(0),
|
|
1755
|
-
"aria-label": "Go to page 1",
|
|
1756
|
-
className: getBtnClass(currentPage === 0),
|
|
1757
|
-
children: "1"
|
|
1758
|
-
},
|
|
1759
|
-
"page-0"
|
|
1760
|
-
)
|
|
1761
|
-
);
|
|
1762
|
-
if (startPage > 1) {
|
|
1763
|
-
pages.push(
|
|
1764
|
-
/* @__PURE__ */ jsx(
|
|
1765
|
-
"span",
|
|
1766
|
-
{
|
|
1767
|
-
className: "flex h-8 w-8 items-center justify-center border-y border-primary/5 border-r border-primary/5 !border-primary/5 !bg-background text-muted-foreground text-xs -ml-px",
|
|
1768
|
-
"aria-hidden": "true",
|
|
1769
|
-
children: "..."
|
|
1770
|
-
},
|
|
1771
|
-
"ellipsis-start"
|
|
1772
|
-
)
|
|
1773
|
-
);
|
|
1774
|
-
}
|
|
1775
|
-
}
|
|
1776
|
-
for (let i = startPage; i <= endPage; i++) {
|
|
1777
|
-
pages.push(
|
|
1778
|
-
/* @__PURE__ */ jsx(
|
|
1779
|
-
"button",
|
|
1780
|
-
{
|
|
1781
|
-
onClick: () => onPageChange(i),
|
|
1782
|
-
"aria-label": `Go to page ${i + 1}`,
|
|
1783
|
-
"aria-current": currentPage === i ? "page" : void 0,
|
|
1784
|
-
className: getBtnClass(currentPage === i),
|
|
1785
|
-
children: i + 1
|
|
1786
|
-
},
|
|
1787
|
-
i
|
|
1788
|
-
)
|
|
1789
|
-
);
|
|
1790
|
-
}
|
|
1791
|
-
if (endPage < totalPages - 1) {
|
|
1792
|
-
if (endPage < totalPages - 2) {
|
|
1793
|
-
pages.push(
|
|
1794
|
-
/* @__PURE__ */ jsx(
|
|
1795
|
-
"span",
|
|
1796
|
-
{
|
|
1797
|
-
className: "flex h-8 w-8 items-center justify-center border-y border-primary/5 border-r border-primary/5 !border-primary/5 !bg-background text-muted-foreground text-xs -ml-px",
|
|
1798
|
-
"aria-hidden": "true",
|
|
1799
|
-
children: "..."
|
|
1800
|
-
},
|
|
1801
|
-
"ellipsis-end"
|
|
1802
|
-
)
|
|
1803
|
-
);
|
|
1804
|
-
}
|
|
1805
|
-
pages.push(
|
|
1806
|
-
/* @__PURE__ */ jsx(
|
|
1807
|
-
"button",
|
|
1808
|
-
{
|
|
1809
|
-
onClick: () => onPageChange(totalPages - 1),
|
|
1810
|
-
"aria-label": `Go to page ${totalPages}`,
|
|
1811
|
-
className: getBtnClass(currentPage === totalPages - 1),
|
|
1812
|
-
children: totalPages
|
|
1813
|
-
},
|
|
1814
|
-
totalPages - 1
|
|
1815
|
-
)
|
|
1816
|
-
);
|
|
1817
|
-
}
|
|
1818
|
-
return pages;
|
|
1819
|
-
}
|
|
1820
|
-
function TablePagination({
|
|
1821
|
-
meta,
|
|
1822
|
-
onPageChange,
|
|
1823
|
-
onPageSizeChange,
|
|
1824
|
-
config,
|
|
1825
|
-
isLoading = false
|
|
1826
|
-
}) {
|
|
1827
|
-
const {
|
|
1828
|
-
showPageSizeSelector = true,
|
|
1829
|
-
pageSizeOptions = [10, 20, 30, 50],
|
|
1830
|
-
maxVisiblePages = 5
|
|
1831
|
-
} = config || {};
|
|
1832
|
-
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col sm:flex-row w-full items-center justify-between gap-4 text-xs sm:text-sm text-muted-foreground p-4 border-t border-primary/5", children: [
|
|
1833
|
-
/* @__PURE__ */ jsxs("div", { className: "whitespace-nowrap order-2 sm:order-1", children: [
|
|
1834
|
-
"Showing ",
|
|
1835
|
-
(meta.page - 1) * meta.limit + 1,
|
|
1836
|
-
"-",
|
|
1837
|
-
Math.min(meta.page * meta.limit, meta.total),
|
|
1838
|
-
" of ",
|
|
1839
|
-
meta.total,
|
|
1840
|
-
" entries"
|
|
1841
|
-
] }),
|
|
1842
|
-
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center justify-center gap-4 sm:gap-6 lg:gap-8 order-1 sm:order-2", children: [
|
|
1843
|
-
showPageSizeSelector && /* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-2", children: [
|
|
1844
|
-
/* @__PURE__ */ jsx("span", { className: "whitespace-nowrap hidden sm:inline-block", children: "Rows per page" }),
|
|
1845
|
-
/* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
1846
|
-
/* @__PURE__ */ jsx(
|
|
1847
|
-
"select",
|
|
1848
|
-
{
|
|
1849
|
-
id: "pageSize",
|
|
1850
|
-
value: meta.limit,
|
|
1851
|
-
onChange: (e) => {
|
|
1852
|
-
const newPageSize = Number(e.target.value);
|
|
1853
|
-
onPageSizeChange(newPageSize);
|
|
1854
|
-
},
|
|
1855
|
-
className: "h-8 w-[70px] appearance-none rounded-none border border-primary/5 bg-background px-2 py-1 text-sm font-medium focus-visible:outline-none focus:ring-1 focus:ring-ring disabled:opacity-50 hover-muted cursor-pointer",
|
|
1856
|
-
disabled: isLoading,
|
|
1857
|
-
children: pageSizeOptions.map((size) => /* @__PURE__ */ jsx("option", { value: size, children: size }, size))
|
|
1858
|
-
}
|
|
1859
|
-
),
|
|
1860
|
-
/* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute inset-y-0 right-0 flex items-center px-2 text-muted-foreground", children: /* @__PURE__ */ jsx(
|
|
1861
|
-
"svg",
|
|
1862
|
-
{
|
|
1863
|
-
className: "h-3 w-3",
|
|
1864
|
-
fill: "none",
|
|
1865
|
-
viewBox: "0 0 24 24",
|
|
1866
|
-
stroke: "currentColor",
|
|
1867
|
-
children: /* @__PURE__ */ jsx(
|
|
1868
|
-
"path",
|
|
1869
|
-
{
|
|
1870
|
-
strokeLinecap: "round",
|
|
1871
|
-
strokeLinejoin: "round",
|
|
1872
|
-
strokeWidth: 2,
|
|
1873
|
-
d: "M19 9l-7 7-7-7"
|
|
1874
|
-
}
|
|
1875
|
-
)
|
|
1876
|
-
}
|
|
1877
|
-
) })
|
|
1878
|
-
] })
|
|
1879
|
-
] }),
|
|
1880
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center -space-x-px", children: [
|
|
1881
|
-
/* @__PURE__ */ jsx(
|
|
1882
|
-
"button",
|
|
1883
|
-
{
|
|
1884
|
-
onClick: () => onPageChange(0),
|
|
1885
|
-
disabled: meta.page === 0 || isLoading,
|
|
1886
|
-
className: "hidden sm:flex h-8 w-8 items-center justify-center rounded-none border border-primary/5 bg-background hover-muted disabled:opacity-50 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring z-10",
|
|
1887
|
-
"aria-label": "First page",
|
|
1888
|
-
children: /* @__PURE__ */ jsx(ChevronsLeft, { className: "h-4 w-4" })
|
|
1889
|
-
}
|
|
1890
|
-
),
|
|
1891
|
-
/* @__PURE__ */ jsx(
|
|
1892
|
-
"button",
|
|
1893
|
-
{
|
|
1894
|
-
onClick: () => onPageChange(meta.page - 1),
|
|
1895
|
-
disabled: meta.page === 0 || isLoading,
|
|
1896
|
-
className: "flex h-8 w-8 items-center justify-center rounded-none sm:rounded-none border border-primary/5 bg-background hover-muted disabled:opacity-50 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring z-10",
|
|
1897
|
-
"aria-label": "Previous page",
|
|
1898
|
-
children: /* @__PURE__ */ jsx(ChevronLeft, { className: "h-4 w-4" })
|
|
1899
|
-
}
|
|
1900
|
-
),
|
|
1901
|
-
/* @__PURE__ */ jsx("div", { className: "flex", children: renderPageNumbers(
|
|
1902
|
-
meta.page,
|
|
1903
|
-
meta.totalPages,
|
|
1904
|
-
maxVisiblePages,
|
|
1905
|
-
onPageChange
|
|
1906
|
-
) }),
|
|
1907
|
-
/* @__PURE__ */ jsx(
|
|
1908
|
-
"button",
|
|
1909
|
-
{
|
|
1910
|
-
onClick: () => onPageChange(meta.page + 1),
|
|
1911
|
-
disabled: meta.page >= meta.totalPages - 1 || isLoading,
|
|
1912
|
-
className: "flex h-8 w-8 items-center justify-center rounded-none sm:rounded-none border-y border-primary/5 border-x border-primary/5 sm :border-r border-primary/5 bg-background hover-muted disabled:opacity-50 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring z-10",
|
|
1913
|
-
"aria-label": "Next page",
|
|
1914
|
-
children: /* @__PURE__ */ jsx(ChevronRight, { className: "h-4 w-4" })
|
|
1915
|
-
}
|
|
1916
|
-
),
|
|
1917
|
-
/* @__PURE__ */ jsx(
|
|
1918
|
-
"button",
|
|
1919
|
-
{
|
|
1920
|
-
onClick: () => onPageChange(meta.totalPages - 1),
|
|
1921
|
-
disabled: meta.page >= meta.totalPages - 1 || isLoading,
|
|
1922
|
-
className: "hidden sm:flex h-8 w-8 items-center justify-center rounded-none border border-primary/5 bg-background hover-muted disabled:opacity-50 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring z-10",
|
|
1923
|
-
"aria-label": "Last page",
|
|
1924
|
-
children: /* @__PURE__ */ jsx(ChevronsRight, { className: "h-4 w-4" })
|
|
1925
|
-
}
|
|
1926
|
-
)
|
|
1927
|
-
] }),
|
|
1928
|
-
/* @__PURE__ */ jsxs("div", { className: "whitespace-nowrap hidden sm:block", children: [
|
|
1929
|
-
"Page ",
|
|
1930
|
-
meta.page + 1,
|
|
1931
|
-
" of ",
|
|
1932
|
-
meta.totalPages
|
|
1933
|
-
] })
|
|
1934
|
-
] })
|
|
2207
|
+
return /* @__PURE__ */ jsxs11("div", { className: "flex flex-col items-center justify-center gap-4 p-16 text-center text-muted-foreground", children: [
|
|
2208
|
+
/* @__PURE__ */ jsx32("div", { className: "flex h-12 w-12 items-center justify-center rounded-md bg-primary/5", children: /* @__PURE__ */ jsx32(FileQuestion, { className: "h-6 w-6" }) }),
|
|
2209
|
+
/* @__PURE__ */ jsx32("span", { className: "text-sm font-medium", children: message })
|
|
1935
2210
|
] });
|
|
1936
2211
|
}
|
|
1937
|
-
|
|
2212
|
+
|
|
2213
|
+
// src/components/table-skeleton.tsx
|
|
2214
|
+
import { Fragment, jsx as jsx33, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
2215
|
+
var GrayBar = ({ className }) => /* @__PURE__ */ jsx33(Skeleton, { className });
|
|
1938
2216
|
var TableSkeleton = ({
|
|
1939
2217
|
columns = 5,
|
|
1940
2218
|
rowCount = 8,
|
|
1941
2219
|
hideWrapper = false,
|
|
1942
2220
|
hideFooter = false
|
|
1943
2221
|
}) => {
|
|
1944
|
-
const content = /* @__PURE__ */
|
|
1945
|
-
/* @__PURE__ */
|
|
1946
|
-
/* @__PURE__ */
|
|
1947
|
-
/* @__PURE__ */
|
|
1948
|
-
/* @__PURE__ */
|
|
1949
|
-
/* @__PURE__ */
|
|
1950
|
-
/* @__PURE__ */
|
|
1951
|
-
/* @__PURE__ */
|
|
2222
|
+
const content = /* @__PURE__ */ jsxs12(Fragment, { children: [
|
|
2223
|
+
/* @__PURE__ */ jsx33("div", { className: "border-0 rounded-none shadow-none", children: /* @__PURE__ */ jsxs12(Table, { children: [
|
|
2224
|
+
/* @__PURE__ */ jsx33(TableHeader, { children: /* @__PURE__ */ jsx33(TableRow, { children: Array.from({ length: columns }).map((_, colIdx) => /* @__PURE__ */ jsx33(TableHead, { className: "py-3", children: colIdx === 0 ? /* @__PURE__ */ jsx33(GrayBar, { className: "h-4 w-4" }) : colIdx === columns - 1 ? /* @__PURE__ */ jsx33("div", { className: "flex justify-center", children: /* @__PURE__ */ jsx33(Skeleton, { className: "h-4 w-4 rounded-sm" }) }) : colIdx === 1 ? /* @__PURE__ */ jsx33(GrayBar, { className: "h-4 w-[70%] max-w-[180px]" }) : /* @__PURE__ */ jsx33(GrayBar, { className: "h-4 w-[60%] max-w-[120px]" }) }, `skeleton-header-${colIdx}`)) }) }),
|
|
2225
|
+
/* @__PURE__ */ jsx33(TableBody, { children: Array.from({ length: rowCount }).map((_, rowIdx) => /* @__PURE__ */ jsx33(TableRow, { className: "border-b border-border", children: Array.from({ length: columns }).map((_2, colIdx) => /* @__PURE__ */ jsx33(TableCell, { className: "py-3", children: colIdx === 0 ? /* @__PURE__ */ jsx33(GrayBar, { className: "h-4 w-4" }) : colIdx === columns - 1 ? /* @__PURE__ */ jsx33("div", { className: "flex justify-center", children: /* @__PURE__ */ jsx33(Skeleton, { className: "h-8 w-8 rounded-md" }) }) : colIdx === 1 ? /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-3", children: [
|
|
2226
|
+
/* @__PURE__ */ jsx33(Skeleton, { className: "w-9 rounded-md shrink-0" }),
|
|
2227
|
+
/* @__PURE__ */ jsxs12("div", { className: "space-y-1.5 flex-1", children: [
|
|
2228
|
+
/* @__PURE__ */ jsx33(Skeleton, { className: "h-4 w-[120px]" }),
|
|
2229
|
+
/* @__PURE__ */ jsx33(Skeleton, { className: "h-3 w-[80px]" })
|
|
1952
2230
|
] })
|
|
1953
|
-
] }) : /* @__PURE__ */
|
|
2231
|
+
] }) : /* @__PURE__ */ jsx33(GrayBar, { className: "h-4 w-[60%] max-w-[120px]" }) }, colIdx)) }, rowIdx)) })
|
|
1954
2232
|
] }) }),
|
|
1955
|
-
!hideFooter && /* @__PURE__ */
|
|
1956
|
-
/* @__PURE__ */
|
|
1957
|
-
/* @__PURE__ */
|
|
1958
|
-
/* @__PURE__ */
|
|
1959
|
-
/* @__PURE__ */
|
|
1960
|
-
/* @__PURE__ */
|
|
2233
|
+
!hideFooter && /* @__PURE__ */ jsx33("div", { className: "table-footer border-t border-border", children: /* @__PURE__ */ jsxs12("div", { className: "flex items-center justify-between px-2 py-4", children: [
|
|
2234
|
+
/* @__PURE__ */ jsx33("div", { className: "flex items-center gap-2 text-sm", children: /* @__PURE__ */ jsx33(GrayBar, { className: "h-4 w-[120px]" }) }),
|
|
2235
|
+
/* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-6", children: [
|
|
2236
|
+
/* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-2", children: [
|
|
2237
|
+
/* @__PURE__ */ jsx33(GrayBar, { className: "h-4 w-20" }),
|
|
2238
|
+
/* @__PURE__ */ jsx33(GrayBar, { className: "h-8 w-[70px]" })
|
|
1961
2239
|
] }),
|
|
1962
|
-
/* @__PURE__ */
|
|
1963
|
-
/* @__PURE__ */
|
|
1964
|
-
/* @__PURE__ */
|
|
1965
|
-
/* @__PURE__ */
|
|
1966
|
-
/* @__PURE__ */
|
|
1967
|
-
/* @__PURE__ */
|
|
2240
|
+
/* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-1", children: [
|
|
2241
|
+
/* @__PURE__ */ jsx33(GrayBar, { className: "h-8 w-8" }),
|
|
2242
|
+
/* @__PURE__ */ jsx33(GrayBar, { className: "h-8 w-8" }),
|
|
2243
|
+
/* @__PURE__ */ jsx33(GrayBar, { className: "h-8 w-8" }),
|
|
2244
|
+
/* @__PURE__ */ jsx33(GrayBar, { className: "h-8 w-8" }),
|
|
2245
|
+
/* @__PURE__ */ jsx33(GrayBar, { className: "h-8 w-8" })
|
|
1968
2246
|
] }),
|
|
1969
|
-
/* @__PURE__ */
|
|
2247
|
+
/* @__PURE__ */ jsx33(GrayBar, { className: "h-4 w-[120px]" })
|
|
1970
2248
|
] })
|
|
1971
2249
|
] }) })
|
|
1972
2250
|
] });
|
|
1973
2251
|
if (hideWrapper) {
|
|
1974
2252
|
return content;
|
|
1975
2253
|
}
|
|
1976
|
-
return /* @__PURE__ */
|
|
2254
|
+
return /* @__PURE__ */ jsx33("div", { className: "table-wrapper rounded-md border border-border bg-card overflow-hidden", children: content });
|
|
1977
2255
|
};
|
|
1978
2256
|
TableSkeleton.displayName = "TableSkeleton";
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
);
|
|
1994
|
-
const
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
);
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
const
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2257
|
+
|
|
2258
|
+
// src/components/color-picker.tsx
|
|
2259
|
+
import { Pipette } from "lucide-react";
|
|
2260
|
+
import * as React9 from "react";
|
|
2261
|
+
|
|
2262
|
+
// src/lib/color/convert.ts
|
|
2263
|
+
var clamp01 = (n) => n < 0 ? 0 : n > 1 ? 1 : n;
|
|
2264
|
+
function normalizeHue(hue) {
|
|
2265
|
+
if (!Number.isFinite(hue)) return 0;
|
|
2266
|
+
const wrapped = hue % 360;
|
|
2267
|
+
return wrapped < 0 ? wrapped + 360 : wrapped;
|
|
2268
|
+
}
|
|
2269
|
+
function hsvToRgb({ h, s, v }) {
|
|
2270
|
+
const hue = normalizeHue(h);
|
|
2271
|
+
const sat = clamp01(s);
|
|
2272
|
+
const val = clamp01(v);
|
|
2273
|
+
const sector = hue / 60;
|
|
2274
|
+
const chroma = val * sat;
|
|
2275
|
+
const x = chroma * (1 - Math.abs(sector % 2 - 1));
|
|
2276
|
+
const base = val - chroma;
|
|
2277
|
+
let rgb;
|
|
2278
|
+
if (sector < 1) rgb = [chroma, x, 0];
|
|
2279
|
+
else if (sector < 2) rgb = [x, chroma, 0];
|
|
2280
|
+
else if (sector < 3) rgb = [0, chroma, x];
|
|
2281
|
+
else if (sector < 4) rgb = [0, x, chroma];
|
|
2282
|
+
else if (sector < 5) rgb = [x, 0, chroma];
|
|
2283
|
+
else rgb = [chroma, 0, x];
|
|
2284
|
+
return { r: rgb[0] + base, g: rgb[1] + base, b: rgb[2] + base };
|
|
2285
|
+
}
|
|
2286
|
+
function rgbToHsv({ r, g, b }) {
|
|
2287
|
+
const red = clamp01(r);
|
|
2288
|
+
const green = clamp01(g);
|
|
2289
|
+
const blue = clamp01(b);
|
|
2290
|
+
const max = Math.max(red, green, blue);
|
|
2291
|
+
const min = Math.min(red, green, blue);
|
|
2292
|
+
const chroma = max - min;
|
|
2293
|
+
let hue = 0;
|
|
2294
|
+
if (chroma !== 0) {
|
|
2295
|
+
if (max === red) hue = (green - blue) / chroma % 6;
|
|
2296
|
+
else if (max === green) hue = (blue - red) / chroma + 2;
|
|
2297
|
+
else hue = (red - green) / chroma + 4;
|
|
2298
|
+
hue *= 60;
|
|
2299
|
+
}
|
|
2300
|
+
return {
|
|
2301
|
+
h: normalizeHue(hue),
|
|
2302
|
+
s: max === 0 ? 0 : chroma / max,
|
|
2303
|
+
v: max
|
|
2304
|
+
};
|
|
2305
|
+
}
|
|
2306
|
+
|
|
2307
|
+
// src/lib/color/hex.ts
|
|
2308
|
+
var HEX = /^#?(?:[0-9a-f]{3,4}|[0-9a-f]{6}|[0-9a-f]{8})$/i;
|
|
2309
|
+
var clamp012 = (n) => n < 0 ? 0 : n > 1 ? 1 : n;
|
|
2310
|
+
function pair(channel) {
|
|
2311
|
+
const value = Number.isFinite(channel) ? clamp012(channel) : 0;
|
|
2312
|
+
return Math.round(value * 255).toString(16).padStart(2, "0");
|
|
2313
|
+
}
|
|
2314
|
+
function parseHex(input) {
|
|
2315
|
+
const text = input.trim();
|
|
2316
|
+
if (!HEX.test(text)) return null;
|
|
2317
|
+
const digits = text.replace("#", "");
|
|
2318
|
+
const short = digits.length < 6;
|
|
2319
|
+
const size = short ? 1 : 2;
|
|
2320
|
+
const channel = (index) => {
|
|
2321
|
+
const slice = digits.slice(index * size, index * size + size);
|
|
2322
|
+
return parseInt(short ? slice + slice : slice, 16) / 255;
|
|
2323
|
+
};
|
|
2324
|
+
const hasAlpha = digits.length === 4 || digits.length === 8;
|
|
2325
|
+
return {
|
|
2326
|
+
r: channel(0),
|
|
2327
|
+
g: channel(1),
|
|
2328
|
+
b: channel(2),
|
|
2329
|
+
alpha: hasAlpha ? channel(3) : 1
|
|
2330
|
+
};
|
|
2331
|
+
}
|
|
2332
|
+
function toHex(color, alpha = 1) {
|
|
2333
|
+
const opacity = Number.isFinite(alpha) ? clamp012(alpha) : 1;
|
|
2334
|
+
const opaque = `#${pair(color.r)}${pair(color.g)}${pair(color.b)}`;
|
|
2335
|
+
return opacity === 1 ? opaque : `${opaque}${pair(opacity)}`;
|
|
2336
|
+
}
|
|
2337
|
+
|
|
2338
|
+
// src/lib/color/picker-geometry.ts
|
|
2339
|
+
var clamp013 = (n) => n < 0 ? 0 : n > 1 ? 1 : n;
|
|
2340
|
+
function pointOnSurface(clientX, clientY, rect) {
|
|
2341
|
+
return {
|
|
2342
|
+
x: rect.width === 0 ? 0 : clamp013((clientX - rect.left) / rect.width),
|
|
2343
|
+
y: rect.height === 0 ? 0 : clamp013((clientY - rect.top) / rect.height)
|
|
2344
|
+
};
|
|
2345
|
+
}
|
|
2346
|
+
function saturationValueAt(point) {
|
|
2347
|
+
return { s: clamp013(point.x), v: 1 - clamp013(point.y) };
|
|
2348
|
+
}
|
|
2349
|
+
function surfacePointFor(s, v) {
|
|
2350
|
+
return { x: clamp013(s), y: 1 - clamp013(v) };
|
|
2351
|
+
}
|
|
2352
|
+
function hueAt(fraction) {
|
|
2353
|
+
const hue = clamp013(fraction) * 360;
|
|
2354
|
+
return hue >= 360 ? 0 : hue;
|
|
2355
|
+
}
|
|
2356
|
+
function huePosition(hue) {
|
|
2357
|
+
const wrapped = (hue % 360 + 360) % 360;
|
|
2358
|
+
return wrapped / 360;
|
|
2359
|
+
}
|
|
2360
|
+
function hueSliderValue(hue, max) {
|
|
2361
|
+
const step = Math.round(huePosition(hue) * (max + 1));
|
|
2362
|
+
return step > max ? max : step;
|
|
2363
|
+
}
|
|
2364
|
+
|
|
2365
|
+
// src/components/color-picker.tsx
|
|
2366
|
+
import { Fragment as Fragment2, jsx as jsx34, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
2367
|
+
function toHsva(hex) {
|
|
2368
|
+
const parsed = parseHex(hex);
|
|
2369
|
+
if (!parsed) return { h: 0, s: 0, v: 0, a: 1 };
|
|
2370
|
+
const { r, g, b, alpha } = parsed;
|
|
2371
|
+
return { ...rgbToHsv({ r, g, b }), a: alpha };
|
|
2372
|
+
}
|
|
2373
|
+
function toHexString(hsva, withAlpha) {
|
|
2374
|
+
return toHex(hsvToRgb(hsva), withAlpha ? hsva.a : 1);
|
|
2375
|
+
}
|
|
2376
|
+
var HUE_MAX = 359;
|
|
2377
|
+
function hsvaFrom(color, alpha, currentHue) {
|
|
2378
|
+
const hsv = rgbToHsv(color);
|
|
2379
|
+
return { ...hsv, h: hsv.s === 0 ? currentHue : hsv.h, a: alpha };
|
|
2380
|
+
}
|
|
2381
|
+
var SLIDER = "h-3 w-full cursor-pointer appearance-none rounded-full";
|
|
2382
|
+
var CHECKERBOARD = "repeating-conic-gradient(#c8c8c8 0% 25%, #ffffff 0% 50%)";
|
|
2383
|
+
function eyeDropperSupported() {
|
|
2384
|
+
return typeof window !== "undefined" && "EyeDropper" in window;
|
|
2385
|
+
}
|
|
2386
|
+
function ColorPicker({
|
|
2387
|
+
color,
|
|
2388
|
+
onColorChange,
|
|
2389
|
+
swatches = [],
|
|
2390
|
+
onSwatchSelect,
|
|
2391
|
+
recentColors = [],
|
|
2392
|
+
showAlpha = false,
|
|
2393
|
+
className
|
|
2394
|
+
}) {
|
|
2395
|
+
const fieldId = React9.useId();
|
|
2396
|
+
const surfaceRef = React9.useRef(null);
|
|
2397
|
+
const [hsva, setHsva] = React9.useState(() => toHsva(color));
|
|
2398
|
+
const [draftHex, setDraftHex] = React9.useState(null);
|
|
2399
|
+
const rendered = toHexString(hsva, showAlpha);
|
|
2400
|
+
React9.useEffect(() => {
|
|
2401
|
+
const incoming = parseHex(color);
|
|
2402
|
+
if (incoming && toHex(incoming, showAlpha ? incoming.alpha : 1) !== rendered) {
|
|
2403
|
+
setHsva((prev) => hsvaFrom(incoming, incoming.alpha, prev.h));
|
|
2404
|
+
}
|
|
2405
|
+
}, [color, rendered, showAlpha]);
|
|
2406
|
+
const commit = (next) => {
|
|
2407
|
+
setHsva(next);
|
|
2408
|
+
setDraftHex(null);
|
|
2409
|
+
onColorChange(toHexString(next, showAlpha));
|
|
2410
|
+
};
|
|
2411
|
+
const trackPointer = (event) => {
|
|
2412
|
+
const rect = surfaceRef.current?.getBoundingClientRect();
|
|
2413
|
+
if (!rect) return;
|
|
2414
|
+
const { s, v } = saturationValueAt(
|
|
2415
|
+
pointOnSurface(event.clientX, event.clientY, rect)
|
|
2416
|
+
);
|
|
2417
|
+
commit({ ...hsva, s, v });
|
|
2418
|
+
};
|
|
2419
|
+
const nudge = (ds, dv) => {
|
|
2420
|
+
const { s, v } = saturationValueAt(
|
|
2421
|
+
surfacePointFor(hsva.s + ds, hsva.v + dv)
|
|
2422
|
+
);
|
|
2423
|
+
commit({ ...hsva, s, v });
|
|
2424
|
+
};
|
|
2425
|
+
const handleSurfaceKey = (event) => {
|
|
2426
|
+
const step = event.shiftKey ? 0.1 : 0.01;
|
|
2427
|
+
const moves = {
|
|
2428
|
+
ArrowLeft: [-step, 0],
|
|
2429
|
+
ArrowRight: [step, 0],
|
|
2430
|
+
ArrowUp: [0, step],
|
|
2431
|
+
ArrowDown: [0, -step]
|
|
2432
|
+
};
|
|
2433
|
+
const move = moves[event.key];
|
|
2434
|
+
if (!move) return;
|
|
2435
|
+
event.preventDefault();
|
|
2436
|
+
nudge(move[0], move[1]);
|
|
2437
|
+
};
|
|
2438
|
+
const [canPickFromScreen, setCanPickFromScreen] = React9.useState(false);
|
|
2439
|
+
React9.useEffect(() => {
|
|
2440
|
+
setCanPickFromScreen(eyeDropperSupported());
|
|
2441
|
+
}, []);
|
|
2442
|
+
const handle = surfacePointFor(hsva.s, hsva.v);
|
|
2443
|
+
const hueOnly = toHex(hsvToRgb({ h: hsva.h, s: 1, v: 1 }));
|
|
2444
|
+
const pickFromScreen = async () => {
|
|
2445
|
+
const ctor = window.EyeDropper;
|
|
2446
|
+
if (!ctor) return;
|
|
2447
|
+
let sampled;
|
|
2448
|
+
try {
|
|
2449
|
+
sampled = (await new ctor().open()).sRGBHex;
|
|
2450
|
+
} catch {
|
|
2451
|
+
return;
|
|
2452
|
+
}
|
|
2453
|
+
const parsed = parseHex(sampled);
|
|
2454
|
+
if (parsed) commit(hsvaFrom(parsed, hsva.a, hsva.h));
|
|
2455
|
+
};
|
|
2456
|
+
return /* @__PURE__ */ jsxs13("div", { className: cn("w-64 space-y-3", className), children: [
|
|
2457
|
+
/* @__PURE__ */ jsx34(
|
|
2035
2458
|
"div",
|
|
2036
2459
|
{
|
|
2037
|
-
ref,
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2460
|
+
ref: surfaceRef,
|
|
2461
|
+
role: "application",
|
|
2462
|
+
tabIndex: 0,
|
|
2463
|
+
"aria-label": `Saturation and brightness: ${Math.round(hsva.s * 100)}% saturation, ${Math.round(hsva.v * 100)}% brightness. Arrow keys adjust.`,
|
|
2464
|
+
className: "ring-offset-background focus-visible:ring-ring relative h-40 w-full cursor-crosshair touch-none rounded-md focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none",
|
|
2465
|
+
style: {
|
|
2466
|
+
backgroundColor: hueOnly,
|
|
2467
|
+
// Value on TOP of saturation. CSS paints the first layer nearest the
|
|
2468
|
+
// viewer, so the reverse order lets the opaque white end of the
|
|
2469
|
+
// saturation ramp cover the black end of the value ramp: the
|
|
2470
|
+
// bottom-left corner displays white while selecting black.
|
|
2471
|
+
backgroundImage: "linear-gradient(to top, #000, transparent), linear-gradient(to right, #fff, transparent)"
|
|
2472
|
+
},
|
|
2473
|
+
onKeyDown: handleSurfaceKey,
|
|
2474
|
+
onPointerDown: (event) => {
|
|
2475
|
+
event.currentTarget.setPointerCapture(event.pointerId);
|
|
2476
|
+
trackPointer(event);
|
|
2477
|
+
},
|
|
2478
|
+
onPointerMove: (event) => {
|
|
2479
|
+
if (event.buttons === 1) trackPointer(event);
|
|
2480
|
+
},
|
|
2481
|
+
children: /* @__PURE__ */ jsx34(
|
|
2482
|
+
"span",
|
|
2483
|
+
{
|
|
2484
|
+
"aria-hidden": "true",
|
|
2485
|
+
className: "pointer-events-none absolute size-3 -translate-x-1/2 -translate-y-1/2 rounded-full border-2 border-white shadow-sm ring-1 ring-black/60",
|
|
2486
|
+
style: { left: `${handle.x * 100}%`, top: `${handle.y * 100}%` }
|
|
2487
|
+
}
|
|
2488
|
+
)
|
|
2043
2489
|
}
|
|
2044
|
-
)
|
|
2490
|
+
),
|
|
2491
|
+
/* @__PURE__ */ jsx34("label", { className: "sr-only", htmlFor: `${fieldId}-hue`, children: "Hue" }),
|
|
2492
|
+
/* @__PURE__ */ jsx34(
|
|
2493
|
+
"input",
|
|
2494
|
+
{
|
|
2495
|
+
id: `${fieldId}-hue`,
|
|
2496
|
+
type: "range",
|
|
2497
|
+
min: 0,
|
|
2498
|
+
max: HUE_MAX,
|
|
2499
|
+
step: 1,
|
|
2500
|
+
value: hueSliderValue(hsva.h, HUE_MAX),
|
|
2501
|
+
onChange: (event) => commit({ ...hsva, h: hueAt(+event.target.value / (HUE_MAX + 1)) }),
|
|
2502
|
+
className: SLIDER,
|
|
2503
|
+
style: {
|
|
2504
|
+
backgroundImage: "linear-gradient(to right, #f00, #ff0, #0f0, #0ff, #00f, #f0f, #f00)"
|
|
2505
|
+
}
|
|
2506
|
+
}
|
|
2507
|
+
),
|
|
2508
|
+
showAlpha && /* @__PURE__ */ jsxs13(Fragment2, { children: [
|
|
2509
|
+
/* @__PURE__ */ jsx34("label", { className: "sr-only", htmlFor: `${fieldId}-alpha`, children: "Opacity" }),
|
|
2510
|
+
/* @__PURE__ */ jsx34(
|
|
2511
|
+
"input",
|
|
2512
|
+
{
|
|
2513
|
+
id: `${fieldId}-alpha`,
|
|
2514
|
+
type: "range",
|
|
2515
|
+
min: 0,
|
|
2516
|
+
max: 100,
|
|
2517
|
+
step: 1,
|
|
2518
|
+
value: Math.round(hsva.a * 100),
|
|
2519
|
+
onChange: (event) => commit({ ...hsva, a: +event.target.value / 100 }),
|
|
2520
|
+
className: SLIDER,
|
|
2521
|
+
style: {
|
|
2522
|
+
// The ramp runs to the colour being edited, over a chequerboard,
|
|
2523
|
+
// so the track shows what the slider actually controls. Without
|
|
2524
|
+
// any background this rendered as a blank 12px strip whose only
|
|
2525
|
+
// label was screen-reader-only.
|
|
2526
|
+
backgroundImage: `linear-gradient(to right, transparent, ${toHexString({ ...hsva, a: 1 }, false)}), ${CHECKERBOARD}`,
|
|
2527
|
+
backgroundSize: "100% 100%, 8px 8px"
|
|
2528
|
+
}
|
|
2529
|
+
}
|
|
2530
|
+
)
|
|
2531
|
+
] }),
|
|
2532
|
+
/* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-2", children: [
|
|
2533
|
+
/* @__PURE__ */ jsx34("label", { className: "sr-only", htmlFor: `${fieldId}-hex`, children: "Hex colour" }),
|
|
2534
|
+
/* @__PURE__ */ jsx34(
|
|
2535
|
+
Input,
|
|
2536
|
+
{
|
|
2537
|
+
id: `${fieldId}-hex`,
|
|
2538
|
+
className: "font-mono",
|
|
2539
|
+
value: draftHex ?? rendered,
|
|
2540
|
+
onChange: (event) => {
|
|
2541
|
+
const text = event.target.value;
|
|
2542
|
+
setDraftHex(text);
|
|
2543
|
+
const parsed = parseHex(text);
|
|
2544
|
+
if (parsed) {
|
|
2545
|
+
setHsva(hsvaFrom(parsed, parsed.alpha, hsva.h));
|
|
2546
|
+
onColorChange(toHex(parsed, showAlpha ? parsed.alpha : 1));
|
|
2547
|
+
}
|
|
2548
|
+
},
|
|
2549
|
+
onBlur: () => setDraftHex(null)
|
|
2550
|
+
}
|
|
2551
|
+
),
|
|
2552
|
+
canPickFromScreen && /* @__PURE__ */ jsx34(
|
|
2553
|
+
Button,
|
|
2554
|
+
{
|
|
2555
|
+
type: "button",
|
|
2556
|
+
variant: "outline",
|
|
2557
|
+
size: "icon",
|
|
2558
|
+
"aria-label": "Pick a colour from the screen",
|
|
2559
|
+
onClick: () => void pickFromScreen(),
|
|
2560
|
+
children: /* @__PURE__ */ jsx34(Pipette, { className: "size-4" })
|
|
2561
|
+
}
|
|
2562
|
+
)
|
|
2563
|
+
] }),
|
|
2564
|
+
swatches.length > 0 && /* @__PURE__ */ jsxs13("div", { children: [
|
|
2565
|
+
/* @__PURE__ */ jsx34("p", { className: "text-muted-foreground mb-1 text-xs", children: "Presets" }),
|
|
2566
|
+
/* @__PURE__ */ jsx34("div", { className: "flex flex-wrap gap-1", children: swatches.map((swatch) => /* @__PURE__ */ jsx34(
|
|
2567
|
+
"button",
|
|
2568
|
+
{
|
|
2569
|
+
type: "button",
|
|
2570
|
+
title: swatch.label,
|
|
2571
|
+
"aria-label": swatch.label,
|
|
2572
|
+
className: "size-6 rounded border shadow-sm",
|
|
2573
|
+
style: { backgroundColor: swatch.color },
|
|
2574
|
+
onClick: () => onSwatchSelect?.(swatch)
|
|
2575
|
+
},
|
|
2576
|
+
swatch.id
|
|
2577
|
+
)) })
|
|
2578
|
+
] }),
|
|
2579
|
+
recentColors.length > 0 && /* @__PURE__ */ jsxs13("div", { children: [
|
|
2580
|
+
/* @__PURE__ */ jsx34("p", { className: "text-muted-foreground mb-1 text-xs", children: "Recent" }),
|
|
2581
|
+
/* @__PURE__ */ jsx34("div", { className: "flex flex-wrap gap-1", children: recentColors.map((recent) => /* @__PURE__ */ jsx34(
|
|
2582
|
+
"button",
|
|
2583
|
+
{
|
|
2584
|
+
type: "button",
|
|
2585
|
+
title: recent,
|
|
2586
|
+
"aria-label": recent,
|
|
2587
|
+
className: "size-6 rounded border shadow-sm",
|
|
2588
|
+
style: { backgroundColor: recent },
|
|
2589
|
+
onClick: () => {
|
|
2590
|
+
const parsed = parseHex(recent);
|
|
2591
|
+
if (parsed) commit(hsvaFrom(parsed, parsed.alpha, hsva.h));
|
|
2592
|
+
}
|
|
2593
|
+
},
|
|
2594
|
+
recent
|
|
2595
|
+
)) })
|
|
2596
|
+
] })
|
|
2597
|
+
] });
|
|
2598
|
+
}
|
|
2599
|
+
|
|
2600
|
+
// src/components/context-menu.tsx
|
|
2601
|
+
import * as ContextMenuPrimitive from "@radix-ui/react-context-menu";
|
|
2602
|
+
import { Check as Check4, ChevronRight as ChevronRight2, Circle as Circle2 } from "lucide-react";
|
|
2603
|
+
import * as React10 from "react";
|
|
2604
|
+
import { jsx as jsx35, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
2605
|
+
var menuItemBase2 = "cursor-pointer transition-colors data-[highlighted]:bg-muted data-[highlighted]:text-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50";
|
|
2606
|
+
var menuSurface = "z-50 max-h-[var(--radix-context-menu-content-available-height)] min-w-[8rem] overflow-y-auto overflow-x-hidden rounded-lg border border-border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 origin-[--radix-context-menu-content-transform-origin]";
|
|
2607
|
+
var ContextMenu = ContextMenuPrimitive.Root;
|
|
2608
|
+
var ContextMenuTrigger = ContextMenuPrimitive.Trigger;
|
|
2609
|
+
var ContextMenuGroup = ContextMenuPrimitive.Group;
|
|
2610
|
+
var ContextMenuSub = ContextMenuPrimitive.Sub;
|
|
2611
|
+
var ContextMenuRadioGroup = ContextMenuPrimitive.RadioGroup;
|
|
2612
|
+
var ContextMenuSubTrigger = React10.forwardRef(({ className, inset, children, ...props }, ref) => /* @__PURE__ */ jsxs14(
|
|
2613
|
+
ContextMenuPrimitive.SubTrigger,
|
|
2614
|
+
{
|
|
2615
|
+
ref,
|
|
2616
|
+
className: cn(
|
|
2617
|
+
"flex select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none data-[state=open]:bg-muted [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
|
2618
|
+
menuItemBase2,
|
|
2619
|
+
inset && "pl-8",
|
|
2620
|
+
className
|
|
2621
|
+
),
|
|
2622
|
+
...props,
|
|
2623
|
+
children: [
|
|
2624
|
+
children,
|
|
2625
|
+
/* @__PURE__ */ jsx35(ChevronRight2, { className: "ml-auto" })
|
|
2626
|
+
]
|
|
2627
|
+
}
|
|
2628
|
+
));
|
|
2629
|
+
ContextMenuSubTrigger.displayName = ContextMenuPrimitive.SubTrigger.displayName;
|
|
2630
|
+
var ContextMenuSubContent = React10.forwardRef(({ className, ...props }, ref) => {
|
|
2631
|
+
const portalContainer = usePortalContainer();
|
|
2632
|
+
return /* @__PURE__ */ jsx35(ContextMenuPrimitive.Portal, { container: portalContainer, children: /* @__PURE__ */ jsx35(
|
|
2633
|
+
ContextMenuPrimitive.SubContent,
|
|
2634
|
+
{
|
|
2635
|
+
ref,
|
|
2636
|
+
className: cn(menuSurface, className),
|
|
2637
|
+
...props
|
|
2638
|
+
}
|
|
2639
|
+
) });
|
|
2640
|
+
});
|
|
2641
|
+
ContextMenuSubContent.displayName = ContextMenuPrimitive.SubContent.displayName;
|
|
2642
|
+
var ContextMenuContent = React10.forwardRef(({ className, ...props }, ref) => {
|
|
2643
|
+
const portalContainer = usePortalContainer();
|
|
2644
|
+
return /* @__PURE__ */ jsx35(ContextMenuPrimitive.Portal, { container: portalContainer, children: /* @__PURE__ */ jsx35(
|
|
2645
|
+
ContextMenuPrimitive.Content,
|
|
2646
|
+
{
|
|
2647
|
+
ref,
|
|
2648
|
+
className: cn(menuSurface, className),
|
|
2649
|
+
...props
|
|
2650
|
+
}
|
|
2651
|
+
) });
|
|
2652
|
+
});
|
|
2653
|
+
ContextMenuContent.displayName = ContextMenuPrimitive.Content.displayName;
|
|
2654
|
+
var ContextMenuItem = React10.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ jsx35(
|
|
2655
|
+
ContextMenuPrimitive.Item,
|
|
2656
|
+
{
|
|
2657
|
+
ref,
|
|
2658
|
+
className: cn(
|
|
2659
|
+
"relative flex select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
|
2660
|
+
menuItemBase2,
|
|
2661
|
+
inset && "pl-8",
|
|
2662
|
+
className
|
|
2663
|
+
),
|
|
2664
|
+
...props
|
|
2045
2665
|
}
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2666
|
+
));
|
|
2667
|
+
ContextMenuItem.displayName = ContextMenuPrimitive.Item.displayName;
|
|
2668
|
+
var ContextMenuCheckboxItem = React10.forwardRef(({ className, children, checked, ...props }, ref) => /* @__PURE__ */ jsxs14(
|
|
2669
|
+
ContextMenuPrimitive.CheckboxItem,
|
|
2670
|
+
{
|
|
2671
|
+
ref,
|
|
2672
|
+
className: cn(
|
|
2673
|
+
"relative flex select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none",
|
|
2674
|
+
menuItemBase2,
|
|
2675
|
+
className
|
|
2676
|
+
),
|
|
2677
|
+
checked,
|
|
2678
|
+
...props,
|
|
2679
|
+
children: [
|
|
2680
|
+
/* @__PURE__ */ jsx35("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsx35(ContextMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx35(Check4, { className: "h-4 w-4" }) }) }),
|
|
2681
|
+
children
|
|
2682
|
+
]
|
|
2683
|
+
}
|
|
2684
|
+
));
|
|
2685
|
+
ContextMenuCheckboxItem.displayName = ContextMenuPrimitive.CheckboxItem.displayName;
|
|
2686
|
+
var ContextMenuRadioItem = React10.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs14(
|
|
2687
|
+
ContextMenuPrimitive.RadioItem,
|
|
2688
|
+
{
|
|
2689
|
+
ref,
|
|
2690
|
+
className: cn(
|
|
2691
|
+
"relative flex select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none",
|
|
2692
|
+
menuItemBase2,
|
|
2693
|
+
className
|
|
2694
|
+
),
|
|
2695
|
+
...props,
|
|
2696
|
+
children: [
|
|
2697
|
+
/* @__PURE__ */ jsx35("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsx35(ContextMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx35(Circle2, { className: "h-2 w-2 fill-current" }) }) }),
|
|
2698
|
+
children
|
|
2699
|
+
]
|
|
2700
|
+
}
|
|
2701
|
+
));
|
|
2702
|
+
ContextMenuRadioItem.displayName = ContextMenuPrimitive.RadioItem.displayName;
|
|
2703
|
+
var ContextMenuLabel = React10.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ jsx35(
|
|
2704
|
+
ContextMenuPrimitive.Label,
|
|
2705
|
+
{
|
|
2706
|
+
ref,
|
|
2707
|
+
className: cn(
|
|
2708
|
+
"px-2 py-1.5 text-sm font-semibold text-foreground",
|
|
2709
|
+
inset && "pl-8",
|
|
2710
|
+
className
|
|
2711
|
+
),
|
|
2712
|
+
...props
|
|
2713
|
+
}
|
|
2714
|
+
));
|
|
2715
|
+
ContextMenuLabel.displayName = ContextMenuPrimitive.Label.displayName;
|
|
2716
|
+
var ContextMenuSeparator = React10.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx35(
|
|
2717
|
+
ContextMenuPrimitive.Separator,
|
|
2718
|
+
{
|
|
2719
|
+
ref,
|
|
2720
|
+
className: cn("-mx-1 my-1 h-px bg-border", className),
|
|
2721
|
+
...props
|
|
2722
|
+
}
|
|
2723
|
+
));
|
|
2724
|
+
ContextMenuSeparator.displayName = ContextMenuPrimitive.Separator.displayName;
|
|
2725
|
+
var ContextMenuShortcut = ({
|
|
2726
|
+
className,
|
|
2727
|
+
...props
|
|
2728
|
+
}) => /* @__PURE__ */ jsx35(
|
|
2729
|
+
"span",
|
|
2730
|
+
{
|
|
2731
|
+
className: cn(
|
|
2732
|
+
"ml-auto text-xs tracking-widest text-muted-foreground",
|
|
2733
|
+
className
|
|
2734
|
+
),
|
|
2735
|
+
...props
|
|
2736
|
+
}
|
|
2737
|
+
);
|
|
2738
|
+
ContextMenuShortcut.displayName = "ContextMenuShortcut";
|
|
2739
|
+
|
|
2740
|
+
// src/components/resizable.tsx
|
|
2741
|
+
import { GripVertical } from "lucide-react";
|
|
2742
|
+
import * as ResizablePrimitive from "react-resizable-panels";
|
|
2743
|
+
import { jsx as jsx36, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
2744
|
+
var ResizablePanelGroup = ({
|
|
2745
|
+
className,
|
|
2746
|
+
...props
|
|
2747
|
+
}) => /* @__PURE__ */ jsx36(
|
|
2748
|
+
ResizablePrimitive.Group,
|
|
2749
|
+
{
|
|
2750
|
+
className: cn("h-full w-full", className),
|
|
2751
|
+
...props
|
|
2752
|
+
}
|
|
2753
|
+
);
|
|
2754
|
+
var ResizablePanel = ResizablePrimitive.Panel;
|
|
2755
|
+
var ResizableHandle = ({
|
|
2756
|
+
withGrip,
|
|
2757
|
+
className,
|
|
2758
|
+
children,
|
|
2759
|
+
...props
|
|
2760
|
+
}) => /* @__PURE__ */ jsxs15(
|
|
2761
|
+
ResizablePrimitive.Separator,
|
|
2762
|
+
{
|
|
2763
|
+
className: cn(
|
|
2764
|
+
// The drawn line is 1px; the element around it is wider and transparent, so the pointer
|
|
2765
|
+
// target is comfortably larger than what it appears to grab (WCAG 2.5.8).
|
|
2766
|
+
"relative flex items-center justify-center bg-border",
|
|
2767
|
+
// Keyed off `aria-orientation`, which is what the separator actually carries, and read as
|
|
2768
|
+
// the ARIA spec defines it: the attribute describes the SEPARATOR, not the group. A
|
|
2769
|
+
// horizontal group puts its panels side by side, so its separator is a vertical line.
|
|
2770
|
+
"aria-[orientation=vertical]:w-px aria-[orientation=horizontal]:h-px",
|
|
2771
|
+
"focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-background",
|
|
2772
|
+
// Reachable without precision pointing, without drawing a heavier divider: the hit area
|
|
2773
|
+
// grows across the line, so a vertical line widens and a horizontal one deepens.
|
|
2774
|
+
"after:absolute after:inset-0",
|
|
2775
|
+
"aria-[orientation=vertical]:after:-inset-x-1 aria-[orientation=horizontal]:after:-inset-y-1",
|
|
2776
|
+
className
|
|
2777
|
+
),
|
|
2778
|
+
...props,
|
|
2779
|
+
children: [
|
|
2780
|
+
withGrip ? /* @__PURE__ */ jsx36("div", { className: "z-10 flex h-4 w-3 items-center justify-center rounded-sm border border-border bg-border", children: /* @__PURE__ */ jsx36(GripVertical, { className: "h-2.5 w-2.5 text-muted-foreground" }) }) : null,
|
|
2781
|
+
children
|
|
2782
|
+
]
|
|
2783
|
+
}
|
|
2784
|
+
);
|
|
2785
|
+
|
|
2786
|
+
// src/components/tree-view.tsx
|
|
2787
|
+
import { useVirtualizer } from "@tanstack/react-virtual";
|
|
2788
|
+
import { ChevronRight as ChevronRight3 } from "lucide-react";
|
|
2789
|
+
import * as React11 from "react";
|
|
2790
|
+
import { jsx as jsx37, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
2791
|
+
var ROW_HEIGHT = 28;
|
|
2792
|
+
var INDENT_PER_LEVEL = 12;
|
|
2793
|
+
function textOf(node) {
|
|
2794
|
+
if (typeof node.textValue === "string") return node.textValue;
|
|
2795
|
+
return typeof node.label === "string" ? node.label : "";
|
|
2796
|
+
}
|
|
2797
|
+
function flatten(nodes, expanded) {
|
|
2798
|
+
const rows = [];
|
|
2799
|
+
const pending = [{ list: nodes, index: 0, level: 0 }];
|
|
2800
|
+
while (pending.length > 0) {
|
|
2801
|
+
const frame = pending[pending.length - 1];
|
|
2802
|
+
if (frame === void 0 || frame.index >= frame.list.length) {
|
|
2803
|
+
pending.pop();
|
|
2804
|
+
continue;
|
|
2805
|
+
}
|
|
2806
|
+
const node = frame.list[frame.index];
|
|
2807
|
+
const posInSet = frame.index;
|
|
2808
|
+
frame.index += 1;
|
|
2809
|
+
if (node === void 0) continue;
|
|
2810
|
+
const hasChildren = node.children !== void 0;
|
|
2811
|
+
rows.push({
|
|
2812
|
+
node,
|
|
2813
|
+
level: frame.level,
|
|
2814
|
+
setSize: frame.list.length,
|
|
2815
|
+
posInSet,
|
|
2816
|
+
parentId: frame.parentId,
|
|
2817
|
+
hasChildren
|
|
2818
|
+
});
|
|
2819
|
+
if (hasChildren && expanded.has(node.id)) {
|
|
2820
|
+
pending.push({
|
|
2821
|
+
list: node.children ?? [],
|
|
2822
|
+
index: 0,
|
|
2823
|
+
level: frame.level + 1,
|
|
2824
|
+
parentId: node.id
|
|
2825
|
+
});
|
|
2826
|
+
}
|
|
2827
|
+
}
|
|
2828
|
+
return rows;
|
|
2829
|
+
}
|
|
2830
|
+
function useControllable(controlled, fallback) {
|
|
2831
|
+
const [uncontrolled, setUncontrolled] = React11.useState(fallback);
|
|
2832
|
+
return [
|
|
2833
|
+
controlled === void 0 ? uncontrolled : controlled,
|
|
2834
|
+
setUncontrolled
|
|
2835
|
+
];
|
|
2836
|
+
}
|
|
2837
|
+
var TreeView = React11.forwardRef(
|
|
2838
|
+
({
|
|
2839
|
+
nodes,
|
|
2840
|
+
expandedIds,
|
|
2841
|
+
defaultExpandedIds,
|
|
2842
|
+
onExpandedChange,
|
|
2843
|
+
selectedId,
|
|
2844
|
+
defaultSelectedId,
|
|
2845
|
+
onSelectedChange,
|
|
2846
|
+
className,
|
|
2847
|
+
"aria-label": ariaLabel,
|
|
2848
|
+
"aria-labelledby": ariaLabelledBy,
|
|
2849
|
+
"aria-describedby": ariaDescribedBy,
|
|
2850
|
+
...props
|
|
2851
|
+
}, forwardedRef) => {
|
|
2852
|
+
const scrollRef = React11.useRef(null);
|
|
2853
|
+
const attachScroll = React11.useCallback(
|
|
2854
|
+
(node) => {
|
|
2855
|
+
scrollRef.current = node;
|
|
2856
|
+
if (typeof forwardedRef === "function") forwardedRef(node);
|
|
2857
|
+
else if (forwardedRef !== null && forwardedRef !== void 0) {
|
|
2858
|
+
forwardedRef.current = node;
|
|
2859
|
+
}
|
|
2860
|
+
},
|
|
2861
|
+
[forwardedRef]
|
|
2862
|
+
);
|
|
2863
|
+
const [expandedState, setExpandedState] = useControllable(
|
|
2864
|
+
expandedIds === void 0 ? void 0 : [...expandedIds],
|
|
2865
|
+
[...defaultExpandedIds ?? []]
|
|
2866
|
+
);
|
|
2867
|
+
const expanded = React11.useMemo(
|
|
2868
|
+
() => new Set(expandedIds ?? expandedState),
|
|
2869
|
+
[expandedIds, expandedState]
|
|
2870
|
+
);
|
|
2871
|
+
const [selected, setSelected] = useControllable(
|
|
2872
|
+
selectedId === void 0 ? void 0 : selectedId,
|
|
2873
|
+
defaultSelectedId ?? null
|
|
2874
|
+
);
|
|
2875
|
+
const rows = React11.useMemo(
|
|
2876
|
+
() => flatten(nodes, expanded),
|
|
2877
|
+
[nodes, expanded]
|
|
2878
|
+
);
|
|
2879
|
+
const [activeId, setActiveId] = React11.useState(null);
|
|
2880
|
+
const activeIndex = Math.max(
|
|
2881
|
+
0,
|
|
2882
|
+
rows.findIndex((row) => row.node.id === (activeId ?? selected))
|
|
2883
|
+
);
|
|
2884
|
+
const virtualizer = useVirtualizer({
|
|
2885
|
+
count: rows.length,
|
|
2886
|
+
getScrollElement: () => scrollRef.current,
|
|
2887
|
+
estimateSize: () => ROW_HEIGHT,
|
|
2888
|
+
overscan: 8
|
|
2889
|
+
});
|
|
2890
|
+
const commitExpanded = (next) => {
|
|
2891
|
+
const ids = [...next];
|
|
2892
|
+
if (expandedIds === void 0) setExpandedState(ids);
|
|
2893
|
+
onExpandedChange?.(ids);
|
|
2894
|
+
};
|
|
2895
|
+
const setExpansion = (id, open) => {
|
|
2896
|
+
const next = new Set(expanded);
|
|
2897
|
+
if (open) next.add(id);
|
|
2898
|
+
else next.delete(id);
|
|
2899
|
+
commitExpanded(next);
|
|
2900
|
+
};
|
|
2901
|
+
const choose = (id) => {
|
|
2902
|
+
if (selectedId === void 0) setSelected(id);
|
|
2903
|
+
onSelectedChange?.(id);
|
|
2904
|
+
};
|
|
2905
|
+
const focusRow = (index) => {
|
|
2906
|
+
const row = rows[index];
|
|
2907
|
+
if (row === void 0) return;
|
|
2908
|
+
setActiveId(row.node.id);
|
|
2909
|
+
virtualizer.scrollToIndex(index, { align: "auto" });
|
|
2910
|
+
requestAnimationFrame(() => {
|
|
2911
|
+
const element = scrollRef.current?.querySelector(
|
|
2912
|
+
`[data-tree-index="${index}"]`
|
|
2913
|
+
);
|
|
2914
|
+
element?.focus();
|
|
2915
|
+
});
|
|
2916
|
+
};
|
|
2917
|
+
const step = (from, delta) => {
|
|
2918
|
+
for (let index = from + delta; index >= 0 && index < rows.length; index += delta) {
|
|
2919
|
+
if (rows[index]?.node.disabled !== true) return index;
|
|
2920
|
+
}
|
|
2921
|
+
return from;
|
|
2922
|
+
};
|
|
2923
|
+
const typeahead = React11.useRef({ query: "", at: 0 });
|
|
2924
|
+
const onKeyDown = (event) => {
|
|
2925
|
+
const index = activeIndex;
|
|
2926
|
+
const row = rows[index];
|
|
2927
|
+
if (row === void 0) return;
|
|
2928
|
+
switch (event.key) {
|
|
2929
|
+
case "ArrowDown":
|
|
2930
|
+
event.preventDefault();
|
|
2931
|
+
focusRow(step(index, 1));
|
|
2932
|
+
return;
|
|
2933
|
+
case "ArrowUp":
|
|
2934
|
+
event.preventDefault();
|
|
2935
|
+
focusRow(step(index, -1));
|
|
2936
|
+
return;
|
|
2937
|
+
case "ArrowRight":
|
|
2938
|
+
event.preventDefault();
|
|
2939
|
+
if (row.hasChildren && !expanded.has(row.node.id)) {
|
|
2940
|
+
setExpansion(row.node.id, true);
|
|
2941
|
+
} else if (row.hasChildren) {
|
|
2942
|
+
for (let child = index + 1; child < rows.length && (rows[child]?.level ?? 0) > row.level; child += 1) {
|
|
2943
|
+
if (rows[child]?.parentId === row.node.id && rows[child]?.node.disabled !== true) {
|
|
2944
|
+
focusRow(child);
|
|
2945
|
+
break;
|
|
2946
|
+
}
|
|
2947
|
+
}
|
|
2948
|
+
}
|
|
2949
|
+
return;
|
|
2950
|
+
case "ArrowLeft":
|
|
2951
|
+
event.preventDefault();
|
|
2952
|
+
if (row.hasChildren && expanded.has(row.node.id)) {
|
|
2953
|
+
setExpansion(row.node.id, false);
|
|
2954
|
+
} else if (row.parentId !== void 0) {
|
|
2955
|
+
let ancestor = row.parentId;
|
|
2956
|
+
while (ancestor !== void 0) {
|
|
2957
|
+
const at = rows.findIndex(
|
|
2958
|
+
(candidate) => candidate.node.id === ancestor
|
|
2959
|
+
);
|
|
2960
|
+
if (at < 0) break;
|
|
2961
|
+
if (rows[at]?.node.disabled !== true) {
|
|
2962
|
+
focusRow(at);
|
|
2963
|
+
break;
|
|
2964
|
+
}
|
|
2965
|
+
ancestor = rows[at]?.parentId;
|
|
2966
|
+
}
|
|
2967
|
+
}
|
|
2968
|
+
return;
|
|
2969
|
+
case "Home":
|
|
2970
|
+
event.preventDefault();
|
|
2971
|
+
focusRow(rows[0]?.node.disabled === true ? step(0, 1) : 0);
|
|
2972
|
+
return;
|
|
2973
|
+
case "End": {
|
|
2974
|
+
event.preventDefault();
|
|
2975
|
+
const last = rows.length - 1;
|
|
2976
|
+
focusRow(rows[last]?.node.disabled === true ? step(last, -1) : last);
|
|
2977
|
+
return;
|
|
2978
|
+
}
|
|
2979
|
+
case "Enter":
|
|
2980
|
+
case " ":
|
|
2981
|
+
event.preventDefault();
|
|
2982
|
+
if (row.node.disabled !== true) choose(row.node.id);
|
|
2983
|
+
return;
|
|
2984
|
+
case "*": {
|
|
2985
|
+
event.preventDefault();
|
|
2986
|
+
const next = new Set(expanded);
|
|
2987
|
+
for (const sibling of rows) {
|
|
2988
|
+
if (sibling.parentId === row.parentId && sibling.hasChildren) {
|
|
2989
|
+
next.add(sibling.node.id);
|
|
2990
|
+
}
|
|
2991
|
+
}
|
|
2992
|
+
commitExpanded(next);
|
|
2993
|
+
return;
|
|
2994
|
+
}
|
|
2995
|
+
default:
|
|
2996
|
+
break;
|
|
2997
|
+
}
|
|
2998
|
+
if (event.key.length !== 1 || event.metaKey || event.ctrlKey || event.altKey) {
|
|
2999
|
+
return;
|
|
3000
|
+
}
|
|
3001
|
+
event.preventDefault();
|
|
3002
|
+
const now = Date.now();
|
|
3003
|
+
const state = typeahead.current;
|
|
3004
|
+
state.query = now - state.at > 500 ? event.key : state.query + event.key;
|
|
3005
|
+
state.at = now;
|
|
3006
|
+
const query = state.query.toLowerCase();
|
|
3007
|
+
for (let offset = 1; offset <= rows.length; offset += 1) {
|
|
3008
|
+
const candidate = rows[(index + offset) % rows.length];
|
|
3009
|
+
if (candidate === void 0 || candidate.node.disabled === true)
|
|
3010
|
+
continue;
|
|
3011
|
+
if (textOf(candidate.node).toLowerCase().startsWith(query)) {
|
|
3012
|
+
focusRow(rows.indexOf(candidate));
|
|
3013
|
+
return;
|
|
3014
|
+
}
|
|
3015
|
+
}
|
|
3016
|
+
};
|
|
3017
|
+
const virtualItems = virtualizer.getVirtualItems();
|
|
3018
|
+
const usable = (index) => rows[index]?.node.disabled !== true;
|
|
3019
|
+
const tabStopIndex = virtualItems.some((item) => item.index === activeIndex) && usable(activeIndex) ? activeIndex : virtualItems.find((item) => usable(item.index))?.index ?? -1;
|
|
3020
|
+
return /* @__PURE__ */ jsx37(
|
|
3021
|
+
"div",
|
|
3022
|
+
{
|
|
3023
|
+
ref: attachScroll,
|
|
3024
|
+
className: cn("overflow-auto", className),
|
|
3025
|
+
...props,
|
|
3026
|
+
children: /* @__PURE__ */ jsx37(
|
|
2051
3027
|
"div",
|
|
2052
3028
|
{
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
children:
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
3029
|
+
role: "tree",
|
|
3030
|
+
"aria-label": ariaLabel,
|
|
3031
|
+
"aria-labelledby": ariaLabelledBy,
|
|
3032
|
+
"aria-describedby": ariaDescribedBy,
|
|
3033
|
+
onKeyDown,
|
|
3034
|
+
style: { height: virtualizer.getTotalSize(), position: "relative" },
|
|
3035
|
+
children: virtualItems.map((item) => {
|
|
3036
|
+
const row = rows[item.index];
|
|
3037
|
+
if (row === void 0) return null;
|
|
3038
|
+
const isSelected = selected === row.node.id;
|
|
3039
|
+
return /* @__PURE__ */ jsxs16(
|
|
3040
|
+
"div",
|
|
3041
|
+
{
|
|
3042
|
+
"data-tree-index": item.index,
|
|
3043
|
+
role: "treeitem",
|
|
3044
|
+
"aria-level": row.level + 1,
|
|
3045
|
+
"aria-setsize": row.setSize,
|
|
3046
|
+
"aria-posinset": row.posInSet + 1,
|
|
3047
|
+
"aria-selected": isSelected,
|
|
3048
|
+
"aria-expanded": row.hasChildren ? expanded.has(row.node.id) : void 0,
|
|
3049
|
+
"aria-disabled": row.node.disabled === true ? true : void 0,
|
|
3050
|
+
tabIndex: item.index === tabStopIndex ? 0 : -1,
|
|
3051
|
+
onFocus: () => setActiveId(row.node.id),
|
|
3052
|
+
onClick: () => {
|
|
3053
|
+
if (row.node.disabled === true) return;
|
|
3054
|
+
setActiveId(row.node.id);
|
|
3055
|
+
choose(row.node.id);
|
|
3056
|
+
},
|
|
3057
|
+
className: cn(
|
|
3058
|
+
"absolute left-0 flex w-full select-none items-center gap-1 rounded-sm pr-2 text-sm outline-none",
|
|
3059
|
+
"focus-visible:ring-1 focus-visible:ring-ring",
|
|
3060
|
+
row.node.disabled === true ? "pointer-events-none opacity-50" : "cursor-pointer",
|
|
3061
|
+
isSelected ? "bg-muted text-foreground" : "hover:bg-muted/50"
|
|
3062
|
+
),
|
|
3063
|
+
style: {
|
|
3064
|
+
height: item.size,
|
|
3065
|
+
transform: `translateY(${item.start}px)`,
|
|
3066
|
+
paddingLeft: 4 + row.level * INDENT_PER_LEVEL
|
|
3067
|
+
},
|
|
3068
|
+
children: [
|
|
3069
|
+
/* @__PURE__ */ jsx37(
|
|
3070
|
+
"span",
|
|
3071
|
+
{
|
|
3072
|
+
"aria-hidden": "true",
|
|
3073
|
+
className: "flex size-4 shrink-0 items-center justify-center",
|
|
3074
|
+
onClick: (event) => {
|
|
3075
|
+
if (!row.hasChildren) return;
|
|
3076
|
+
event.stopPropagation();
|
|
3077
|
+
setExpansion(row.node.id, !expanded.has(row.node.id));
|
|
3078
|
+
},
|
|
3079
|
+
children: row.hasChildren ? /* @__PURE__ */ jsx37(
|
|
3080
|
+
ChevronRight3,
|
|
3081
|
+
{
|
|
3082
|
+
className: cn(
|
|
3083
|
+
"size-3.5 text-muted-foreground transition-transform",
|
|
3084
|
+
expanded.has(row.node.id) && "rotate-90"
|
|
3085
|
+
)
|
|
3086
|
+
}
|
|
3087
|
+
) : null
|
|
3088
|
+
}
|
|
3089
|
+
),
|
|
3090
|
+
row.node.icon !== void 0 ? /* @__PURE__ */ jsx37("span", { className: "flex size-4 shrink-0 items-center justify-center text-muted-foreground", children: row.node.icon }) : null,
|
|
3091
|
+
/* @__PURE__ */ jsx37("span", { className: "truncate", children: row.node.label })
|
|
3092
|
+
]
|
|
3093
|
+
},
|
|
3094
|
+
row.node.id
|
|
3095
|
+
);
|
|
3096
|
+
})
|
|
3097
|
+
}
|
|
3098
|
+
)
|
|
3099
|
+
}
|
|
3100
|
+
);
|
|
3101
|
+
}
|
|
3102
|
+
);
|
|
3103
|
+
TreeView.displayName = "TreeView";
|
|
3104
|
+
|
|
3105
|
+
// src/components/slider.tsx
|
|
3106
|
+
import * as SliderPrimitive from "@radix-ui/react-slider";
|
|
3107
|
+
import * as React12 from "react";
|
|
3108
|
+
|
|
3109
|
+
// src/lib/dev-warn.ts
|
|
3110
|
+
var emitted = /* @__PURE__ */ new Set();
|
|
3111
|
+
var SPEAKING_ENVIRONMENTS = /* @__PURE__ */ new Set(["development", "test"]);
|
|
3112
|
+
function isDevelopmentRuntime() {
|
|
3113
|
+
if (typeof process === "undefined") return false;
|
|
3114
|
+
const env = process?.env?.NODE_ENV;
|
|
3115
|
+
return env !== void 0 && SPEAKING_ENVIRONMENTS.has(env);
|
|
3116
|
+
}
|
|
3117
|
+
function devWarnOnce(condition, message) {
|
|
3118
|
+
if (condition) return;
|
|
3119
|
+
if (!isDevelopmentRuntime()) return;
|
|
3120
|
+
if (emitted.has(message)) return;
|
|
3121
|
+
emitted.add(message);
|
|
3122
|
+
console.warn(`[@nextlyhq/ui] ${message}`);
|
|
3123
|
+
}
|
|
3124
|
+
|
|
3125
|
+
// src/components/slider.tsx
|
|
3126
|
+
import { jsx as jsx38, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
3127
|
+
function thumbCount(value, defaultValue) {
|
|
3128
|
+
return Math.max(1, value?.length ?? defaultValue?.length ?? 1);
|
|
3129
|
+
}
|
|
3130
|
+
function hasAccessibleName(value) {
|
|
3131
|
+
return value !== void 0 && value.trim() !== "";
|
|
3132
|
+
}
|
|
3133
|
+
var Slider = React12.forwardRef(
|
|
3134
|
+
({
|
|
3135
|
+
className,
|
|
3136
|
+
value,
|
|
3137
|
+
defaultValue,
|
|
3138
|
+
thumbs,
|
|
3139
|
+
orientation = "horizontal",
|
|
3140
|
+
"aria-label": ariaLabel,
|
|
3141
|
+
"aria-labelledby": ariaLabelledBy,
|
|
3142
|
+
...props
|
|
3143
|
+
}, ref) => {
|
|
3144
|
+
const initialUncontrolledCount = React12.useRef(
|
|
3145
|
+
thumbCount(void 0, defaultValue)
|
|
3146
|
+
).current;
|
|
3147
|
+
const count = value?.length ?? initialUncontrolledCount;
|
|
3148
|
+
const isEmptyDefault = defaultValue !== void 0 && defaultValue.length === 0;
|
|
3149
|
+
const isEmptyControlled = value !== void 0 && value.length === 0;
|
|
3150
|
+
devWarnOnce(
|
|
3151
|
+
!isEmptyDefault && !isEmptyControlled,
|
|
3152
|
+
"Slider: `value`/`defaultValue` must hold one number per thumb, and an empty array holds none \u2014 the control has nothing to slide. An empty `defaultValue` falls back to `min`; an empty `value` renders nothing at all, because a controlled slider cannot be given a value without taking state the caller owns. Render nothing until the value is loaded rather than passing `[]`."
|
|
3153
|
+
);
|
|
3154
|
+
if (isEmptyControlled) return null;
|
|
3155
|
+
const isNamed = (index) => {
|
|
3156
|
+
const own = thumbs?.[index];
|
|
3157
|
+
if (hasAccessibleName(own?.["aria-label"])) return true;
|
|
3158
|
+
if (hasAccessibleName(own?.["aria-labelledby"])) return true;
|
|
3159
|
+
return count === 1 && (hasAccessibleName(ariaLabel) || hasAccessibleName(ariaLabelledBy));
|
|
3160
|
+
};
|
|
3161
|
+
devWarnOnce(
|
|
3162
|
+
Array.from({ length: count }).every((_, i) => isNamed(i)),
|
|
3163
|
+
"Slider: every thumb needs an accessible name. A single thumb may take it from the root's `aria-label`/`aria-labelledby`; a range needs one `thumbs` entry per thumb, because the root's name is not inherited and two thumbs sharing one name are announced identically."
|
|
3164
|
+
);
|
|
3165
|
+
const ariaFor = (index) => {
|
|
3166
|
+
const supplied = thumbs?.[index] ?? {};
|
|
3167
|
+
const ownLabel = hasAccessibleName(supplied["aria-label"]) ? supplied["aria-label"] : void 0;
|
|
3168
|
+
const ownLabelledBy = hasAccessibleName(supplied["aria-labelledby"]) ? supplied["aria-labelledby"] : void 0;
|
|
3169
|
+
if (count !== 1) {
|
|
3170
|
+
return {
|
|
3171
|
+
...supplied,
|
|
3172
|
+
"aria-label": ownLabel,
|
|
3173
|
+
"aria-labelledby": ownLabelledBy
|
|
3174
|
+
};
|
|
2063
3175
|
}
|
|
2064
|
-
|
|
2065
|
-
|
|
3176
|
+
const namesItself = ownLabel !== void 0 || ownLabelledBy !== void 0;
|
|
3177
|
+
return {
|
|
3178
|
+
"aria-label": namesItself ? ownLabel : ariaLabel,
|
|
3179
|
+
"aria-labelledby": namesItself ? ownLabelledBy : ariaLabelledBy,
|
|
3180
|
+
"aria-valuetext": supplied["aria-valuetext"],
|
|
3181
|
+
"aria-describedby": supplied["aria-describedby"]
|
|
3182
|
+
};
|
|
3183
|
+
};
|
|
3184
|
+
const isVertical = orientation === "vertical";
|
|
3185
|
+
return (
|
|
3186
|
+
// `aria-label`/`aria-labelledby` are destructured out above rather than
|
|
3187
|
+
// spread here: left on the root they would be a second, roleless copy
|
|
3188
|
+
// of a name only the thumb is read for.
|
|
3189
|
+
/* @__PURE__ */ jsxs17(
|
|
3190
|
+
SliderPrimitive.Root,
|
|
2066
3191
|
{
|
|
2067
|
-
|
|
3192
|
+
ref,
|
|
2068
3193
|
className: cn(
|
|
2069
|
-
|
|
2070
|
-
|
|
3194
|
+
"relative flex touch-none select-none items-center",
|
|
3195
|
+
// WCAG 2.5.8 wants a 24px target. Padding alone does not reach it: the
|
|
3196
|
+
// thumb is absolutely positioned, so the cross-axis size is the 6px
|
|
3197
|
+
// track plus the padding — 22px with `py-2`. An explicit minimum
|
|
3198
|
+
// states the target rather than leaving it to arithmetic that moves
|
|
3199
|
+
// whenever the track thickness does.
|
|
3200
|
+
isVertical ? (
|
|
3201
|
+
// A vertical slider needs a LENGTH, and it cannot inherit one:
|
|
3202
|
+
// `h-full` inside an auto-height parent resolves to zero, leaving
|
|
3203
|
+
// a control with no track to drag along. A concrete default is
|
|
3204
|
+
// usable everywhere and, being a plain utility, is replaced by a
|
|
3205
|
+
// caller's own `h-*` — including `h-full`, for the fill-the-parent
|
|
3206
|
+
// case this default gives up.
|
|
3207
|
+
"h-44 min-w-6 flex-col px-2"
|
|
3208
|
+
) : "min-h-6 w-full py-2",
|
|
3209
|
+
"data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
|
3210
|
+
className
|
|
2071
3211
|
),
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
"aria-label": onRowClick ? `View details for ${primaryValue}` : void 0,
|
|
3212
|
+
orientation,
|
|
3213
|
+
value,
|
|
3214
|
+
defaultValue: isEmptyDefault ? void 0 : defaultValue,
|
|
3215
|
+
...props,
|
|
2077
3216
|
children: [
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
"div",
|
|
2081
|
-
{
|
|
2082
|
-
className: "flex items-start justify-between gap-4 text-sm",
|
|
2083
|
-
children: [
|
|
2084
|
-
!column.hideLabelOnMobile && /* @__PURE__ */ jsxs("dt", { className: "text-muted-foreground min-w-[80px] shrink-0", children: [
|
|
2085
|
-
column.label,
|
|
2086
|
-
":"
|
|
2087
|
-
] }),
|
|
2088
|
-
/* @__PURE__ */ jsx(
|
|
2089
|
-
"dd",
|
|
2090
|
-
{
|
|
2091
|
-
className: cn(
|
|
2092
|
-
"font-medium flex-1",
|
|
2093
|
-
!column.hideLabelOnMobile ? "text-right" : "text-left"
|
|
2094
|
-
),
|
|
2095
|
-
children: column.render ? column.render(item[column.key], item) : String(item[column.key])
|
|
2096
|
-
}
|
|
2097
|
-
)
|
|
2098
|
-
]
|
|
2099
|
-
},
|
|
2100
|
-
String(column.key)
|
|
2101
|
-
)) }) })
|
|
2102
|
-
]
|
|
2103
|
-
},
|
|
2104
|
-
item.id
|
|
2105
|
-
);
|
|
2106
|
-
}) }),
|
|
2107
|
-
/* @__PURE__ */ jsx(
|
|
2108
|
-
"div",
|
|
2109
|
-
{
|
|
2110
|
-
className: cn(
|
|
2111
|
-
"table-wrapper hidden md:block overflow-hidden rounded-none border border-primary/5",
|
|
2112
|
-
tableWrapperClassName
|
|
2113
|
-
),
|
|
2114
|
-
children: /* @__PURE__ */ jsxs(Table, { "aria-label": ariaLabel || "Data table", children: [
|
|
2115
|
-
/* @__PURE__ */ jsx(TableHeader, { className: "bg-[hsl(var(--table-header-bg))]", children: /* @__PURE__ */ jsx(TableRow, { children: columns.map((column) => /* @__PURE__ */ jsx(
|
|
2116
|
-
TableHead,
|
|
2117
|
-
{
|
|
2118
|
-
className: column.headerClassName,
|
|
2119
|
-
children: column.label
|
|
2120
|
-
},
|
|
2121
|
-
String(column.key)
|
|
2122
|
-
)) }) }),
|
|
2123
|
-
/* @__PURE__ */ jsx(TableBody, { children: data.map((item) => {
|
|
2124
|
-
const primaryValue = primaryColumn ? String(item[primaryColumn.key]) : String(item.id);
|
|
2125
|
-
return /* @__PURE__ */ jsx(
|
|
2126
|
-
TableRow,
|
|
3217
|
+
/* @__PURE__ */ jsx38(
|
|
3218
|
+
SliderPrimitive.Track,
|
|
2127
3219
|
{
|
|
2128
3220
|
className: cn(
|
|
2129
|
-
"
|
|
2130
|
-
|
|
3221
|
+
"bg-secondary relative grow overflow-hidden rounded-full",
|
|
3222
|
+
isVertical ? "h-full w-1.5" : "h-1.5 w-full"
|
|
2131
3223
|
),
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
tabIndex: onRowClick ? 0 : void 0,
|
|
2135
|
-
onKeyDown: onRowClick ? handleCardKeyDown(item) : void 0,
|
|
2136
|
-
"aria-label": onRowClick ? `View details for ${primaryValue}` : void 0,
|
|
2137
|
-
children: columns.map((column) => /* @__PURE__ */ jsx(
|
|
2138
|
-
TableCell,
|
|
3224
|
+
children: /* @__PURE__ */ jsx38(
|
|
3225
|
+
SliderPrimitive.Range,
|
|
2139
3226
|
{
|
|
2140
|
-
className:
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
3227
|
+
className: cn(
|
|
3228
|
+
"bg-primary absolute",
|
|
3229
|
+
isVertical ? "w-full" : "h-full"
|
|
3230
|
+
)
|
|
3231
|
+
}
|
|
3232
|
+
)
|
|
3233
|
+
}
|
|
3234
|
+
),
|
|
3235
|
+
Array.from({ length: count }, (_, i) => /* @__PURE__ */ jsx38(
|
|
3236
|
+
SliderPrimitive.Thumb,
|
|
3237
|
+
{
|
|
3238
|
+
...ariaFor(i),
|
|
3239
|
+
className: cn(
|
|
3240
|
+
"border-primary bg-background block h-4 w-4 rounded-full border-2",
|
|
3241
|
+
"ring-offset-background transition-colors",
|
|
3242
|
+
"focus-visible:ring-ring focus-visible:outline-none focus-visible:ring-2",
|
|
3243
|
+
"focus-visible:ring-offset-2",
|
|
3244
|
+
"disabled:pointer-events-none disabled:opacity-50"
|
|
3245
|
+
)
|
|
2145
3246
|
},
|
|
2146
|
-
|
|
2147
|
-
)
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
)
|
|
2152
|
-
|
|
2153
|
-
|
|
3247
|
+
i
|
|
3248
|
+
))
|
|
3249
|
+
]
|
|
3250
|
+
}
|
|
3251
|
+
)
|
|
3252
|
+
);
|
|
3253
|
+
}
|
|
3254
|
+
);
|
|
3255
|
+
Slider.displayName = SliderPrimitive.Root.displayName;
|
|
3256
|
+
|
|
3257
|
+
// src/lib/shortcuts/react.tsx
|
|
3258
|
+
import * as React13 from "react";
|
|
3259
|
+
|
|
3260
|
+
// src/lib/shortcuts/key-spec.ts
|
|
3261
|
+
function normalizeKey(key) {
|
|
3262
|
+
return [...key].length === 1 ? key.toLowerCase() : key;
|
|
3263
|
+
}
|
|
3264
|
+
function shiftIsMeaningful(key) {
|
|
3265
|
+
if (key.length > 1) return true;
|
|
3266
|
+
if (key === " ") return true;
|
|
3267
|
+
return /[\p{L}\p{N}]/u.test(key);
|
|
3268
|
+
}
|
|
3269
|
+
function parseKeys(spec) {
|
|
3270
|
+
const steps = spec.trim().split(/\s+/).filter(Boolean);
|
|
3271
|
+
if (steps.length === 0) {
|
|
3272
|
+
throw new Error(`Shortcut spec is empty: ${JSON.stringify(spec)}`);
|
|
3273
|
+
}
|
|
3274
|
+
return steps.map((step) => parseChord(step, spec));
|
|
3275
|
+
}
|
|
3276
|
+
function parseChord(step, spec) {
|
|
3277
|
+
const trailingPlusIsKey = step.length > 2 && step.endsWith("++");
|
|
3278
|
+
const body = trailingPlusIsKey ? step.slice(0, -1) : step;
|
|
3279
|
+
const parts = step === "+" ? ["+"] : body.split("+").filter(Boolean);
|
|
3280
|
+
let mod = false;
|
|
3281
|
+
let ctrl = false;
|
|
3282
|
+
let meta = false;
|
|
3283
|
+
let alt = false;
|
|
3284
|
+
let shift = false;
|
|
3285
|
+
let key;
|
|
3286
|
+
for (const raw of parts) {
|
|
3287
|
+
switch (raw.toLowerCase()) {
|
|
3288
|
+
case "mod":
|
|
3289
|
+
mod = true;
|
|
3290
|
+
break;
|
|
3291
|
+
case "ctrl":
|
|
3292
|
+
case "control":
|
|
3293
|
+
ctrl = true;
|
|
3294
|
+
break;
|
|
3295
|
+
case "meta":
|
|
3296
|
+
case "cmd":
|
|
3297
|
+
case "command":
|
|
3298
|
+
meta = true;
|
|
3299
|
+
break;
|
|
3300
|
+
case "alt":
|
|
3301
|
+
case "option":
|
|
3302
|
+
alt = true;
|
|
3303
|
+
break;
|
|
3304
|
+
case "shift":
|
|
3305
|
+
shift = true;
|
|
3306
|
+
break;
|
|
3307
|
+
case "space":
|
|
3308
|
+
key = " ";
|
|
3309
|
+
break;
|
|
3310
|
+
default:
|
|
3311
|
+
if (key !== void 0) {
|
|
3312
|
+
throw new Error(
|
|
3313
|
+
`Shortcut step "${step}" names two keys ("${key}" and "${raw}") in ${JSON.stringify(spec)}`
|
|
3314
|
+
);
|
|
3315
|
+
}
|
|
3316
|
+
key = raw;
|
|
3317
|
+
}
|
|
3318
|
+
}
|
|
3319
|
+
if (trailingPlusIsKey) {
|
|
3320
|
+
if (key !== void 0) {
|
|
3321
|
+
throw new Error(
|
|
3322
|
+
`Shortcut step has more than one key: ${JSON.stringify(step)} in ${JSON.stringify(spec)}`
|
|
3323
|
+
);
|
|
3324
|
+
}
|
|
3325
|
+
key = "+";
|
|
3326
|
+
}
|
|
3327
|
+
if (key === void 0) {
|
|
3328
|
+
throw new Error(
|
|
3329
|
+
`Shortcut step "${step}" names modifiers but no key, in ${JSON.stringify(spec)}`
|
|
3330
|
+
);
|
|
3331
|
+
}
|
|
3332
|
+
return { key: normalizeKey(key), mod, ctrl, meta, alt, shift };
|
|
3333
|
+
}
|
|
3334
|
+
function chordMatches(chord, key, state, isApple) {
|
|
3335
|
+
if (normalizeKey(key) !== chord.key) return false;
|
|
3336
|
+
const wantsCtrl = chord.ctrl || chord.mod && !isApple;
|
|
3337
|
+
const wantsMeta = chord.meta || chord.mod && isApple;
|
|
3338
|
+
if (state.metaKey !== wantsMeta) return false;
|
|
3339
|
+
const altGraph = state.getModifierState?.("AltGraph") ?? false;
|
|
3340
|
+
const synthetic = altGraph && [...chord.key].length === 1 && !wantsCtrl && !chord.alt;
|
|
3341
|
+
if (!synthetic) {
|
|
3342
|
+
if (state.ctrlKey !== wantsCtrl) return false;
|
|
3343
|
+
if (state.altKey !== chord.alt) return false;
|
|
3344
|
+
}
|
|
3345
|
+
if (shiftIsMeaningful(chord.key) && state.shiftKey !== chord.shift)
|
|
3346
|
+
return false;
|
|
3347
|
+
return true;
|
|
3348
|
+
}
|
|
3349
|
+
function detectApplePlatform() {
|
|
3350
|
+
if (typeof navigator === "undefined") return false;
|
|
3351
|
+
const candidate = navigator;
|
|
3352
|
+
const platform = candidate.userAgentData?.platform ?? navigator.platform ?? "";
|
|
3353
|
+
return /mac|iphone|ipad|ipod/i.test(platform);
|
|
2154
3354
|
}
|
|
2155
|
-
var ResponsiveTable = React5.forwardRef(ResponsiveTableInner);
|
|
2156
3355
|
|
|
2157
|
-
// src/
|
|
2158
|
-
var
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
3356
|
+
// src/lib/shortcuts/manager.ts
|
|
3357
|
+
var DEFAULT_SEQUENCE_TIMEOUT_MS = 1e3;
|
|
3358
|
+
function signature(event) {
|
|
3359
|
+
return event.code || event.key;
|
|
3360
|
+
}
|
|
3361
|
+
function eventTarget(event) {
|
|
3362
|
+
const path = event.composedPath?.();
|
|
3363
|
+
return path && path.length > 0 ? path[0] ?? null : event.target;
|
|
3364
|
+
}
|
|
3365
|
+
function asElement(target) {
|
|
3366
|
+
if (target === null || typeof target !== "object") return null;
|
|
3367
|
+
const node = target;
|
|
3368
|
+
if (node.nodeType !== 1 || typeof node.tagName !== "string") return null;
|
|
3369
|
+
return target;
|
|
3370
|
+
}
|
|
3371
|
+
function inputType(element) {
|
|
3372
|
+
if (element.tagName !== "INPUT") return "";
|
|
3373
|
+
const value = element.type;
|
|
3374
|
+
return typeof value === "string" ? value.toLowerCase() : "";
|
|
3375
|
+
}
|
|
3376
|
+
function controlOwnsKey(target, event) {
|
|
3377
|
+
if (event.ctrlKey || event.metaKey || event.altKey) return false;
|
|
3378
|
+
const element = asElement(target);
|
|
3379
|
+
if (!element) return false;
|
|
3380
|
+
const tag = element.tagName;
|
|
3381
|
+
const type = inputType(element);
|
|
3382
|
+
if (tag === "BUTTON" || type === "button" || type === "submit" || type === "reset" || type === "image") {
|
|
3383
|
+
return event.key === " " || event.key === "Enter";
|
|
3384
|
+
}
|
|
3385
|
+
if (tag === "A" && element.getAttribute("href") !== null) {
|
|
3386
|
+
return event.key === "Enter";
|
|
3387
|
+
}
|
|
3388
|
+
if (tag === "SUMMARY") return event.key === " " || event.key === "Enter";
|
|
3389
|
+
if (type === "checkbox") return event.key === " ";
|
|
3390
|
+
if (type === "color") return event.key === " " || event.key === "Enter";
|
|
3391
|
+
if (type === "file") return event.key === " " || event.key === "Enter";
|
|
3392
|
+
if (type === "range") {
|
|
3393
|
+
return event.key.startsWith("Arrow") || RANGE_KEYS.has(event.key);
|
|
3394
|
+
}
|
|
3395
|
+
if (type === "radio") {
|
|
3396
|
+
return event.key === " " || event.key.startsWith("Arrow");
|
|
3397
|
+
}
|
|
3398
|
+
return false;
|
|
3399
|
+
}
|
|
3400
|
+
function isTypingTarget(target) {
|
|
3401
|
+
const element = asElement(target);
|
|
3402
|
+
if (!element) return false;
|
|
3403
|
+
if (element.isContentEditable) return true;
|
|
3404
|
+
const tag = element.tagName;
|
|
3405
|
+
if (tag === "TEXTAREA") return true;
|
|
3406
|
+
if (tag === "SELECT") return true;
|
|
3407
|
+
if (tag === "INPUT") {
|
|
3408
|
+
return !NON_TEXT_INPUT_TYPES.has(inputType(element));
|
|
3409
|
+
}
|
|
3410
|
+
const role = element.getAttribute("role");
|
|
3411
|
+
return role !== null && TYPE_AHEAD_ROLES.has(role);
|
|
3412
|
+
}
|
|
3413
|
+
var NON_TEXT_INPUT_TYPES = /* @__PURE__ */ new Set([
|
|
3414
|
+
"button",
|
|
3415
|
+
"checkbox",
|
|
3416
|
+
"color",
|
|
3417
|
+
"file",
|
|
3418
|
+
"hidden",
|
|
3419
|
+
"image",
|
|
3420
|
+
"radio",
|
|
3421
|
+
"range",
|
|
3422
|
+
"reset",
|
|
3423
|
+
"submit"
|
|
3424
|
+
]);
|
|
3425
|
+
function firesWhileTyping(prepared) {
|
|
3426
|
+
const explicit = prepared.binding.whenTyping;
|
|
3427
|
+
if (explicit !== void 0) return explicit;
|
|
3428
|
+
const first = prepared.keys[0];
|
|
3429
|
+
if (first === void 0) return false;
|
|
3430
|
+
return first.mod || first.ctrl || first.meta || first.alt || first.key === "Escape";
|
|
3431
|
+
}
|
|
3432
|
+
function createShortcutManager(options = {}) {
|
|
3433
|
+
const isApple = options.isApple ?? detectApplePlatform();
|
|
3434
|
+
const sequenceTimeoutMs = options.sequenceTimeoutMs ?? DEFAULT_SEQUENCE_TIMEOUT_MS;
|
|
3435
|
+
const now = options.now ?? (() => Date.now());
|
|
3436
|
+
const layers = /* @__PURE__ */ new Set();
|
|
3437
|
+
let nextSequence = 0;
|
|
3438
|
+
let pendingAt = null;
|
|
3439
|
+
let pendingLayer = null;
|
|
3440
|
+
const consumedPresses = /* @__PURE__ */ new Map();
|
|
3441
|
+
let pendingKey = null;
|
|
3442
|
+
function layerShape(bindings, options2) {
|
|
3443
|
+
const keys = bindings.map((b) => b.binding.keys).join("\0");
|
|
3444
|
+
return `${keys}${options2.depth}${options2.priority ?? 0}${options2.blocking === true}${options2.enabled !== false}`;
|
|
3445
|
+
}
|
|
3446
|
+
function blocking() {
|
|
3447
|
+
return ordered().some((layer) => layer.options.blocking === true);
|
|
3448
|
+
}
|
|
3449
|
+
function abandonSequence() {
|
|
3450
|
+
pendingAt = null;
|
|
3451
|
+
pressedEvents.length = 0;
|
|
3452
|
+
pendingLayer = null;
|
|
3453
|
+
pendingKey = null;
|
|
3454
|
+
}
|
|
3455
|
+
function prepare(bindings) {
|
|
3456
|
+
return bindings.map((binding) => ({
|
|
3457
|
+
binding,
|
|
3458
|
+
keys: parseKeys(binding.keys)
|
|
3459
|
+
}));
|
|
3460
|
+
}
|
|
3461
|
+
function ordered() {
|
|
3462
|
+
return [...layers].filter((layer) => layer.options.enabled !== false).sort(
|
|
3463
|
+
(a, b) => (b.options.priority ?? 0) - (a.options.priority ?? 0) || b.options.depth - a.options.depth || b.sequence - a.sequence
|
|
3464
|
+
);
|
|
3465
|
+
}
|
|
3466
|
+
function matchDepth(prepared, pressed) {
|
|
3467
|
+
if (pressed.length > prepared.keys.length) return "none";
|
|
3468
|
+
for (let i = 0; i < pressed.length; i++) {
|
|
3469
|
+
const chord = prepared.keys[i];
|
|
3470
|
+
const event = pressed[i];
|
|
3471
|
+
if (chord === void 0 || event === void 0) return "none";
|
|
3472
|
+
if (!chordMatches(chord, event.key, event, isApple)) return "none";
|
|
3473
|
+
}
|
|
3474
|
+
return pressed.length === prepared.keys.length ? "exact" : "prefix";
|
|
3475
|
+
}
|
|
3476
|
+
function fire(prepared, event, invoke) {
|
|
3477
|
+
if (prepared.binding.preventDefault !== false) event.preventDefault();
|
|
3478
|
+
if (invoke) prepared.binding.run(event);
|
|
3479
|
+
}
|
|
3480
|
+
function insertsText(event, typing) {
|
|
3481
|
+
if (event.key === "Tab")
|
|
3482
|
+
return !event.ctrlKey && !event.metaKey && !event.altKey;
|
|
3483
|
+
if (!typing) return false;
|
|
3484
|
+
const altGraph = event.getModifierState?.("AltGraph") ?? false;
|
|
3485
|
+
if (!altGraph && (event.ctrlKey || event.metaKey)) {
|
|
3486
|
+
const letter = event.key.length === 1 ? event.key.toLowerCase() : event.key;
|
|
3487
|
+
if (letter === "z" && event.shiftKey) return !event.altKey;
|
|
3488
|
+
if (letter === REDO_LETTER)
|
|
3489
|
+
return !isApple && !event.shiftKey && !event.altKey;
|
|
3490
|
+
if (EDITING_NAVIGATION.has(event.key)) return !event.altKey || isApple;
|
|
3491
|
+
if (event.shiftKey || event.altKey) return false;
|
|
3492
|
+
return EDITING_LETTERS.has(letter);
|
|
3493
|
+
}
|
|
3494
|
+
if (!altGraph && event.altKey) {
|
|
3495
|
+
if ((event.key === "ArrowDown" || event.key === "ArrowUp") && asElement(eventTarget(event))?.tagName === "SELECT") {
|
|
3496
|
+
return true;
|
|
3497
|
+
}
|
|
3498
|
+
if (!isApple) return false;
|
|
3499
|
+
if (EDITING_NAVIGATION.has(event.key)) return true;
|
|
3500
|
+
}
|
|
3501
|
+
if (event.key === "Dead" || event.key === "Process") return true;
|
|
3502
|
+
if ([...event.key].length === 1) return true;
|
|
3503
|
+
if (AMBIGUOUS_KEYS.has(event.key)) return targetOwnsAmbiguousKey(event);
|
|
3504
|
+
return FIELD_KEYS.has(event.key);
|
|
3505
|
+
}
|
|
3506
|
+
function offer(pressed, event, typing, invoke) {
|
|
3507
|
+
for (const layer of ordered()) {
|
|
3508
|
+
const mayMatch = pressed.length <= 1 || pendingLayer === null || layer === pendingLayer;
|
|
3509
|
+
if (mayMatch) {
|
|
3510
|
+
let prefixed = false;
|
|
3511
|
+
for (const prepared of layer.bindings) {
|
|
3512
|
+
if (typing && !firesWhileTyping(prepared)) continue;
|
|
3513
|
+
if (prepared.binding.when && !prepared.binding.when()) continue;
|
|
3514
|
+
const depth = matchDepth(prepared, pressed);
|
|
3515
|
+
if (depth === "exact") {
|
|
3516
|
+
fire(prepared, event, invoke);
|
|
3517
|
+
return "fired";
|
|
3518
|
+
}
|
|
3519
|
+
if (depth === "prefix") prefixed = true;
|
|
2202
3520
|
}
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
}
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
3521
|
+
if (prefixed) {
|
|
3522
|
+
pendingLayer = layer;
|
|
3523
|
+
event.preventDefault();
|
|
3524
|
+
return "pending";
|
|
3525
|
+
}
|
|
3526
|
+
}
|
|
3527
|
+
if (layer.options.blocking) return "blocked";
|
|
3528
|
+
}
|
|
3529
|
+
return "none";
|
|
3530
|
+
}
|
|
3531
|
+
function warnOnPrefixConflicts(prepared, layerName) {
|
|
3532
|
+
const resolved = (chord) => {
|
|
3533
|
+
const ctrl = chord.ctrl || chord.mod && !isApple;
|
|
3534
|
+
const meta = chord.meta || chord.mod && isApple;
|
|
3535
|
+
const shift = shiftIsMeaningful(chord.key) ? chord.shift : false;
|
|
3536
|
+
return `${chord.key}\0${ctrl}${meta}${chord.alt}${shift}`;
|
|
3537
|
+
};
|
|
3538
|
+
const sameChord = (a, b) => resolved(a) === resolved(b);
|
|
3539
|
+
for (const short of prepared) {
|
|
3540
|
+
for (const long of prepared) {
|
|
3541
|
+
if (short === long || short.keys.length >= long.keys.length) continue;
|
|
3542
|
+
if (short.binding.when !== void 0) continue;
|
|
3543
|
+
if (!firesWhileTyping(short) && firesWhileTyping(long)) continue;
|
|
3544
|
+
if (short.keys.every((chord, i) => sameChord(chord, long.keys[i]))) {
|
|
3545
|
+
devWarnOnce(
|
|
3546
|
+
false,
|
|
3547
|
+
`shortcuts: in layer "${layerName}", "${short.binding.keys}" is a prefix of "${long.binding.keys}", so the longer one can never fire. Bind one or the other.`
|
|
3548
|
+
);
|
|
3549
|
+
}
|
|
3550
|
+
}
|
|
3551
|
+
}
|
|
3552
|
+
}
|
|
3553
|
+
const watchers = /* @__PURE__ */ new Set();
|
|
3554
|
+
let snapshot = null;
|
|
3555
|
+
function computeSnapshot() {
|
|
3556
|
+
return ordered().flatMap(
|
|
3557
|
+
(layer) => layer.bindings.map((prepared) => ({
|
|
3558
|
+
keys: prepared.binding.keys,
|
|
3559
|
+
description: prepared.binding.description,
|
|
3560
|
+
layer: layer.options.name
|
|
3561
|
+
}))
|
|
3562
|
+
);
|
|
3563
|
+
}
|
|
3564
|
+
function sameShortcuts(a, b) {
|
|
3565
|
+
return a.length === b.length && a.every(
|
|
3566
|
+
(entry, index) => entry.keys === b[index]?.keys && entry.description === b[index]?.description && entry.layer === b[index]?.layer
|
|
3567
|
+
);
|
|
3568
|
+
}
|
|
3569
|
+
function changed() {
|
|
3570
|
+
const previous = snapshot;
|
|
3571
|
+
snapshot = null;
|
|
3572
|
+
if (watchers.size === 0) return;
|
|
3573
|
+
const next = computeSnapshot();
|
|
3574
|
+
if (previous && sameShortcuts(previous, next)) {
|
|
3575
|
+
snapshot = previous;
|
|
3576
|
+
return;
|
|
3577
|
+
}
|
|
3578
|
+
snapshot = next;
|
|
3579
|
+
for (const watcher of watchers) watcher();
|
|
3580
|
+
}
|
|
3581
|
+
const pressedEvents = [];
|
|
3582
|
+
function runOffer(pressed, event, typing) {
|
|
3583
|
+
try {
|
|
3584
|
+
return offer(pressed, event, typing, true);
|
|
3585
|
+
} catch (error) {
|
|
3586
|
+
abandonSequence();
|
|
3587
|
+
consumedPresses.delete(signature(event));
|
|
3588
|
+
throw error;
|
|
3589
|
+
}
|
|
3590
|
+
}
|
|
3591
|
+
function handle(event) {
|
|
3592
|
+
if (typeof event.key !== "string") return false;
|
|
3593
|
+
if (event.defaultPrevented) {
|
|
3594
|
+
abandonSequence();
|
|
3595
|
+
return true;
|
|
3596
|
+
}
|
|
3597
|
+
if (event.isComposing) {
|
|
3598
|
+
abandonSequence();
|
|
3599
|
+
return true;
|
|
3600
|
+
}
|
|
3601
|
+
if (MODIFIER_KEYS.has(event.key)) return blocking();
|
|
3602
|
+
if (controlOwnsKey(eventTarget(event), event)) {
|
|
3603
|
+
abandonSequence();
|
|
3604
|
+
return true;
|
|
3605
|
+
}
|
|
3606
|
+
const typing = isTypingTarget(eventTarget(event));
|
|
3607
|
+
if (event.repeat) {
|
|
3608
|
+
if (pendingKey !== signature(event)) {
|
|
3609
|
+
abandonSequence();
|
|
3610
|
+
}
|
|
3611
|
+
const held = consumedPresses.get(signature(event));
|
|
3612
|
+
if (held) {
|
|
3613
|
+
if (held.prevented) {
|
|
3614
|
+
event.preventDefault();
|
|
3615
|
+
} else {
|
|
3616
|
+
const still = offer([event], event, typing, false);
|
|
3617
|
+
if (still !== "fired" && !insertsText(event, typing)) {
|
|
3618
|
+
event.preventDefault();
|
|
3619
|
+
}
|
|
3620
|
+
}
|
|
3621
|
+
return true;
|
|
3622
|
+
}
|
|
3623
|
+
const repeated = offer([event], event, typing, false);
|
|
3624
|
+
if (repeated === "blocked" && !insertsText(event, typing)) {
|
|
3625
|
+
event.preventDefault();
|
|
3626
|
+
}
|
|
3627
|
+
return repeated !== "none";
|
|
3628
|
+
}
|
|
3629
|
+
if (pendingAt !== null && now() - pendingAt > sequenceTimeoutMs) {
|
|
3630
|
+
abandonSequence();
|
|
3631
|
+
}
|
|
3632
|
+
pressedEvents.push(event);
|
|
3633
|
+
let outcome = runOffer(pressedEvents, event, typing);
|
|
3634
|
+
if (pressedEvents.length > 1 && (outcome === "none" || outcome === "blocked")) {
|
|
3635
|
+
abandonSequence();
|
|
3636
|
+
pressedEvents.push(event);
|
|
3637
|
+
outcome = runOffer(pressedEvents, event, typing);
|
|
3638
|
+
}
|
|
3639
|
+
if (outcome === "pending") {
|
|
3640
|
+
pendingAt = now();
|
|
3641
|
+
pendingKey = signature(event);
|
|
3642
|
+
consumedPresses.set(signature(event), {
|
|
3643
|
+
prevented: event.defaultPrevented
|
|
3644
|
+
});
|
|
3645
|
+
return true;
|
|
3646
|
+
}
|
|
3647
|
+
abandonSequence();
|
|
3648
|
+
if (outcome === "blocked") {
|
|
3649
|
+
if (!insertsText(event, typing)) event.preventDefault();
|
|
3650
|
+
}
|
|
3651
|
+
const consumed = outcome === "fired" || outcome === "blocked";
|
|
3652
|
+
if (consumed) {
|
|
3653
|
+
consumedPresses.set(signature(event), {
|
|
3654
|
+
prevented: event.defaultPrevented
|
|
3655
|
+
});
|
|
3656
|
+
} else {
|
|
3657
|
+
consumedPresses.delete(signature(event));
|
|
3658
|
+
}
|
|
3659
|
+
return consumed;
|
|
3660
|
+
}
|
|
3661
|
+
return {
|
|
3662
|
+
register(bindings, layerOptions) {
|
|
3663
|
+
const prepared = prepare(bindings);
|
|
3664
|
+
const layer = {
|
|
3665
|
+
options: layerOptions,
|
|
3666
|
+
bindings: prepared,
|
|
3667
|
+
sequence: nextSequence++,
|
|
3668
|
+
shape: layerShape(prepared, layerOptions)
|
|
3669
|
+
};
|
|
3670
|
+
warnOnPrefixConflicts(layer.bindings, layerOptions.name);
|
|
3671
|
+
layers.add(layer);
|
|
3672
|
+
changed();
|
|
3673
|
+
return {
|
|
3674
|
+
update(nextBindings, nextOptions) {
|
|
3675
|
+
layer.bindings = prepare(nextBindings);
|
|
3676
|
+
layer.options = nextOptions;
|
|
3677
|
+
warnOnPrefixConflicts(layer.bindings, nextOptions.name);
|
|
3678
|
+
const shape = layerShape(layer.bindings, nextOptions);
|
|
3679
|
+
const shapeChanged = shape !== layer.shape;
|
|
3680
|
+
layer.shape = shape;
|
|
3681
|
+
if (shapeChanged && pendingLayer === layer) abandonSequence();
|
|
3682
|
+
changed();
|
|
2213
3683
|
},
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
3684
|
+
dispose() {
|
|
3685
|
+
layers.delete(layer);
|
|
3686
|
+
changed();
|
|
3687
|
+
if (pendingLayer === layer) abandonSequence();
|
|
2217
3688
|
}
|
|
2218
|
-
}
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
3689
|
+
};
|
|
3690
|
+
},
|
|
3691
|
+
handle,
|
|
3692
|
+
attach(target) {
|
|
3693
|
+
const listener = (event) => {
|
|
3694
|
+
try {
|
|
3695
|
+
if (handle(event)) event.stopPropagation();
|
|
3696
|
+
} catch (error) {
|
|
3697
|
+
event.stopPropagation();
|
|
3698
|
+
throw error;
|
|
3699
|
+
}
|
|
3700
|
+
};
|
|
3701
|
+
target.addEventListener("keydown", listener);
|
|
3702
|
+
return () => {
|
|
3703
|
+
target.removeEventListener("keydown", listener);
|
|
3704
|
+
abandonSequence();
|
|
3705
|
+
consumedPresses.clear();
|
|
3706
|
+
};
|
|
3707
|
+
},
|
|
3708
|
+
subscribe(onChange) {
|
|
3709
|
+
watchers.add(onChange);
|
|
3710
|
+
return () => {
|
|
3711
|
+
watchers.delete(onChange);
|
|
3712
|
+
};
|
|
3713
|
+
},
|
|
3714
|
+
activeBindings() {
|
|
3715
|
+
if (snapshot) return snapshot;
|
|
3716
|
+
snapshot = computeSnapshot();
|
|
3717
|
+
return snapshot;
|
|
3718
|
+
}
|
|
3719
|
+
};
|
|
3720
|
+
}
|
|
3721
|
+
var MODIFIER_KEYS = /* @__PURE__ */ new Set([
|
|
3722
|
+
"Control",
|
|
3723
|
+
"Meta",
|
|
3724
|
+
"Alt",
|
|
3725
|
+
"Shift",
|
|
3726
|
+
// A dedicated AltGraph key reports its own keydown before the character-producing one. Without
|
|
3727
|
+
// it here, pressing AltGraph mid-sequence abandons the sequence before the character that would
|
|
3728
|
+
// have completed it ever arrives.
|
|
3729
|
+
"AltGraph"
|
|
3730
|
+
]);
|
|
3731
|
+
var TYPE_AHEAD_ROLES = /* @__PURE__ */ new Set([
|
|
3732
|
+
"textbox",
|
|
3733
|
+
"combobox",
|
|
3734
|
+
"listbox",
|
|
3735
|
+
// The focused element inside an open listbox is the OPTION, and it is what the event reports;
|
|
3736
|
+
// the listbox itself is only its ancestor.
|
|
3737
|
+
"option",
|
|
3738
|
+
"menu",
|
|
3739
|
+
"menuitem",
|
|
3740
|
+
"menuitemcheckbox",
|
|
3741
|
+
"menuitemradio"
|
|
3742
|
+
]);
|
|
3743
|
+
var RANGE_KEYS = /* @__PURE__ */ new Set(["Home", "End", "PageUp", "PageDown"]);
|
|
3744
|
+
var EDITING_LETTERS = /* @__PURE__ */ new Set(["a", "c", "v", "x", "z"]);
|
|
3745
|
+
var REDO_LETTER = "y";
|
|
3746
|
+
var EDITING_NAVIGATION = /* @__PURE__ */ new Set([
|
|
3747
|
+
"Insert",
|
|
3748
|
+
"ArrowLeft",
|
|
3749
|
+
"ArrowRight",
|
|
3750
|
+
"ArrowUp",
|
|
3751
|
+
"ArrowDown",
|
|
3752
|
+
"Home",
|
|
3753
|
+
"End",
|
|
3754
|
+
"Backspace",
|
|
3755
|
+
"Delete"
|
|
3756
|
+
]);
|
|
3757
|
+
var AMBIGUOUS_KEYS = /* @__PURE__ */ new Set(["Enter", "PageUp", "PageDown"]);
|
|
3758
|
+
function targetOwnsAmbiguousKey(event) {
|
|
3759
|
+
const element = asElement(eventTarget(event));
|
|
3760
|
+
if (element === null) return false;
|
|
3761
|
+
const multiline = element.tagName === "TEXTAREA" || element.isContentEditable;
|
|
3762
|
+
if (event.key === "Enter") return multiline;
|
|
3763
|
+
return multiline || element.tagName === "SELECT";
|
|
3764
|
+
}
|
|
3765
|
+
var FIELD_KEYS = /* @__PURE__ */ new Set([
|
|
3766
|
+
"Backspace",
|
|
3767
|
+
"Delete",
|
|
3768
|
+
"ArrowUp",
|
|
3769
|
+
"ArrowDown",
|
|
3770
|
+
"ArrowLeft",
|
|
3771
|
+
"ArrowRight",
|
|
3772
|
+
"Home",
|
|
3773
|
+
"End",
|
|
3774
|
+
// Shift+Insert pastes and carries no ctrl or meta, so it arrives here rather than at the
|
|
3775
|
+
// chord branch where Ctrl+Insert is recognised.
|
|
3776
|
+
"Insert",
|
|
3777
|
+
// Tab moves focus, and a blocking layer must NOT take it. The documented case for blocking is
|
|
3778
|
+
// a modal, whose focus trap only calls `preventDefault()` at the first and last tabbable
|
|
3779
|
+
// element — ordinary moves between the controls inside it rely on the browser default.
|
|
3780
|
+
// Suppressing every Tab therefore pinned focus to one control in exactly the situation
|
|
3781
|
+
// blocking exists to serve. A layer that genuinely wants Tab binds it.
|
|
3782
|
+
"Tab"
|
|
3783
|
+
]);
|
|
3784
|
+
|
|
3785
|
+
// src/lib/shortcuts/react.tsx
|
|
3786
|
+
import { jsx as jsx39 } from "react/jsx-runtime";
|
|
3787
|
+
var ShortcutContext = React13.createContext(null);
|
|
3788
|
+
var ownersByTarget = /* @__PURE__ */ new WeakMap();
|
|
3789
|
+
var useIsomorphicLayoutEffect = typeof document === "undefined" ? React13.useEffect : React13.useLayoutEffect;
|
|
3790
|
+
function optionsFingerprint(options) {
|
|
3791
|
+
return [
|
|
3792
|
+
options.isApple ?? "auto",
|
|
3793
|
+
options.sequenceTimeoutMs ?? "default",
|
|
3794
|
+
options.now ? "clock" : "no-clock"
|
|
3795
|
+
].join("\0");
|
|
3796
|
+
}
|
|
3797
|
+
function ShortcutProvider({
|
|
3798
|
+
children,
|
|
3799
|
+
target,
|
|
3800
|
+
...managerOptions
|
|
3801
|
+
}) {
|
|
3802
|
+
const parent = React13.useContext(ShortcutContext);
|
|
3803
|
+
const resolvedTarget = target === null ? null : target ?? (typeof document === "undefined" ? null : document);
|
|
3804
|
+
const nestedOnSameTarget = parent !== null && parent.target === resolvedTarget;
|
|
3805
|
+
const optionsRef = React13.useRef(managerOptions);
|
|
3806
|
+
const ownManagers = React13.useRef(/* @__PURE__ */ new WeakMap());
|
|
3807
|
+
const ownDetached = React13.useRef(null);
|
|
3808
|
+
const detached = React13.useMemo(() => {
|
|
3809
|
+
if (resolvedTarget === null) {
|
|
3810
|
+
ownDetached.current ??= createShortcutManager(optionsRef.current);
|
|
3811
|
+
return ownDetached.current;
|
|
3812
|
+
}
|
|
3813
|
+
const existing = ownManagers.current.get(resolvedTarget);
|
|
3814
|
+
if (existing) return existing;
|
|
3815
|
+
const created = createShortcutManager(optionsRef.current);
|
|
3816
|
+
ownManagers.current.set(resolvedTarget, created);
|
|
3817
|
+
return created;
|
|
3818
|
+
}, [resolvedTarget]);
|
|
3819
|
+
let owner = resolvedTarget === null ? null : ownersByTarget.get(resolvedTarget);
|
|
3820
|
+
const fingerprint = optionsFingerprint(optionsRef.current);
|
|
3821
|
+
if (resolvedTarget !== null && (!owner || owner.retired)) {
|
|
3822
|
+
owner = {
|
|
3823
|
+
manager: detached,
|
|
3824
|
+
providers: 0,
|
|
3825
|
+
retired: false,
|
|
3826
|
+
options: fingerprint
|
|
3827
|
+
};
|
|
3828
|
+
ownersByTarget.set(resolvedTarget, owner);
|
|
3829
|
+
}
|
|
3830
|
+
const adoptedDiffers = Boolean(owner) && owner?.options !== fingerprint || nestedOnSameTarget && parent !== null && parent.options !== fingerprint;
|
|
3831
|
+
devWarnOnce(
|
|
3832
|
+
!adoptedDiffers,
|
|
3833
|
+
"ShortcutProvider: another provider is already listening on this target with different options, so the ones passed here are being ignored. Managers are shared per target; give the providers matching options, or a target of their own."
|
|
3834
|
+
);
|
|
3835
|
+
const manager = nestedOnSameTarget && parent ? parent.manager : owner ? owner.manager : detached;
|
|
3836
|
+
useIsomorphicLayoutEffect(() => {
|
|
3837
|
+
if (resolvedTarget === null) return;
|
|
3838
|
+
let entry = ownersByTarget.get(resolvedTarget);
|
|
3839
|
+
if (!entry) {
|
|
3840
|
+
entry = {
|
|
3841
|
+
manager,
|
|
3842
|
+
providers: 0,
|
|
3843
|
+
retired: false,
|
|
3844
|
+
options: optionsFingerprint(optionsRef.current)
|
|
3845
|
+
};
|
|
3846
|
+
ownersByTarget.set(resolvedTarget, entry);
|
|
3847
|
+
}
|
|
3848
|
+
const owned = entry;
|
|
3849
|
+
owned.providers += 1;
|
|
3850
|
+
owned.retired = false;
|
|
3851
|
+
if (owned.providers === 1) {
|
|
3852
|
+
owned.detach = owned.manager.attach(resolvedTarget);
|
|
3853
|
+
}
|
|
3854
|
+
return () => {
|
|
3855
|
+
owned.providers -= 1;
|
|
3856
|
+
if (owned.providers === 0) {
|
|
3857
|
+
owned.detach?.();
|
|
3858
|
+
owned.detach = void 0;
|
|
3859
|
+
owned.retired = true;
|
|
2222
3860
|
}
|
|
3861
|
+
};
|
|
3862
|
+
}, [resolvedTarget, manager]);
|
|
3863
|
+
const depth = nestedOnSameTarget && parent ? parent.depth : 0;
|
|
3864
|
+
const value = React13.useMemo(
|
|
3865
|
+
() => ({ manager, depth, target: resolvedTarget, options: fingerprint }),
|
|
3866
|
+
[manager, depth, resolvedTarget, fingerprint]
|
|
3867
|
+
);
|
|
3868
|
+
return /* @__PURE__ */ jsx39(ShortcutContext.Provider, { value, children });
|
|
3869
|
+
}
|
|
3870
|
+
function ShortcutScope({
|
|
3871
|
+
children
|
|
3872
|
+
}) {
|
|
3873
|
+
const parent = React13.useContext(ShortcutContext);
|
|
3874
|
+
if (!parent) {
|
|
3875
|
+
throw new Error("ShortcutScope must be rendered inside a ShortcutProvider");
|
|
3876
|
+
}
|
|
3877
|
+
const value = React13.useMemo(
|
|
3878
|
+
() => ({
|
|
3879
|
+
manager: parent.manager,
|
|
3880
|
+
depth: parent.depth + 1,
|
|
3881
|
+
target: parent.target,
|
|
3882
|
+
// Inherited: a scope raises precedence, it does not build a manager, so the options in force
|
|
3883
|
+
// are still the ones the provider above it used.
|
|
3884
|
+
options: parent.options
|
|
3885
|
+
}),
|
|
3886
|
+
[parent.manager, parent.depth, parent.target, parent.options]
|
|
3887
|
+
);
|
|
3888
|
+
return /* @__PURE__ */ jsx39(ShortcutContext.Provider, { value, children });
|
|
3889
|
+
}
|
|
3890
|
+
function useShortcuts(bindings, options) {
|
|
3891
|
+
const context = React13.useContext(ShortcutContext);
|
|
3892
|
+
if (!context) {
|
|
3893
|
+
throw new Error("useShortcuts must be called inside a ShortcutProvider");
|
|
3894
|
+
}
|
|
3895
|
+
const { manager, depth } = context;
|
|
3896
|
+
const registration = React13.useRef(null);
|
|
3897
|
+
const latest = React13.useRef({ bindings, options });
|
|
3898
|
+
useIsomorphicLayoutEffect(() => {
|
|
3899
|
+
registration.current = manager.register([], {
|
|
3900
|
+
name: latest.current.options.name,
|
|
3901
|
+
depth
|
|
3902
|
+
});
|
|
3903
|
+
return () => {
|
|
3904
|
+
registration.current?.dispose();
|
|
3905
|
+
registration.current = null;
|
|
3906
|
+
};
|
|
3907
|
+
}, [manager, depth]);
|
|
3908
|
+
useIsomorphicLayoutEffect(() => {
|
|
3909
|
+
latest.current = { bindings, options };
|
|
3910
|
+
registration.current?.update(bindings, {
|
|
3911
|
+
name: options.name,
|
|
3912
|
+
depth,
|
|
3913
|
+
enabled: options.enabled,
|
|
3914
|
+
blocking: options.blocking,
|
|
3915
|
+
priority: options.priority
|
|
3916
|
+
});
|
|
3917
|
+
});
|
|
3918
|
+
}
|
|
3919
|
+
function useShortcutManager() {
|
|
3920
|
+
const context = React13.useContext(ShortcutContext);
|
|
3921
|
+
if (!context) {
|
|
3922
|
+
throw new Error(
|
|
3923
|
+
"useShortcutManager must be called inside a ShortcutProvider"
|
|
3924
|
+
);
|
|
3925
|
+
}
|
|
3926
|
+
return context.manager;
|
|
3927
|
+
}
|
|
3928
|
+
function useActiveShortcuts() {
|
|
3929
|
+
const manager = useShortcutManager();
|
|
3930
|
+
return React13.useSyncExternalStore(
|
|
3931
|
+
manager.subscribe,
|
|
3932
|
+
manager.activeBindings,
|
|
3933
|
+
manager.activeBindings
|
|
3934
|
+
);
|
|
3935
|
+
}
|
|
3936
|
+
|
|
3937
|
+
// src/components/field-shell.tsx
|
|
3938
|
+
import { cva as cva13 } from "class-variance-authority";
|
|
3939
|
+
import { cloneElement, Fragment as Fragment3, useEffect as useEffect3, useId as useId2 } from "react";
|
|
3940
|
+
import { jsx as jsx40, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
3941
|
+
var controlWidth = cva13("w-full", {
|
|
3942
|
+
variants: {
|
|
3943
|
+
width: {
|
|
3944
|
+
half: "max-w-[var(--nx-field-half,380px)]",
|
|
3945
|
+
full: "max-w-[var(--nx-field-full,760px)]",
|
|
3946
|
+
fill: ""
|
|
2223
3947
|
}
|
|
3948
|
+
},
|
|
3949
|
+
defaultVariants: { width: "half" }
|
|
3950
|
+
});
|
|
3951
|
+
function readControlProps(child) {
|
|
3952
|
+
const props = child.props;
|
|
3953
|
+
return props && typeof props === "object" ? props : {};
|
|
3954
|
+
}
|
|
3955
|
+
function isRenderFunction(children) {
|
|
3956
|
+
return typeof children === "function";
|
|
3957
|
+
}
|
|
3958
|
+
function computeControlWiring(ownProps, requestedId, renderedMessageIds, hasError) {
|
|
3959
|
+
const ownId = typeof ownProps.id === "string" && ownProps.id !== "" ? ownProps.id : void 0;
|
|
3960
|
+
const id = ownId ?? requestedId;
|
|
3961
|
+
const ownDescribedByIds = typeof ownProps["aria-describedby"] === "string" ? ownProps["aria-describedby"].split(" ").filter(Boolean) : [];
|
|
3962
|
+
const describedByIds = Array.from(
|
|
3963
|
+
/* @__PURE__ */ new Set([...ownDescribedByIds, ...renderedMessageIds])
|
|
3964
|
+
);
|
|
3965
|
+
const describedBy = describedByIds.length > 0 ? describedByIds.join(" ") : void 0;
|
|
3966
|
+
const ownInvalid = typeof ownProps["aria-invalid"] === "boolean" ? ownProps["aria-invalid"] : void 0;
|
|
3967
|
+
const invalid = hasError ? true : ownInvalid;
|
|
3968
|
+
return { id, describedBy, invalid };
|
|
3969
|
+
}
|
|
3970
|
+
function FieldShell({
|
|
3971
|
+
label,
|
|
3972
|
+
description,
|
|
3973
|
+
error,
|
|
3974
|
+
width = "half",
|
|
3975
|
+
htmlFor,
|
|
3976
|
+
className,
|
|
3977
|
+
children
|
|
3978
|
+
}) {
|
|
3979
|
+
const generatedControlId = useId2();
|
|
3980
|
+
const messageBaseId = useId2();
|
|
3981
|
+
const descriptionId = `${messageBaseId}-description`;
|
|
3982
|
+
const errorId = `${messageBaseId}-error`;
|
|
3983
|
+
const requestedId = htmlFor ?? generatedControlId;
|
|
3984
|
+
const renderedMessageIds = [
|
|
3985
|
+
description ? descriptionId : null,
|
|
3986
|
+
error ? errorId : null
|
|
3987
|
+
].filter((id) => id !== null);
|
|
3988
|
+
const wiring = isRenderFunction(children) ? computeControlWiring({}, requestedId, renderedMessageIds, Boolean(error)) : computeControlWiring(
|
|
3989
|
+
readControlProps(children),
|
|
3990
|
+
requestedId,
|
|
3991
|
+
renderedMessageIds,
|
|
3992
|
+
Boolean(error)
|
|
3993
|
+
);
|
|
3994
|
+
const isFragmentChild = !isRenderFunction(children) && children.type === Fragment3;
|
|
3995
|
+
useEffect3(() => {
|
|
3996
|
+
if (!isDevelopmentRuntime()) return;
|
|
3997
|
+
if (isFragmentChild) return;
|
|
3998
|
+
const landed = document.getElementById(wiring.id) !== null;
|
|
3999
|
+
const fieldName = typeof label === "string" ? `"${label}"` : "this field";
|
|
4000
|
+
devWarnOnce(
|
|
4001
|
+
landed,
|
|
4002
|
+
`FieldShell: the id computed for ${fieldName} never appeared on any element in the document, so its label and any description are not connected to the control. This happens when the control is a compound component \u2014 a Radix \`Select\`, \`RadioGroup\`, or similar \u2014 whose root does not forward \`id\`/\`aria-describedby\`/\`aria-invalid\` to a real DOM node. Pass \`children\` as a function and apply those to the control's actual focusable element (its trigger) instead of a single top-level clone.`
|
|
4003
|
+
);
|
|
4004
|
+
}, [wiring.id, label, isFragmentChild]);
|
|
4005
|
+
let control;
|
|
4006
|
+
if (isRenderFunction(children)) {
|
|
4007
|
+
control = children(wiring);
|
|
4008
|
+
} else {
|
|
4009
|
+
devWarnOnce(
|
|
4010
|
+
!isFragmentChild,
|
|
4011
|
+
"FieldShell: `children` must be a single element, not a Fragment. A Fragment forwards no props to the elements inside it, so the id, aria-describedby and aria-invalid this component computes would have nowhere to land \u2014 the label and the control would look wired up and never actually connect. Wrap the intended elements in a real element instead, such as a `<div>`."
|
|
4012
|
+
);
|
|
4013
|
+
const controlOverrides = {
|
|
4014
|
+
id: wiring.id,
|
|
4015
|
+
...wiring.describedBy !== void 0 ? { "aria-describedby": wiring.describedBy } : {},
|
|
4016
|
+
...wiring.invalid !== void 0 ? { "aria-invalid": wiring.invalid } : {}
|
|
4017
|
+
};
|
|
4018
|
+
control = isFragmentChild ? children : cloneElement(children, controlOverrides);
|
|
2224
4019
|
}
|
|
2225
|
-
|
|
2226
|
-
|
|
4020
|
+
return /* @__PURE__ */ jsxs18("div", { className: cn("flex flex-col gap-1.5", className), children: [
|
|
4021
|
+
label ? /* @__PURE__ */ jsx40(
|
|
4022
|
+
"label",
|
|
4023
|
+
{
|
|
4024
|
+
htmlFor: wiring.id,
|
|
4025
|
+
className: "text-sm font-medium text-foreground",
|
|
4026
|
+
children: label
|
|
4027
|
+
}
|
|
4028
|
+
) : null,
|
|
4029
|
+
/* @__PURE__ */ jsx40("div", { className: controlWidth({ width }), children: control }),
|
|
4030
|
+
description ? /* @__PURE__ */ jsx40("p", { id: descriptionId, className: "text-sm text-muted-foreground", children: description }) : null,
|
|
4031
|
+
error ? /* @__PURE__ */ jsx40("p", { id: errorId, className: "text-sm font-medium text-destructive", children: error }) : null
|
|
4032
|
+
] });
|
|
4033
|
+
}
|
|
4034
|
+
|
|
4035
|
+
// src/components/form-section.tsx
|
|
4036
|
+
import { useId as useId3 } from "react";
|
|
4037
|
+
import { jsx as jsx41, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
4038
|
+
function FormSection({
|
|
4039
|
+
label,
|
|
4040
|
+
description,
|
|
4041
|
+
className,
|
|
4042
|
+
children
|
|
4043
|
+
}) {
|
|
4044
|
+
const labelId = useId3();
|
|
4045
|
+
return /* @__PURE__ */ jsxs19("section", { "aria-labelledby": labelId, className: cn("space-y-2", className), children: [
|
|
4046
|
+
/* @__PURE__ */ jsxs19("div", { className: "space-y-1", children: [
|
|
4047
|
+
/* @__PURE__ */ jsx41(
|
|
4048
|
+
"p",
|
|
4049
|
+
{
|
|
4050
|
+
id: labelId,
|
|
4051
|
+
className: "text-xs font-semibold tracking-[0.08em] uppercase text-muted-foreground",
|
|
4052
|
+
children: label
|
|
4053
|
+
}
|
|
4054
|
+
),
|
|
4055
|
+
description ? /* @__PURE__ */ jsx41("p", { className: "text-sm text-muted-foreground", children: description }) : null
|
|
4056
|
+
] }),
|
|
4057
|
+
/* @__PURE__ */ jsx41(Card, { className: "overflow-hidden", children: /* @__PURE__ */ jsx41("div", { className: "divide-y divide-foreground/10 px-6", children }) })
|
|
4058
|
+
] });
|
|
4059
|
+
}
|
|
2227
4060
|
|
|
2228
|
-
|
|
2229
|
-
|
|
4061
|
+
// src/components/form-layout.tsx
|
|
4062
|
+
import { cva as cva14 } from "class-variance-authority";
|
|
4063
|
+
import { jsx as jsx42, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
4064
|
+
var measure = cva14("mx-auto w-full px-6 py-8", {
|
|
4065
|
+
variants: {
|
|
4066
|
+
width: {
|
|
4067
|
+
form: "max-w-[56rem]",
|
|
4068
|
+
wide: "max-w-[72rem]"
|
|
4069
|
+
}
|
|
4070
|
+
},
|
|
4071
|
+
defaultVariants: { width: "form" }
|
|
4072
|
+
});
|
|
4073
|
+
function FormLayout({
|
|
4074
|
+
width = "form",
|
|
4075
|
+
className,
|
|
4076
|
+
children
|
|
4077
|
+
}) {
|
|
4078
|
+
return /* @__PURE__ */ jsx42("div", { className: cn(measure({ width }), className), children });
|
|
4079
|
+
}
|
|
4080
|
+
function FormActions({ dirty, className, children }) {
|
|
4081
|
+
return /* @__PURE__ */ jsxs20(
|
|
4082
|
+
"div",
|
|
4083
|
+
{
|
|
4084
|
+
className: cn(
|
|
4085
|
+
"sticky bottom-0 mt-8 flex items-center justify-end gap-3",
|
|
4086
|
+
"border-t border-border bg-background/95 py-4 backdrop-blur",
|
|
4087
|
+
className
|
|
4088
|
+
),
|
|
4089
|
+
children: [
|
|
4090
|
+
dirty ? (
|
|
4091
|
+
// `role="status"` (implying `aria-live="polite"`) so a screen-reader
|
|
4092
|
+
// user is told when the flag flips false to true, not only sighted
|
|
4093
|
+
// users watching the bar. This is the only live region FormActions
|
|
4094
|
+
// renders, one per form.
|
|
4095
|
+
/* @__PURE__ */ jsx42("span", { role: "status", className: "mr-auto text-sm text-muted-foreground", children: "You have unsaved changes" })
|
|
4096
|
+
) : null,
|
|
4097
|
+
children
|
|
4098
|
+
]
|
|
4099
|
+
}
|
|
4100
|
+
);
|
|
4101
|
+
}
|
|
4102
|
+
export {
|
|
4103
|
+
Accordion,
|
|
4104
|
+
AccordionContent,
|
|
4105
|
+
AccordionItem,
|
|
4106
|
+
AccordionTrigger,
|
|
4107
|
+
Alert,
|
|
4108
|
+
AlertDescription,
|
|
4109
|
+
AlertDialog,
|
|
4110
|
+
AlertDialogAction,
|
|
4111
|
+
AlertDialogCancel,
|
|
4112
|
+
AlertDialogContent,
|
|
4113
|
+
AlertDialogDescription,
|
|
4114
|
+
AlertDialogFooter,
|
|
4115
|
+
AlertDialogHeader,
|
|
4116
|
+
AlertDialogOverlay,
|
|
4117
|
+
AlertDialogPortal,
|
|
4118
|
+
AlertDialogTitle,
|
|
4119
|
+
AlertDialogTrigger,
|
|
4120
|
+
AlertTitle,
|
|
4121
|
+
Avatar,
|
|
4122
|
+
AvatarFallback,
|
|
4123
|
+
AvatarImage,
|
|
4124
|
+
Badge,
|
|
4125
|
+
Button,
|
|
4126
|
+
Card,
|
|
4127
|
+
CardAction,
|
|
4128
|
+
CardContent,
|
|
4129
|
+
CardDescription,
|
|
4130
|
+
CardFooter,
|
|
4131
|
+
CardHeader,
|
|
4132
|
+
CardTitle,
|
|
4133
|
+
Checkbox,
|
|
4134
|
+
Collapsible,
|
|
4135
|
+
CollapsibleContent2 as CollapsibleContent,
|
|
4136
|
+
CollapsibleTrigger2 as CollapsibleTrigger,
|
|
4137
|
+
ColorPicker,
|
|
4138
|
+
Command,
|
|
4139
|
+
CommandDialog,
|
|
4140
|
+
CommandEmpty,
|
|
4141
|
+
CommandGroup,
|
|
4142
|
+
CommandInput,
|
|
4143
|
+
CommandItem,
|
|
4144
|
+
CommandList,
|
|
4145
|
+
CommandSeparator,
|
|
4146
|
+
CommandShortcut,
|
|
4147
|
+
ContextMenu,
|
|
4148
|
+
ContextMenuCheckboxItem,
|
|
4149
|
+
ContextMenuContent,
|
|
4150
|
+
ContextMenuGroup,
|
|
4151
|
+
ContextMenuItem,
|
|
4152
|
+
ContextMenuLabel,
|
|
4153
|
+
ContextMenuRadioGroup,
|
|
4154
|
+
ContextMenuRadioItem,
|
|
4155
|
+
ContextMenuSeparator,
|
|
4156
|
+
ContextMenuShortcut,
|
|
4157
|
+
ContextMenuSub,
|
|
4158
|
+
ContextMenuSubContent,
|
|
4159
|
+
ContextMenuSubTrigger,
|
|
4160
|
+
ContextMenuTrigger,
|
|
4161
|
+
Dialog,
|
|
4162
|
+
DialogClose,
|
|
4163
|
+
DialogContent,
|
|
4164
|
+
DialogDescription,
|
|
4165
|
+
DialogFooter,
|
|
4166
|
+
DialogHeader,
|
|
4167
|
+
DialogOverlay,
|
|
4168
|
+
DialogPortal,
|
|
4169
|
+
DialogTitle,
|
|
4170
|
+
DialogTrigger,
|
|
4171
|
+
DropdownMenu,
|
|
4172
|
+
DropdownMenuCheckboxItem,
|
|
4173
|
+
DropdownMenuContent,
|
|
4174
|
+
DropdownMenuGroup,
|
|
4175
|
+
DropdownMenuItem,
|
|
4176
|
+
DropdownMenuLabel,
|
|
4177
|
+
DropdownMenuPortal,
|
|
4178
|
+
DropdownMenuRadioGroup,
|
|
4179
|
+
DropdownMenuRadioItem,
|
|
4180
|
+
DropdownMenuSeparator,
|
|
4181
|
+
DropdownMenuShortcut,
|
|
4182
|
+
DropdownMenuSub,
|
|
4183
|
+
DropdownMenuSubContent,
|
|
4184
|
+
DropdownMenuSubTrigger,
|
|
4185
|
+
DropdownMenuTrigger,
|
|
4186
|
+
FieldShell,
|
|
4187
|
+
FormActions,
|
|
4188
|
+
FormLabelWithTooltip,
|
|
4189
|
+
FormLayout,
|
|
4190
|
+
FormSection,
|
|
4191
|
+
Grid,
|
|
4192
|
+
Input,
|
|
4193
|
+
Label,
|
|
4194
|
+
Popover,
|
|
4195
|
+
PopoverAnchor,
|
|
4196
|
+
PopoverContent,
|
|
4197
|
+
PopoverTrigger,
|
|
4198
|
+
PortalProvider,
|
|
4199
|
+
Progress,
|
|
4200
|
+
RadioGroup,
|
|
4201
|
+
RadioGroupItem,
|
|
4202
|
+
ResizableHandle,
|
|
4203
|
+
ResizablePanel,
|
|
4204
|
+
ResizablePanelGroup,
|
|
4205
|
+
Select,
|
|
4206
|
+
SelectContent,
|
|
4207
|
+
SelectGroup,
|
|
4208
|
+
SelectItem,
|
|
4209
|
+
SelectLabel,
|
|
4210
|
+
SelectScrollDownButton,
|
|
4211
|
+
SelectScrollUpButton,
|
|
4212
|
+
SelectSeparator,
|
|
4213
|
+
SelectTrigger,
|
|
4214
|
+
SelectValue,
|
|
4215
|
+
Separator,
|
|
4216
|
+
Sheet,
|
|
4217
|
+
SheetClose,
|
|
4218
|
+
SheetContent,
|
|
4219
|
+
SheetDescription,
|
|
4220
|
+
SheetFooter,
|
|
4221
|
+
SheetHeader,
|
|
4222
|
+
SheetOverlay,
|
|
4223
|
+
SheetPortal,
|
|
4224
|
+
SheetTitle,
|
|
4225
|
+
SheetTrigger,
|
|
4226
|
+
ShortcutProvider,
|
|
4227
|
+
ShortcutScope,
|
|
4228
|
+
Skeleton,
|
|
4229
|
+
Slider,
|
|
4230
|
+
Spinner,
|
|
4231
|
+
Stack,
|
|
4232
|
+
Stat,
|
|
4233
|
+
Switch,
|
|
4234
|
+
Table,
|
|
4235
|
+
TableBody,
|
|
4236
|
+
TableCaption,
|
|
4237
|
+
TableCell,
|
|
4238
|
+
TableEmpty,
|
|
4239
|
+
TableError,
|
|
4240
|
+
TableFooter,
|
|
4241
|
+
TableHead,
|
|
4242
|
+
TableHeader,
|
|
4243
|
+
TableLoading,
|
|
4244
|
+
TableRow,
|
|
4245
|
+
TableSearch,
|
|
4246
|
+
TableSkeleton,
|
|
4247
|
+
Tabs,
|
|
4248
|
+
TabsContent,
|
|
4249
|
+
TabsList,
|
|
4250
|
+
TabsTrigger,
|
|
4251
|
+
Textarea,
|
|
4252
|
+
Toaster,
|
|
4253
|
+
Tooltip,
|
|
4254
|
+
TooltipContent,
|
|
4255
|
+
TooltipProvider,
|
|
4256
|
+
TooltipTrigger,
|
|
4257
|
+
TreeView,
|
|
4258
|
+
alertVariants,
|
|
4259
|
+
avatarVariants,
|
|
4260
|
+
badgeVariants,
|
|
4261
|
+
buttonVariants,
|
|
4262
|
+
cardVariants,
|
|
4263
|
+
commandDefaultFilter,
|
|
4264
|
+
createShortcutManager,
|
|
4265
|
+
dialogContentVariants,
|
|
4266
|
+
inputVariants,
|
|
4267
|
+
parseKeys,
|
|
4268
|
+
progressVariants,
|
|
4269
|
+
selectTriggerVariants,
|
|
4270
|
+
sheetVariants,
|
|
4271
|
+
spinnerVariants,
|
|
4272
|
+
toast,
|
|
4273
|
+
useActiveShortcuts,
|
|
4274
|
+
usePortalContainer,
|
|
4275
|
+
useShortcutManager,
|
|
4276
|
+
useShortcuts
|
|
4277
|
+
};
|
|
2230
4278
|
//# sourceMappingURL=index.mjs.map
|