@memelabui/ui 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +22 -4
- package/dist/index.cjs +1196 -127
- package/dist/index.d.cts +162 -2
- package/dist/index.d.ts +162 -2
- package/dist/index.js +1060 -13
- package/dist/styles/index.css +269 -0
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var React = require('react');
|
|
4
4
|
var jsxRuntime = require('react/jsx-runtime');
|
|
5
5
|
var reactDom = require('react-dom');
|
|
6
6
|
|
|
7
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
8
|
+
|
|
9
|
+
var React__default = /*#__PURE__*/_interopDefault(React);
|
|
10
|
+
|
|
7
11
|
// src/utils/cn.ts
|
|
8
12
|
function toClassName(out, value) {
|
|
9
13
|
if (!value) return;
|
|
@@ -59,16 +63,16 @@ function focusSafely(el) {
|
|
|
59
63
|
}
|
|
60
64
|
}
|
|
61
65
|
function useClipboard(timeout = 2e3) {
|
|
62
|
-
const [copied, setCopied] =
|
|
63
|
-
const timerRef =
|
|
64
|
-
|
|
66
|
+
const [copied, setCopied] = React.useState(false);
|
|
67
|
+
const timerRef = React.useRef(null);
|
|
68
|
+
React.useEffect(() => {
|
|
65
69
|
return () => {
|
|
66
70
|
if (timerRef.current !== null) {
|
|
67
71
|
clearTimeout(timerRef.current);
|
|
68
72
|
}
|
|
69
73
|
};
|
|
70
74
|
}, []);
|
|
71
|
-
const copy =
|
|
75
|
+
const copy = React.useCallback(
|
|
72
76
|
async (text) => {
|
|
73
77
|
try {
|
|
74
78
|
await navigator.clipboard.writeText(text);
|
|
@@ -89,18 +93,18 @@ function useClipboard(timeout = 2e3) {
|
|
|
89
93
|
return { copy, copied };
|
|
90
94
|
}
|
|
91
95
|
function useDisclosure(defaultOpen = false) {
|
|
92
|
-
const [isOpen, setIsOpen] =
|
|
93
|
-
const open =
|
|
94
|
-
const close =
|
|
95
|
-
const toggle =
|
|
96
|
+
const [isOpen, setIsOpen] = React.useState(defaultOpen);
|
|
97
|
+
const open = React.useCallback(() => setIsOpen(true), []);
|
|
98
|
+
const close = React.useCallback(() => setIsOpen(false), []);
|
|
99
|
+
const toggle = React.useCallback(() => setIsOpen((prev) => !prev), []);
|
|
96
100
|
return { isOpen, open, close, toggle };
|
|
97
101
|
}
|
|
98
102
|
function useMediaQuery(query) {
|
|
99
|
-
const [matches, setMatches] =
|
|
103
|
+
const [matches, setMatches] = React.useState(() => {
|
|
100
104
|
if (typeof window === "undefined") return false;
|
|
101
105
|
return window.matchMedia(query).matches;
|
|
102
106
|
});
|
|
103
|
-
|
|
107
|
+
React.useEffect(() => {
|
|
104
108
|
if (typeof window === "undefined") return;
|
|
105
109
|
const mediaQueryList = window.matchMedia(query);
|
|
106
110
|
setMatches(mediaQueryList.matches);
|
|
@@ -115,8 +119,8 @@ function useMediaQuery(query) {
|
|
|
115
119
|
return matches;
|
|
116
120
|
}
|
|
117
121
|
function useDebounce(value, delayMs = 300) {
|
|
118
|
-
const [debouncedValue, setDebouncedValue] =
|
|
119
|
-
|
|
122
|
+
const [debouncedValue, setDebouncedValue] = React.useState(value);
|
|
123
|
+
React.useEffect(() => {
|
|
120
124
|
const timer = setTimeout(() => {
|
|
121
125
|
setDebouncedValue(value);
|
|
122
126
|
}, delayMs);
|
|
@@ -146,8 +150,56 @@ var colors = {
|
|
|
146
150
|
warning: "#f59e0b",
|
|
147
151
|
danger: "#f43f5e"
|
|
148
152
|
};
|
|
149
|
-
var base = "inline-flex items-center justify-center gap-2 rounded-xl font-semibold leading-none transition-[transform,background-color,box-shadow,opacity] select-none [-webkit-tap-highlight-color:transparent] active:translate-y-[0.5px] disabled:opacity-60 disabled:pointer-events-none focus-visible:ring-2 focus-visible:ring-primary/40 focus-visible:ring-offset-2 focus-visible:ring-offset-transparent";
|
|
150
153
|
var sizeClass = {
|
|
154
|
+
sm: "w-8 h-8 text-xs",
|
|
155
|
+
md: "w-10 h-10 text-sm",
|
|
156
|
+
lg: "w-12 h-12 text-base",
|
|
157
|
+
xl: "w-16 h-16 text-lg"
|
|
158
|
+
};
|
|
159
|
+
function getInitials(name) {
|
|
160
|
+
if (!name) return "";
|
|
161
|
+
const parts = name.trim().split(/\s+/);
|
|
162
|
+
const first = parts[0]?.[0] ?? "";
|
|
163
|
+
const second = parts[1]?.[0] ?? "";
|
|
164
|
+
return (first + second).toUpperCase();
|
|
165
|
+
}
|
|
166
|
+
var Avatar = React.forwardRef(function Avatar2({ src, alt, name, size = "md", className }, ref) {
|
|
167
|
+
const [imgError, setImgError] = React.useState(false);
|
|
168
|
+
const showFallback = !src || imgError;
|
|
169
|
+
const initials = getInitials(name);
|
|
170
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
171
|
+
"div",
|
|
172
|
+
{
|
|
173
|
+
ref,
|
|
174
|
+
className: cn(
|
|
175
|
+
"relative inline-flex items-center justify-center shrink-0 rounded-full overflow-hidden ring-1 ring-white/10",
|
|
176
|
+
sizeClass[size],
|
|
177
|
+
className
|
|
178
|
+
),
|
|
179
|
+
children: [
|
|
180
|
+
!showFallback && /* @__PURE__ */ jsxRuntime.jsx(
|
|
181
|
+
"img",
|
|
182
|
+
{
|
|
183
|
+
src,
|
|
184
|
+
alt: alt ?? name ?? "",
|
|
185
|
+
onError: () => setImgError(true),
|
|
186
|
+
className: "w-full h-full object-cover"
|
|
187
|
+
}
|
|
188
|
+
),
|
|
189
|
+
showFallback && /* @__PURE__ */ jsxRuntime.jsx(
|
|
190
|
+
"span",
|
|
191
|
+
{
|
|
192
|
+
"aria-label": name,
|
|
193
|
+
className: "w-full h-full inline-flex items-center justify-center bg-gradient-to-br from-primary to-accent font-semibold text-white leading-none select-none",
|
|
194
|
+
children: initials
|
|
195
|
+
}
|
|
196
|
+
)
|
|
197
|
+
]
|
|
198
|
+
}
|
|
199
|
+
);
|
|
200
|
+
});
|
|
201
|
+
var base = "inline-flex items-center justify-center gap-2 rounded-xl font-semibold leading-none transition-[transform,background-color,box-shadow,opacity] select-none [-webkit-tap-highlight-color:transparent] active:translate-y-[0.5px] disabled:opacity-60 disabled:pointer-events-none focus-visible:ring-2 focus-visible:ring-primary/40 focus-visible:ring-offset-2 focus-visible:ring-offset-transparent";
|
|
202
|
+
var sizeClass2 = {
|
|
151
203
|
sm: "px-3 py-2 text-sm",
|
|
152
204
|
md: "px-3.5 py-2.5 text-sm",
|
|
153
205
|
lg: "px-4 py-3 text-base"
|
|
@@ -160,7 +212,7 @@ var variantClass = {
|
|
|
160
212
|
secondary: "text-white bg-white/5 ring-1 ring-white/10 hover:bg-white/10 hover:ring-white/20 backdrop-blur-sm",
|
|
161
213
|
ghost: "text-white/70 hover:text-white hover:bg-white/5"
|
|
162
214
|
};
|
|
163
|
-
var Button =
|
|
215
|
+
var Button = React.forwardRef(function Button2({ variant = "secondary", size = "md", leftIcon, rightIcon, loading, className, disabled, children, type, ...props }, ref) {
|
|
164
216
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
165
217
|
"button",
|
|
166
218
|
{
|
|
@@ -169,7 +221,7 @@ var Button = react.forwardRef(function Button2({ variant = "secondary", size = "
|
|
|
169
221
|
...props,
|
|
170
222
|
disabled: disabled || loading,
|
|
171
223
|
...loading ? { "aria-busy": true } : {},
|
|
172
|
-
className: cn(base,
|
|
224
|
+
className: cn(base, sizeClass2[size], variantClass[variant], className),
|
|
173
225
|
children: loading ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center justify-center gap-2", children: [
|
|
174
226
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "w-4 h-4 border-2 border-white/30 border-t-white rounded-full animate-spin" }),
|
|
175
227
|
children
|
|
@@ -182,7 +234,7 @@ var Button = react.forwardRef(function Button2({ variant = "secondary", size = "
|
|
|
182
234
|
);
|
|
183
235
|
});
|
|
184
236
|
var base2 = "inline-flex items-center justify-center rounded-xl font-semibold leading-none transition-[transform,background-color,box-shadow,opacity] select-none [-webkit-tap-highlight-color:transparent] active:translate-y-[0.5px] disabled:opacity-60 disabled:pointer-events-none focus-visible:ring-2 focus-visible:ring-primary/40 focus-visible:ring-offset-2 focus-visible:ring-offset-transparent";
|
|
185
|
-
var
|
|
237
|
+
var sizeClass3 = {
|
|
186
238
|
sm: "p-1.5 w-7 h-7",
|
|
187
239
|
md: "p-2 w-9 h-9",
|
|
188
240
|
lg: "p-2.5 w-11 h-11"
|
|
@@ -195,7 +247,7 @@ var variantClass2 = {
|
|
|
195
247
|
secondary: "text-white bg-white/10 shadow-sm ring-1 ring-white/10",
|
|
196
248
|
ghost: "text-white hover:bg-white/10"
|
|
197
249
|
};
|
|
198
|
-
var IconButton =
|
|
250
|
+
var IconButton = React.forwardRef(function IconButton2({ icon, variant = "ghost", size = "md", className, disabled, type, ...props }, ref) {
|
|
199
251
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
200
252
|
"button",
|
|
201
253
|
{
|
|
@@ -203,14 +255,14 @@ var IconButton = react.forwardRef(function IconButton2({ icon, variant = "ghost"
|
|
|
203
255
|
type: type === "submit" ? "submit" : type === "reset" ? "reset" : "button",
|
|
204
256
|
...props,
|
|
205
257
|
disabled,
|
|
206
|
-
className: cn(base2,
|
|
258
|
+
className: cn(base2, sizeClass3[size], variantClass2[variant], className),
|
|
207
259
|
children: /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", children: icon })
|
|
208
260
|
}
|
|
209
261
|
);
|
|
210
262
|
});
|
|
211
263
|
var inputBase = "w-full rounded-xl px-3 py-2.5 text-sm bg-white/10 text-white shadow-sm outline-none placeholder-white/30 focus-visible:ring-2 focus-visible:ring-primary/40 transition-shadow";
|
|
212
|
-
var Input =
|
|
213
|
-
const generatedId =
|
|
264
|
+
var Input = React.forwardRef(function Input2({ hasError, label, error, helperText, className, id: externalId, ...props }, ref) {
|
|
265
|
+
const generatedId = React.useId();
|
|
214
266
|
const inputId = externalId || generatedId;
|
|
215
267
|
const showError = hasError || !!error;
|
|
216
268
|
const errorId = error ? `${inputId}-error` : void 0;
|
|
@@ -235,8 +287,8 @@ var Input = react.forwardRef(function Input2({ hasError, label, error, helperTex
|
|
|
235
287
|
] });
|
|
236
288
|
});
|
|
237
289
|
var inputBase2 = "w-full rounded-xl pl-10 pr-3 py-2.5 text-sm bg-white/10 text-white shadow-sm outline-none placeholder-white/30 focus-visible:ring-2 focus-visible:ring-primary/40 transition-shadow";
|
|
238
|
-
var SearchInput =
|
|
239
|
-
const generatedId =
|
|
290
|
+
var SearchInput = React.forwardRef(function SearchInput2({ label, onClear, className, id: externalId, placeholder = "Search...", value, ...props }, ref) {
|
|
291
|
+
const generatedId = React.useId();
|
|
240
292
|
const inputId = externalId || generatedId;
|
|
241
293
|
const hasValue = value !== void 0 && value !== "";
|
|
242
294
|
const wrapper = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
|
|
@@ -307,8 +359,8 @@ var SearchInput = react.forwardRef(function SearchInput2({ label, onClear, class
|
|
|
307
359
|
] });
|
|
308
360
|
});
|
|
309
361
|
var selectBase = "w-full rounded-xl px-3 py-2.5 text-sm bg-white/10 text-white shadow-sm outline-none focus-visible:ring-2 focus-visible:ring-primary/40 transition-shadow";
|
|
310
|
-
var Select =
|
|
311
|
-
const generatedId =
|
|
362
|
+
var Select = React.forwardRef(function Select2({ hasError, label, error, helperText, className, id: externalId, children, ...props }, ref) {
|
|
363
|
+
const generatedId = React.useId();
|
|
312
364
|
const selectId = externalId || generatedId;
|
|
313
365
|
const showError = hasError || !!error;
|
|
314
366
|
const errorId = error ? `${selectId}-error` : void 0;
|
|
@@ -334,8 +386,8 @@ var Select = react.forwardRef(function Select2({ hasError, label, error, helperT
|
|
|
334
386
|
] });
|
|
335
387
|
});
|
|
336
388
|
var textareaBase = "w-full rounded-xl px-3 py-2.5 text-sm bg-white/10 text-white shadow-sm outline-none placeholder-white/30 focus-visible:ring-2 focus-visible:ring-primary/40 transition-shadow resize-y";
|
|
337
|
-
var Textarea =
|
|
338
|
-
const generatedId =
|
|
389
|
+
var Textarea = React.forwardRef(function Textarea2({ hasError, label, error, helperText, className, id: externalId, ...props }, ref) {
|
|
390
|
+
const generatedId = React.useId();
|
|
339
391
|
const textareaId = externalId || generatedId;
|
|
340
392
|
const showError = hasError || !!error;
|
|
341
393
|
const errorId = error ? `${textareaId}-error` : void 0;
|
|
@@ -359,8 +411,128 @@ var Textarea = react.forwardRef(function Textarea2({ hasError, label, error, hel
|
|
|
359
411
|
helperText && !error && /* @__PURE__ */ jsxRuntime.jsx("p", { id: helperId, className: "text-white/40 text-xs mt-1", children: helperText })
|
|
360
412
|
] });
|
|
361
413
|
});
|
|
414
|
+
function TagInput({
|
|
415
|
+
value,
|
|
416
|
+
onChange,
|
|
417
|
+
placeholder,
|
|
418
|
+
disabled = false,
|
|
419
|
+
label,
|
|
420
|
+
error,
|
|
421
|
+
maxTags,
|
|
422
|
+
className,
|
|
423
|
+
id: externalId
|
|
424
|
+
}) {
|
|
425
|
+
const generatedId = React.useId();
|
|
426
|
+
const inputId = externalId ?? generatedId;
|
|
427
|
+
const errorId = error ? `${inputId}-error` : void 0;
|
|
428
|
+
const inputRef = React.useRef(null);
|
|
429
|
+
const atMax = maxTags !== void 0 && value.length >= maxTags;
|
|
430
|
+
function addTag(raw) {
|
|
431
|
+
const tag = raw.trim();
|
|
432
|
+
if (!tag || value.includes(tag) || atMax) return;
|
|
433
|
+
onChange([...value, tag]);
|
|
434
|
+
}
|
|
435
|
+
function removeTag(index) {
|
|
436
|
+
onChange(value.filter((_, i) => i !== index));
|
|
437
|
+
}
|
|
438
|
+
function handleKeyDown(e) {
|
|
439
|
+
const input = inputRef.current;
|
|
440
|
+
if (!input) return;
|
|
441
|
+
if (e.key === "Enter" || e.key === "," || e.key === "Tab") {
|
|
442
|
+
if (input.value) {
|
|
443
|
+
e.preventDefault();
|
|
444
|
+
addTag(input.value);
|
|
445
|
+
input.value = "";
|
|
446
|
+
}
|
|
447
|
+
return;
|
|
448
|
+
}
|
|
449
|
+
if (e.key === "Backspace" && !input.value && value.length > 0) {
|
|
450
|
+
removeTag(value.length - 1);
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
function handlePaste(e) {
|
|
454
|
+
const pasted = e.clipboardData.getData("text");
|
|
455
|
+
if (!pasted.includes(",")) return;
|
|
456
|
+
e.preventDefault();
|
|
457
|
+
const parts = pasted.split(",");
|
|
458
|
+
const next = [...value];
|
|
459
|
+
for (const part of parts) {
|
|
460
|
+
const tag = part.trim();
|
|
461
|
+
if (tag && !next.includes(tag)) {
|
|
462
|
+
if (maxTags !== void 0 && next.length >= maxTags) break;
|
|
463
|
+
next.push(tag);
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
onChange(next);
|
|
467
|
+
if (inputRef.current) inputRef.current.value = "";
|
|
468
|
+
}
|
|
469
|
+
const wrapper = /* @__PURE__ */ jsxRuntime.jsxs(
|
|
470
|
+
"div",
|
|
471
|
+
{
|
|
472
|
+
className: cn(
|
|
473
|
+
"flex flex-wrap items-center gap-1.5 min-h-[42px] w-full rounded-xl px-3 py-2 bg-white/10 ring-1 ring-white/10 transition-shadow focus-within:ring-2 focus-within:ring-primary/40",
|
|
474
|
+
error && "ring-2 ring-rose-500/40 focus-within:ring-rose-500/40",
|
|
475
|
+
disabled && "opacity-50 cursor-not-allowed",
|
|
476
|
+
className
|
|
477
|
+
),
|
|
478
|
+
onClick: () => inputRef.current?.focus(),
|
|
479
|
+
children: [
|
|
480
|
+
value.map((tag, i) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
481
|
+
"span",
|
|
482
|
+
{
|
|
483
|
+
className: "inline-flex items-center gap-1 bg-white/10 text-white/90 rounded-full text-xs px-2.5 py-1 ring-1 ring-white/10",
|
|
484
|
+
children: [
|
|
485
|
+
tag,
|
|
486
|
+
!disabled && /* @__PURE__ */ jsxRuntime.jsx(
|
|
487
|
+
"button",
|
|
488
|
+
{
|
|
489
|
+
type: "button",
|
|
490
|
+
"aria-label": `Remove ${tag}`,
|
|
491
|
+
onClick: (e) => {
|
|
492
|
+
e.stopPropagation();
|
|
493
|
+
removeTag(i);
|
|
494
|
+
},
|
|
495
|
+
className: "text-white/50 hover:text-white/90 transition-colors leading-none",
|
|
496
|
+
children: "\u2715"
|
|
497
|
+
}
|
|
498
|
+
)
|
|
499
|
+
]
|
|
500
|
+
},
|
|
501
|
+
`${tag}-${i}`
|
|
502
|
+
)),
|
|
503
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
504
|
+
"input",
|
|
505
|
+
{
|
|
506
|
+
ref: inputRef,
|
|
507
|
+
id: inputId,
|
|
508
|
+
type: "text",
|
|
509
|
+
disabled: disabled || atMax,
|
|
510
|
+
placeholder: value.length === 0 ? placeholder : void 0,
|
|
511
|
+
"aria-invalid": !!error || void 0,
|
|
512
|
+
"aria-describedby": errorId,
|
|
513
|
+
onKeyDown: handleKeyDown,
|
|
514
|
+
onPaste: handlePaste,
|
|
515
|
+
onBlur: (e) => {
|
|
516
|
+
if (e.target.value) {
|
|
517
|
+
addTag(e.target.value);
|
|
518
|
+
e.target.value = "";
|
|
519
|
+
}
|
|
520
|
+
},
|
|
521
|
+
className: "flex-1 min-w-[120px] bg-transparent text-sm text-white outline-none placeholder-white/30 disabled:cursor-not-allowed"
|
|
522
|
+
}
|
|
523
|
+
)
|
|
524
|
+
]
|
|
525
|
+
}
|
|
526
|
+
);
|
|
527
|
+
if (!label && !error) return wrapper;
|
|
528
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
529
|
+
label && /* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: inputId, className: "block text-sm text-white/70 mb-1.5", children: label }),
|
|
530
|
+
wrapper,
|
|
531
|
+
error && /* @__PURE__ */ jsxRuntime.jsx("p", { id: errorId, className: "text-rose-400 text-xs mt-1", children: error })
|
|
532
|
+
] });
|
|
533
|
+
}
|
|
362
534
|
var base3 = "inline-flex items-center justify-center rounded-full font-semibold ring-1 ring-white/10";
|
|
363
|
-
var
|
|
535
|
+
var sizeClass4 = {
|
|
364
536
|
sm: "text-xs px-2.5 py-1",
|
|
365
537
|
md: "text-sm px-3 py-1.5"
|
|
366
538
|
};
|
|
@@ -374,8 +546,8 @@ var variantClass3 = {
|
|
|
374
546
|
dangerSolid: "bg-rose-600 text-white ring-0",
|
|
375
547
|
accent: "bg-accent/15 text-accent-light ring-accent/20"
|
|
376
548
|
};
|
|
377
|
-
var Badge =
|
|
378
|
-
return /* @__PURE__ */ jsxRuntime.jsx("span", { ref, ...props, className: cn(base3,
|
|
549
|
+
var Badge = React.forwardRef(function Badge2({ children, variant = "neutral", size = "sm", className, ...props }, ref) {
|
|
550
|
+
return /* @__PURE__ */ jsxRuntime.jsx("span", { ref, ...props, className: cn(base3, sizeClass4[size], variantClass3[variant], className), children });
|
|
379
551
|
});
|
|
380
552
|
var Pill = Badge;
|
|
381
553
|
var trackSize = {
|
|
@@ -386,8 +558,8 @@ var thumbSize = {
|
|
|
386
558
|
sm: { base: "w-4 h-4", translate: "translate-x-4" },
|
|
387
559
|
md: { base: "w-5 h-5", translate: "translate-x-5" }
|
|
388
560
|
};
|
|
389
|
-
var Toggle =
|
|
390
|
-
const generatedId =
|
|
561
|
+
var Toggle = React.forwardRef(function Toggle2({ checked, onChange, disabled, label, size = "md", id: externalId, "aria-label": ariaLabel }, ref) {
|
|
562
|
+
const generatedId = React.useId();
|
|
391
563
|
const toggleId = externalId || generatedId;
|
|
392
564
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
|
|
393
565
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -422,12 +594,180 @@ var Toggle = react.forwardRef(function Toggle2({ checked, onChange, disabled, la
|
|
|
422
594
|
label && /* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: toggleId, className: "text-sm text-white/60 cursor-pointer", children: label })
|
|
423
595
|
] });
|
|
424
596
|
});
|
|
425
|
-
var
|
|
426
|
-
|
|
597
|
+
var Slider = React.forwardRef(function Slider2({
|
|
598
|
+
label,
|
|
599
|
+
showValue = false,
|
|
600
|
+
formatValue,
|
|
601
|
+
onChange,
|
|
602
|
+
disabled,
|
|
603
|
+
min = 0,
|
|
604
|
+
max = 100,
|
|
605
|
+
step = 1,
|
|
606
|
+
value,
|
|
607
|
+
defaultValue,
|
|
608
|
+
className,
|
|
609
|
+
id: externalId,
|
|
610
|
+
...props
|
|
611
|
+
}, ref) {
|
|
612
|
+
const generatedId = React.useId();
|
|
613
|
+
const sliderId = externalId || generatedId;
|
|
614
|
+
const numericValue = React.useMemo(() => {
|
|
615
|
+
const raw = value !== void 0 ? value : defaultValue;
|
|
616
|
+
return raw !== void 0 ? Number(raw) : Number(min);
|
|
617
|
+
}, [value, defaultValue, min]);
|
|
618
|
+
const percentage = React.useMemo(() => {
|
|
619
|
+
const numMin = Number(min);
|
|
620
|
+
const numMax = Number(max);
|
|
621
|
+
if (numMax === numMin) return 0;
|
|
622
|
+
return Math.max(0, Math.min(100, (numericValue - numMin) / (numMax - numMin) * 100));
|
|
623
|
+
}, [numericValue, min, max]);
|
|
624
|
+
const trackGradient = `linear-gradient(to right, var(--ml-primary, #8b5cf6) ${percentage}%, rgba(255,255,255,0.1) ${percentage}%)`;
|
|
625
|
+
const displayValue = formatValue ? formatValue(numericValue) : String(numericValue);
|
|
626
|
+
const handleChange = (e) => {
|
|
627
|
+
onChange?.(Number(e.target.value));
|
|
628
|
+
};
|
|
629
|
+
const inputEl = /* @__PURE__ */ jsxRuntime.jsx(
|
|
630
|
+
"input",
|
|
631
|
+
{
|
|
632
|
+
...props,
|
|
633
|
+
ref,
|
|
634
|
+
id: sliderId,
|
|
635
|
+
type: "range",
|
|
636
|
+
min,
|
|
637
|
+
max,
|
|
638
|
+
step,
|
|
639
|
+
value,
|
|
640
|
+
defaultValue: value === void 0 ? defaultValue ?? Number(min) : void 0,
|
|
641
|
+
disabled,
|
|
642
|
+
onChange: handleChange,
|
|
643
|
+
style: { background: trackGradient },
|
|
644
|
+
className: cn(
|
|
645
|
+
// Layout + reset
|
|
646
|
+
"w-full h-2 appearance-none rounded-full outline-none cursor-pointer",
|
|
647
|
+
// bg is set via inline style (trackGradient); keep transparent fallback for SSR
|
|
648
|
+
"bg-white/10",
|
|
649
|
+
// Webkit thumb
|
|
650
|
+
"[&::-webkit-slider-thumb]:appearance-none",
|
|
651
|
+
"[&::-webkit-slider-thumb]:w-4",
|
|
652
|
+
"[&::-webkit-slider-thumb]:h-4",
|
|
653
|
+
"[&::-webkit-slider-thumb]:rounded-full",
|
|
654
|
+
"[&::-webkit-slider-thumb]:bg-white",
|
|
655
|
+
"[&::-webkit-slider-thumb]:border-2",
|
|
656
|
+
"[&::-webkit-slider-thumb]:border-[var(--ml-primary,#8b5cf6)]",
|
|
657
|
+
"[&::-webkit-slider-thumb]:transition-shadow",
|
|
658
|
+
"[&::-webkit-slider-thumb]:duration-150",
|
|
659
|
+
// Moz thumb
|
|
660
|
+
"[&::-moz-range-thumb]:w-4",
|
|
661
|
+
"[&::-moz-range-thumb]:h-4",
|
|
662
|
+
"[&::-moz-range-thumb]:rounded-full",
|
|
663
|
+
"[&::-moz-range-thumb]:bg-white",
|
|
664
|
+
"[&::-moz-range-thumb]:border-2",
|
|
665
|
+
"[&::-moz-range-thumb]:border-[var(--ml-primary,#8b5cf6)]",
|
|
666
|
+
"[&::-moz-range-thumb]:transition-shadow",
|
|
667
|
+
"[&::-moz-range-thumb]:duration-150",
|
|
668
|
+
// Moz track — transparent so the gradient on the element shows through
|
|
669
|
+
"[&::-moz-range-track]:bg-transparent",
|
|
670
|
+
"[&::-moz-range-track]:rounded-full",
|
|
671
|
+
// Focus ring on thumb
|
|
672
|
+
"focus-visible:outline-none",
|
|
673
|
+
"focus-visible:[&::-webkit-slider-thumb]:ring-2",
|
|
674
|
+
"focus-visible:[&::-webkit-slider-thumb]:ring-primary/40",
|
|
675
|
+
"focus-visible:[&::-webkit-slider-thumb]:ring-offset-2",
|
|
676
|
+
"focus-visible:[&::-webkit-slider-thumb]:ring-offset-surface",
|
|
677
|
+
"focus-visible:[&::-moz-range-thumb]:ring-2",
|
|
678
|
+
"focus-visible:[&::-moz-range-thumb]:ring-primary/40",
|
|
679
|
+
// Disabled
|
|
680
|
+
disabled && "opacity-50 cursor-not-allowed",
|
|
681
|
+
className
|
|
682
|
+
)
|
|
683
|
+
}
|
|
684
|
+
);
|
|
685
|
+
if (!label && !showValue) return inputEl;
|
|
686
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-full space-y-1.5", children: [
|
|
687
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-2", children: [
|
|
688
|
+
label && /* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: sliderId, className: "text-sm text-white/70", children: label }),
|
|
689
|
+
showValue && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium text-white/90 tabular-nums ml-auto", children: displayValue })
|
|
690
|
+
] }),
|
|
691
|
+
inputEl
|
|
692
|
+
] });
|
|
693
|
+
});
|
|
694
|
+
var ColorInput = React.forwardRef(function ColorInput2({ value, onChange, label, disabled, className, id: idProp }, ref) {
|
|
695
|
+
const autoId = React.useId();
|
|
696
|
+
const id = idProp ?? autoId;
|
|
697
|
+
const nativePickerRef = React.useRef(null);
|
|
698
|
+
function handleSwatchClick() {
|
|
699
|
+
if (!disabled) {
|
|
700
|
+
nativePickerRef.current?.click();
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
function handleTextChange(e) {
|
|
704
|
+
onChange(e.target.value);
|
|
705
|
+
}
|
|
706
|
+
function handleNativeChange(e) {
|
|
707
|
+
onChange(e.target.value);
|
|
708
|
+
}
|
|
709
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex flex-col gap-1.5", className), children: [
|
|
710
|
+
label ? /* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: id, className: "block text-sm text-white/70", children: label }) : null,
|
|
711
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
712
|
+
"div",
|
|
713
|
+
{
|
|
714
|
+
className: cn(
|
|
715
|
+
"flex items-center gap-2 bg-white/10 rounded-xl ring-1 ring-white/10 px-3 py-2 transition-shadow",
|
|
716
|
+
"focus-within:ring-2 focus-within:ring-primary/40",
|
|
717
|
+
disabled && "opacity-60 pointer-events-none"
|
|
718
|
+
),
|
|
719
|
+
children: [
|
|
720
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
721
|
+
"input",
|
|
722
|
+
{
|
|
723
|
+
type: "color",
|
|
724
|
+
ref: nativePickerRef,
|
|
725
|
+
value,
|
|
726
|
+
onChange: handleNativeChange,
|
|
727
|
+
disabled,
|
|
728
|
+
"aria-hidden": "true",
|
|
729
|
+
tabIndex: -1,
|
|
730
|
+
className: "sr-only"
|
|
731
|
+
}
|
|
732
|
+
),
|
|
733
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
734
|
+
"button",
|
|
735
|
+
{
|
|
736
|
+
type: "button",
|
|
737
|
+
onClick: handleSwatchClick,
|
|
738
|
+
disabled,
|
|
739
|
+
"aria-label": "Open color picker",
|
|
740
|
+
className: cn(
|
|
741
|
+
"w-8 h-8 rounded-lg border border-white/20 flex-shrink-0 transition-transform hover:scale-105 active:scale-95 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/60"
|
|
742
|
+
),
|
|
743
|
+
style: { backgroundColor: value }
|
|
744
|
+
}
|
|
745
|
+
),
|
|
746
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
747
|
+
"input",
|
|
748
|
+
{
|
|
749
|
+
ref,
|
|
750
|
+
id,
|
|
751
|
+
type: "text",
|
|
752
|
+
value,
|
|
753
|
+
onChange: handleTextChange,
|
|
754
|
+
disabled,
|
|
755
|
+
spellCheck: false,
|
|
756
|
+
className: "flex-1 min-w-0 bg-transparent text-sm text-white placeholder:text-white/30 outline-none font-mono",
|
|
757
|
+
placeholder: "#000000"
|
|
758
|
+
}
|
|
759
|
+
)
|
|
760
|
+
]
|
|
761
|
+
}
|
|
762
|
+
)
|
|
763
|
+
] });
|
|
764
|
+
});
|
|
765
|
+
var Checkbox = React.forwardRef(function Checkbox2({ label, error, indeterminate, className, id: externalId, disabled, checked, onChange, ...props }, ref) {
|
|
766
|
+
const generatedId = React.useId();
|
|
427
767
|
const inputId = externalId || generatedId;
|
|
428
768
|
const errorId = error ? `${inputId}-error` : void 0;
|
|
429
|
-
const internalRef =
|
|
430
|
-
|
|
769
|
+
const internalRef = React.useRef(null);
|
|
770
|
+
React.useEffect(() => {
|
|
431
771
|
const el = internalRef.current;
|
|
432
772
|
if (el) {
|
|
433
773
|
el.indeterminate = indeterminate ?? false;
|
|
@@ -514,9 +854,9 @@ var Checkbox = react.forwardRef(function Checkbox2({ label, error, indeterminate
|
|
|
514
854
|
error && /* @__PURE__ */ jsxRuntime.jsx("p", { id: errorId, className: "text-rose-400 text-xs ml-7", children: error })
|
|
515
855
|
] });
|
|
516
856
|
});
|
|
517
|
-
var RadioGroupContext =
|
|
857
|
+
var RadioGroupContext = React.createContext(null);
|
|
518
858
|
function useRadioGroup() {
|
|
519
|
-
const ctx =
|
|
859
|
+
const ctx = React.useContext(RadioGroupContext);
|
|
520
860
|
if (!ctx) {
|
|
521
861
|
throw new Error("RadioItem must be used inside a RadioGroup");
|
|
522
862
|
}
|
|
@@ -534,13 +874,13 @@ function RadioGroup({
|
|
|
534
874
|
children,
|
|
535
875
|
className
|
|
536
876
|
}) {
|
|
537
|
-
const groupId =
|
|
538
|
-
const generatedName =
|
|
877
|
+
const groupId = React.useId();
|
|
878
|
+
const generatedName = React.useId();
|
|
539
879
|
const name = externalName ?? generatedName;
|
|
540
|
-
const [uncontrolledValue, setUncontrolledValue] =
|
|
880
|
+
const [uncontrolledValue, setUncontrolledValue] = React.useState(defaultValue);
|
|
541
881
|
const isControlled = controlledValue !== void 0;
|
|
542
882
|
const currentValue = isControlled ? controlledValue : uncontrolledValue;
|
|
543
|
-
const handleChange =
|
|
883
|
+
const handleChange = React.useCallback(
|
|
544
884
|
(val) => {
|
|
545
885
|
if (!isControlled) setUncontrolledValue(val);
|
|
546
886
|
onValueChange?.(val);
|
|
@@ -549,7 +889,7 @@ function RadioGroup({
|
|
|
549
889
|
);
|
|
550
890
|
const labelId = label ? `${groupId}-label` : void 0;
|
|
551
891
|
const errorId = error ? `${groupId}-error` : void 0;
|
|
552
|
-
const ctxValue =
|
|
892
|
+
const ctxValue = React.useMemo(
|
|
553
893
|
() => ({ value: currentValue, onChange: handleChange, name, disabled, groupId }),
|
|
554
894
|
[currentValue, handleChange, name, disabled, groupId]
|
|
555
895
|
);
|
|
@@ -580,8 +920,8 @@ function RadioGroup({
|
|
|
580
920
|
}
|
|
581
921
|
function RadioItem({ value, disabled: itemDisabled, children, className }) {
|
|
582
922
|
const { value: groupValue, onChange, name, disabled: groupDisabled, groupId } = useRadioGroup();
|
|
583
|
-
const inputId =
|
|
584
|
-
const inputRef =
|
|
923
|
+
const inputId = React.useId();
|
|
924
|
+
const inputRef = React.useRef(null);
|
|
585
925
|
const isDisabled = groupDisabled || itemDisabled;
|
|
586
926
|
const isSelected = groupValue === value;
|
|
587
927
|
const handleKeyDown = (e) => {
|
|
@@ -647,7 +987,7 @@ function RadioItem({ value, disabled: itemDisabled, children, className }) {
|
|
|
647
987
|
}
|
|
648
988
|
);
|
|
649
989
|
}
|
|
650
|
-
var
|
|
990
|
+
var sizeClass5 = {
|
|
651
991
|
sm: "h-3 w-3 border",
|
|
652
992
|
md: "h-4 w-4 border-2",
|
|
653
993
|
lg: "h-6 w-6 border-2"
|
|
@@ -656,7 +996,7 @@ function Spinner({ className, size = "md", label }) {
|
|
|
656
996
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
657
997
|
"span",
|
|
658
998
|
{
|
|
659
|
-
className: cn("inline-block rounded-full border-white/15 border-t-primary animate-spin",
|
|
999
|
+
className: cn("inline-block rounded-full border-white/15 border-t-primary animate-spin", sizeClass5[size], className),
|
|
660
1000
|
role: label ? "status" : void 0,
|
|
661
1001
|
"aria-hidden": label ? void 0 : "true",
|
|
662
1002
|
"aria-label": label || void 0
|
|
@@ -672,9 +1012,9 @@ function Skeleton({ className, circle }) {
|
|
|
672
1012
|
}
|
|
673
1013
|
);
|
|
674
1014
|
}
|
|
675
|
-
var TabsContext =
|
|
1015
|
+
var TabsContext = React.createContext(null);
|
|
676
1016
|
function useTabsContext() {
|
|
677
|
-
const ctx =
|
|
1017
|
+
const ctx = React.useContext(TabsContext);
|
|
678
1018
|
if (!ctx) throw new Error("Tabs sub-components must be used inside <Tabs>");
|
|
679
1019
|
return ctx;
|
|
680
1020
|
}
|
|
@@ -686,18 +1026,18 @@ function Tabs({
|
|
|
686
1026
|
children,
|
|
687
1027
|
className
|
|
688
1028
|
}) {
|
|
689
|
-
const baseId =
|
|
1029
|
+
const baseId = React.useId();
|
|
690
1030
|
const isControlled = value !== void 0;
|
|
691
|
-
const [internalValue, setInternalValue] =
|
|
1031
|
+
const [internalValue, setInternalValue] = React.useState(defaultValue);
|
|
692
1032
|
const activeValue = isControlled ? value ?? "" : internalValue;
|
|
693
|
-
const setActiveValue =
|
|
1033
|
+
const setActiveValue = React.useCallback(
|
|
694
1034
|
(next) => {
|
|
695
1035
|
if (!isControlled) setInternalValue(next);
|
|
696
1036
|
onValueChange?.(next);
|
|
697
1037
|
},
|
|
698
1038
|
[isControlled, onValueChange]
|
|
699
1039
|
);
|
|
700
|
-
const ctxValue =
|
|
1040
|
+
const ctxValue = React.useMemo(
|
|
701
1041
|
() => ({ activeValue, setActiveValue, variant, baseId }),
|
|
702
1042
|
[activeValue, setActiveValue, variant, baseId]
|
|
703
1043
|
);
|
|
@@ -705,7 +1045,7 @@ function Tabs({
|
|
|
705
1045
|
}
|
|
706
1046
|
function TabList({ children, className }) {
|
|
707
1047
|
const { variant } = useTabsContext();
|
|
708
|
-
const listRef =
|
|
1048
|
+
const listRef = React.useRef(null);
|
|
709
1049
|
const handleKeyDown = (e) => {
|
|
710
1050
|
const list = listRef.current;
|
|
711
1051
|
if (!list) return;
|
|
@@ -810,7 +1150,7 @@ function TabPanel({ value, children, className }) {
|
|
|
810
1150
|
}
|
|
811
1151
|
);
|
|
812
1152
|
}
|
|
813
|
-
var Card =
|
|
1153
|
+
var Card = React.forwardRef(function Card2({ hoverable, variant = "surface", className, ...props }, ref) {
|
|
814
1154
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
815
1155
|
"div",
|
|
816
1156
|
{
|
|
@@ -850,9 +1190,9 @@ function Modal({
|
|
|
850
1190
|
contentClassName,
|
|
851
1191
|
zIndexClassName = "z-50"
|
|
852
1192
|
}) {
|
|
853
|
-
const dialogRef =
|
|
854
|
-
const lastActiveElementRef =
|
|
855
|
-
|
|
1193
|
+
const dialogRef = React.useRef(null);
|
|
1194
|
+
const lastActiveElementRef = React.useRef(null);
|
|
1195
|
+
React.useEffect(() => {
|
|
856
1196
|
if (!isOpen) return;
|
|
857
1197
|
lastActiveElementRef.current = document.activeElement instanceof HTMLElement ? document.activeElement : null;
|
|
858
1198
|
const raf = window.requestAnimationFrame(() => {
|
|
@@ -868,7 +1208,7 @@ function Modal({
|
|
|
868
1208
|
if (lastActive?.isConnected) focusSafely(lastActive);
|
|
869
1209
|
};
|
|
870
1210
|
}, [isOpen]);
|
|
871
|
-
|
|
1211
|
+
React.useEffect(() => {
|
|
872
1212
|
if (!isOpen) return;
|
|
873
1213
|
lockScroll();
|
|
874
1214
|
return () => unlockScroll();
|
|
@@ -961,7 +1301,7 @@ function ConfirmDialog({
|
|
|
961
1301
|
variant = "danger",
|
|
962
1302
|
isLoading = false
|
|
963
1303
|
}) {
|
|
964
|
-
const titleId =
|
|
1304
|
+
const titleId = React.useId();
|
|
965
1305
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
966
1306
|
Modal,
|
|
967
1307
|
{
|
|
@@ -1006,22 +1346,22 @@ function ConfirmDialog({
|
|
|
1006
1346
|
);
|
|
1007
1347
|
}
|
|
1008
1348
|
function Tooltip({ content, delayMs = 500, placement = "top", className, children }) {
|
|
1009
|
-
const tooltipId =
|
|
1010
|
-
const openTimerRef =
|
|
1011
|
-
const anchorRef =
|
|
1012
|
-
const [open, setOpen] =
|
|
1013
|
-
const [pos, setPos] =
|
|
1014
|
-
|
|
1349
|
+
const tooltipId = React.useId();
|
|
1350
|
+
const openTimerRef = React.useRef(null);
|
|
1351
|
+
const anchorRef = React.useRef(null);
|
|
1352
|
+
const [open, setOpen] = React.useState(false);
|
|
1353
|
+
const [pos, setPos] = React.useState(null);
|
|
1354
|
+
React.useMemo(() => {
|
|
1015
1355
|
if (typeof content === "string") return content.trim();
|
|
1016
1356
|
return "";
|
|
1017
1357
|
}, [content]);
|
|
1018
|
-
const clearTimer =
|
|
1358
|
+
const clearTimer = React.useCallback(() => {
|
|
1019
1359
|
if (openTimerRef.current !== null) {
|
|
1020
1360
|
window.clearTimeout(openTimerRef.current);
|
|
1021
1361
|
openTimerRef.current = null;
|
|
1022
1362
|
}
|
|
1023
1363
|
}, []);
|
|
1024
|
-
const updatePosition =
|
|
1364
|
+
const updatePosition = React.useCallback(() => {
|
|
1025
1365
|
const el = anchorRef.current;
|
|
1026
1366
|
if (!el) return;
|
|
1027
1367
|
const r = el.getBoundingClientRect();
|
|
@@ -1037,17 +1377,17 @@ function Tooltip({ content, delayMs = 500, placement = "top", className, childre
|
|
|
1037
1377
|
placement: effPlacement
|
|
1038
1378
|
});
|
|
1039
1379
|
}, [placement]);
|
|
1040
|
-
const scheduleOpen =
|
|
1380
|
+
const scheduleOpen = React.useCallback(() => {
|
|
1041
1381
|
clearTimer();
|
|
1042
1382
|
openTimerRef.current = window.setTimeout(() => {
|
|
1043
1383
|
setOpen(true);
|
|
1044
1384
|
}, Math.max(0, delayMs));
|
|
1045
1385
|
}, [clearTimer, delayMs]);
|
|
1046
|
-
const close =
|
|
1386
|
+
const close = React.useCallback(() => {
|
|
1047
1387
|
clearTimer();
|
|
1048
1388
|
setOpen(false);
|
|
1049
1389
|
}, [clearTimer]);
|
|
1050
|
-
|
|
1390
|
+
React.useEffect(() => {
|
|
1051
1391
|
if (!open) return;
|
|
1052
1392
|
updatePosition();
|
|
1053
1393
|
const onScroll = () => updatePosition();
|
|
@@ -1059,11 +1399,11 @@ function Tooltip({ content, delayMs = 500, placement = "top", className, childre
|
|
|
1059
1399
|
window.removeEventListener("resize", onResize);
|
|
1060
1400
|
};
|
|
1061
1401
|
}, [open, updatePosition]);
|
|
1062
|
-
|
|
1402
|
+
React.useEffect(() => {
|
|
1063
1403
|
return () => clearTimer();
|
|
1064
1404
|
}, [clearTimer]);
|
|
1065
|
-
if (!
|
|
1066
|
-
const child =
|
|
1405
|
+
if (!React.isValidElement(children)) return children;
|
|
1406
|
+
const child = React.cloneElement(children, {
|
|
1067
1407
|
ref: (node) => {
|
|
1068
1408
|
anchorRef.current = node;
|
|
1069
1409
|
const childProps = children.props;
|
|
@@ -1128,8 +1468,8 @@ function EmptyState({ icon: Icon, title, description, actionLabel, onAction, chi
|
|
|
1128
1468
|
] });
|
|
1129
1469
|
}
|
|
1130
1470
|
function CollapsibleSection({ title, defaultOpen = true, children, right, className }) {
|
|
1131
|
-
const [isOpen, setIsOpen] =
|
|
1132
|
-
const contentId =
|
|
1471
|
+
const [isOpen, setIsOpen] = React.useState(defaultOpen);
|
|
1472
|
+
const contentId = React.useId();
|
|
1133
1473
|
const titleId = `${contentId}-title`;
|
|
1134
1474
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("rounded-xl ring-1 ring-white/10 bg-white/5 overflow-hidden", className), children: [
|
|
1135
1475
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -1176,21 +1516,21 @@ function CollapsibleSection({ title, defaultOpen = true, children, right, classN
|
|
|
1176
1516
|
)
|
|
1177
1517
|
] });
|
|
1178
1518
|
}
|
|
1179
|
-
var DropdownContext =
|
|
1519
|
+
var DropdownContext = React.createContext(null);
|
|
1180
1520
|
function useDropdownContext(component) {
|
|
1181
|
-
const ctx =
|
|
1521
|
+
const ctx = React.useContext(DropdownContext);
|
|
1182
1522
|
if (!ctx) {
|
|
1183
1523
|
throw new Error(`<${component}> must be rendered inside <Dropdown>`);
|
|
1184
1524
|
}
|
|
1185
1525
|
return ctx;
|
|
1186
1526
|
}
|
|
1187
1527
|
function Dropdown({ children, className }) {
|
|
1188
|
-
const [open, setOpen] =
|
|
1189
|
-
const triggerId =
|
|
1190
|
-
const menuId =
|
|
1191
|
-
const triggerRef =
|
|
1192
|
-
const toggleOpen =
|
|
1193
|
-
const ctxValue =
|
|
1528
|
+
const [open, setOpen] = React.useState(false);
|
|
1529
|
+
const triggerId = React.useId();
|
|
1530
|
+
const menuId = React.useId();
|
|
1531
|
+
const triggerRef = React.useRef(null);
|
|
1532
|
+
const toggleOpen = React.useCallback(() => setOpen((prev) => !prev), []);
|
|
1533
|
+
const ctxValue = React.useMemo(
|
|
1194
1534
|
() => ({ open, setOpen, toggleOpen, triggerId, menuId, triggerRef }),
|
|
1195
1535
|
[open, setOpen, toggleOpen, triggerId, menuId, triggerRef]
|
|
1196
1536
|
);
|
|
@@ -1198,8 +1538,8 @@ function Dropdown({ children, className }) {
|
|
|
1198
1538
|
}
|
|
1199
1539
|
function DropdownTrigger({ children, className }) {
|
|
1200
1540
|
const { open, toggleOpen, triggerId, menuId, triggerRef } = useDropdownContext("DropdownTrigger");
|
|
1201
|
-
if (!
|
|
1202
|
-
return
|
|
1541
|
+
if (!React.isValidElement(children)) return children;
|
|
1542
|
+
return React.cloneElement(children, {
|
|
1203
1543
|
id: triggerId,
|
|
1204
1544
|
"aria-haspopup": "menu",
|
|
1205
1545
|
"aria-expanded": open,
|
|
@@ -1221,10 +1561,10 @@ function DropdownTrigger({ children, className }) {
|
|
|
1221
1561
|
}
|
|
1222
1562
|
function DropdownMenu({ children, className, align = "left" }) {
|
|
1223
1563
|
const { open, setOpen, menuId, triggerId, triggerRef } = useDropdownContext("DropdownMenu");
|
|
1224
|
-
const menuRef =
|
|
1225
|
-
const [pos, setPos] =
|
|
1226
|
-
const [visible, setVisible] =
|
|
1227
|
-
const updatePosition =
|
|
1564
|
+
const menuRef = React.useRef(null);
|
|
1565
|
+
const [pos, setPos] = React.useState(null);
|
|
1566
|
+
const [visible, setVisible] = React.useState(false);
|
|
1567
|
+
const updatePosition = React.useCallback(() => {
|
|
1228
1568
|
const trigger = triggerRef.current;
|
|
1229
1569
|
if (!trigger) return;
|
|
1230
1570
|
const rect = trigger.getBoundingClientRect();
|
|
@@ -1234,7 +1574,7 @@ function DropdownMenu({ children, className, align = "left" }) {
|
|
|
1234
1574
|
left: Math.round(left)
|
|
1235
1575
|
});
|
|
1236
1576
|
}, [align, triggerRef]);
|
|
1237
|
-
|
|
1577
|
+
React.useEffect(() => {
|
|
1238
1578
|
if (!open) {
|
|
1239
1579
|
setVisible(false);
|
|
1240
1580
|
return;
|
|
@@ -1249,7 +1589,7 @@ function DropdownMenu({ children, className, align = "left" }) {
|
|
|
1249
1589
|
});
|
|
1250
1590
|
return () => window.cancelAnimationFrame(raf);
|
|
1251
1591
|
}, [open, updatePosition]);
|
|
1252
|
-
|
|
1592
|
+
React.useEffect(() => {
|
|
1253
1593
|
if (!open) return;
|
|
1254
1594
|
function handlePointerDown(e) {
|
|
1255
1595
|
const target = e.target;
|
|
@@ -1260,7 +1600,7 @@ function DropdownMenu({ children, className, align = "left" }) {
|
|
|
1260
1600
|
document.addEventListener("pointerdown", handlePointerDown, true);
|
|
1261
1601
|
return () => document.removeEventListener("pointerdown", handlePointerDown, true);
|
|
1262
1602
|
}, [open, setOpen, triggerRef]);
|
|
1263
|
-
|
|
1603
|
+
React.useEffect(() => {
|
|
1264
1604
|
if (!open) return;
|
|
1265
1605
|
const onScroll = () => updatePosition();
|
|
1266
1606
|
const onResize = () => updatePosition();
|
|
@@ -1336,7 +1676,7 @@ function DropdownMenu({ children, className, align = "left" }) {
|
|
|
1336
1676
|
}
|
|
1337
1677
|
function DropdownItem({ onSelect, disabled = false, children, className }) {
|
|
1338
1678
|
const { setOpen, triggerRef } = useDropdownContext("DropdownItem");
|
|
1339
|
-
const handleSelect =
|
|
1679
|
+
const handleSelect = React.useCallback(() => {
|
|
1340
1680
|
if (disabled) return;
|
|
1341
1681
|
setOpen(false);
|
|
1342
1682
|
focusSafely(triggerRef.current);
|
|
@@ -1389,10 +1729,10 @@ function DropZone({
|
|
|
1389
1729
|
className,
|
|
1390
1730
|
"aria-label": ariaLabel = "File drop zone"
|
|
1391
1731
|
}) {
|
|
1392
|
-
const [isDragging, setIsDragging] =
|
|
1393
|
-
const inputRef =
|
|
1394
|
-
const dragCounterRef =
|
|
1395
|
-
const processFiles =
|
|
1732
|
+
const [isDragging, setIsDragging] = React.useState(false);
|
|
1733
|
+
const inputRef = React.useRef(null);
|
|
1734
|
+
const dragCounterRef = React.useRef(0);
|
|
1735
|
+
const processFiles = React.useCallback(
|
|
1396
1736
|
(fileList) => {
|
|
1397
1737
|
if (!fileList || disabled) return;
|
|
1398
1738
|
let files = Array.from(fileList);
|
|
@@ -1409,7 +1749,7 @@ function DropZone({
|
|
|
1409
1749
|
},
|
|
1410
1750
|
[accept, disabled, maxFiles, maxSize, onFilesDropped]
|
|
1411
1751
|
);
|
|
1412
|
-
const handleDragEnter =
|
|
1752
|
+
const handleDragEnter = React.useCallback(
|
|
1413
1753
|
(e) => {
|
|
1414
1754
|
e.preventDefault();
|
|
1415
1755
|
dragCounterRef.current++;
|
|
@@ -1417,18 +1757,18 @@ function DropZone({
|
|
|
1417
1757
|
},
|
|
1418
1758
|
[disabled]
|
|
1419
1759
|
);
|
|
1420
|
-
const handleDragOver =
|
|
1760
|
+
const handleDragOver = React.useCallback(
|
|
1421
1761
|
(e) => {
|
|
1422
1762
|
e.preventDefault();
|
|
1423
1763
|
},
|
|
1424
1764
|
[]
|
|
1425
1765
|
);
|
|
1426
|
-
const handleDragLeave =
|
|
1766
|
+
const handleDragLeave = React.useCallback((e) => {
|
|
1427
1767
|
e.preventDefault();
|
|
1428
1768
|
dragCounterRef.current--;
|
|
1429
1769
|
if (dragCounterRef.current === 0) setIsDragging(false);
|
|
1430
1770
|
}, []);
|
|
1431
|
-
const handleDrop =
|
|
1771
|
+
const handleDrop = React.useCallback(
|
|
1432
1772
|
(e) => {
|
|
1433
1773
|
e.preventDefault();
|
|
1434
1774
|
dragCounterRef.current = 0;
|
|
@@ -1438,10 +1778,10 @@ function DropZone({
|
|
|
1438
1778
|
},
|
|
1439
1779
|
[disabled, processFiles]
|
|
1440
1780
|
);
|
|
1441
|
-
const handleClick =
|
|
1781
|
+
const handleClick = React.useCallback(() => {
|
|
1442
1782
|
if (!disabled) inputRef.current?.click();
|
|
1443
1783
|
}, [disabled]);
|
|
1444
|
-
const handleKeyDown =
|
|
1784
|
+
const handleKeyDown = React.useCallback(
|
|
1445
1785
|
(e) => {
|
|
1446
1786
|
if (disabled) return;
|
|
1447
1787
|
if (e.key === "Enter" || e.key === " ") {
|
|
@@ -1451,7 +1791,7 @@ function DropZone({
|
|
|
1451
1791
|
},
|
|
1452
1792
|
[disabled]
|
|
1453
1793
|
);
|
|
1454
|
-
const handleInputChange =
|
|
1794
|
+
const handleInputChange = React.useCallback(() => {
|
|
1455
1795
|
processFiles(inputRef.current?.files ?? null);
|
|
1456
1796
|
if (inputRef.current) inputRef.current.value = "";
|
|
1457
1797
|
}, [processFiles]);
|
|
@@ -1519,6 +1859,404 @@ function DropZone({
|
|
|
1519
1859
|
}
|
|
1520
1860
|
);
|
|
1521
1861
|
}
|
|
1862
|
+
function FormField({ label, error, helperText, children, className, id: idProp }) {
|
|
1863
|
+
const autoId = React.useId();
|
|
1864
|
+
const id = idProp ?? autoId;
|
|
1865
|
+
const descIds = [];
|
|
1866
|
+
const errorId = error ? `${id}-error` : void 0;
|
|
1867
|
+
const helperId = helperText ? `${id}-helper` : void 0;
|
|
1868
|
+
if (errorId) descIds.push(errorId);
|
|
1869
|
+
if (helperId) descIds.push(helperId);
|
|
1870
|
+
const describedBy = descIds.length > 0 ? descIds.join(" ") : void 0;
|
|
1871
|
+
const child = React.cloneElement(children, {
|
|
1872
|
+
id,
|
|
1873
|
+
...describedBy ? { "aria-describedby": describedBy } : {},
|
|
1874
|
+
...error ? { "aria-invalid": true } : {}
|
|
1875
|
+
});
|
|
1876
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex flex-col", className), children: [
|
|
1877
|
+
label ? /* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: id, className: "block text-sm text-white/70 mb-1.5", children: label }) : null,
|
|
1878
|
+
child,
|
|
1879
|
+
error ? /* @__PURE__ */ jsxRuntime.jsx("p", { id: errorId, className: "text-rose-400 text-xs mt-1", role: "alert", children: error }) : null,
|
|
1880
|
+
helperText && !error ? /* @__PURE__ */ jsxRuntime.jsx("p", { id: helperId, className: "text-white/40 text-xs mt-1", children: helperText }) : null
|
|
1881
|
+
] });
|
|
1882
|
+
}
|
|
1883
|
+
function Divider({ orientation = "horizontal", label, className }) {
|
|
1884
|
+
if (orientation === "vertical") {
|
|
1885
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1886
|
+
"div",
|
|
1887
|
+
{
|
|
1888
|
+
role: "separator",
|
|
1889
|
+
"aria-orientation": "vertical",
|
|
1890
|
+
className: cn("border-l border-white/10 h-full mx-3 self-stretch", className)
|
|
1891
|
+
}
|
|
1892
|
+
);
|
|
1893
|
+
}
|
|
1894
|
+
if (label) {
|
|
1895
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1896
|
+
"div",
|
|
1897
|
+
{
|
|
1898
|
+
role: "separator",
|
|
1899
|
+
"aria-orientation": "horizontal",
|
|
1900
|
+
className: cn("flex items-center gap-3 my-3 w-full", className),
|
|
1901
|
+
children: [
|
|
1902
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1 border-t border-white/10" }),
|
|
1903
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-white/40 leading-none select-none", children: label }),
|
|
1904
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1 border-t border-white/10" })
|
|
1905
|
+
]
|
|
1906
|
+
}
|
|
1907
|
+
);
|
|
1908
|
+
}
|
|
1909
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1910
|
+
"hr",
|
|
1911
|
+
{
|
|
1912
|
+
role: "separator",
|
|
1913
|
+
"aria-orientation": "horizontal",
|
|
1914
|
+
className: cn("border-t border-white/10 w-full my-3", className)
|
|
1915
|
+
}
|
|
1916
|
+
);
|
|
1917
|
+
}
|
|
1918
|
+
var Table = React.forwardRef(({ children, className }, ref) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-xl ring-1 ring-white/10 overflow-hidden bg-white/5", children: /* @__PURE__ */ jsxRuntime.jsx("table", { ref, className: cn("w-full text-sm text-white", className), children }) }));
|
|
1919
|
+
Table.displayName = "Table";
|
|
1920
|
+
var TableHeader = React.forwardRef(
|
|
1921
|
+
({ children, className }, ref) => /* @__PURE__ */ jsxRuntime.jsx("thead", { ref, className: cn("bg-white/5 border-b border-white/10", className), children })
|
|
1922
|
+
);
|
|
1923
|
+
TableHeader.displayName = "TableHeader";
|
|
1924
|
+
var TableBody = React.forwardRef(
|
|
1925
|
+
({ children, className }, ref) => /* @__PURE__ */ jsxRuntime.jsx("tbody", { ref, className: cn("divide-y divide-white/[0.06]", className), children })
|
|
1926
|
+
);
|
|
1927
|
+
TableBody.displayName = "TableBody";
|
|
1928
|
+
var TableRow = React.forwardRef(
|
|
1929
|
+
({ children, className, hoverable }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
1930
|
+
"tr",
|
|
1931
|
+
{
|
|
1932
|
+
ref,
|
|
1933
|
+
className: cn(hoverable && "hover:bg-white/[0.03] transition-colors", className),
|
|
1934
|
+
children
|
|
1935
|
+
}
|
|
1936
|
+
)
|
|
1937
|
+
);
|
|
1938
|
+
TableRow.displayName = "TableRow";
|
|
1939
|
+
var TableHead = React.forwardRef(
|
|
1940
|
+
({ children, className }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
1941
|
+
"th",
|
|
1942
|
+
{
|
|
1943
|
+
ref,
|
|
1944
|
+
className: cn(
|
|
1945
|
+
"px-4 py-3 text-left text-xs font-semibold text-white/50 uppercase tracking-wider",
|
|
1946
|
+
className
|
|
1947
|
+
),
|
|
1948
|
+
children
|
|
1949
|
+
}
|
|
1950
|
+
)
|
|
1951
|
+
);
|
|
1952
|
+
TableHead.displayName = "TableHead";
|
|
1953
|
+
var alignClass = {
|
|
1954
|
+
left: "text-left",
|
|
1955
|
+
center: "text-center",
|
|
1956
|
+
right: "text-right"
|
|
1957
|
+
};
|
|
1958
|
+
var TableCell = React.forwardRef(
|
|
1959
|
+
({ children, className, align = "left" }, ref) => /* @__PURE__ */ jsxRuntime.jsx("td", { ref, className: cn("px-4 py-3 text-white/80", alignClass[align], className), children })
|
|
1960
|
+
);
|
|
1961
|
+
TableCell.displayName = "TableCell";
|
|
1962
|
+
function TrendIndicator({ trend }) {
|
|
1963
|
+
if (trend.value > 0) {
|
|
1964
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center gap-1 text-xs text-emerald-400", children: [
|
|
1965
|
+
/* @__PURE__ */ jsxRuntime.jsx("svg", { "aria-hidden": "true", className: "w-3 h-3 shrink-0", fill: "none", viewBox: "0 0 12 12", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 9V3M3 6l3-3 3 3" }) }),
|
|
1966
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
1967
|
+
"+",
|
|
1968
|
+
trend.value,
|
|
1969
|
+
trend.label ? ` ${trend.label}` : ""
|
|
1970
|
+
] })
|
|
1971
|
+
] });
|
|
1972
|
+
}
|
|
1973
|
+
if (trend.value < 0) {
|
|
1974
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center gap-1 text-xs text-rose-400", children: [
|
|
1975
|
+
/* @__PURE__ */ jsxRuntime.jsx("svg", { "aria-hidden": "true", className: "w-3 h-3 shrink-0", fill: "none", viewBox: "0 0 12 12", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 3v6M3 6l3 3 3-3" }) }),
|
|
1976
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
1977
|
+
trend.value,
|
|
1978
|
+
trend.label ? ` ${trend.label}` : ""
|
|
1979
|
+
] })
|
|
1980
|
+
] });
|
|
1981
|
+
}
|
|
1982
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center gap-1 text-xs text-white/40", children: [
|
|
1983
|
+
/* @__PURE__ */ jsxRuntime.jsx("svg", { "aria-hidden": "true", className: "w-3 h-3 shrink-0", fill: "none", viewBox: "0 0 12 12", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M2 6h8" }) }),
|
|
1984
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
1985
|
+
trend.value,
|
|
1986
|
+
trend.label ? ` ${trend.label}` : ""
|
|
1987
|
+
] })
|
|
1988
|
+
] });
|
|
1989
|
+
}
|
|
1990
|
+
function StatCard({ value, label, icon, trend, className }) {
|
|
1991
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1992
|
+
"div",
|
|
1993
|
+
{
|
|
1994
|
+
className: cn(
|
|
1995
|
+
"bg-white/5 ring-1 ring-white/10 rounded-xl p-4 flex items-start gap-3",
|
|
1996
|
+
className
|
|
1997
|
+
),
|
|
1998
|
+
children: [
|
|
1999
|
+
icon != null && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-10 h-10 rounded-lg bg-white/10 flex items-center justify-center text-primary shrink-0", children: icon }),
|
|
2000
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-0.5 min-w-0", children: [
|
|
2001
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-2xl font-bold text-white tabular-nums leading-none", children: value }),
|
|
2002
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-white/50 truncate", children: label }),
|
|
2003
|
+
trend != null && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1", children: /* @__PURE__ */ jsxRuntime.jsx(TrendIndicator, { trend }) })
|
|
2004
|
+
] })
|
|
2005
|
+
]
|
|
2006
|
+
}
|
|
2007
|
+
);
|
|
2008
|
+
}
|
|
2009
|
+
function getPageRange(page, totalPages, siblingCount) {
|
|
2010
|
+
if (totalPages <= 1) return [1];
|
|
2011
|
+
const siblingStart = Math.max(2, page - siblingCount);
|
|
2012
|
+
const siblingEnd = Math.min(totalPages - 1, page + siblingCount);
|
|
2013
|
+
const showLeftEllipsis = siblingStart > 2;
|
|
2014
|
+
const showRightEllipsis = siblingEnd < totalPages - 1;
|
|
2015
|
+
const items = [1];
|
|
2016
|
+
if (showLeftEllipsis) {
|
|
2017
|
+
items.push("...");
|
|
2018
|
+
} else {
|
|
2019
|
+
for (let i = 2; i < siblingStart; i++) {
|
|
2020
|
+
items.push(i);
|
|
2021
|
+
}
|
|
2022
|
+
}
|
|
2023
|
+
for (let i = siblingStart; i <= siblingEnd; i++) {
|
|
2024
|
+
items.push(i);
|
|
2025
|
+
}
|
|
2026
|
+
if (showRightEllipsis) {
|
|
2027
|
+
items.push("...");
|
|
2028
|
+
} else {
|
|
2029
|
+
for (let i = siblingEnd + 1; i < totalPages; i++) {
|
|
2030
|
+
items.push(i);
|
|
2031
|
+
}
|
|
2032
|
+
}
|
|
2033
|
+
if (totalPages > 1) {
|
|
2034
|
+
items.push(totalPages);
|
|
2035
|
+
}
|
|
2036
|
+
return items;
|
|
2037
|
+
}
|
|
2038
|
+
var buttonBase = "inline-flex items-center justify-center rounded-lg px-3 py-2 text-sm font-medium transition-[background-color,opacity] select-none focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/40";
|
|
2039
|
+
var pageButton = cn(buttonBase, "bg-white/5 ring-1 ring-white/10 text-white/80 hover:bg-white/10 hover:text-white");
|
|
2040
|
+
var activeButton = cn(buttonBase, "bg-primary text-white ring-1 ring-primary/20");
|
|
2041
|
+
var navButton = cn(buttonBase, "bg-white/5 ring-1 ring-white/10 text-white/80 hover:bg-white/10 hover:text-white");
|
|
2042
|
+
var ChevronLeft = () => /* @__PURE__ */ jsxRuntime.jsx(
|
|
2043
|
+
"svg",
|
|
2044
|
+
{
|
|
2045
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2046
|
+
width: "16",
|
|
2047
|
+
height: "16",
|
|
2048
|
+
viewBox: "0 0 24 24",
|
|
2049
|
+
fill: "none",
|
|
2050
|
+
stroke: "currentColor",
|
|
2051
|
+
strokeWidth: "2",
|
|
2052
|
+
strokeLinecap: "round",
|
|
2053
|
+
strokeLinejoin: "round",
|
|
2054
|
+
"aria-hidden": "true",
|
|
2055
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "15 18 9 12 15 6" })
|
|
2056
|
+
}
|
|
2057
|
+
);
|
|
2058
|
+
var ChevronRight = () => /* @__PURE__ */ jsxRuntime.jsx(
|
|
2059
|
+
"svg",
|
|
2060
|
+
{
|
|
2061
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2062
|
+
width: "16",
|
|
2063
|
+
height: "16",
|
|
2064
|
+
viewBox: "0 0 24 24",
|
|
2065
|
+
fill: "none",
|
|
2066
|
+
stroke: "currentColor",
|
|
2067
|
+
strokeWidth: "2",
|
|
2068
|
+
strokeLinecap: "round",
|
|
2069
|
+
strokeLinejoin: "round",
|
|
2070
|
+
"aria-hidden": "true",
|
|
2071
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "9 18 15 12 9 6" })
|
|
2072
|
+
}
|
|
2073
|
+
);
|
|
2074
|
+
function Pagination({
|
|
2075
|
+
page,
|
|
2076
|
+
totalPages,
|
|
2077
|
+
onPageChange,
|
|
2078
|
+
siblingCount = 1,
|
|
2079
|
+
className
|
|
2080
|
+
}) {
|
|
2081
|
+
if (totalPages <= 1) return null;
|
|
2082
|
+
const items = getPageRange(page, totalPages, siblingCount);
|
|
2083
|
+
const isPrevDisabled = page <= 1;
|
|
2084
|
+
const isNextDisabled = page >= totalPages;
|
|
2085
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2086
|
+
"nav",
|
|
2087
|
+
{
|
|
2088
|
+
role: "navigation",
|
|
2089
|
+
"aria-label": "Pagination",
|
|
2090
|
+
className: cn("flex items-center gap-1", className),
|
|
2091
|
+
children: [
|
|
2092
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2093
|
+
"button",
|
|
2094
|
+
{
|
|
2095
|
+
type: "button",
|
|
2096
|
+
onClick: () => onPageChange(page - 1),
|
|
2097
|
+
disabled: isPrevDisabled,
|
|
2098
|
+
"aria-label": "Previous page",
|
|
2099
|
+
className: cn(navButton, isPrevDisabled && "opacity-40 cursor-not-allowed pointer-events-none"),
|
|
2100
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(ChevronLeft, {})
|
|
2101
|
+
}
|
|
2102
|
+
),
|
|
2103
|
+
items.map(
|
|
2104
|
+
(item, index) => item === "..." ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2105
|
+
"span",
|
|
2106
|
+
{
|
|
2107
|
+
className: "inline-flex items-center justify-center px-3 py-2 text-sm text-white/40 select-none",
|
|
2108
|
+
"aria-hidden": "true",
|
|
2109
|
+
children: "\u2026"
|
|
2110
|
+
},
|
|
2111
|
+
`ellipsis-${index}`
|
|
2112
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
2113
|
+
"button",
|
|
2114
|
+
{
|
|
2115
|
+
type: "button",
|
|
2116
|
+
onClick: () => onPageChange(item),
|
|
2117
|
+
"aria-label": `Page ${item}`,
|
|
2118
|
+
"aria-current": item === page ? "page" : void 0,
|
|
2119
|
+
className: item === page ? activeButton : pageButton,
|
|
2120
|
+
children: item
|
|
2121
|
+
},
|
|
2122
|
+
item
|
|
2123
|
+
)
|
|
2124
|
+
),
|
|
2125
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2126
|
+
"button",
|
|
2127
|
+
{
|
|
2128
|
+
type: "button",
|
|
2129
|
+
onClick: () => onPageChange(page + 1),
|
|
2130
|
+
disabled: isNextDisabled,
|
|
2131
|
+
"aria-label": "Next page",
|
|
2132
|
+
className: cn(navButton, isNextDisabled && "opacity-40 cursor-not-allowed pointer-events-none"),
|
|
2133
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(ChevronRight, {})
|
|
2134
|
+
}
|
|
2135
|
+
)
|
|
2136
|
+
]
|
|
2137
|
+
}
|
|
2138
|
+
);
|
|
2139
|
+
}
|
|
2140
|
+
function Stepper({ steps, activeStep, className }) {
|
|
2141
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("flex items-start w-full", className), children: steps.map((step, index) => {
|
|
2142
|
+
const isCompleted = index < activeStep;
|
|
2143
|
+
const isActive = index === activeStep;
|
|
2144
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(React__default.default.Fragment, { children: [
|
|
2145
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2146
|
+
"div",
|
|
2147
|
+
{
|
|
2148
|
+
className: "flex flex-col items-center",
|
|
2149
|
+
"aria-current": isActive ? "step" : void 0,
|
|
2150
|
+
children: [
|
|
2151
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2152
|
+
"div",
|
|
2153
|
+
{
|
|
2154
|
+
className: cn(
|
|
2155
|
+
"w-8 h-8 rounded-full flex items-center justify-center text-sm font-semibold",
|
|
2156
|
+
isCompleted && "bg-emerald-600 text-white",
|
|
2157
|
+
isActive && "bg-primary text-white ring-2 ring-primary/40",
|
|
2158
|
+
!isCompleted && !isActive && "bg-white/10 text-white/40"
|
|
2159
|
+
),
|
|
2160
|
+
children: isCompleted ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2161
|
+
"svg",
|
|
2162
|
+
{
|
|
2163
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2164
|
+
viewBox: "0 0 20 20",
|
|
2165
|
+
fill: "currentColor",
|
|
2166
|
+
className: "w-4 h-4",
|
|
2167
|
+
"aria-hidden": "true",
|
|
2168
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2169
|
+
"path",
|
|
2170
|
+
{
|
|
2171
|
+
fillRule: "evenodd",
|
|
2172
|
+
d: "M16.704 4.153a.75.75 0 01.143 1.052l-8 10.5a.75.75 0 01-1.127.075l-4.5-4.5a.75.75 0 011.06-1.06l3.894 3.893 7.48-9.817a.75.75 0 011.05-.143z",
|
|
2173
|
+
clipRule: "evenodd"
|
|
2174
|
+
}
|
|
2175
|
+
)
|
|
2176
|
+
}
|
|
2177
|
+
) : /* @__PURE__ */ jsxRuntime.jsx("span", { children: index + 1 })
|
|
2178
|
+
}
|
|
2179
|
+
),
|
|
2180
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2181
|
+
"span",
|
|
2182
|
+
{
|
|
2183
|
+
className: cn(
|
|
2184
|
+
"text-xs mt-2 text-center max-w-[6rem]",
|
|
2185
|
+
isActive ? "text-white/80" : "text-white/50"
|
|
2186
|
+
),
|
|
2187
|
+
children: step.label
|
|
2188
|
+
}
|
|
2189
|
+
),
|
|
2190
|
+
step.description && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs mt-0.5 text-center text-white/30 max-w-[6rem]", children: step.description })
|
|
2191
|
+
]
|
|
2192
|
+
}
|
|
2193
|
+
),
|
|
2194
|
+
index < steps.length - 1 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
2195
|
+
"div",
|
|
2196
|
+
{
|
|
2197
|
+
className: cn(
|
|
2198
|
+
"h-0.5 flex-1 mx-2 mt-4 self-start",
|
|
2199
|
+
isCompleted ? "bg-emerald-600" : "bg-white/10"
|
|
2200
|
+
),
|
|
2201
|
+
"aria-hidden": "true"
|
|
2202
|
+
}
|
|
2203
|
+
)
|
|
2204
|
+
] }, index);
|
|
2205
|
+
}) });
|
|
2206
|
+
}
|
|
2207
|
+
var sizeClasses = {
|
|
2208
|
+
sm: "h-1",
|
|
2209
|
+
md: "h-2",
|
|
2210
|
+
lg: "h-3"
|
|
2211
|
+
};
|
|
2212
|
+
var variantClasses = {
|
|
2213
|
+
primary: "bg-primary",
|
|
2214
|
+
success: "bg-emerald-500",
|
|
2215
|
+
warning: "bg-amber-500",
|
|
2216
|
+
danger: "bg-rose-500"
|
|
2217
|
+
};
|
|
2218
|
+
function ProgressBar({
|
|
2219
|
+
value,
|
|
2220
|
+
max = 100,
|
|
2221
|
+
variant = "primary",
|
|
2222
|
+
label,
|
|
2223
|
+
showValue = false,
|
|
2224
|
+
size = "md",
|
|
2225
|
+
className
|
|
2226
|
+
}) {
|
|
2227
|
+
const percentage = Math.min(100, Math.max(0, value / max * 100));
|
|
2228
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("w-full", className), children: [
|
|
2229
|
+
(label || showValue) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between mb-1", children: [
|
|
2230
|
+
label && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-white/60", children: label }),
|
|
2231
|
+
showValue && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs text-white/60 ml-auto", children: [
|
|
2232
|
+
Math.round(percentage),
|
|
2233
|
+
"%"
|
|
2234
|
+
] })
|
|
2235
|
+
] }),
|
|
2236
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2237
|
+
"div",
|
|
2238
|
+
{
|
|
2239
|
+
className: cn("w-full rounded-full bg-white/10", sizeClasses[size]),
|
|
2240
|
+
role: "progressbar",
|
|
2241
|
+
"aria-valuenow": value,
|
|
2242
|
+
"aria-valuemin": 0,
|
|
2243
|
+
"aria-valuemax": max,
|
|
2244
|
+
"aria-label": label,
|
|
2245
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2246
|
+
"div",
|
|
2247
|
+
{
|
|
2248
|
+
className: cn(
|
|
2249
|
+
"rounded-full transition-[width] duration-300 ease-out",
|
|
2250
|
+
sizeClasses[size],
|
|
2251
|
+
variantClasses[variant]
|
|
2252
|
+
),
|
|
2253
|
+
style: { width: `${percentage}%` }
|
|
2254
|
+
}
|
|
2255
|
+
)
|
|
2256
|
+
}
|
|
2257
|
+
)
|
|
2258
|
+
] });
|
|
2259
|
+
}
|
|
1522
2260
|
var maxWidthClass = {
|
|
1523
2261
|
sm: "max-w-2xl",
|
|
1524
2262
|
md: "max-w-4xl",
|
|
@@ -1625,7 +2363,320 @@ function DashboardLayout({ children, navbar, sidebar, className, mainClassName,
|
|
|
1625
2363
|
] })
|
|
1626
2364
|
] });
|
|
1627
2365
|
}
|
|
1628
|
-
var
|
|
2366
|
+
var variantBorderColor = {
|
|
2367
|
+
info: "border-blue-500",
|
|
2368
|
+
success: "border-emerald-500",
|
|
2369
|
+
warning: "border-amber-500",
|
|
2370
|
+
error: "border-rose-500"
|
|
2371
|
+
};
|
|
2372
|
+
var variantIconColor = {
|
|
2373
|
+
info: "text-blue-400",
|
|
2374
|
+
success: "text-emerald-400",
|
|
2375
|
+
warning: "text-amber-400",
|
|
2376
|
+
error: "text-rose-400"
|
|
2377
|
+
};
|
|
2378
|
+
function InfoIcon() {
|
|
2379
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2380
|
+
"svg",
|
|
2381
|
+
{
|
|
2382
|
+
"aria-hidden": "true",
|
|
2383
|
+
width: "18",
|
|
2384
|
+
height: "18",
|
|
2385
|
+
viewBox: "0 0 18 18",
|
|
2386
|
+
fill: "none",
|
|
2387
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2388
|
+
children: [
|
|
2389
|
+
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "9", cy: "9", r: "7.5", stroke: "currentColor", strokeWidth: "1.5" }),
|
|
2390
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M9 8v5", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round" }),
|
|
2391
|
+
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "9", cy: "5.5", r: "0.875", fill: "currentColor" })
|
|
2392
|
+
]
|
|
2393
|
+
}
|
|
2394
|
+
);
|
|
2395
|
+
}
|
|
2396
|
+
function SuccessIcon() {
|
|
2397
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2398
|
+
"svg",
|
|
2399
|
+
{
|
|
2400
|
+
"aria-hidden": "true",
|
|
2401
|
+
width: "18",
|
|
2402
|
+
height: "18",
|
|
2403
|
+
viewBox: "0 0 18 18",
|
|
2404
|
+
fill: "none",
|
|
2405
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2406
|
+
children: [
|
|
2407
|
+
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "9", cy: "9", r: "7.5", stroke: "currentColor", strokeWidth: "1.5" }),
|
|
2408
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2409
|
+
"path",
|
|
2410
|
+
{
|
|
2411
|
+
d: "M5.5 9.5l2.5 2.5 4.5-5",
|
|
2412
|
+
stroke: "currentColor",
|
|
2413
|
+
strokeWidth: "1.75",
|
|
2414
|
+
strokeLinecap: "round",
|
|
2415
|
+
strokeLinejoin: "round"
|
|
2416
|
+
}
|
|
2417
|
+
)
|
|
2418
|
+
]
|
|
2419
|
+
}
|
|
2420
|
+
);
|
|
2421
|
+
}
|
|
2422
|
+
function WarningIcon() {
|
|
2423
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2424
|
+
"svg",
|
|
2425
|
+
{
|
|
2426
|
+
"aria-hidden": "true",
|
|
2427
|
+
width: "18",
|
|
2428
|
+
height: "18",
|
|
2429
|
+
viewBox: "0 0 18 18",
|
|
2430
|
+
fill: "none",
|
|
2431
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2432
|
+
children: [
|
|
2433
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2434
|
+
"path",
|
|
2435
|
+
{
|
|
2436
|
+
d: "M7.634 2.896a1.6 1.6 0 0 1 2.732 0l5.866 10.167A1.6 1.6 0 0 1 14.866 15.5H3.134a1.6 1.6 0 0 1-1.366-2.437L7.634 2.896Z",
|
|
2437
|
+
stroke: "currentColor",
|
|
2438
|
+
strokeWidth: "1.5",
|
|
2439
|
+
strokeLinejoin: "round"
|
|
2440
|
+
}
|
|
2441
|
+
),
|
|
2442
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M9 7v4", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round" }),
|
|
2443
|
+
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "9", cy: "12.5", r: "0.875", fill: "currentColor" })
|
|
2444
|
+
]
|
|
2445
|
+
}
|
|
2446
|
+
);
|
|
2447
|
+
}
|
|
2448
|
+
function ErrorIcon() {
|
|
2449
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2450
|
+
"svg",
|
|
2451
|
+
{
|
|
2452
|
+
"aria-hidden": "true",
|
|
2453
|
+
width: "18",
|
|
2454
|
+
height: "18",
|
|
2455
|
+
viewBox: "0 0 18 18",
|
|
2456
|
+
fill: "none",
|
|
2457
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2458
|
+
children: [
|
|
2459
|
+
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "9", cy: "9", r: "7.5", stroke: "currentColor", strokeWidth: "1.5" }),
|
|
2460
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2461
|
+
"path",
|
|
2462
|
+
{
|
|
2463
|
+
d: "M6.5 6.5l5 5M11.5 6.5l-5 5",
|
|
2464
|
+
stroke: "currentColor",
|
|
2465
|
+
strokeWidth: "1.75",
|
|
2466
|
+
strokeLinecap: "round"
|
|
2467
|
+
}
|
|
2468
|
+
)
|
|
2469
|
+
]
|
|
2470
|
+
}
|
|
2471
|
+
);
|
|
2472
|
+
}
|
|
2473
|
+
var variantIcon = {
|
|
2474
|
+
info: InfoIcon,
|
|
2475
|
+
success: SuccessIcon,
|
|
2476
|
+
warning: WarningIcon,
|
|
2477
|
+
error: ErrorIcon
|
|
2478
|
+
};
|
|
2479
|
+
function Alert({ variant = "info", title, children, onDismiss, className }) {
|
|
2480
|
+
const Icon = variantIcon[variant];
|
|
2481
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2482
|
+
"div",
|
|
2483
|
+
{
|
|
2484
|
+
role: "alert",
|
|
2485
|
+
className: cn(
|
|
2486
|
+
"flex items-start gap-3 rounded-xl bg-white/5 ring-1 ring-white/10",
|
|
2487
|
+
"border-l-4 pl-4 pr-3 py-3",
|
|
2488
|
+
variantBorderColor[variant],
|
|
2489
|
+
className
|
|
2490
|
+
),
|
|
2491
|
+
children: [
|
|
2492
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("mt-0.5 shrink-0", variantIconColor[variant]), children: /* @__PURE__ */ jsxRuntime.jsx(Icon, {}) }),
|
|
2493
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
2494
|
+
title && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-semibold text-white leading-snug mb-0.5", children: title }),
|
|
2495
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm text-white/70 leading-relaxed", children })
|
|
2496
|
+
] }),
|
|
2497
|
+
onDismiss && /* @__PURE__ */ jsxRuntime.jsx(
|
|
2498
|
+
"button",
|
|
2499
|
+
{
|
|
2500
|
+
type: "button",
|
|
2501
|
+
"aria-label": "Dismiss",
|
|
2502
|
+
onClick: onDismiss,
|
|
2503
|
+
className: cn(
|
|
2504
|
+
"shrink-0 flex items-center justify-center h-6 w-6 rounded-lg mt-0.5",
|
|
2505
|
+
"text-white/40 transition-colors hover:bg-white/10 hover:text-white/80",
|
|
2506
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/40"
|
|
2507
|
+
),
|
|
2508
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2509
|
+
"svg",
|
|
2510
|
+
{
|
|
2511
|
+
"aria-hidden": "true",
|
|
2512
|
+
width: "10",
|
|
2513
|
+
height: "10",
|
|
2514
|
+
viewBox: "0 0 10 10",
|
|
2515
|
+
fill: "none",
|
|
2516
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M1 1l8 8M9 1L1 9", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" })
|
|
2517
|
+
}
|
|
2518
|
+
)
|
|
2519
|
+
}
|
|
2520
|
+
)
|
|
2521
|
+
]
|
|
2522
|
+
}
|
|
2523
|
+
);
|
|
2524
|
+
}
|
|
2525
|
+
function CopyIcon() {
|
|
2526
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2527
|
+
"svg",
|
|
2528
|
+
{
|
|
2529
|
+
"aria-hidden": "true",
|
|
2530
|
+
width: "16",
|
|
2531
|
+
height: "16",
|
|
2532
|
+
viewBox: "0 0 16 16",
|
|
2533
|
+
fill: "none",
|
|
2534
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2535
|
+
children: [
|
|
2536
|
+
/* @__PURE__ */ jsxRuntime.jsx("rect", { x: "5", y: "5", width: "9", height: "9", rx: "1.5", stroke: "currentColor", strokeWidth: "1.5" }),
|
|
2537
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2538
|
+
"path",
|
|
2539
|
+
{
|
|
2540
|
+
d: "M3.5 11H3a1.5 1.5 0 0 1-1.5-1.5V3A1.5 1.5 0 0 1 3 1.5h6.5A1.5 1.5 0 0 1 11 3v.5",
|
|
2541
|
+
stroke: "currentColor",
|
|
2542
|
+
strokeWidth: "1.5",
|
|
2543
|
+
strokeLinecap: "round"
|
|
2544
|
+
}
|
|
2545
|
+
)
|
|
2546
|
+
]
|
|
2547
|
+
}
|
|
2548
|
+
);
|
|
2549
|
+
}
|
|
2550
|
+
function CheckIcon() {
|
|
2551
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2552
|
+
"svg",
|
|
2553
|
+
{
|
|
2554
|
+
"aria-hidden": "true",
|
|
2555
|
+
width: "16",
|
|
2556
|
+
height: "16",
|
|
2557
|
+
viewBox: "0 0 16 16",
|
|
2558
|
+
fill: "none",
|
|
2559
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2560
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2561
|
+
"path",
|
|
2562
|
+
{
|
|
2563
|
+
d: "M3 8.5l3.5 3.5 6.5-7",
|
|
2564
|
+
stroke: "currentColor",
|
|
2565
|
+
strokeWidth: "1.75",
|
|
2566
|
+
strokeLinecap: "round",
|
|
2567
|
+
strokeLinejoin: "round"
|
|
2568
|
+
}
|
|
2569
|
+
)
|
|
2570
|
+
}
|
|
2571
|
+
);
|
|
2572
|
+
}
|
|
2573
|
+
function EyeIcon() {
|
|
2574
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2575
|
+
"svg",
|
|
2576
|
+
{
|
|
2577
|
+
"aria-hidden": "true",
|
|
2578
|
+
width: "16",
|
|
2579
|
+
height: "16",
|
|
2580
|
+
viewBox: "0 0 16 16",
|
|
2581
|
+
fill: "none",
|
|
2582
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2583
|
+
children: [
|
|
2584
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2585
|
+
"path",
|
|
2586
|
+
{
|
|
2587
|
+
d: "M1.5 8S3.5 3.5 8 3.5 14.5 8 14.5 8 12.5 12.5 8 12.5 1.5 8 1.5 8Z",
|
|
2588
|
+
stroke: "currentColor",
|
|
2589
|
+
strokeWidth: "1.5",
|
|
2590
|
+
strokeLinejoin: "round"
|
|
2591
|
+
}
|
|
2592
|
+
),
|
|
2593
|
+
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "8", cy: "8", r: "2", stroke: "currentColor", strokeWidth: "1.5" })
|
|
2594
|
+
]
|
|
2595
|
+
}
|
|
2596
|
+
);
|
|
2597
|
+
}
|
|
2598
|
+
function EyeOffIcon() {
|
|
2599
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2600
|
+
"svg",
|
|
2601
|
+
{
|
|
2602
|
+
"aria-hidden": "true",
|
|
2603
|
+
width: "16",
|
|
2604
|
+
height: "16",
|
|
2605
|
+
viewBox: "0 0 16 16",
|
|
2606
|
+
fill: "none",
|
|
2607
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2608
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2609
|
+
"path",
|
|
2610
|
+
{
|
|
2611
|
+
d: "M2 2l12 12M6.5 6.6A2 2 0 0 0 9.4 9.5M4.3 4.4C2.9 5.4 1.5 8 1.5 8S3.5 12.5 8 12.5c1.4 0 2.6-.4 3.7-1.1M6.7 3.6C7.1 3.5 7.5 3.5 8 3.5c4.5 0 6.5 4.5 6.5 4.5s-.5 1.2-1.5 2.3",
|
|
2612
|
+
stroke: "currentColor",
|
|
2613
|
+
strokeWidth: "1.5",
|
|
2614
|
+
strokeLinecap: "round",
|
|
2615
|
+
strokeLinejoin: "round"
|
|
2616
|
+
}
|
|
2617
|
+
)
|
|
2618
|
+
}
|
|
2619
|
+
);
|
|
2620
|
+
}
|
|
2621
|
+
var iconButtonBase = cn(
|
|
2622
|
+
"flex items-center justify-center h-7 w-7 rounded-lg shrink-0",
|
|
2623
|
+
"text-white/40 transition-colors hover:bg-white/10 hover:text-white/80",
|
|
2624
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/40"
|
|
2625
|
+
);
|
|
2626
|
+
function CopyField({ value, label, masked = false, className, id: externalId }) {
|
|
2627
|
+
const generatedId = React.useId();
|
|
2628
|
+
const fieldId = externalId || generatedId;
|
|
2629
|
+
const { copy, copied } = useClipboard();
|
|
2630
|
+
const [revealed, setRevealed] = React.useState(false);
|
|
2631
|
+
const displayValue = masked && !revealed ? "\u2022".repeat(Math.min(value.length, 24)) : value;
|
|
2632
|
+
const field = /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2633
|
+
"div",
|
|
2634
|
+
{
|
|
2635
|
+
className: cn(
|
|
2636
|
+
"flex items-center gap-1 w-full rounded-xl px-3 py-2.5",
|
|
2637
|
+
"bg-white/10 ring-1 ring-white/10",
|
|
2638
|
+
className
|
|
2639
|
+
),
|
|
2640
|
+
children: [
|
|
2641
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2642
|
+
"span",
|
|
2643
|
+
{
|
|
2644
|
+
id: fieldId,
|
|
2645
|
+
className: "flex-1 min-w-0 truncate text-sm text-white select-all font-mono",
|
|
2646
|
+
"aria-label": label,
|
|
2647
|
+
children: displayValue
|
|
2648
|
+
}
|
|
2649
|
+
),
|
|
2650
|
+
masked && /* @__PURE__ */ jsxRuntime.jsx(
|
|
2651
|
+
"button",
|
|
2652
|
+
{
|
|
2653
|
+
type: "button",
|
|
2654
|
+
"aria-label": revealed ? "Hide value" : "Reveal value",
|
|
2655
|
+
onClick: () => setRevealed((v) => !v),
|
|
2656
|
+
className: iconButtonBase,
|
|
2657
|
+
children: revealed ? /* @__PURE__ */ jsxRuntime.jsx(EyeOffIcon, {}) : /* @__PURE__ */ jsxRuntime.jsx(EyeIcon, {})
|
|
2658
|
+
}
|
|
2659
|
+
),
|
|
2660
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2661
|
+
"button",
|
|
2662
|
+
{
|
|
2663
|
+
type: "button",
|
|
2664
|
+
"aria-label": copied ? "Copied!" : "Copy to clipboard",
|
|
2665
|
+
onClick: () => copy(value),
|
|
2666
|
+
className: cn(iconButtonBase, copied && "text-emerald-400 hover:text-emerald-400"),
|
|
2667
|
+
children: copied ? /* @__PURE__ */ jsxRuntime.jsx(CheckIcon, {}) : /* @__PURE__ */ jsxRuntime.jsx(CopyIcon, {})
|
|
2668
|
+
}
|
|
2669
|
+
)
|
|
2670
|
+
]
|
|
2671
|
+
}
|
|
2672
|
+
);
|
|
2673
|
+
if (!label) return field;
|
|
2674
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2675
|
+
/* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: fieldId, className: "block text-sm text-white/70 mb-1.5", children: label }),
|
|
2676
|
+
field
|
|
2677
|
+
] });
|
|
2678
|
+
}
|
|
2679
|
+
var ProgressButton = React.forwardRef(
|
|
1629
2680
|
function ProgressButton2({ isLoading, loadingText, children, disabled, className, ...props }, ref) {
|
|
1630
2681
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1631
2682
|
Button,
|
|
@@ -1664,7 +2715,7 @@ function reducer(state, action) {
|
|
|
1664
2715
|
return state;
|
|
1665
2716
|
}
|
|
1666
2717
|
}
|
|
1667
|
-
var ToastContext =
|
|
2718
|
+
var ToastContext = React.createContext(null);
|
|
1668
2719
|
var variantBarColor = {
|
|
1669
2720
|
success: "bg-emerald-500",
|
|
1670
2721
|
error: "bg-rose-500",
|
|
@@ -1683,7 +2734,7 @@ var variantIconLabel = {
|
|
|
1683
2734
|
warning: "\u26A0",
|
|
1684
2735
|
info: "i"
|
|
1685
2736
|
};
|
|
1686
|
-
var
|
|
2737
|
+
var variantIconColor2 = {
|
|
1687
2738
|
success: "text-emerald-400",
|
|
1688
2739
|
error: "text-rose-400",
|
|
1689
2740
|
warning: "text-amber-400",
|
|
@@ -1697,13 +2748,13 @@ var positionClass = {
|
|
|
1697
2748
|
};
|
|
1698
2749
|
function ToastCard({ toast, onDismiss }) {
|
|
1699
2750
|
const duration = toast.duration ?? 5e3;
|
|
1700
|
-
const [visible, setVisible] =
|
|
1701
|
-
const [exiting, setExiting] =
|
|
1702
|
-
const [started, setStarted] =
|
|
1703
|
-
const dismissedRef =
|
|
1704
|
-
const timerRef =
|
|
1705
|
-
const exitTimerRef =
|
|
1706
|
-
|
|
2751
|
+
const [visible, setVisible] = React.useState(false);
|
|
2752
|
+
const [exiting, setExiting] = React.useState(false);
|
|
2753
|
+
const [started, setStarted] = React.useState(false);
|
|
2754
|
+
const dismissedRef = React.useRef(false);
|
|
2755
|
+
const timerRef = React.useRef(null);
|
|
2756
|
+
const exitTimerRef = React.useRef(null);
|
|
2757
|
+
React.useEffect(() => {
|
|
1707
2758
|
let innerFrame;
|
|
1708
2759
|
const frame = requestAnimationFrame(() => {
|
|
1709
2760
|
setVisible(true);
|
|
@@ -1714,19 +2765,19 @@ function ToastCard({ toast, onDismiss }) {
|
|
|
1714
2765
|
cancelAnimationFrame(innerFrame);
|
|
1715
2766
|
};
|
|
1716
2767
|
}, []);
|
|
1717
|
-
|
|
2768
|
+
React.useEffect(() => {
|
|
1718
2769
|
return () => {
|
|
1719
2770
|
if (exitTimerRef.current !== null) clearTimeout(exitTimerRef.current);
|
|
1720
2771
|
};
|
|
1721
2772
|
}, []);
|
|
1722
|
-
const triggerDismiss =
|
|
2773
|
+
const triggerDismiss = React.useCallback(() => {
|
|
1723
2774
|
if (dismissedRef.current) return;
|
|
1724
2775
|
dismissedRef.current = true;
|
|
1725
2776
|
if (timerRef.current !== null) clearTimeout(timerRef.current);
|
|
1726
2777
|
setExiting(true);
|
|
1727
2778
|
exitTimerRef.current = setTimeout(() => onDismiss(toast.id), 280);
|
|
1728
2779
|
}, [onDismiss, toast.id]);
|
|
1729
|
-
|
|
2780
|
+
React.useEffect(() => {
|
|
1730
2781
|
if (duration <= 0) return;
|
|
1731
2782
|
timerRef.current = setTimeout(triggerDismiss, duration);
|
|
1732
2783
|
return () => {
|
|
@@ -1759,7 +2810,7 @@ function ToastCard({ toast, onDismiss }) {
|
|
|
1759
2810
|
"aria-hidden": "true",
|
|
1760
2811
|
className: cn(
|
|
1761
2812
|
"mt-0.5 flex h-5 w-5 shrink-0 items-center justify-center rounded-full text-[11px] font-bold ring-1",
|
|
1762
|
-
|
|
2813
|
+
variantIconColor2[toast.variant],
|
|
1763
2814
|
"ring-current/30"
|
|
1764
2815
|
),
|
|
1765
2816
|
children: variantIconLabel[toast.variant]
|
|
@@ -1805,11 +2856,11 @@ function ToastCard({ toast, onDismiss }) {
|
|
|
1805
2856
|
);
|
|
1806
2857
|
}
|
|
1807
2858
|
function ToastProvider({ children, position = "top-right", maxToasts = 5 }) {
|
|
1808
|
-
const [toasts, dispatch] =
|
|
1809
|
-
const counterRef =
|
|
1810
|
-
const maxToastsRef =
|
|
2859
|
+
const [toasts, dispatch] = React.useReducer(reducer, []);
|
|
2860
|
+
const counterRef = React.useRef(0);
|
|
2861
|
+
const maxToastsRef = React.useRef(maxToasts);
|
|
1811
2862
|
maxToastsRef.current = maxToasts;
|
|
1812
|
-
const toast =
|
|
2863
|
+
const toast = React.useCallback(
|
|
1813
2864
|
(options) => {
|
|
1814
2865
|
const id = `toast-${++counterRef.current}`;
|
|
1815
2866
|
const newToast = {
|
|
@@ -1824,13 +2875,13 @@ function ToastProvider({ children, position = "top-right", maxToasts = 5 }) {
|
|
|
1824
2875
|
},
|
|
1825
2876
|
[]
|
|
1826
2877
|
);
|
|
1827
|
-
const dismiss =
|
|
2878
|
+
const dismiss = React.useCallback((id) => {
|
|
1828
2879
|
dispatch({ type: "REMOVE", id });
|
|
1829
2880
|
}, []);
|
|
1830
|
-
const dismissAll =
|
|
2881
|
+
const dismissAll = React.useCallback(() => {
|
|
1831
2882
|
dispatch({ type: "REMOVE_ALL" });
|
|
1832
2883
|
}, []);
|
|
1833
|
-
const value =
|
|
2884
|
+
const value = React.useMemo(() => ({ toast, dismiss, dismissAll }), [toast, dismiss, dismissAll]);
|
|
1834
2885
|
const container = typeof document !== "undefined" ? reactDom.createPortal(
|
|
1835
2886
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1836
2887
|
"div",
|
|
@@ -1848,20 +2899,25 @@ function ToastProvider({ children, position = "top-right", maxToasts = 5 }) {
|
|
|
1848
2899
|
] });
|
|
1849
2900
|
}
|
|
1850
2901
|
function useToast() {
|
|
1851
|
-
const ctx =
|
|
2902
|
+
const ctx = React.useContext(ToastContext);
|
|
1852
2903
|
if (!ctx) {
|
|
1853
2904
|
throw new Error("useToast must be used inside <ToastProvider>");
|
|
1854
2905
|
}
|
|
1855
2906
|
return ctx;
|
|
1856
2907
|
}
|
|
1857
2908
|
|
|
2909
|
+
exports.Alert = Alert;
|
|
2910
|
+
exports.Avatar = Avatar;
|
|
1858
2911
|
exports.Badge = Badge;
|
|
1859
2912
|
exports.Button = Button;
|
|
1860
2913
|
exports.Card = Card;
|
|
1861
2914
|
exports.Checkbox = Checkbox;
|
|
1862
2915
|
exports.CollapsibleSection = CollapsibleSection;
|
|
2916
|
+
exports.ColorInput = ColorInput;
|
|
1863
2917
|
exports.ConfirmDialog = ConfirmDialog;
|
|
2918
|
+
exports.CopyField = CopyField;
|
|
1864
2919
|
exports.DashboardLayout = DashboardLayout;
|
|
2920
|
+
exports.Divider = Divider;
|
|
1865
2921
|
exports.DropZone = DropZone;
|
|
1866
2922
|
exports.Dropdown = Dropdown;
|
|
1867
2923
|
exports.DropdownItem = DropdownItem;
|
|
@@ -1869,12 +2925,15 @@ exports.DropdownMenu = DropdownMenu;
|
|
|
1869
2925
|
exports.DropdownSeparator = DropdownSeparator;
|
|
1870
2926
|
exports.DropdownTrigger = DropdownTrigger;
|
|
1871
2927
|
exports.EmptyState = EmptyState;
|
|
2928
|
+
exports.FormField = FormField;
|
|
1872
2929
|
exports.IconButton = IconButton;
|
|
1873
2930
|
exports.Input = Input;
|
|
1874
2931
|
exports.Modal = Modal;
|
|
1875
2932
|
exports.Navbar = Navbar;
|
|
1876
2933
|
exports.PageShell = PageShell;
|
|
2934
|
+
exports.Pagination = Pagination;
|
|
1877
2935
|
exports.Pill = Pill;
|
|
2936
|
+
exports.ProgressBar = ProgressBar;
|
|
1878
2937
|
exports.ProgressButton = ProgressButton;
|
|
1879
2938
|
exports.RadioGroup = RadioGroup;
|
|
1880
2939
|
exports.RadioItem = RadioItem;
|
|
@@ -1882,11 +2941,21 @@ exports.SearchInput = SearchInput;
|
|
|
1882
2941
|
exports.Select = Select;
|
|
1883
2942
|
exports.Sidebar = Sidebar;
|
|
1884
2943
|
exports.Skeleton = Skeleton;
|
|
2944
|
+
exports.Slider = Slider;
|
|
1885
2945
|
exports.Spinner = Spinner;
|
|
2946
|
+
exports.StatCard = StatCard;
|
|
2947
|
+
exports.Stepper = Stepper;
|
|
1886
2948
|
exports.Tab = Tab;
|
|
1887
2949
|
exports.TabList = TabList;
|
|
1888
2950
|
exports.TabPanel = TabPanel;
|
|
2951
|
+
exports.Table = Table;
|
|
2952
|
+
exports.TableBody = TableBody;
|
|
2953
|
+
exports.TableCell = TableCell;
|
|
2954
|
+
exports.TableHead = TableHead;
|
|
2955
|
+
exports.TableHeader = TableHeader;
|
|
2956
|
+
exports.TableRow = TableRow;
|
|
1889
2957
|
exports.Tabs = Tabs;
|
|
2958
|
+
exports.TagInput = TagInput;
|
|
1890
2959
|
exports.Textarea = Textarea;
|
|
1891
2960
|
exports.ToastProvider = ToastProvider;
|
|
1892
2961
|
exports.Toggle = Toggle;
|