@ai-matrx/design-system 0.1.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +101 -0
- package/README.md +4 -2
- package/dist/index.cjs +1955 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +645 -0
- package/dist/index.d.ts +616 -1
- package/dist/index.js +1832 -16
- package/dist/index.js.map +1 -1
- package/package.json +21 -5
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,1955 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
"use strict";
|
|
3
|
+
var __create = Object.create;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __export = (target, all) => {
|
|
10
|
+
for (var name in all)
|
|
11
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
12
|
+
};
|
|
13
|
+
var __copyProps = (to, from, except, desc) => {
|
|
14
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
15
|
+
for (let key of __getOwnPropNames(from))
|
|
16
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
17
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
18
|
+
}
|
|
19
|
+
return to;
|
|
20
|
+
};
|
|
21
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
22
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
23
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
24
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
25
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
26
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
27
|
+
mod
|
|
28
|
+
));
|
|
29
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
30
|
+
|
|
31
|
+
// src/index.ts
|
|
32
|
+
var src_exports = {};
|
|
33
|
+
__export(src_exports, {
|
|
34
|
+
Badge: () => Badge,
|
|
35
|
+
BasicInput: () => BasicInput,
|
|
36
|
+
BottomSheet: () => BottomSheet,
|
|
37
|
+
BottomSheetBody: () => BottomSheetBody,
|
|
38
|
+
BottomSheetFooter: () => BottomSheetFooter,
|
|
39
|
+
BottomSheetHeader: () => BottomSheetHeader,
|
|
40
|
+
Button: () => Button,
|
|
41
|
+
Command: () => Command,
|
|
42
|
+
CommandDialog: () => CommandDialog,
|
|
43
|
+
CommandEmpty: () => CommandEmpty,
|
|
44
|
+
CommandGroup: () => CommandGroup,
|
|
45
|
+
CommandInput: () => CommandInput,
|
|
46
|
+
CommandItem: () => CommandItem,
|
|
47
|
+
CommandList: () => CommandList,
|
|
48
|
+
CommandSeparator: () => CommandSeparator,
|
|
49
|
+
CommandShortcut: () => CommandShortcut,
|
|
50
|
+
CreatablePicker: () => CreatablePicker,
|
|
51
|
+
DEFAULT_SCORE_THRESHOLDS: () => DEFAULT_SCORE_THRESHOLDS,
|
|
52
|
+
EditableLabel: () => EditableLabel,
|
|
53
|
+
EnterInput: () => EnterInput,
|
|
54
|
+
Input: () => Input,
|
|
55
|
+
InputWithPrefix: () => InputWithPrefix,
|
|
56
|
+
Label: () => Label,
|
|
57
|
+
OverflowToolbar: () => OverflowToolbar,
|
|
58
|
+
Popover: () => Popover,
|
|
59
|
+
PopoverAnchor: () => PopoverAnchor,
|
|
60
|
+
PopoverContent: () => PopoverContent,
|
|
61
|
+
PopoverTrigger: () => PopoverTrigger,
|
|
62
|
+
PortalContainerProvider: () => PortalContainerProvider,
|
|
63
|
+
RadixDialogModalProvider: () => RadixDialogModalProvider,
|
|
64
|
+
ScoreRing: () => ScoreRing,
|
|
65
|
+
SegmentedControl: () => SegmentedControl,
|
|
66
|
+
Select: () => Select,
|
|
67
|
+
SelectContent: () => SelectContent,
|
|
68
|
+
SelectGroup: () => SelectGroup,
|
|
69
|
+
SelectItem: () => SelectItem,
|
|
70
|
+
SelectLabel: () => SelectLabel,
|
|
71
|
+
SelectScrollDownButton: () => SelectScrollDownButton,
|
|
72
|
+
SelectScrollUpButton: () => SelectScrollUpButton,
|
|
73
|
+
SelectSeparator: () => SelectSeparator,
|
|
74
|
+
SelectTrigger: () => SelectTrigger,
|
|
75
|
+
SelectValue: () => SelectValue,
|
|
76
|
+
Separator: () => Separator2,
|
|
77
|
+
Sheet: () => Sheet,
|
|
78
|
+
SheetClose: () => SheetClose,
|
|
79
|
+
SheetContent: () => SheetContent,
|
|
80
|
+
SheetDescription: () => SheetDescription,
|
|
81
|
+
SheetFooter: () => SheetFooter,
|
|
82
|
+
SheetHeader: () => SheetHeader,
|
|
83
|
+
SheetOverlay: () => SheetOverlay,
|
|
84
|
+
SheetPortal: () => SheetPortal,
|
|
85
|
+
SheetTitle: () => SheetTitle,
|
|
86
|
+
SheetTrigger: () => SheetTrigger,
|
|
87
|
+
Skeleton: () => Skeleton,
|
|
88
|
+
TabbedBottomSheet: () => TabbedBottomSheet,
|
|
89
|
+
badgeVariants: () => badgeVariants,
|
|
90
|
+
buttonVariants: () => buttonVariants,
|
|
91
|
+
cn: () => cn,
|
|
92
|
+
scoreAccentBgClasses: () => scoreAccentBgClasses,
|
|
93
|
+
scoreRingColorClasses: () => scoreRingColorClasses,
|
|
94
|
+
selectTriggerVariants: () => selectTriggerVariants,
|
|
95
|
+
sheetVariants: () => sheetVariants,
|
|
96
|
+
usePortalContainer: () => usePortalContainer,
|
|
97
|
+
useRadixDialogModal: () => useRadixDialogModal,
|
|
98
|
+
useScrollFade: () => useScrollFade
|
|
99
|
+
});
|
|
100
|
+
module.exports = __toCommonJS(src_exports);
|
|
101
|
+
|
|
102
|
+
// src/badge.tsx
|
|
103
|
+
var import_class_variance_authority = require("class-variance-authority");
|
|
104
|
+
|
|
105
|
+
// src/cn.ts
|
|
106
|
+
var import_clsx = require("clsx");
|
|
107
|
+
var import_tailwind_merge = require("tailwind-merge");
|
|
108
|
+
function cn(...inputs) {
|
|
109
|
+
return (0, import_tailwind_merge.twMerge)((0, import_clsx.clsx)(inputs));
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// src/badge.tsx
|
|
113
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
114
|
+
var badgeVariants = (0, import_class_variance_authority.cva)(
|
|
115
|
+
"inline-flex items-center rounded-md border px-2 py-0.5 text-[11px] font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-0",
|
|
116
|
+
{
|
|
117
|
+
variants: {
|
|
118
|
+
variant: {
|
|
119
|
+
default: "border-transparent bg-primary/15 text-primary",
|
|
120
|
+
secondary: "border-transparent bg-secondary text-secondary-foreground",
|
|
121
|
+
destructive: "border-transparent bg-destructive/15 text-destructive",
|
|
122
|
+
outline: "border-border text-foreground",
|
|
123
|
+
success: "border-transparent bg-success/15 text-success",
|
|
124
|
+
warning: "border-transparent bg-warning/15 text-warning",
|
|
125
|
+
info: "border-blue-200 bg-blue-100 text-blue-800",
|
|
126
|
+
error: "border-transparent bg-red-500/15 text-red-700 dark:text-red-400",
|
|
127
|
+
neutral: "border-border bg-muted text-muted-foreground"
|
|
128
|
+
}
|
|
129
|
+
},
|
|
130
|
+
defaultVariants: {
|
|
131
|
+
variant: "default"
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
);
|
|
135
|
+
function Badge({ className, variant, ...props }) {
|
|
136
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: cn(badgeVariants({ variant }), className), ...props });
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// src/bottom-sheet.tsx
|
|
140
|
+
var import_react_visually_hidden = require("@radix-ui/react-visually-hidden");
|
|
141
|
+
var React2 = __toESM(require("react"), 1);
|
|
142
|
+
var import_vaul = require("vaul");
|
|
143
|
+
|
|
144
|
+
// src/icons.tsx
|
|
145
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
146
|
+
function lucideProps(props) {
|
|
147
|
+
return {
|
|
148
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
149
|
+
viewBox: "0 0 24 24",
|
|
150
|
+
fill: "none",
|
|
151
|
+
stroke: "currentColor",
|
|
152
|
+
strokeWidth: 2,
|
|
153
|
+
strokeLinecap: "round",
|
|
154
|
+
strokeLinejoin: "round",
|
|
155
|
+
"aria-hidden": true,
|
|
156
|
+
...props
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
function Loader2Icon(props) {
|
|
160
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { ...lucideProps(props), children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M21 12a9 9 0 1 1-6.219-8.56" }) });
|
|
161
|
+
}
|
|
162
|
+
function ChevronLeftIcon(props) {
|
|
163
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { ...lucideProps(props), children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "m15 18-6-6 6-6" }) });
|
|
164
|
+
}
|
|
165
|
+
function ChevronRightIcon(props) {
|
|
166
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { ...lucideProps(props), children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "m9 18 6-6-6-6" }) });
|
|
167
|
+
}
|
|
168
|
+
function MoreHorizontalIcon(props) {
|
|
169
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { ...lucideProps(props), children: [
|
|
170
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: "12", cy: "12", r: "1" }),
|
|
171
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: "19", cy: "12", r: "1" }),
|
|
172
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: "5", cy: "12", r: "1" })
|
|
173
|
+
] });
|
|
174
|
+
}
|
|
175
|
+
function LucideCheckIcon(props) {
|
|
176
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { ...lucideProps(props), children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M20 6 9 17l-5-5" }) });
|
|
177
|
+
}
|
|
178
|
+
function ChevronsUpDownIcon(props) {
|
|
179
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { ...lucideProps(props), children: [
|
|
180
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "m7 15 5 5 5-5" }),
|
|
181
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "m7 9 5-5 5 5" })
|
|
182
|
+
] });
|
|
183
|
+
}
|
|
184
|
+
function ExternalLinkIcon(props) {
|
|
185
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { ...lucideProps(props), children: [
|
|
186
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M15 3h6v6" }),
|
|
187
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M10 14 21 3" }),
|
|
188
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" })
|
|
189
|
+
] });
|
|
190
|
+
}
|
|
191
|
+
function LockIcon(props) {
|
|
192
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { ...lucideProps(props), children: [
|
|
193
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("rect", { width: "18", height: "11", x: "3", y: "11", rx: "2", ry: "2" }),
|
|
194
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M7 11V7a5 5 0 0 1 10 0v4" })
|
|
195
|
+
] });
|
|
196
|
+
}
|
|
197
|
+
function PlusIcon(props) {
|
|
198
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { ...lucideProps(props), children: [
|
|
199
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M5 12h14" }),
|
|
200
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M12 5v14" })
|
|
201
|
+
] });
|
|
202
|
+
}
|
|
203
|
+
function XIcon(props) {
|
|
204
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { ...lucideProps(props), children: [
|
|
205
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M18 6 6 18" }),
|
|
206
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "m6 6 12 12" })
|
|
207
|
+
] });
|
|
208
|
+
}
|
|
209
|
+
function radixProps(props) {
|
|
210
|
+
return {
|
|
211
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
212
|
+
viewBox: "0 0 15 15",
|
|
213
|
+
width: 15,
|
|
214
|
+
height: 15,
|
|
215
|
+
fill: "none",
|
|
216
|
+
"aria-hidden": true,
|
|
217
|
+
...props
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
function MagnifyingGlassIcon(props) {
|
|
221
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { ...radixProps(props), children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
222
|
+
"path",
|
|
223
|
+
{
|
|
224
|
+
d: "M10 6.5C10 8.433 8.433 10 6.5 10C4.567 10 3 8.433 3 6.5C3 4.567 4.567 3 6.5 3C8.433 3 10 4.567 10 6.5ZM9.30884 10.0159C8.53901 10.6318 7.56251 11 6.5 11C4.01472 11 2 8.98528 2 6.5C2 4.01472 4.01472 2 6.5 2C8.98528 2 11 4.01472 11 6.5C11 7.56251 10.6318 8.53901 10.0159 9.30884L12.8536 12.1464C13.0488 12.3417 13.0488 12.6583 12.8536 12.8536C12.6583 13.0488 12.3417 13.0488 12.1464 12.8536L9.30884 10.0159Z",
|
|
225
|
+
fill: "currentColor",
|
|
226
|
+
fillRule: "evenodd",
|
|
227
|
+
clipRule: "evenodd"
|
|
228
|
+
}
|
|
229
|
+
) });
|
|
230
|
+
}
|
|
231
|
+
function CheckIcon(props) {
|
|
232
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { ...radixProps(props), children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
233
|
+
"path",
|
|
234
|
+
{
|
|
235
|
+
d: "M11.4669 3.72684C11.7558 3.91574 11.8369 4.30308 11.648 4.59198L7.39799 11.092C7.29783 11.2452 7.13556 11.3467 6.95402 11.3699C6.77247 11.3931 6.58989 11.3355 6.45446 11.2124L3.70446 8.71241C3.44905 8.48022 3.43023 8.08494 3.66242 7.82953C3.89461 7.57412 4.28989 7.55529 4.5453 7.78749L6.75292 9.79441L10.6018 3.90792C10.7907 3.61902 11.178 3.53795 11.4669 3.72684Z",
|
|
236
|
+
fill: "currentColor",
|
|
237
|
+
fillRule: "evenodd",
|
|
238
|
+
clipRule: "evenodd"
|
|
239
|
+
}
|
|
240
|
+
) });
|
|
241
|
+
}
|
|
242
|
+
function RadixChevronDownIcon(props) {
|
|
243
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { ...radixProps(props), children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
244
|
+
"path",
|
|
245
|
+
{
|
|
246
|
+
d: "M3.13523 6.15803C3.3241 5.95657 3.64052 5.94637 3.84197 6.13523L7.5 9.56464L11.158 6.13523C11.3595 5.94637 11.6759 5.95657 11.8648 6.15803C12.0536 6.35949 12.0434 6.67591 11.842 6.86477L7.84197 10.6148C7.64964 10.7951 7.35036 10.7951 7.15803 10.6148L3.15803 6.86477C2.95657 6.67591 2.94637 6.35949 3.13523 6.15803Z",
|
|
247
|
+
fill: "currentColor",
|
|
248
|
+
fillRule: "evenodd",
|
|
249
|
+
clipRule: "evenodd"
|
|
250
|
+
}
|
|
251
|
+
) });
|
|
252
|
+
}
|
|
253
|
+
function RadixChevronUpIcon(props) {
|
|
254
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { ...radixProps(props), children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
255
|
+
"path",
|
|
256
|
+
{
|
|
257
|
+
d: "M3.13523 8.84197C3.3241 9.04343 3.64052 9.05363 3.84197 8.86477L7.5 5.43536L11.158 8.86477C11.3595 9.05363 11.6759 9.04343 11.8648 8.84197C12.0536 8.64051 12.0434 8.32409 11.842 8.13523L7.84197 4.38523C7.64964 4.20492 7.35036 4.20492 7.15803 4.38523L3.15803 8.13523C2.95657 8.32409 2.94637 8.64051 3.13523 8.84197Z",
|
|
258
|
+
fill: "currentColor",
|
|
259
|
+
fillRule: "evenodd",
|
|
260
|
+
clipRule: "evenodd"
|
|
261
|
+
}
|
|
262
|
+
) });
|
|
263
|
+
}
|
|
264
|
+
function Cross2Icon(props) {
|
|
265
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
266
|
+
"svg",
|
|
267
|
+
{
|
|
268
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
269
|
+
viewBox: "0 0 15 15",
|
|
270
|
+
fill: "none",
|
|
271
|
+
"aria-hidden": true,
|
|
272
|
+
...props,
|
|
273
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
274
|
+
"path",
|
|
275
|
+
{
|
|
276
|
+
d: "M11.7816 4.03157C12.0062 3.80702 12.0062 3.44295 11.7816 3.2184C11.5571 2.99385 11.193 2.99385 10.9685 3.2184L7.50005 6.68682L4.03164 3.2184C3.80708 2.99385 3.44301 2.99385 3.21846 3.2184C2.99391 3.44295 2.99391 3.80702 3.21846 4.03157L6.68688 7.49999L3.21846 10.9684C2.99391 11.193 2.99391 11.557 3.21846 11.7816C3.44301 12.0061 3.80708 12.0061 4.03164 11.7816L7.50005 8.31316L10.9685 11.7816C11.193 12.0061 11.5571 12.0061 11.7816 11.7816C12.0062 11.557 12.0062 11.193 11.7816 10.9684L8.31322 7.49999L11.7816 4.03157Z",
|
|
277
|
+
fill: "currentColor",
|
|
278
|
+
fillRule: "evenodd",
|
|
279
|
+
clipRule: "evenodd"
|
|
280
|
+
}
|
|
281
|
+
)
|
|
282
|
+
}
|
|
283
|
+
);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// src/radix-dialog-modal-context.tsx
|
|
287
|
+
var React = __toESM(require("react"), 1);
|
|
288
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
289
|
+
var RadixDialogModalContext = React.createContext(true);
|
|
290
|
+
function RadixDialogModalProvider({
|
|
291
|
+
children,
|
|
292
|
+
modal
|
|
293
|
+
}) {
|
|
294
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(RadixDialogModalContext.Provider, { value: modal, children });
|
|
295
|
+
}
|
|
296
|
+
function useRadixDialogModal() {
|
|
297
|
+
return React.useContext(RadixDialogModalContext);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// src/bottom-sheet.tsx
|
|
301
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
302
|
+
var DrawerRoot = ({
|
|
303
|
+
children,
|
|
304
|
+
shouldScaleBackground = true,
|
|
305
|
+
...props
|
|
306
|
+
}) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(RadixDialogModalProvider, { modal: true, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
307
|
+
import_vaul.Drawer.Root,
|
|
308
|
+
{
|
|
309
|
+
modal: true,
|
|
310
|
+
shouldScaleBackground,
|
|
311
|
+
...props,
|
|
312
|
+
children
|
|
313
|
+
}
|
|
314
|
+
) });
|
|
315
|
+
DrawerRoot.displayName = "DrawerRoot";
|
|
316
|
+
var DrawerContentPrimitive = React2.forwardRef(({ ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_vaul.Drawer.Content, { ...props, ref, "aria-modal": "true" }));
|
|
317
|
+
DrawerContentPrimitive.displayName = "DrawerContentPrimitive";
|
|
318
|
+
function BottomSheet({
|
|
319
|
+
open,
|
|
320
|
+
onOpenChange,
|
|
321
|
+
title = "Bottom Sheet",
|
|
322
|
+
size = "adaptive",
|
|
323
|
+
surface = "glass",
|
|
324
|
+
contentClassName,
|
|
325
|
+
children
|
|
326
|
+
}) {
|
|
327
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(DrawerRoot, { open, onOpenChange, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_vaul.Drawer.Portal, { children: [
|
|
328
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
329
|
+
import_vaul.Drawer.Overlay,
|
|
330
|
+
{
|
|
331
|
+
className: cn("fixed inset-0 z-50 bg-black/80", "fixed inset-0 z-50"),
|
|
332
|
+
style: { background: "rgba(0, 0, 0, 0.08)" }
|
|
333
|
+
}
|
|
334
|
+
),
|
|
335
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
336
|
+
DrawerContentPrimitive,
|
|
337
|
+
{
|
|
338
|
+
className: cn(
|
|
339
|
+
"fixed inset-x-0 bottom-0 z-50 mt-24 flex flex-col rounded-t-2xl overflow-hidden",
|
|
340
|
+
size === "full" ? "h-[92dvh]" : "min-h-[60dvh] max-h-[90dvh]",
|
|
341
|
+
surface === "solid" && "border border-b-0 border-border bg-background shadow-2xl",
|
|
342
|
+
contentClassName
|
|
343
|
+
),
|
|
344
|
+
style: surface === "glass" ? {
|
|
345
|
+
background: "var(--matrx-glass-bg)",
|
|
346
|
+
backdropFilter: "blur(20px) saturate(180%)",
|
|
347
|
+
WebkitBackdropFilter: "blur(20px) saturate(180%)",
|
|
348
|
+
border: "1px solid var(--matrx-glass-border-color)",
|
|
349
|
+
borderBottom: "none"
|
|
350
|
+
} : void 0,
|
|
351
|
+
children: [
|
|
352
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react_visually_hidden.VisuallyHidden, { children: [
|
|
353
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_vaul.Drawer.Title, { children: title }),
|
|
354
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_vaul.Drawer.Description, { children: "Bottom sheet panel." })
|
|
355
|
+
] }),
|
|
356
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mx-auto mt-3 mb-1 h-1.5 w-10 rounded-full bg-muted-foreground/30 flex-shrink-0" }),
|
|
357
|
+
children
|
|
358
|
+
]
|
|
359
|
+
}
|
|
360
|
+
)
|
|
361
|
+
] }) });
|
|
362
|
+
}
|
|
363
|
+
function BottomSheetHeader({
|
|
364
|
+
title,
|
|
365
|
+
showBack = false,
|
|
366
|
+
onBack,
|
|
367
|
+
trailing
|
|
368
|
+
}) {
|
|
369
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex items-center px-2 pt-1 pb-2 flex-shrink-0 min-h-[44px]", children: [
|
|
370
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "min-w-[44px] flex items-center justify-start", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
371
|
+
"button",
|
|
372
|
+
{
|
|
373
|
+
onClick: onBack,
|
|
374
|
+
className: cn(
|
|
375
|
+
"h-8 w-8 rounded-full matrx-glass-thin-border flex items-center justify-center transition-all active:scale-95",
|
|
376
|
+
showBack ? "opacity-100" : "opacity-0 pointer-events-none"
|
|
377
|
+
),
|
|
378
|
+
"aria-hidden": !showBack,
|
|
379
|
+
tabIndex: showBack ? 0 : -1,
|
|
380
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ChevronLeftIcon, { className: "h-4 w-4 text-foreground" })
|
|
381
|
+
}
|
|
382
|
+
) }),
|
|
383
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "text-[17px] font-semibold flex-1 text-center truncate", children: title }),
|
|
384
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "min-w-[44px] flex items-center justify-end", children: trailing })
|
|
385
|
+
] });
|
|
386
|
+
}
|
|
387
|
+
function BottomSheetBody({ children, className }) {
|
|
388
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
389
|
+
"div",
|
|
390
|
+
{
|
|
391
|
+
className: cn(
|
|
392
|
+
// min-h-0 is load-bearing: without it a flex child's min-height:auto
|
|
393
|
+
// floors it at content height and the body grows instead of scrolling.
|
|
394
|
+
"min-h-0 flex-1 overflow-y-auto overscroll-contain pb-safe",
|
|
395
|
+
className
|
|
396
|
+
),
|
|
397
|
+
children
|
|
398
|
+
}
|
|
399
|
+
);
|
|
400
|
+
}
|
|
401
|
+
function BottomSheetFooter({
|
|
402
|
+
children,
|
|
403
|
+
className
|
|
404
|
+
}) {
|
|
405
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
406
|
+
"div",
|
|
407
|
+
{
|
|
408
|
+
className: cn(
|
|
409
|
+
"flex-shrink-0 px-4 py-3 pb-safe border-t border-white/[0.06]",
|
|
410
|
+
className
|
|
411
|
+
),
|
|
412
|
+
children
|
|
413
|
+
}
|
|
414
|
+
);
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
// src/button.tsx
|
|
418
|
+
var import_react_slot = require("@radix-ui/react-slot");
|
|
419
|
+
var import_class_variance_authority2 = require("class-variance-authority");
|
|
420
|
+
var React3 = __toESM(require("react"), 1);
|
|
421
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
422
|
+
var buttonVariants = (0, import_class_variance_authority2.cva)(
|
|
423
|
+
"inline-flex cursor-pointer items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-0 disabled:pointer-events-none disabled:opacity-50 active:scale-[0.98] [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
|
424
|
+
{
|
|
425
|
+
variants: {
|
|
426
|
+
variant: {
|
|
427
|
+
default: "bg-primary text-primary-foreground shadow-sm hover:bg-primary/90",
|
|
428
|
+
destructive: "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
|
|
429
|
+
outline: "border border-border bg-card shadow-sm hover:bg-accent hover:text-accent-foreground",
|
|
430
|
+
secondary: "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
|
|
431
|
+
ghost: "hover:bg-accent hover:text-accent-foreground",
|
|
432
|
+
link: "text-primary underline-offset-4 hover:underline",
|
|
433
|
+
subtle: "border border-transparent bg-muted/50 text-foreground hover:border-border hover:bg-muted"
|
|
434
|
+
},
|
|
435
|
+
size: {
|
|
436
|
+
default: "h-9 px-4 py-2",
|
|
437
|
+
sm: "h-8 rounded-md px-3 text-xs",
|
|
438
|
+
lg: "h-10 rounded-md px-6",
|
|
439
|
+
icon: "h-9 w-9",
|
|
440
|
+
"icon-sm": "h-7 w-7"
|
|
441
|
+
}
|
|
442
|
+
},
|
|
443
|
+
defaultVariants: {
|
|
444
|
+
variant: "default",
|
|
445
|
+
size: "default"
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
);
|
|
449
|
+
var Button = React3.forwardRef(
|
|
450
|
+
({ className, variant, size, asChild = false, ...props }, ref) => {
|
|
451
|
+
const Component = asChild ? import_react_slot.Slot : "button";
|
|
452
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
453
|
+
Component,
|
|
454
|
+
{
|
|
455
|
+
className: cn(buttonVariants({ variant, size, className })),
|
|
456
|
+
ref,
|
|
457
|
+
...props
|
|
458
|
+
}
|
|
459
|
+
);
|
|
460
|
+
}
|
|
461
|
+
);
|
|
462
|
+
Button.displayName = "Button";
|
|
463
|
+
|
|
464
|
+
// src/command.tsx
|
|
465
|
+
var DialogPrimitive = __toESM(require("@radix-ui/react-dialog"), 1);
|
|
466
|
+
var import_cmdk = require("cmdk");
|
|
467
|
+
var React5 = __toESM(require("react"), 1);
|
|
468
|
+
|
|
469
|
+
// src/portal-container.tsx
|
|
470
|
+
var React4 = __toESM(require("react"), 1);
|
|
471
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
472
|
+
var PortalContainerContext = React4.createContext(
|
|
473
|
+
void 0
|
|
474
|
+
);
|
|
475
|
+
function PortalContainerProvider({
|
|
476
|
+
container,
|
|
477
|
+
children
|
|
478
|
+
}) {
|
|
479
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PortalContainerContext.Provider, { value: container ?? void 0, children });
|
|
480
|
+
}
|
|
481
|
+
function usePortalContainer(explicit) {
|
|
482
|
+
const injected = React4.useContext(PortalContainerContext);
|
|
483
|
+
if (explicit !== void 0) {
|
|
484
|
+
return explicit ?? void 0;
|
|
485
|
+
}
|
|
486
|
+
return injected ?? void 0;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
// src/command.tsx
|
|
490
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
491
|
+
var Command = React5.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
492
|
+
import_cmdk.Command,
|
|
493
|
+
{
|
|
494
|
+
ref,
|
|
495
|
+
className: cn(
|
|
496
|
+
"flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground",
|
|
497
|
+
className
|
|
498
|
+
),
|
|
499
|
+
...props
|
|
500
|
+
}
|
|
501
|
+
));
|
|
502
|
+
Command.displayName = import_cmdk.Command.displayName;
|
|
503
|
+
var MOBILE_BREAKPOINT = 768;
|
|
504
|
+
function useIsMobile() {
|
|
505
|
+
const [isMobile, setIsMobile] = React5.useState(false);
|
|
506
|
+
const [hasMounted, setHasMounted] = React5.useState(false);
|
|
507
|
+
React5.useEffect(() => {
|
|
508
|
+
setHasMounted(true);
|
|
509
|
+
const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);
|
|
510
|
+
const onChange = () => {
|
|
511
|
+
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
|
|
512
|
+
};
|
|
513
|
+
onChange();
|
|
514
|
+
mql.addEventListener("change", onChange);
|
|
515
|
+
return () => mql.removeEventListener("change", onChange);
|
|
516
|
+
}, []);
|
|
517
|
+
if (!hasMounted) {
|
|
518
|
+
return false;
|
|
519
|
+
}
|
|
520
|
+
return isMobile;
|
|
521
|
+
}
|
|
522
|
+
var DIALOG_DESKTOP_CLASSES = "fixed left-[50%] top-[50%] z-[10000] grid min-w-0 w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 overflow-x-clip border bg-background p-6 shadow-lg [overflow-wrap:anywhere] [&>*]:min-w-0 [&>*]:max-w-full duration-200 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%] sm:rounded-lg";
|
|
523
|
+
var DIALOG_MOBILE_SHEET_CLASSES = "fixed inset-x-0 bottom-0 left-0 right-0 top-auto z-[10000] flex min-w-0 flex-col w-full max-w-full max-h-[90dvh] translate-x-0 translate-y-0 gap-4 overflow-x-clip border-t bg-background p-4 pb-safe shadow-lg [overflow-wrap:anywhere] [&>*]:min-w-0 [&>*]:max-w-full duration-200 rounded-t-2xl rounded-b-none overflow-y-auto overscroll-contain 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]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom";
|
|
524
|
+
var DIALOG_MOBILE_SHEET_OVERRIDE = "inset-x-0 bottom-0 left-0 right-0 top-auto translate-x-0 translate-y-0 w-full max-w-full max-h-[90dvh] rounded-b-none rounded-t-2xl overflow-y-auto";
|
|
525
|
+
var CommandDialogContent = React5.forwardRef(({ className, children, container, ...props }, ref) => {
|
|
526
|
+
const isMobile = useIsMobile();
|
|
527
|
+
const isModal = useRadixDialogModal();
|
|
528
|
+
const portalContainer = usePortalContainer(container);
|
|
529
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(DialogPrimitive.Portal, { container: portalContainer, children: [
|
|
530
|
+
isModal ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
531
|
+
DialogPrimitive.Overlay,
|
|
532
|
+
{
|
|
533
|
+
className: "fixed inset-0 z-[10000] bg-black/20 dark:bg-black/30 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0"
|
|
534
|
+
}
|
|
535
|
+
) : null,
|
|
536
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
537
|
+
DialogPrimitive.Content,
|
|
538
|
+
{
|
|
539
|
+
ref,
|
|
540
|
+
"aria-modal": isModal || void 0,
|
|
541
|
+
"aria-describedby": void 0,
|
|
542
|
+
className: cn(
|
|
543
|
+
isMobile ? DIALOG_MOBILE_SHEET_CLASSES : DIALOG_DESKTOP_CLASSES,
|
|
544
|
+
className,
|
|
545
|
+
isMobile && DIALOG_MOBILE_SHEET_OVERRIDE,
|
|
546
|
+
!isModal && "z-[900]"
|
|
547
|
+
),
|
|
548
|
+
...props,
|
|
549
|
+
children: [
|
|
550
|
+
children,
|
|
551
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(DialogPrimitive.Close, { className: "absolute right-2 top-4 flex h-10 w-10 items-center justify-center rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground sm:right-4", children: [
|
|
552
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(XIcon, { className: "h-4 w-4" }),
|
|
553
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "sr-only", children: "Close" })
|
|
554
|
+
] })
|
|
555
|
+
]
|
|
556
|
+
}
|
|
557
|
+
)
|
|
558
|
+
] });
|
|
559
|
+
});
|
|
560
|
+
CommandDialogContent.displayName = "CommandDialogContent";
|
|
561
|
+
var CommandDialog = ({
|
|
562
|
+
children,
|
|
563
|
+
container,
|
|
564
|
+
...props
|
|
565
|
+
}) => {
|
|
566
|
+
const modal = props.modal ?? true;
|
|
567
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(RadixDialogModalProvider, { modal, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(DialogPrimitive.Root, { ...props, modal, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
568
|
+
CommandDialogContent,
|
|
569
|
+
{
|
|
570
|
+
className: "overflow-hidden p-0",
|
|
571
|
+
...container !== void 0 ? { container } : {},
|
|
572
|
+
children: [
|
|
573
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(DialogPrimitive.Title, { className: "sr-only" }),
|
|
574
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Command, { className: "[&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-group]]:px-2 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5", children })
|
|
575
|
+
]
|
|
576
|
+
}
|
|
577
|
+
) }) });
|
|
578
|
+
};
|
|
579
|
+
var CommandInput = React5.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex items-center border-b px-3", "cmdk-input-wrapper": "", children: [
|
|
580
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(MagnifyingGlassIcon, { className: "mr-2 h-4 w-4 shrink-0 opacity-50" }),
|
|
581
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
582
|
+
import_cmdk.Command.Input,
|
|
583
|
+
{
|
|
584
|
+
ref,
|
|
585
|
+
className: cn(
|
|
586
|
+
"flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50",
|
|
587
|
+
className
|
|
588
|
+
),
|
|
589
|
+
...props
|
|
590
|
+
}
|
|
591
|
+
)
|
|
592
|
+
] }));
|
|
593
|
+
CommandInput.displayName = import_cmdk.Command.Input.displayName;
|
|
594
|
+
var CommandList = React5.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
595
|
+
import_cmdk.Command.List,
|
|
596
|
+
{
|
|
597
|
+
ref,
|
|
598
|
+
className: cn("max-h-[300px] overflow-y-auto overflow-x-hidden", className),
|
|
599
|
+
...props
|
|
600
|
+
}
|
|
601
|
+
));
|
|
602
|
+
CommandList.displayName = import_cmdk.Command.List.displayName;
|
|
603
|
+
var CommandEmpty = React5.forwardRef((props, ref) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
604
|
+
import_cmdk.Command.Empty,
|
|
605
|
+
{
|
|
606
|
+
ref,
|
|
607
|
+
className: "py-6 text-center text-sm",
|
|
608
|
+
...props
|
|
609
|
+
}
|
|
610
|
+
));
|
|
611
|
+
CommandEmpty.displayName = import_cmdk.Command.Empty.displayName;
|
|
612
|
+
var CommandGroup = React5.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
613
|
+
import_cmdk.Command.Group,
|
|
614
|
+
{
|
|
615
|
+
ref,
|
|
616
|
+
className: cn(
|
|
617
|
+
"overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground",
|
|
618
|
+
className
|
|
619
|
+
),
|
|
620
|
+
...props
|
|
621
|
+
}
|
|
622
|
+
));
|
|
623
|
+
CommandGroup.displayName = import_cmdk.Command.Group.displayName;
|
|
624
|
+
var CommandSeparator = React5.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
625
|
+
import_cmdk.Command.Separator,
|
|
626
|
+
{
|
|
627
|
+
ref,
|
|
628
|
+
className: cn("-mx-1 h-px bg-border", className),
|
|
629
|
+
...props
|
|
630
|
+
}
|
|
631
|
+
));
|
|
632
|
+
CommandSeparator.displayName = import_cmdk.Command.Separator.displayName;
|
|
633
|
+
var CommandItem = React5.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
634
|
+
import_cmdk.Command.Item,
|
|
635
|
+
{
|
|
636
|
+
ref,
|
|
637
|
+
className: cn(
|
|
638
|
+
"relative flex cursor-default gap-2 select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[disabled=true]:pointer-events-none data-[selected=true]:bg-accent data-[selected=true]:text-accent-foreground data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
|
639
|
+
className
|
|
640
|
+
),
|
|
641
|
+
...props
|
|
642
|
+
}
|
|
643
|
+
));
|
|
644
|
+
CommandItem.displayName = import_cmdk.Command.Item.displayName;
|
|
645
|
+
var CommandShortcut = ({
|
|
646
|
+
className,
|
|
647
|
+
...props
|
|
648
|
+
}) => {
|
|
649
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
650
|
+
"span",
|
|
651
|
+
{
|
|
652
|
+
className: cn(
|
|
653
|
+
"ml-auto text-xs tracking-widest text-muted-foreground",
|
|
654
|
+
className
|
|
655
|
+
),
|
|
656
|
+
...props
|
|
657
|
+
}
|
|
658
|
+
);
|
|
659
|
+
};
|
|
660
|
+
CommandShortcut.displayName = "CommandShortcut";
|
|
661
|
+
|
|
662
|
+
// src/creatable-picker.tsx
|
|
663
|
+
var import_react = require("react");
|
|
664
|
+
|
|
665
|
+
// src/popover.tsx
|
|
666
|
+
var PopoverPrimitive = __toESM(require("@radix-ui/react-popover"), 1);
|
|
667
|
+
var React6 = __toESM(require("react"), 1);
|
|
668
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
669
|
+
var Popover = PopoverPrimitive.Root;
|
|
670
|
+
var PopoverTrigger = PopoverPrimitive.Trigger;
|
|
671
|
+
var PopoverAnchor = PopoverPrimitive.Anchor;
|
|
672
|
+
var PopoverContent = React6.forwardRef(
|
|
673
|
+
({ className, align = "center", sideOffset = 4, container, ...props }, ref) => {
|
|
674
|
+
const portalContainer = usePortalContainer(container);
|
|
675
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(PopoverPrimitive.Portal, { container: portalContainer, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
676
|
+
PopoverPrimitive.Content,
|
|
677
|
+
{
|
|
678
|
+
ref,
|
|
679
|
+
align,
|
|
680
|
+
sideOffset,
|
|
681
|
+
className: cn(
|
|
682
|
+
// Cap to the viewport space Radix measured and scroll — a popover taller
|
|
683
|
+
// than the screen must never trap the user with unreachable content.
|
|
684
|
+
// z must EQUAL the dialog layer (z-[10000]), never exceed it: with equal
|
|
685
|
+
// z, DOM portal order decides, so a dialog opened FROM a popover stacks
|
|
686
|
+
// above it, and a popover opened from a dialog still stacks above the
|
|
687
|
+
// dialog. z-[10001] buried dialogs behind fullscreen popovers.
|
|
688
|
+
"z-[10000] w-72 max-h-[var(--radix-popover-content-available-height)] overflow-y-auto overscroll-contain rounded-md 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",
|
|
689
|
+
className
|
|
690
|
+
),
|
|
691
|
+
...props
|
|
692
|
+
}
|
|
693
|
+
) });
|
|
694
|
+
}
|
|
695
|
+
);
|
|
696
|
+
PopoverContent.displayName = PopoverPrimitive.Content.displayName;
|
|
697
|
+
|
|
698
|
+
// src/creatable-picker.tsx
|
|
699
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
700
|
+
function article(noun) {
|
|
701
|
+
return /^[aeiou]/i.test(noun.trim()) ? `an ${noun}` : `a ${noun}`;
|
|
702
|
+
}
|
|
703
|
+
function CreatablePicker({
|
|
704
|
+
value,
|
|
705
|
+
options,
|
|
706
|
+
onSelect,
|
|
707
|
+
placeholder,
|
|
708
|
+
searchPlaceholder,
|
|
709
|
+
noun,
|
|
710
|
+
onCreate,
|
|
711
|
+
onCreateRequiresMore,
|
|
712
|
+
disabled,
|
|
713
|
+
loading,
|
|
714
|
+
className,
|
|
715
|
+
triggerClassName,
|
|
716
|
+
emptyLabel = "No match.",
|
|
717
|
+
ariaLabel,
|
|
718
|
+
lockedNote,
|
|
719
|
+
lockedAction,
|
|
720
|
+
createExtra,
|
|
721
|
+
manageAction,
|
|
722
|
+
footerActions,
|
|
723
|
+
renderSelected,
|
|
724
|
+
size = "sm"
|
|
725
|
+
}) {
|
|
726
|
+
const [open, setOpen] = (0, import_react.useState)(false);
|
|
727
|
+
const [query, setQuery] = (0, import_react.useState)("");
|
|
728
|
+
const [busy, setBusy] = (0, import_react.useState)(false);
|
|
729
|
+
const inputRef = (0, import_react.useRef)(null);
|
|
730
|
+
const [needsName, setNeedsName] = (0, import_react.useState)(false);
|
|
731
|
+
const selected = options.find((option) => option.value === value) ?? null;
|
|
732
|
+
const groups = [];
|
|
733
|
+
for (const option of options) {
|
|
734
|
+
const last = groups[groups.length - 1];
|
|
735
|
+
if (last && last.heading === option.group) last.options.push(option);
|
|
736
|
+
else
|
|
737
|
+
groups.push(
|
|
738
|
+
option.group === void 0 ? { options: [option] } : { heading: option.group, options: [option] }
|
|
739
|
+
);
|
|
740
|
+
}
|
|
741
|
+
const typed = query.trim();
|
|
742
|
+
const exactMatch = options.some(
|
|
743
|
+
(option) => option.label.toLowerCase() === typed.toLowerCase()
|
|
744
|
+
);
|
|
745
|
+
const canCreate = Boolean(onCreate ?? onCreateRequiresMore) && !lockedNote;
|
|
746
|
+
const close = () => {
|
|
747
|
+
setOpen(false);
|
|
748
|
+
setQuery("");
|
|
749
|
+
setNeedsName(false);
|
|
750
|
+
};
|
|
751
|
+
const create = async (text) => {
|
|
752
|
+
const name = text.trim();
|
|
753
|
+
if (busy) return;
|
|
754
|
+
if (onCreateRequiresMore) {
|
|
755
|
+
close();
|
|
756
|
+
onCreateRequiresMore(name);
|
|
757
|
+
return;
|
|
758
|
+
}
|
|
759
|
+
if (!onCreate) return;
|
|
760
|
+
if (!name) {
|
|
761
|
+
setNeedsName(true);
|
|
762
|
+
inputRef.current?.focus();
|
|
763
|
+
return;
|
|
764
|
+
}
|
|
765
|
+
setBusy(true);
|
|
766
|
+
try {
|
|
767
|
+
const next = await onCreate(name);
|
|
768
|
+
if (next) onSelect(next);
|
|
769
|
+
close();
|
|
770
|
+
} finally {
|
|
771
|
+
setBusy(false);
|
|
772
|
+
}
|
|
773
|
+
};
|
|
774
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(Popover, { open, onOpenChange: (next) => next ? setOpen(true) : close(), children: [
|
|
775
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(PopoverTrigger, { asChild: true, disabled, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
776
|
+
"button",
|
|
777
|
+
{
|
|
778
|
+
type: "button",
|
|
779
|
+
"aria-label": ariaLabel ?? placeholder,
|
|
780
|
+
className: cn(
|
|
781
|
+
"flex w-full items-center justify-between gap-2 rounded-md border border-input bg-transparent px-3 text-left shadow-xs transition-colors",
|
|
782
|
+
"hover:border-primary/50 focus:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
783
|
+
"disabled:cursor-not-allowed disabled:opacity-50",
|
|
784
|
+
size === "sm" ? "h-8 text-xs" : "h-9 text-sm",
|
|
785
|
+
className,
|
|
786
|
+
triggerClassName
|
|
787
|
+
),
|
|
788
|
+
children: [
|
|
789
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "min-w-0 flex-1 truncate", children: selected ? renderSelected ?? selected.render ?? selected.label : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "text-muted-foreground", children: loading ? "Loading\u2026" : placeholder }) }),
|
|
790
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ChevronsUpDownIcon, { className: "size-3.5 shrink-0 opacity-50" })
|
|
791
|
+
]
|
|
792
|
+
}
|
|
793
|
+
) }),
|
|
794
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(PopoverContent, { align: "start", className: "w-[--radix-popover-trigger-width] min-w-56 p-0", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
795
|
+
Command,
|
|
796
|
+
{
|
|
797
|
+
filter: (itemValue, search, keywords) => {
|
|
798
|
+
const haystack = `${itemValue} ${keywords?.join(" ") ?? ""}`.toLowerCase();
|
|
799
|
+
return haystack.includes(search.toLowerCase()) ? 1 : 0;
|
|
800
|
+
},
|
|
801
|
+
children: [
|
|
802
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
803
|
+
CommandInput,
|
|
804
|
+
{
|
|
805
|
+
ref: inputRef,
|
|
806
|
+
value: query,
|
|
807
|
+
onValueChange: (next) => {
|
|
808
|
+
setQuery(next);
|
|
809
|
+
if (next.trim()) setNeedsName(false);
|
|
810
|
+
},
|
|
811
|
+
placeholder: searchPlaceholder ?? `Search or add ${article(noun)}\u2026`
|
|
812
|
+
}
|
|
813
|
+
),
|
|
814
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(CommandList, { children: [
|
|
815
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(CommandEmpty, { children: emptyLabel }),
|
|
816
|
+
groups.map((group) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
817
|
+
CommandGroup,
|
|
818
|
+
{
|
|
819
|
+
...group.heading === void 0 ? {} : { heading: group.heading },
|
|
820
|
+
children: group.options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
821
|
+
CommandItem,
|
|
822
|
+
{
|
|
823
|
+
value: option.label,
|
|
824
|
+
...option.keywords ? { keywords: [option.keywords] } : {},
|
|
825
|
+
onSelect: () => {
|
|
826
|
+
onSelect(option.value);
|
|
827
|
+
close();
|
|
828
|
+
},
|
|
829
|
+
className: "gap-2 text-xs",
|
|
830
|
+
children: [
|
|
831
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
832
|
+
LucideCheckIcon,
|
|
833
|
+
{
|
|
834
|
+
className: cn(
|
|
835
|
+
"size-3.5 shrink-0",
|
|
836
|
+
option.value === value ? "opacity-100" : "opacity-0"
|
|
837
|
+
)
|
|
838
|
+
}
|
|
839
|
+
),
|
|
840
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "min-w-0 flex-1 truncate", children: option.render ?? option.label }),
|
|
841
|
+
option.hint ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "shrink-0 text-[10px] text-muted-foreground", children: option.hint }) : null
|
|
842
|
+
]
|
|
843
|
+
},
|
|
844
|
+
option.value
|
|
845
|
+
))
|
|
846
|
+
},
|
|
847
|
+
group.heading ?? "__ungrouped__"
|
|
848
|
+
))
|
|
849
|
+
] }),
|
|
850
|
+
canCreate ? /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "space-y-1 border-t border-border p-1", children: [
|
|
851
|
+
createExtra && typed && !exactMatch ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "px-1 pt-0.5", children: typeof createExtra === "function" ? createExtra(typed) : createExtra }) : null,
|
|
852
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
853
|
+
"button",
|
|
854
|
+
{
|
|
855
|
+
type: "button",
|
|
856
|
+
disabled: busy,
|
|
857
|
+
onClick: () => void create(typed),
|
|
858
|
+
className: "flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-left text-xs text-muted-foreground transition-colors hover:bg-accent hover:text-foreground disabled:opacity-50",
|
|
859
|
+
children: [
|
|
860
|
+
busy ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Loader2Icon, { className: "size-3.5 shrink-0 animate-spin" }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(PlusIcon, { className: "size-3.5 shrink-0" }),
|
|
861
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "min-w-0 truncate", children: typed && !exactMatch ? `Create \u201C${typed}\u201D` : `Add ${article(noun)}\u2026` })
|
|
862
|
+
]
|
|
863
|
+
}
|
|
864
|
+
),
|
|
865
|
+
needsName ? /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("p", { className: "px-2 pb-0.5 text-[11px] leading-snug text-muted-foreground", children: [
|
|
866
|
+
"Type the name of the ",
|
|
867
|
+
noun,
|
|
868
|
+
" you want to add \u2014 then this creates it."
|
|
869
|
+
] }) : null
|
|
870
|
+
] }) : null,
|
|
871
|
+
footerActions?.length || manageAction ? /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "space-y-0.5 border-t border-border p-1", children: [
|
|
872
|
+
footerActions?.map((action) => {
|
|
873
|
+
const Icon2 = action.icon;
|
|
874
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { children: [
|
|
875
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
876
|
+
"button",
|
|
877
|
+
{
|
|
878
|
+
type: "button",
|
|
879
|
+
onClick: () => {
|
|
880
|
+
close();
|
|
881
|
+
action.onSelect();
|
|
882
|
+
},
|
|
883
|
+
className: "flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-left text-xs text-muted-foreground transition-colors hover:bg-accent hover:text-foreground",
|
|
884
|
+
children: [
|
|
885
|
+
Icon2 ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Icon2, { className: "size-3.5 shrink-0" }) : null,
|
|
886
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "min-w-0 truncate", children: action.label })
|
|
887
|
+
]
|
|
888
|
+
}
|
|
889
|
+
),
|
|
890
|
+
action.note ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { className: "px-2 pb-1 text-[10px] leading-snug text-muted-foreground", children: action.note }) : null
|
|
891
|
+
] }, action.label);
|
|
892
|
+
}),
|
|
893
|
+
manageAction ? /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
894
|
+
"a",
|
|
895
|
+
{
|
|
896
|
+
href: manageAction.href,
|
|
897
|
+
target: "_blank",
|
|
898
|
+
rel: "noopener noreferrer",
|
|
899
|
+
onClick: close,
|
|
900
|
+
className: "flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-left text-xs text-muted-foreground transition-colors hover:bg-accent hover:text-foreground",
|
|
901
|
+
children: [
|
|
902
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ExternalLinkIcon, { className: "size-3.5 shrink-0" }),
|
|
903
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "min-w-0 truncate", children: manageAction.label })
|
|
904
|
+
]
|
|
905
|
+
}
|
|
906
|
+
) : null
|
|
907
|
+
] }) : null,
|
|
908
|
+
lockedNote ? /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "space-y-1 border-t border-border p-2", children: [
|
|
909
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("p", { className: "flex gap-1.5 text-[11px] leading-snug text-muted-foreground", children: [
|
|
910
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(LockIcon, { className: "mt-px size-3 shrink-0" }),
|
|
911
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { children: lockedNote })
|
|
912
|
+
] }),
|
|
913
|
+
lockedAction ? /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
914
|
+
"button",
|
|
915
|
+
{
|
|
916
|
+
type: "button",
|
|
917
|
+
onClick: () => {
|
|
918
|
+
close();
|
|
919
|
+
lockedAction.onSelect();
|
|
920
|
+
},
|
|
921
|
+
className: "flex w-full items-center gap-2 rounded-sm px-1 py-1 text-left text-xs font-medium text-primary transition-colors hover:bg-accent",
|
|
922
|
+
children: [
|
|
923
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(PlusIcon, { className: "size-3.5 shrink-0" }),
|
|
924
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "min-w-0 truncate", children: lockedAction.label })
|
|
925
|
+
]
|
|
926
|
+
}
|
|
927
|
+
) : null
|
|
928
|
+
] }) : null
|
|
929
|
+
]
|
|
930
|
+
}
|
|
931
|
+
) })
|
|
932
|
+
] });
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
// src/editable-label.tsx
|
|
936
|
+
var import_react2 = require("react");
|
|
937
|
+
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
938
|
+
function EditableLabel({
|
|
939
|
+
value,
|
|
940
|
+
onCommit,
|
|
941
|
+
commitMode = "optimistic",
|
|
942
|
+
validate,
|
|
943
|
+
emptyFallback,
|
|
944
|
+
maxLength = 120,
|
|
945
|
+
activation = "click",
|
|
946
|
+
editing: editingProp,
|
|
947
|
+
onEditingChange,
|
|
948
|
+
selectOnEdit = true,
|
|
949
|
+
placeholder,
|
|
950
|
+
ariaLabel = "Name",
|
|
951
|
+
truncate = true,
|
|
952
|
+
className,
|
|
953
|
+
displayClassName,
|
|
954
|
+
inputClassName
|
|
955
|
+
}) {
|
|
956
|
+
const controlled = activation === "controlled";
|
|
957
|
+
const [internalEditing, setInternalEditing] = (0, import_react2.useState)(false);
|
|
958
|
+
const editing = controlled ? !!editingProp : internalEditing;
|
|
959
|
+
const [draft, setDraft] = (0, import_react2.useState)(value);
|
|
960
|
+
const [error, setError] = (0, import_react2.useState)(null);
|
|
961
|
+
const [busy, setBusy] = (0, import_react2.useState)(false);
|
|
962
|
+
const inputRef = (0, import_react2.useRef)(null);
|
|
963
|
+
(0, import_react2.useEffect)(() => {
|
|
964
|
+
if (!editing) setDraft(value);
|
|
965
|
+
}, [value, editing]);
|
|
966
|
+
(0, import_react2.useEffect)(() => {
|
|
967
|
+
if (editing && inputRef.current) {
|
|
968
|
+
inputRef.current.focus();
|
|
969
|
+
if (selectOnEdit) inputRef.current.select();
|
|
970
|
+
}
|
|
971
|
+
}, [editing, selectOnEdit]);
|
|
972
|
+
const setEditing = (0, import_react2.useCallback)(
|
|
973
|
+
(next) => {
|
|
974
|
+
if (controlled) {
|
|
975
|
+
onEditingChange?.(next);
|
|
976
|
+
} else {
|
|
977
|
+
setInternalEditing(next);
|
|
978
|
+
onEditingChange?.(next);
|
|
979
|
+
}
|
|
980
|
+
},
|
|
981
|
+
[controlled, onEditingChange]
|
|
982
|
+
);
|
|
983
|
+
const startEdit = (0, import_react2.useCallback)(() => {
|
|
984
|
+
setDraft(value);
|
|
985
|
+
setError(null);
|
|
986
|
+
setEditing(true);
|
|
987
|
+
}, [value, setEditing]);
|
|
988
|
+
const cancel = (0, import_react2.useCallback)(() => {
|
|
989
|
+
setDraft(value);
|
|
990
|
+
setError(null);
|
|
991
|
+
setBusy(false);
|
|
992
|
+
setEditing(false);
|
|
993
|
+
}, [value, setEditing]);
|
|
994
|
+
const commit = (0, import_react2.useCallback)(() => {
|
|
995
|
+
if (busy) return;
|
|
996
|
+
const trimmed = draft.trim();
|
|
997
|
+
const next = trimmed || emptyFallback;
|
|
998
|
+
if (next === void 0) {
|
|
999
|
+
cancel();
|
|
1000
|
+
return;
|
|
1001
|
+
}
|
|
1002
|
+
const validationError = validate?.(next) ?? null;
|
|
1003
|
+
if (validationError) {
|
|
1004
|
+
setError(validationError);
|
|
1005
|
+
return;
|
|
1006
|
+
}
|
|
1007
|
+
if (next === value) {
|
|
1008
|
+
setEditing(false);
|
|
1009
|
+
setError(null);
|
|
1010
|
+
return;
|
|
1011
|
+
}
|
|
1012
|
+
if (commitMode === "await") {
|
|
1013
|
+
const result2 = onCommit(next);
|
|
1014
|
+
if (result2 instanceof Promise) {
|
|
1015
|
+
setBusy(true);
|
|
1016
|
+
result2.then(() => {
|
|
1017
|
+
setBusy(false);
|
|
1018
|
+
setEditing(false);
|
|
1019
|
+
}).catch(() => {
|
|
1020
|
+
setBusy(false);
|
|
1021
|
+
});
|
|
1022
|
+
return;
|
|
1023
|
+
}
|
|
1024
|
+
setEditing(false);
|
|
1025
|
+
return;
|
|
1026
|
+
}
|
|
1027
|
+
setEditing(false);
|
|
1028
|
+
setError(null);
|
|
1029
|
+
const result = onCommit(next);
|
|
1030
|
+
if (result instanceof Promise) result.catch(() => {
|
|
1031
|
+
});
|
|
1032
|
+
}, [
|
|
1033
|
+
busy,
|
|
1034
|
+
draft,
|
|
1035
|
+
emptyFallback,
|
|
1036
|
+
validate,
|
|
1037
|
+
value,
|
|
1038
|
+
commitMode,
|
|
1039
|
+
onCommit,
|
|
1040
|
+
cancel,
|
|
1041
|
+
setEditing
|
|
1042
|
+
]);
|
|
1043
|
+
if (editing) {
|
|
1044
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: cn("relative flex min-w-0 flex-1 items-center", className), children: [
|
|
1045
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1046
|
+
"input",
|
|
1047
|
+
{
|
|
1048
|
+
ref: inputRef,
|
|
1049
|
+
type: "text",
|
|
1050
|
+
value: draft,
|
|
1051
|
+
disabled: busy,
|
|
1052
|
+
placeholder,
|
|
1053
|
+
onChange: (e) => {
|
|
1054
|
+
setDraft(e.target.value);
|
|
1055
|
+
if (error) setError(null);
|
|
1056
|
+
},
|
|
1057
|
+
onBlur: commit,
|
|
1058
|
+
onClick: (e) => e.stopPropagation(),
|
|
1059
|
+
onDoubleClick: (e) => e.stopPropagation(),
|
|
1060
|
+
onKeyDown: (e) => {
|
|
1061
|
+
if (e.key === "Enter") {
|
|
1062
|
+
e.preventDefault();
|
|
1063
|
+
e.stopPropagation();
|
|
1064
|
+
commit();
|
|
1065
|
+
} else if (e.key === "Escape") {
|
|
1066
|
+
e.preventDefault();
|
|
1067
|
+
e.stopPropagation();
|
|
1068
|
+
cancel();
|
|
1069
|
+
} else if (e.key === " ") {
|
|
1070
|
+
e.stopPropagation();
|
|
1071
|
+
}
|
|
1072
|
+
},
|
|
1073
|
+
maxLength,
|
|
1074
|
+
"aria-label": ariaLabel,
|
|
1075
|
+
"aria-invalid": error ? true : void 0,
|
|
1076
|
+
className: cn(
|
|
1077
|
+
"w-full min-w-0 rounded-sm bg-transparent px-1 outline-none",
|
|
1078
|
+
"text-base md:text-sm",
|
|
1079
|
+
"focus:bg-background focus:ring-1 focus:ring-ring",
|
|
1080
|
+
busy && "opacity-60",
|
|
1081
|
+
inputClassName
|
|
1082
|
+
)
|
|
1083
|
+
}
|
|
1084
|
+
),
|
|
1085
|
+
busy && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Loader2Icon, { className: "absolute right-1 h-3.5 w-3.5 animate-spin text-muted-foreground" }),
|
|
1086
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "absolute left-0 top-full mt-0.5 whitespace-nowrap text-xs text-destructive", children: error })
|
|
1087
|
+
] });
|
|
1088
|
+
}
|
|
1089
|
+
if (controlled) return null;
|
|
1090
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1091
|
+
"button",
|
|
1092
|
+
{
|
|
1093
|
+
type: "button",
|
|
1094
|
+
onClick: activation === "click" ? (e) => {
|
|
1095
|
+
e.stopPropagation();
|
|
1096
|
+
startEdit();
|
|
1097
|
+
} : void 0,
|
|
1098
|
+
onDoubleClick: activation === "doubleClick" ? (e) => {
|
|
1099
|
+
e.stopPropagation();
|
|
1100
|
+
startEdit();
|
|
1101
|
+
} : void 0,
|
|
1102
|
+
onKeyDown: (e) => {
|
|
1103
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
1104
|
+
e.preventDefault();
|
|
1105
|
+
e.stopPropagation();
|
|
1106
|
+
startEdit();
|
|
1107
|
+
}
|
|
1108
|
+
},
|
|
1109
|
+
title: activation === "doubleClick" ? "Double-click to rename" : "Click to rename",
|
|
1110
|
+
"aria-label": `Rename ${ariaLabel.toLowerCase()}: ${value}`,
|
|
1111
|
+
className: cn(
|
|
1112
|
+
"min-w-0 max-w-full rounded-sm px-1 text-left transition-colors",
|
|
1113
|
+
"hover:bg-accent/40 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
1114
|
+
truncate && "block truncate",
|
|
1115
|
+
className,
|
|
1116
|
+
displayClassName
|
|
1117
|
+
),
|
|
1118
|
+
children: value || placeholder || ""
|
|
1119
|
+
}
|
|
1120
|
+
);
|
|
1121
|
+
}
|
|
1122
|
+
|
|
1123
|
+
// src/input.tsx
|
|
1124
|
+
var React7 = __toESM(require("react"), 1);
|
|
1125
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
1126
|
+
var getVariantStyles = (variant = "default") => {
|
|
1127
|
+
const baseStyles = `flex h-10 w-full border border-border bg-background text-black dark:text-white shadow-input rounded-md px-3 py-2 text-sm file:border-0 file:bg-transparent
|
|
1128
|
+
file:text-sm file:font-medium placeholder:text-neutral-400 dark:placeholder-text-neutral-600
|
|
1129
|
+
focus-visible:outline-none focus-visible:ring-[2px] focus-visible:ring-neutral-400 dark:focus-visible:ring-neutral-600
|
|
1130
|
+
disabled:cursor-not-allowed disabled:opacity-50
|
|
1131
|
+
dark:shadow-[0px_0px_1px_1px_var(--neutral-700)]
|
|
1132
|
+
transition duration-400
|
|
1133
|
+
[&:-webkit-autofill]:bg-background [&:-webkit-autofill]:shadow-[0_0_0_1000px_hsl(var(--background))_inset] [&:-webkit-autofill]:[caret-color:currentColor]
|
|
1134
|
+
dark:[&:-webkit-autofill]:shadow-[0_0_0_1000px_hsl(var(--background))_inset] dark:[&:-webkit-autofill]:[-webkit-text-fill-color:white]
|
|
1135
|
+
[&:-webkit-autofill:hover]:shadow-[0_0_0_1000px_hsl(var(--background))_inset] [&:-webkit-autofill:focus]:shadow-[0_0_0_1000px_hsl(var(--background))_inset]`;
|
|
1136
|
+
switch (variant) {
|
|
1137
|
+
case "destructive":
|
|
1138
|
+
return `${baseStyles} bg-destructive text-destructive-foreground`;
|
|
1139
|
+
case "outline":
|
|
1140
|
+
return `${baseStyles} border-2`;
|
|
1141
|
+
case "secondary":
|
|
1142
|
+
return `${baseStyles} bg-secondary text-secondary-foreground`;
|
|
1143
|
+
case "ghost":
|
|
1144
|
+
return `${baseStyles} bg-transparent shadow-none`;
|
|
1145
|
+
case "link":
|
|
1146
|
+
return `${baseStyles} bg-transparent underline-offset-4 hover:underline`;
|
|
1147
|
+
case "primary":
|
|
1148
|
+
return `${baseStyles} bg-primary text-primary-foreground`;
|
|
1149
|
+
default:
|
|
1150
|
+
return baseStyles;
|
|
1151
|
+
}
|
|
1152
|
+
};
|
|
1153
|
+
var Input = React7.forwardRef(
|
|
1154
|
+
({ className, type, variant = "default", ...props }, ref) => {
|
|
1155
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1156
|
+
"input",
|
|
1157
|
+
{
|
|
1158
|
+
type,
|
|
1159
|
+
className: cn(getVariantStyles(variant), className),
|
|
1160
|
+
ref,
|
|
1161
|
+
...props
|
|
1162
|
+
}
|
|
1163
|
+
);
|
|
1164
|
+
}
|
|
1165
|
+
);
|
|
1166
|
+
Input.displayName = "Input";
|
|
1167
|
+
var EnterInput = React7.forwardRef(
|
|
1168
|
+
({ onEnter, ...props }, ref) => {
|
|
1169
|
+
const handleKeyDown = (e) => {
|
|
1170
|
+
if (e.key === "Enter" && onEnter) {
|
|
1171
|
+
e.preventDefault();
|
|
1172
|
+
onEnter();
|
|
1173
|
+
}
|
|
1174
|
+
};
|
|
1175
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1176
|
+
Input,
|
|
1177
|
+
{
|
|
1178
|
+
...props,
|
|
1179
|
+
ref,
|
|
1180
|
+
onKeyDown: (e) => {
|
|
1181
|
+
handleKeyDown(e);
|
|
1182
|
+
if (props.onKeyDown) {
|
|
1183
|
+
props.onKeyDown(e);
|
|
1184
|
+
}
|
|
1185
|
+
}
|
|
1186
|
+
}
|
|
1187
|
+
);
|
|
1188
|
+
}
|
|
1189
|
+
);
|
|
1190
|
+
EnterInput.displayName = "EnterInput";
|
|
1191
|
+
var BasicInput = React7.forwardRef(
|
|
1192
|
+
// `variant` is accepted (prop-compatible with Input) but intentionally
|
|
1193
|
+
// unused — and destructured so it never leaks onto the DOM element.
|
|
1194
|
+
({ className, type, variant: _variant = "default", ...props }, ref) => {
|
|
1195
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1196
|
+
"input",
|
|
1197
|
+
{
|
|
1198
|
+
type,
|
|
1199
|
+
className: cn(
|
|
1200
|
+
"flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors 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",
|
|
1201
|
+
className
|
|
1202
|
+
),
|
|
1203
|
+
ref,
|
|
1204
|
+
...props
|
|
1205
|
+
}
|
|
1206
|
+
);
|
|
1207
|
+
}
|
|
1208
|
+
);
|
|
1209
|
+
BasicInput.displayName = "BasicInput";
|
|
1210
|
+
var InputWithPrefix = React7.forwardRef(({ prefix, className, wrapperClassName, ...props }, ref) => {
|
|
1211
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: cn("relative", wrapperClassName), children: [
|
|
1212
|
+
prefix && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground", children: prefix }),
|
|
1213
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1214
|
+
Input,
|
|
1215
|
+
{
|
|
1216
|
+
ref,
|
|
1217
|
+
className: cn(prefix && "pl-10", className),
|
|
1218
|
+
...props
|
|
1219
|
+
}
|
|
1220
|
+
)
|
|
1221
|
+
] });
|
|
1222
|
+
});
|
|
1223
|
+
InputWithPrefix.displayName = "InputWithPrefix";
|
|
1224
|
+
|
|
1225
|
+
// src/label.tsx
|
|
1226
|
+
var LabelPrimitive = __toESM(require("@radix-ui/react-label"), 1);
|
|
1227
|
+
var React8 = __toESM(require("react"), 1);
|
|
1228
|
+
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
1229
|
+
var Label = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1230
|
+
LabelPrimitive.Root,
|
|
1231
|
+
{
|
|
1232
|
+
ref,
|
|
1233
|
+
className: cn(
|
|
1234
|
+
"text-sm font-medium leading-none text-foreground peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
|
|
1235
|
+
className
|
|
1236
|
+
),
|
|
1237
|
+
...props
|
|
1238
|
+
}
|
|
1239
|
+
));
|
|
1240
|
+
Label.displayName = LabelPrimitive.Root.displayName;
|
|
1241
|
+
|
|
1242
|
+
// src/overflow-toolbar.tsx
|
|
1243
|
+
var import_react3 = require("react");
|
|
1244
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
1245
|
+
var GAP_PX = 6;
|
|
1246
|
+
var TONE = {
|
|
1247
|
+
default: "border border-border bg-background hover:bg-accent text-foreground",
|
|
1248
|
+
primary: "bg-primary text-primary-foreground hover:bg-primary/90",
|
|
1249
|
+
destructive: "border border-destructive/40 text-destructive hover:bg-destructive/10"
|
|
1250
|
+
};
|
|
1251
|
+
function ToolbarButton({
|
|
1252
|
+
action,
|
|
1253
|
+
enableTooltip = false,
|
|
1254
|
+
renderTooltip
|
|
1255
|
+
}) {
|
|
1256
|
+
const tone = action.tone ?? "default";
|
|
1257
|
+
const Icon2 = action.running ? Loader2Icon : action.icon;
|
|
1258
|
+
const showLabel = !action.hideLabel || action.running && action.runningLabel;
|
|
1259
|
+
const text = action.running && action.runningLabel ? action.runningLabel : action.label;
|
|
1260
|
+
const className = cn(
|
|
1261
|
+
"inline-flex items-center gap-1 h-7 rounded-md text-[11px] font-medium transition-colors whitespace-nowrap",
|
|
1262
|
+
"disabled:opacity-50 disabled:pointer-events-none",
|
|
1263
|
+
action.hideLabel && !action.running ? "w-7 justify-center px-0" : "px-2",
|
|
1264
|
+
TONE[tone]
|
|
1265
|
+
);
|
|
1266
|
+
const inner = /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
|
|
1267
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
1268
|
+
Icon2,
|
|
1269
|
+
{
|
|
1270
|
+
className: cn("w-3.5 h-3.5 shrink-0", action.running && "animate-spin")
|
|
1271
|
+
}
|
|
1272
|
+
),
|
|
1273
|
+
showLabel && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { children: text })
|
|
1274
|
+
] });
|
|
1275
|
+
const control = action.href && !action.disabled ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
1276
|
+
"a",
|
|
1277
|
+
{
|
|
1278
|
+
href: action.href,
|
|
1279
|
+
target: action.target,
|
|
1280
|
+
rel: action.target === "_blank" ? "noopener noreferrer" : void 0,
|
|
1281
|
+
className,
|
|
1282
|
+
"aria-label": action.label,
|
|
1283
|
+
children: inner
|
|
1284
|
+
}
|
|
1285
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
1286
|
+
"button",
|
|
1287
|
+
{
|
|
1288
|
+
type: "button",
|
|
1289
|
+
onClick: action.onSelect,
|
|
1290
|
+
disabled: action.disabled,
|
|
1291
|
+
className,
|
|
1292
|
+
"aria-label": action.label,
|
|
1293
|
+
children: inner
|
|
1294
|
+
}
|
|
1295
|
+
);
|
|
1296
|
+
if (enableTooltip && action.hideLabel && renderTooltip) {
|
|
1297
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_jsx_runtime13.Fragment, { children: renderTooltip(control, action.label) });
|
|
1298
|
+
}
|
|
1299
|
+
return control;
|
|
1300
|
+
}
|
|
1301
|
+
function OverflowTrigger({ ariaLabel }) {
|
|
1302
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
1303
|
+
"button",
|
|
1304
|
+
{
|
|
1305
|
+
type: "button",
|
|
1306
|
+
"aria-label": ariaLabel,
|
|
1307
|
+
"aria-haspopup": "menu",
|
|
1308
|
+
title: "More actions",
|
|
1309
|
+
className: cn(
|
|
1310
|
+
"inline-flex items-center justify-center h-7 w-7 rounded-md transition-colors",
|
|
1311
|
+
"border border-border bg-background hover:bg-accent text-foreground"
|
|
1312
|
+
),
|
|
1313
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(MoreHorizontalIcon, { className: "w-3.5 h-3.5" })
|
|
1314
|
+
}
|
|
1315
|
+
);
|
|
1316
|
+
}
|
|
1317
|
+
function OverflowToolbar({
|
|
1318
|
+
actions,
|
|
1319
|
+
leading,
|
|
1320
|
+
overflowAriaLabel = "More actions",
|
|
1321
|
+
className,
|
|
1322
|
+
renderOverflowMenu,
|
|
1323
|
+
renderTooltip
|
|
1324
|
+
}) {
|
|
1325
|
+
const visibleActions = (0, import_react3.useMemo)(
|
|
1326
|
+
() => actions.filter((a) => !a.hidden),
|
|
1327
|
+
[actions]
|
|
1328
|
+
);
|
|
1329
|
+
const containerRef = (0, import_react3.useRef)(null);
|
|
1330
|
+
const ghostRef = (0, import_react3.useRef)(null);
|
|
1331
|
+
const leadingRef = (0, import_react3.useRef)(null);
|
|
1332
|
+
const [visibleCount, setVisibleCount] = (0, import_react3.useState)(visibleActions.length);
|
|
1333
|
+
const signature = visibleActions.map(
|
|
1334
|
+
(a) => `${a.id}:${a.hideLabel ? 1 : 0}:${a.running ? 1 : 0}:${a.runningLabel ?? ""}:${a.label}`
|
|
1335
|
+
).join("|");
|
|
1336
|
+
(0, import_react3.useLayoutEffect)(() => {
|
|
1337
|
+
const container = containerRef.current;
|
|
1338
|
+
const ghost = ghostRef.current;
|
|
1339
|
+
if (!container || !ghost) return void 0;
|
|
1340
|
+
const compute = () => {
|
|
1341
|
+
const available = container.clientWidth;
|
|
1342
|
+
const n = visibleActions.length;
|
|
1343
|
+
const children = Array.from(ghost.children);
|
|
1344
|
+
const hasLeading = leading != null;
|
|
1345
|
+
const leadingW = hasLeading ? leadingRef.current?.offsetWidth ?? 0 : 0;
|
|
1346
|
+
const itemW = (i) => children[i]?.offsetWidth ?? 0;
|
|
1347
|
+
const kebabW = children[n]?.offsetWidth ?? 28;
|
|
1348
|
+
const base = leadingW + (hasLeading && n > 0 ? GAP_PX : 0);
|
|
1349
|
+
let totalAll = base;
|
|
1350
|
+
for (let i = 0; i < n; i++) totalAll += itemW(i) + (i > 0 ? GAP_PX : 0);
|
|
1351
|
+
if (totalAll <= available) {
|
|
1352
|
+
setVisibleCount(n);
|
|
1353
|
+
return;
|
|
1354
|
+
}
|
|
1355
|
+
let used = base;
|
|
1356
|
+
let count = 0;
|
|
1357
|
+
for (let i = 0; i < n; i++) {
|
|
1358
|
+
const add = itemW(i) + (count > 0 ? GAP_PX : 0);
|
|
1359
|
+
if (used + add + GAP_PX + kebabW <= available) {
|
|
1360
|
+
used += add;
|
|
1361
|
+
count += 1;
|
|
1362
|
+
} else break;
|
|
1363
|
+
}
|
|
1364
|
+
setVisibleCount(count);
|
|
1365
|
+
};
|
|
1366
|
+
compute();
|
|
1367
|
+
const ro = new ResizeObserver(compute);
|
|
1368
|
+
ro.observe(container);
|
|
1369
|
+
return () => ro.disconnect();
|
|
1370
|
+
}, [signature, leading != null]);
|
|
1371
|
+
const shown = visibleActions.slice(0, visibleCount);
|
|
1372
|
+
const hidden = visibleActions.slice(visibleCount);
|
|
1373
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { ref: containerRef, className: cn("relative min-w-0", className), children: [
|
|
1374
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
|
|
1375
|
+
"div",
|
|
1376
|
+
{
|
|
1377
|
+
ref: ghostRef,
|
|
1378
|
+
"aria-hidden": true,
|
|
1379
|
+
className: "pointer-events-none absolute left-0 top-0 flex items-center gap-1.5 opacity-0",
|
|
1380
|
+
children: [
|
|
1381
|
+
visibleActions.map((a) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ToolbarButton, { action: a }, a.id)),
|
|
1382
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(OverflowTrigger, { ariaLabel: overflowAriaLabel })
|
|
1383
|
+
]
|
|
1384
|
+
}
|
|
1385
|
+
),
|
|
1386
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex items-center justify-end gap-1.5", children: [
|
|
1387
|
+
leading != null && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { ref: leadingRef, className: "shrink-0", children: leading }),
|
|
1388
|
+
shown.map((a) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
1389
|
+
ToolbarButton,
|
|
1390
|
+
{
|
|
1391
|
+
action: a,
|
|
1392
|
+
enableTooltip: true,
|
|
1393
|
+
renderTooltip
|
|
1394
|
+
},
|
|
1395
|
+
a.id
|
|
1396
|
+
)),
|
|
1397
|
+
hidden.length > 0 && renderOverflowMenu({
|
|
1398
|
+
actions: hidden,
|
|
1399
|
+
trigger: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(OverflowTrigger, { ariaLabel: overflowAriaLabel })
|
|
1400
|
+
})
|
|
1401
|
+
] })
|
|
1402
|
+
] });
|
|
1403
|
+
}
|
|
1404
|
+
|
|
1405
|
+
// src/score-ring.tsx
|
|
1406
|
+
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
1407
|
+
var DEFAULT_SCORE_THRESHOLDS = {
|
|
1408
|
+
good: 75,
|
|
1409
|
+
warning: 50
|
|
1410
|
+
};
|
|
1411
|
+
function scoreRingColorClasses(pct, thresholds = DEFAULT_SCORE_THRESHOLDS) {
|
|
1412
|
+
if (pct === null) return "text-muted-foreground";
|
|
1413
|
+
if (pct >= thresholds.good) return "text-green-500";
|
|
1414
|
+
if (pct >= thresholds.warning) return "text-orange-500";
|
|
1415
|
+
return "text-red-500";
|
|
1416
|
+
}
|
|
1417
|
+
function scoreAccentBgClasses(pct, thresholds = DEFAULT_SCORE_THRESHOLDS) {
|
|
1418
|
+
if (pct === null) return "bg-muted-foreground/30";
|
|
1419
|
+
if (pct >= thresholds.good) return "bg-green-500";
|
|
1420
|
+
if (pct >= thresholds.warning) return "bg-orange-500";
|
|
1421
|
+
return "bg-red-500";
|
|
1422
|
+
}
|
|
1423
|
+
function ScoreRing({
|
|
1424
|
+
pct,
|
|
1425
|
+
size = 112,
|
|
1426
|
+
strokeWidth = 8,
|
|
1427
|
+
label,
|
|
1428
|
+
valueClassName,
|
|
1429
|
+
className,
|
|
1430
|
+
thresholds = DEFAULT_SCORE_THRESHOLDS,
|
|
1431
|
+
suffix = "%"
|
|
1432
|
+
}) {
|
|
1433
|
+
const radius = 50 - strokeWidth / 2;
|
|
1434
|
+
const circumference = 2 * Math.PI * radius;
|
|
1435
|
+
const boundedPct = pct === null ? 0 : Math.max(0, Math.min(100, pct));
|
|
1436
|
+
const dashOffset = circumference * (1 - boundedPct / 100);
|
|
1437
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
|
|
1438
|
+
"div",
|
|
1439
|
+
{
|
|
1440
|
+
className: cn(
|
|
1441
|
+
"relative flex shrink-0 items-center justify-center",
|
|
1442
|
+
className
|
|
1443
|
+
),
|
|
1444
|
+
style: { width: size, height: size },
|
|
1445
|
+
role: "img",
|
|
1446
|
+
"aria-label": `${label ?? "Score"}: ${pct === null ? "not available" : `${pct} out of 100`}`,
|
|
1447
|
+
children: [
|
|
1448
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("svg", { viewBox: "0 0 100 100", className: "h-full w-full -rotate-90", children: [
|
|
1449
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1450
|
+
"circle",
|
|
1451
|
+
{
|
|
1452
|
+
cx: "50",
|
|
1453
|
+
cy: "50",
|
|
1454
|
+
r: radius,
|
|
1455
|
+
className: "stroke-muted",
|
|
1456
|
+
strokeWidth,
|
|
1457
|
+
fill: "none"
|
|
1458
|
+
}
|
|
1459
|
+
),
|
|
1460
|
+
pct !== null ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1461
|
+
"circle",
|
|
1462
|
+
{
|
|
1463
|
+
cx: "50",
|
|
1464
|
+
cy: "50",
|
|
1465
|
+
r: radius,
|
|
1466
|
+
className: cn(
|
|
1467
|
+
"transition-[stroke-dashoffset] duration-700 ease-out",
|
|
1468
|
+
scoreRingColorClasses(pct, thresholds)
|
|
1469
|
+
),
|
|
1470
|
+
stroke: "currentColor",
|
|
1471
|
+
strokeWidth,
|
|
1472
|
+
strokeLinecap: "round",
|
|
1473
|
+
fill: "none",
|
|
1474
|
+
strokeDasharray: circumference,
|
|
1475
|
+
strokeDashoffset: dashOffset
|
|
1476
|
+
}
|
|
1477
|
+
) : null
|
|
1478
|
+
] }),
|
|
1479
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "absolute flex flex-col items-center justify-center", children: [
|
|
1480
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1481
|
+
"span",
|
|
1482
|
+
{
|
|
1483
|
+
className: cn(
|
|
1484
|
+
"font-bold tabular-nums text-foreground",
|
|
1485
|
+
valueClassName ?? "text-2xl"
|
|
1486
|
+
),
|
|
1487
|
+
children: pct === null ? "\u2014" : `${pct}${suffix}`
|
|
1488
|
+
}
|
|
1489
|
+
),
|
|
1490
|
+
label ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "max-w-[74px] truncate text-[9px] font-semibold uppercase tracking-wide text-muted-foreground", children: label }) : null
|
|
1491
|
+
] })
|
|
1492
|
+
]
|
|
1493
|
+
}
|
|
1494
|
+
);
|
|
1495
|
+
}
|
|
1496
|
+
|
|
1497
|
+
// src/segmented-control.tsx
|
|
1498
|
+
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
1499
|
+
function SegmentedControl({
|
|
1500
|
+
value,
|
|
1501
|
+
onValueChange,
|
|
1502
|
+
data,
|
|
1503
|
+
name: _name,
|
|
1504
|
+
className,
|
|
1505
|
+
fullWidth = false,
|
|
1506
|
+
size = "md"
|
|
1507
|
+
}) {
|
|
1508
|
+
const sizeClasses = {
|
|
1509
|
+
sm: "h-7 text-xs",
|
|
1510
|
+
md: "h-9 text-sm",
|
|
1511
|
+
lg: "h-10 text-base"
|
|
1512
|
+
};
|
|
1513
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
1514
|
+
"div",
|
|
1515
|
+
{
|
|
1516
|
+
className: cn(
|
|
1517
|
+
"inline-flex p-0.5 bg-muted rounded-md",
|
|
1518
|
+
fullWidth && "w-full",
|
|
1519
|
+
className
|
|
1520
|
+
),
|
|
1521
|
+
role: "tablist",
|
|
1522
|
+
children: data.map((option) => {
|
|
1523
|
+
const isActive = value === option.value;
|
|
1524
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
1525
|
+
"button",
|
|
1526
|
+
{
|
|
1527
|
+
type: "button",
|
|
1528
|
+
role: "tab",
|
|
1529
|
+
"aria-selected": isActive,
|
|
1530
|
+
disabled: option.disabled,
|
|
1531
|
+
onClick: () => onValueChange(option.value),
|
|
1532
|
+
className: cn(
|
|
1533
|
+
"relative flex items-center justify-center rounded-[0.2rem] px-3 py-1.5 transition-all",
|
|
1534
|
+
sizeClasses[size],
|
|
1535
|
+
fullWidth && "flex-1",
|
|
1536
|
+
isActive ? "bg-background text-foreground shadow-sm" : "text-muted-foreground hover:text-foreground hover:bg-background/50",
|
|
1537
|
+
option.disabled && "opacity-50 cursor-not-allowed"
|
|
1538
|
+
),
|
|
1539
|
+
children: option.label
|
|
1540
|
+
},
|
|
1541
|
+
option.value
|
|
1542
|
+
);
|
|
1543
|
+
})
|
|
1544
|
+
}
|
|
1545
|
+
);
|
|
1546
|
+
}
|
|
1547
|
+
|
|
1548
|
+
// src/select.tsx
|
|
1549
|
+
var SelectPrimitive = __toESM(require("@radix-ui/react-select"), 1);
|
|
1550
|
+
var import_class_variance_authority3 = require("class-variance-authority");
|
|
1551
|
+
var React10 = __toESM(require("react"), 1);
|
|
1552
|
+
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
1553
|
+
var Select = SelectPrimitive.Root;
|
|
1554
|
+
var SelectGroup = SelectPrimitive.Group;
|
|
1555
|
+
var SelectValue = SelectPrimitive.Value;
|
|
1556
|
+
var selectTriggerVariants = (0, import_class_variance_authority3.cva)(
|
|
1557
|
+
"flex w-full items-center justify-between whitespace-nowrap rounded-md border border-border bg-card text-sm shadow-sm ring-offset-background placeholder:text-muted-foreground transition-colors hover:bg-accent hover:border-accent-foreground/20 focus:outline-none focus:ring-1 focus:ring-primary/30 focus:border-primary/40 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",
|
|
1558
|
+
{
|
|
1559
|
+
variants: {
|
|
1560
|
+
size: {
|
|
1561
|
+
sm: "h-7 px-2 py-1 text-xs",
|
|
1562
|
+
default: "h-9 px-3 py-1",
|
|
1563
|
+
lg: "h-10 px-3 py-2"
|
|
1564
|
+
}
|
|
1565
|
+
},
|
|
1566
|
+
defaultVariants: {
|
|
1567
|
+
size: "default"
|
|
1568
|
+
}
|
|
1569
|
+
}
|
|
1570
|
+
);
|
|
1571
|
+
var SelectTrigger = React10.forwardRef(({ className, children, hideArrow = false, size, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
|
|
1572
|
+
SelectPrimitive.Trigger,
|
|
1573
|
+
{
|
|
1574
|
+
ref,
|
|
1575
|
+
className: cn(selectTriggerVariants({ size, className })),
|
|
1576
|
+
...props,
|
|
1577
|
+
children: [
|
|
1578
|
+
children,
|
|
1579
|
+
!hideArrow && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(SelectPrimitive.Icon, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(RadixChevronDownIcon, { className: "h-4 w-4 opacity-50" }) })
|
|
1580
|
+
]
|
|
1581
|
+
}
|
|
1582
|
+
));
|
|
1583
|
+
SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
|
|
1584
|
+
var SelectScrollUpButton = React10.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
1585
|
+
SelectPrimitive.ScrollUpButton,
|
|
1586
|
+
{
|
|
1587
|
+
ref,
|
|
1588
|
+
className: cn(
|
|
1589
|
+
"flex cursor-default items-center justify-center py-1",
|
|
1590
|
+
className
|
|
1591
|
+
),
|
|
1592
|
+
...props,
|
|
1593
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(RadixChevronUpIcon, {})
|
|
1594
|
+
}
|
|
1595
|
+
));
|
|
1596
|
+
SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
|
|
1597
|
+
var SelectScrollDownButton = React10.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
1598
|
+
SelectPrimitive.ScrollDownButton,
|
|
1599
|
+
{
|
|
1600
|
+
ref,
|
|
1601
|
+
className: cn(
|
|
1602
|
+
"flex cursor-default items-center justify-center py-1",
|
|
1603
|
+
className
|
|
1604
|
+
),
|
|
1605
|
+
...props,
|
|
1606
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(RadixChevronDownIcon, {})
|
|
1607
|
+
}
|
|
1608
|
+
));
|
|
1609
|
+
SelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName;
|
|
1610
|
+
var SelectContent = React10.forwardRef(({ className, children, position = "popper", container, ...props }, ref) => {
|
|
1611
|
+
const portalContainer = usePortalContainer(container);
|
|
1612
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(SelectPrimitive.Portal, { container: portalContainer, children: /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
|
|
1613
|
+
SelectPrimitive.Content,
|
|
1614
|
+
{
|
|
1615
|
+
ref,
|
|
1616
|
+
className: cn(
|
|
1617
|
+
"relative z-[10001] max-h-96 min-w-[8rem] overflow-hidden rounded-md border bg-popover 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",
|
|
1618
|
+
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",
|
|
1619
|
+
className
|
|
1620
|
+
),
|
|
1621
|
+
position,
|
|
1622
|
+
...props,
|
|
1623
|
+
children: [
|
|
1624
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(SelectScrollUpButton, {}),
|
|
1625
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
1626
|
+
SelectPrimitive.Viewport,
|
|
1627
|
+
{
|
|
1628
|
+
className: cn(
|
|
1629
|
+
"p-0.5 overflow-y-auto",
|
|
1630
|
+
position === "popper" && "w-full min-w-[var(--radix-select-trigger-width)] max-h-[var(--radix-select-content-available-height)]"
|
|
1631
|
+
),
|
|
1632
|
+
children
|
|
1633
|
+
}
|
|
1634
|
+
),
|
|
1635
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(SelectScrollDownButton, {})
|
|
1636
|
+
]
|
|
1637
|
+
}
|
|
1638
|
+
) });
|
|
1639
|
+
});
|
|
1640
|
+
SelectContent.displayName = SelectPrimitive.Content.displayName;
|
|
1641
|
+
var SelectLabel = React10.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
1642
|
+
SelectPrimitive.Label,
|
|
1643
|
+
{
|
|
1644
|
+
ref,
|
|
1645
|
+
className: cn("px-2 py-1.5 text-sm font-semibold", className),
|
|
1646
|
+
...props
|
|
1647
|
+
}
|
|
1648
|
+
));
|
|
1649
|
+
SelectLabel.displayName = SelectPrimitive.Label.displayName;
|
|
1650
|
+
var SelectItem = React10.forwardRef(({ className, children, description, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
|
|
1651
|
+
SelectPrimitive.Item,
|
|
1652
|
+
{
|
|
1653
|
+
ref,
|
|
1654
|
+
className: cn(
|
|
1655
|
+
"relative flex w-full cursor-default select-none rounded-sm py-1 pl-2 pr-8 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
|
1656
|
+
description ? "flex-col items-start gap-0.5 py-1.5" : "items-center",
|
|
1657
|
+
className
|
|
1658
|
+
),
|
|
1659
|
+
...props,
|
|
1660
|
+
children: [
|
|
1661
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "absolute right-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(SelectPrimitive.ItemIndicator, { children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(CheckIcon, { className: "h-4 w-4" }) }) }),
|
|
1662
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(SelectPrimitive.ItemText, { children }),
|
|
1663
|
+
description ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "block text-xs leading-snug text-muted-foreground", children: description }) : null
|
|
1664
|
+
]
|
|
1665
|
+
}
|
|
1666
|
+
));
|
|
1667
|
+
SelectItem.displayName = SelectPrimitive.Item.displayName;
|
|
1668
|
+
var SelectSeparator = React10.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
1669
|
+
SelectPrimitive.Separator,
|
|
1670
|
+
{
|
|
1671
|
+
ref,
|
|
1672
|
+
className: cn("-mx-1 my-1 h-px bg-muted", className),
|
|
1673
|
+
...props
|
|
1674
|
+
}
|
|
1675
|
+
));
|
|
1676
|
+
SelectSeparator.displayName = SelectPrimitive.Separator.displayName;
|
|
1677
|
+
|
|
1678
|
+
// src/separator.tsx
|
|
1679
|
+
var SeparatorPrimitive = __toESM(require("@radix-ui/react-separator"), 1);
|
|
1680
|
+
var React11 = __toESM(require("react"), 1);
|
|
1681
|
+
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
1682
|
+
var Separator2 = React11.forwardRef(({ className, orientation = "horizontal", decorative = true, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
1683
|
+
SeparatorPrimitive.Root,
|
|
1684
|
+
{
|
|
1685
|
+
ref,
|
|
1686
|
+
decorative,
|
|
1687
|
+
orientation,
|
|
1688
|
+
className: cn(
|
|
1689
|
+
"shrink-0 bg-border",
|
|
1690
|
+
orientation === "horizontal" ? "h-px w-full" : "h-full w-px",
|
|
1691
|
+
className
|
|
1692
|
+
),
|
|
1693
|
+
...props
|
|
1694
|
+
}
|
|
1695
|
+
));
|
|
1696
|
+
Separator2.displayName = SeparatorPrimitive.Root.displayName;
|
|
1697
|
+
|
|
1698
|
+
// src/sheet.tsx
|
|
1699
|
+
var SheetPrimitive = __toESM(require("@radix-ui/react-dialog"), 1);
|
|
1700
|
+
var import_react_tree = require("@ai-matrx/kit/react-tree");
|
|
1701
|
+
var import_class_variance_authority4 = require("class-variance-authority");
|
|
1702
|
+
var React12 = __toESM(require("react"), 1);
|
|
1703
|
+
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
1704
|
+
var SheetContentBase = React12.forwardRef(({ ...props }, ref) => {
|
|
1705
|
+
const isModal = useRadixDialogModal();
|
|
1706
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
1707
|
+
SheetPrimitive.Content,
|
|
1708
|
+
{
|
|
1709
|
+
...props,
|
|
1710
|
+
ref,
|
|
1711
|
+
"aria-modal": isModal || void 0
|
|
1712
|
+
}
|
|
1713
|
+
);
|
|
1714
|
+
});
|
|
1715
|
+
SheetContentBase.displayName = "SheetContentBase";
|
|
1716
|
+
var Sheet = React12.forwardRef(({ children, ...props }, _ref) => {
|
|
1717
|
+
const modal = props.modal ?? true;
|
|
1718
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(RadixDialogModalProvider, { modal, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(SheetPrimitive.Root, { ...props, modal, children }) });
|
|
1719
|
+
});
|
|
1720
|
+
Sheet.displayName = "Sheet";
|
|
1721
|
+
var SheetTrigger = SheetPrimitive.Trigger;
|
|
1722
|
+
var SheetClose = SheetPrimitive.Close;
|
|
1723
|
+
var SheetPortal = SheetPrimitive.Portal;
|
|
1724
|
+
var SheetOverlay = React12.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
1725
|
+
SheetPrimitive.Overlay,
|
|
1726
|
+
{
|
|
1727
|
+
className: cn(
|
|
1728
|
+
"fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
1729
|
+
className
|
|
1730
|
+
),
|
|
1731
|
+
...props,
|
|
1732
|
+
ref
|
|
1733
|
+
}
|
|
1734
|
+
));
|
|
1735
|
+
SheetOverlay.displayName = SheetPrimitive.Overlay.displayName;
|
|
1736
|
+
var sheetVariants = (0, import_class_variance_authority4.cva)(
|
|
1737
|
+
"fixed z-50 gap-4 bg-background p-6 shadow-lg transition ease-in-out data-[state=closed]:duration-300 data-[state=open]:duration-500 data-[state=open]:animate-in data-[state=closed]:animate-out",
|
|
1738
|
+
{
|
|
1739
|
+
variants: {
|
|
1740
|
+
side: {
|
|
1741
|
+
top: "inset-x-0 top-0 border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top",
|
|
1742
|
+
bottom: "inset-x-0 bottom-0 border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom",
|
|
1743
|
+
left: "inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm",
|
|
1744
|
+
right: "inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm",
|
|
1745
|
+
center: "inset-0 m-auto max-h-full max-w-full border rounded-lg data-[state=closed]:fade-out data-[state=open]:fade-in"
|
|
1746
|
+
}
|
|
1747
|
+
},
|
|
1748
|
+
defaultVariants: {
|
|
1749
|
+
side: "right"
|
|
1750
|
+
}
|
|
1751
|
+
}
|
|
1752
|
+
);
|
|
1753
|
+
var SheetDescription = React12.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
1754
|
+
SheetPrimitive.Description,
|
|
1755
|
+
{
|
|
1756
|
+
ref,
|
|
1757
|
+
className: cn("text-sm text-muted-foreground", className),
|
|
1758
|
+
...props
|
|
1759
|
+
}
|
|
1760
|
+
));
|
|
1761
|
+
SheetDescription.displayName = SheetPrimitive.Description.displayName;
|
|
1762
|
+
var SheetContent = React12.forwardRef(
|
|
1763
|
+
({
|
|
1764
|
+
side = "right",
|
|
1765
|
+
className,
|
|
1766
|
+
children,
|
|
1767
|
+
hideCloseButton = false,
|
|
1768
|
+
hideOverlay = false,
|
|
1769
|
+
overlayClassName,
|
|
1770
|
+
...props
|
|
1771
|
+
}, ref) => {
|
|
1772
|
+
const hasDescription = (0, import_react_tree.treeContainsComponent)(children, SheetDescription) || (0, import_react_tree.treeContainsComponent)(children, SheetPrimitive.Description);
|
|
1773
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(SheetPortal, { children: [
|
|
1774
|
+
!hideOverlay && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(SheetOverlay, { className: overlayClassName }),
|
|
1775
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
|
|
1776
|
+
SheetContentBase,
|
|
1777
|
+
{
|
|
1778
|
+
ref,
|
|
1779
|
+
className: cn(sheetVariants({ side }), className),
|
|
1780
|
+
...hasDescription ? {} : { "aria-describedby": void 0 },
|
|
1781
|
+
...props,
|
|
1782
|
+
children: [
|
|
1783
|
+
!hideCloseButton && /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(SheetPrimitive.Close, { className: "absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-secondary", children: [
|
|
1784
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Cross2Icon, { className: "h-4 w-4" }),
|
|
1785
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "sr-only", children: "Close" })
|
|
1786
|
+
] }),
|
|
1787
|
+
children
|
|
1788
|
+
]
|
|
1789
|
+
}
|
|
1790
|
+
)
|
|
1791
|
+
] });
|
|
1792
|
+
}
|
|
1793
|
+
);
|
|
1794
|
+
SheetContent.displayName = SheetPrimitive.Content.displayName;
|
|
1795
|
+
var SheetHeader = ({
|
|
1796
|
+
className,
|
|
1797
|
+
...props
|
|
1798
|
+
}) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
1799
|
+
"div",
|
|
1800
|
+
{
|
|
1801
|
+
className: cn(
|
|
1802
|
+
"flex flex-col space-y-2 text-center sm:text-left",
|
|
1803
|
+
className
|
|
1804
|
+
),
|
|
1805
|
+
...props
|
|
1806
|
+
}
|
|
1807
|
+
);
|
|
1808
|
+
SheetHeader.displayName = "SheetHeader";
|
|
1809
|
+
var SheetFooter = ({
|
|
1810
|
+
className,
|
|
1811
|
+
...props
|
|
1812
|
+
}) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
1813
|
+
"div",
|
|
1814
|
+
{
|
|
1815
|
+
className: cn(
|
|
1816
|
+
"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
|
|
1817
|
+
className
|
|
1818
|
+
),
|
|
1819
|
+
...props
|
|
1820
|
+
}
|
|
1821
|
+
);
|
|
1822
|
+
SheetFooter.displayName = "SheetFooter";
|
|
1823
|
+
var SheetTitle = React12.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
1824
|
+
SheetPrimitive.Title,
|
|
1825
|
+
{
|
|
1826
|
+
ref,
|
|
1827
|
+
className: cn("text-lg font-semibold text-foreground", className),
|
|
1828
|
+
...props
|
|
1829
|
+
}
|
|
1830
|
+
));
|
|
1831
|
+
SheetTitle.displayName = SheetPrimitive.Title.displayName;
|
|
1832
|
+
|
|
1833
|
+
// src/skeleton.tsx
|
|
1834
|
+
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
1835
|
+
function Skeleton({
|
|
1836
|
+
className,
|
|
1837
|
+
...props
|
|
1838
|
+
}) {
|
|
1839
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
1840
|
+
"div",
|
|
1841
|
+
{
|
|
1842
|
+
className: cn("animate-pulse rounded-md bg-primary/10", className),
|
|
1843
|
+
...props
|
|
1844
|
+
}
|
|
1845
|
+
);
|
|
1846
|
+
}
|
|
1847
|
+
|
|
1848
|
+
// src/tabbed-bottom-sheet.tsx
|
|
1849
|
+
var import_react4 = require("react");
|
|
1850
|
+
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
1851
|
+
function TabbedBottomSheet({
|
|
1852
|
+
open,
|
|
1853
|
+
onOpenChange,
|
|
1854
|
+
title,
|
|
1855
|
+
tabs
|
|
1856
|
+
}) {
|
|
1857
|
+
const [selectedTabId, setSelectedTabId] = (0, import_react4.useState)(null);
|
|
1858
|
+
const [wasOpen, setWasOpen] = (0, import_react4.useState)(open);
|
|
1859
|
+
if (open !== wasOpen) {
|
|
1860
|
+
setWasOpen(open);
|
|
1861
|
+
if (open) setSelectedTabId(null);
|
|
1862
|
+
}
|
|
1863
|
+
const selectedTab = selectedTabId ? tabs.find((tab) => tab.id === selectedTabId) : null;
|
|
1864
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
1865
|
+
BottomSheet,
|
|
1866
|
+
{
|
|
1867
|
+
open,
|
|
1868
|
+
onOpenChange,
|
|
1869
|
+
title,
|
|
1870
|
+
size: "full",
|
|
1871
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "matrx-mobile-sheet flex min-h-0 flex-1 flex-col", children: [
|
|
1872
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
1873
|
+
BottomSheetHeader,
|
|
1874
|
+
{
|
|
1875
|
+
title: selectedTab ? selectedTab.label : title,
|
|
1876
|
+
showBack: !!selectedTab,
|
|
1877
|
+
onBack: () => setSelectedTabId(null)
|
|
1878
|
+
}
|
|
1879
|
+
),
|
|
1880
|
+
selectedTab ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "flex min-h-0 flex-1 flex-col overflow-hidden pb-safe", children: selectedTab.content }) : /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(BottomSheetBody, { children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("ul", { className: "divide-y divide-border", children: tabs.map((tab) => {
|
|
1881
|
+
const Icon2 = tab.icon;
|
|
1882
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
1883
|
+
"button",
|
|
1884
|
+
{
|
|
1885
|
+
type: "button",
|
|
1886
|
+
onClick: () => setSelectedTabId(tab.id),
|
|
1887
|
+
className: "flex w-full items-center gap-3 px-4 py-3.5 text-left transition-colors hover:bg-muted/60 active:bg-muted",
|
|
1888
|
+
children: [
|
|
1889
|
+
Icon2 ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Icon2, { className: "h-5 w-5 shrink-0 text-muted-foreground" }) : null,
|
|
1890
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "min-w-0 flex-1 text-base text-foreground", children: tab.label }),
|
|
1891
|
+
tab.trailing,
|
|
1892
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ChevronRightIcon, { className: "h-5 w-5 shrink-0 text-muted-foreground" })
|
|
1893
|
+
]
|
|
1894
|
+
}
|
|
1895
|
+
) }, tab.id);
|
|
1896
|
+
}) }) })
|
|
1897
|
+
] })
|
|
1898
|
+
}
|
|
1899
|
+
);
|
|
1900
|
+
}
|
|
1901
|
+
|
|
1902
|
+
// src/use-scroll-fade.ts
|
|
1903
|
+
var import_react5 = require("react");
|
|
1904
|
+
var EPSILON = 2;
|
|
1905
|
+
function useScrollFade() {
|
|
1906
|
+
const [state, setState] = (0, import_react5.useState)({
|
|
1907
|
+
top: false,
|
|
1908
|
+
bottom: false
|
|
1909
|
+
});
|
|
1910
|
+
const nodeRef = (0, import_react5.useRef)(null);
|
|
1911
|
+
const cleanupRef = (0, import_react5.useRef)(null);
|
|
1912
|
+
const measure = (0, import_react5.useCallback)(() => {
|
|
1913
|
+
const el = nodeRef.current;
|
|
1914
|
+
if (!el) return;
|
|
1915
|
+
const overflowing = el.scrollHeight - el.clientHeight > EPSILON;
|
|
1916
|
+
const next = {
|
|
1917
|
+
top: overflowing && el.scrollTop > EPSILON,
|
|
1918
|
+
bottom: overflowing && el.scrollTop + el.clientHeight < el.scrollHeight - EPSILON
|
|
1919
|
+
};
|
|
1920
|
+
setState(
|
|
1921
|
+
(prev) => prev.top === next.top && prev.bottom === next.bottom ? prev : next
|
|
1922
|
+
);
|
|
1923
|
+
}, []);
|
|
1924
|
+
const ref = (0, import_react5.useCallback)(
|
|
1925
|
+
(node) => {
|
|
1926
|
+
cleanupRef.current?.();
|
|
1927
|
+
cleanupRef.current = null;
|
|
1928
|
+
nodeRef.current = node;
|
|
1929
|
+
if (!node) return;
|
|
1930
|
+
node.addEventListener("scroll", measure, { passive: true });
|
|
1931
|
+
const ro = new ResizeObserver(measure);
|
|
1932
|
+
ro.observe(node);
|
|
1933
|
+
const mo = new MutationObserver(measure);
|
|
1934
|
+
mo.observe(node, { childList: true, subtree: true });
|
|
1935
|
+
cleanupRef.current = () => {
|
|
1936
|
+
node.removeEventListener("scroll", measure);
|
|
1937
|
+
ro.disconnect();
|
|
1938
|
+
mo.disconnect();
|
|
1939
|
+
};
|
|
1940
|
+
requestAnimationFrame(measure);
|
|
1941
|
+
},
|
|
1942
|
+
[measure]
|
|
1943
|
+
);
|
|
1944
|
+
(0, import_react5.useEffect)(() => () => cleanupRef.current?.(), []);
|
|
1945
|
+
return {
|
|
1946
|
+
ref,
|
|
1947
|
+
state,
|
|
1948
|
+
fadeProps: {
|
|
1949
|
+
"data-fade-top": state.top ? "" : void 0,
|
|
1950
|
+
"data-fade-bottom": state.bottom ? "" : void 0,
|
|
1951
|
+
className: "matrx-scroll-fade"
|
|
1952
|
+
}
|
|
1953
|
+
};
|
|
1954
|
+
}
|
|
1955
|
+
//# sourceMappingURL=index.cjs.map
|