@memelabui/ui 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1,9 +1,13 @@
1
1
  'use strict';
2
2
 
3
- var react = require('react');
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] = react.useState(false);
63
- const timerRef = react.useRef(null);
64
- react.useEffect(() => {
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 = react.useCallback(
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] = react.useState(defaultOpen);
93
- const open = react.useCallback(() => setIsOpen(true), []);
94
- const close = react.useCallback(() => setIsOpen(false), []);
95
- const toggle = react.useCallback(() => setIsOpen((prev) => !prev), []);
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] = react.useState(() => {
103
+ const [matches, setMatches] = React.useState(() => {
100
104
  if (typeof window === "undefined") return false;
101
105
  return window.matchMedia(query).matches;
102
106
  });
103
- react.useEffect(() => {
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] = react.useState(value);
119
- react.useEffect(() => {
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 = react.forwardRef(function Button2({ variant = "secondary", size = "md", leftIcon, rightIcon, loading, className, disabled, children, type, ...props }, ref) {
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, sizeClass[size], variantClass[variant], className),
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 sizeClass2 = {
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 = react.forwardRef(function IconButton2({ icon, variant = "ghost", size = "md", className, disabled, type, ...props }, ref) {
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, sizeClass2[size], variantClass2[variant], className),
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 = react.forwardRef(function Input2({ hasError, label, error, helperText, className, id: externalId, ...props }, ref) {
213
- const generatedId = react.useId();
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 = react.forwardRef(function SearchInput2({ label, onClear, className, id: externalId, placeholder = "Search...", value, ...props }, ref) {
239
- const generatedId = react.useId();
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 = react.forwardRef(function Select2({ hasError, label, error, helperText, className, id: externalId, children, ...props }, ref) {
311
- const generatedId = react.useId();
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 = react.forwardRef(function Textarea2({ hasError, label, error, helperText, className, id: externalId, ...props }, ref) {
338
- const generatedId = react.useId();
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 sizeClass3 = {
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 = react.forwardRef(function Badge2({ children, variant = "neutral", size = "sm", className, ...props }, ref) {
378
- return /* @__PURE__ */ jsxRuntime.jsx("span", { ref, ...props, className: cn(base3, sizeClass3[size], variantClass3[variant], className), children });
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 = react.forwardRef(function Toggle2({ checked, onChange, disabled, label, size = "md", id: externalId, "aria-label": ariaLabel }, ref) {
390
- const generatedId = react.useId();
561
+ var Toggle = React.forwardRef(function Toggle2({ checked, onChange, disabled, busy, 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(
@@ -399,7 +571,8 @@ var Toggle = react.forwardRef(function Toggle2({ checked, onChange, disabled, la
399
571
  role: "switch",
400
572
  "aria-checked": checked,
401
573
  "aria-label": ariaLabel || label,
402
- disabled,
574
+ disabled: disabled || busy,
575
+ "aria-busy": busy || void 0,
403
576
  onClick: () => onChange(!checked),
404
577
  className: cn(
405
578
  "relative rounded-full transition-colors duration-200 focus-visible:ring-2 focus-visible:ring-primary/40 focus-visible:ring-offset-2 focus-visible:ring-offset-surface",
@@ -411,9 +584,18 @@ var Toggle = react.forwardRef(function Toggle2({ checked, onChange, disabled, la
411
584
  "span",
412
585
  {
413
586
  className: cn(
414
- "absolute top-0.5 left-0.5 rounded-full bg-white transition-transform duration-200",
587
+ "absolute top-0.5 left-0.5 rounded-full bg-white transition-transform duration-200 flex items-center justify-center",
415
588
  thumbSize[size].base,
416
589
  checked ? thumbSize[size].translate : "translate-x-0"
590
+ ),
591
+ children: busy && /* @__PURE__ */ jsxRuntime.jsx(
592
+ "span",
593
+ {
594
+ className: cn(
595
+ "border-2 border-primary/30 border-t-primary rounded-full animate-spin",
596
+ size === "sm" ? "w-2.5 h-2.5" : "w-3 h-3"
597
+ )
598
+ }
417
599
  )
418
600
  }
419
601
  )
@@ -422,12 +604,180 @@ var Toggle = react.forwardRef(function Toggle2({ checked, onChange, disabled, la
422
604
  label && /* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: toggleId, className: "text-sm text-white/60 cursor-pointer", children: label })
423
605
  ] });
424
606
  });
425
- var Checkbox = react.forwardRef(function Checkbox2({ label, error, indeterminate, className, id: externalId, disabled, checked, onChange, ...props }, ref) {
426
- const generatedId = react.useId();
607
+ var Slider = React.forwardRef(function Slider2({
608
+ label,
609
+ showValue = false,
610
+ formatValue,
611
+ onChange,
612
+ disabled,
613
+ min = 0,
614
+ max = 100,
615
+ step = 1,
616
+ value,
617
+ defaultValue,
618
+ className,
619
+ id: externalId,
620
+ ...props
621
+ }, ref) {
622
+ const generatedId = React.useId();
623
+ const sliderId = externalId || generatedId;
624
+ const numericValue = React.useMemo(() => {
625
+ const raw = value !== void 0 ? value : defaultValue;
626
+ return raw !== void 0 ? Number(raw) : Number(min);
627
+ }, [value, defaultValue, min]);
628
+ const percentage = React.useMemo(() => {
629
+ const numMin = Number(min);
630
+ const numMax = Number(max);
631
+ if (numMax === numMin) return 0;
632
+ return Math.max(0, Math.min(100, (numericValue - numMin) / (numMax - numMin) * 100));
633
+ }, [numericValue, min, max]);
634
+ const trackGradient = `linear-gradient(to right, var(--ml-primary, #8b5cf6) ${percentage}%, rgba(255,255,255,0.1) ${percentage}%)`;
635
+ const displayValue = formatValue ? formatValue(numericValue) : String(numericValue);
636
+ const handleChange = (e) => {
637
+ onChange?.(Number(e.target.value));
638
+ };
639
+ const inputEl = /* @__PURE__ */ jsxRuntime.jsx(
640
+ "input",
641
+ {
642
+ ...props,
643
+ ref,
644
+ id: sliderId,
645
+ type: "range",
646
+ min,
647
+ max,
648
+ step,
649
+ value,
650
+ defaultValue: value === void 0 ? defaultValue ?? Number(min) : void 0,
651
+ disabled,
652
+ onChange: handleChange,
653
+ style: { background: trackGradient },
654
+ className: cn(
655
+ // Layout + reset
656
+ "w-full h-2 appearance-none rounded-full outline-none cursor-pointer",
657
+ // bg is set via inline style (trackGradient); keep transparent fallback for SSR
658
+ "bg-white/10",
659
+ // Webkit thumb
660
+ "[&::-webkit-slider-thumb]:appearance-none",
661
+ "[&::-webkit-slider-thumb]:w-4",
662
+ "[&::-webkit-slider-thumb]:h-4",
663
+ "[&::-webkit-slider-thumb]:rounded-full",
664
+ "[&::-webkit-slider-thumb]:bg-white",
665
+ "[&::-webkit-slider-thumb]:border-2",
666
+ "[&::-webkit-slider-thumb]:border-[var(--ml-primary,#8b5cf6)]",
667
+ "[&::-webkit-slider-thumb]:transition-shadow",
668
+ "[&::-webkit-slider-thumb]:duration-150",
669
+ // Moz thumb
670
+ "[&::-moz-range-thumb]:w-4",
671
+ "[&::-moz-range-thumb]:h-4",
672
+ "[&::-moz-range-thumb]:rounded-full",
673
+ "[&::-moz-range-thumb]:bg-white",
674
+ "[&::-moz-range-thumb]:border-2",
675
+ "[&::-moz-range-thumb]:border-[var(--ml-primary,#8b5cf6)]",
676
+ "[&::-moz-range-thumb]:transition-shadow",
677
+ "[&::-moz-range-thumb]:duration-150",
678
+ // Moz track — transparent so the gradient on the element shows through
679
+ "[&::-moz-range-track]:bg-transparent",
680
+ "[&::-moz-range-track]:rounded-full",
681
+ // Focus ring on thumb
682
+ "focus-visible:outline-none",
683
+ "focus-visible:[&::-webkit-slider-thumb]:ring-2",
684
+ "focus-visible:[&::-webkit-slider-thumb]:ring-primary/40",
685
+ "focus-visible:[&::-webkit-slider-thumb]:ring-offset-2",
686
+ "focus-visible:[&::-webkit-slider-thumb]:ring-offset-surface",
687
+ "focus-visible:[&::-moz-range-thumb]:ring-2",
688
+ "focus-visible:[&::-moz-range-thumb]:ring-primary/40",
689
+ // Disabled
690
+ disabled && "opacity-50 cursor-not-allowed",
691
+ className
692
+ )
693
+ }
694
+ );
695
+ if (!label && !showValue) return inputEl;
696
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-full space-y-1.5", children: [
697
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-2", children: [
698
+ label && /* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: sliderId, className: "text-sm text-white/70", children: label }),
699
+ showValue && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium text-white/90 tabular-nums ml-auto", children: displayValue })
700
+ ] }),
701
+ inputEl
702
+ ] });
703
+ });
704
+ var ColorInput = React.forwardRef(function ColorInput2({ value, onChange, label, disabled, className, id: idProp }, ref) {
705
+ const autoId = React.useId();
706
+ const id = idProp ?? autoId;
707
+ const nativePickerRef = React.useRef(null);
708
+ function handleSwatchClick() {
709
+ if (!disabled) {
710
+ nativePickerRef.current?.click();
711
+ }
712
+ }
713
+ function handleTextChange(e) {
714
+ onChange(e.target.value);
715
+ }
716
+ function handleNativeChange(e) {
717
+ onChange(e.target.value);
718
+ }
719
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex flex-col gap-1.5", className), children: [
720
+ label ? /* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: id, className: "block text-sm text-white/70", children: label }) : null,
721
+ /* @__PURE__ */ jsxRuntime.jsxs(
722
+ "div",
723
+ {
724
+ className: cn(
725
+ "flex items-center gap-2 bg-white/10 rounded-xl ring-1 ring-white/10 px-3 py-2 transition-shadow",
726
+ "focus-within:ring-2 focus-within:ring-primary/40",
727
+ disabled && "opacity-60 pointer-events-none"
728
+ ),
729
+ children: [
730
+ /* @__PURE__ */ jsxRuntime.jsx(
731
+ "input",
732
+ {
733
+ type: "color",
734
+ ref: nativePickerRef,
735
+ value,
736
+ onChange: handleNativeChange,
737
+ disabled,
738
+ "aria-hidden": "true",
739
+ tabIndex: -1,
740
+ className: "sr-only"
741
+ }
742
+ ),
743
+ /* @__PURE__ */ jsxRuntime.jsx(
744
+ "button",
745
+ {
746
+ type: "button",
747
+ onClick: handleSwatchClick,
748
+ disabled,
749
+ "aria-label": "Open color picker",
750
+ className: cn(
751
+ "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"
752
+ ),
753
+ style: { backgroundColor: value }
754
+ }
755
+ ),
756
+ /* @__PURE__ */ jsxRuntime.jsx(
757
+ "input",
758
+ {
759
+ ref,
760
+ id,
761
+ type: "text",
762
+ value,
763
+ onChange: handleTextChange,
764
+ disabled,
765
+ spellCheck: false,
766
+ className: "flex-1 min-w-0 bg-transparent text-sm text-white placeholder:text-white/30 outline-none font-mono",
767
+ placeholder: "#000000"
768
+ }
769
+ )
770
+ ]
771
+ }
772
+ )
773
+ ] });
774
+ });
775
+ var Checkbox = React.forwardRef(function Checkbox2({ label, error, indeterminate, className, id: externalId, disabled, checked, onChange, ...props }, ref) {
776
+ const generatedId = React.useId();
427
777
  const inputId = externalId || generatedId;
428
778
  const errorId = error ? `${inputId}-error` : void 0;
429
- const internalRef = react.useRef(null);
430
- react.useEffect(() => {
779
+ const internalRef = React.useRef(null);
780
+ React.useEffect(() => {
431
781
  const el = internalRef.current;
432
782
  if (el) {
433
783
  el.indeterminate = indeterminate ?? false;
@@ -514,9 +864,9 @@ var Checkbox = react.forwardRef(function Checkbox2({ label, error, indeterminate
514
864
  error && /* @__PURE__ */ jsxRuntime.jsx("p", { id: errorId, className: "text-rose-400 text-xs ml-7", children: error })
515
865
  ] });
516
866
  });
517
- var RadioGroupContext = react.createContext(null);
867
+ var RadioGroupContext = React.createContext(null);
518
868
  function useRadioGroup() {
519
- const ctx = react.useContext(RadioGroupContext);
869
+ const ctx = React.useContext(RadioGroupContext);
520
870
  if (!ctx) {
521
871
  throw new Error("RadioItem must be used inside a RadioGroup");
522
872
  }
@@ -534,13 +884,13 @@ function RadioGroup({
534
884
  children,
535
885
  className
536
886
  }) {
537
- const groupId = react.useId();
538
- const generatedName = react.useId();
887
+ const groupId = React.useId();
888
+ const generatedName = React.useId();
539
889
  const name = externalName ?? generatedName;
540
- const [uncontrolledValue, setUncontrolledValue] = react.useState(defaultValue);
890
+ const [uncontrolledValue, setUncontrolledValue] = React.useState(defaultValue);
541
891
  const isControlled = controlledValue !== void 0;
542
892
  const currentValue = isControlled ? controlledValue : uncontrolledValue;
543
- const handleChange = react.useCallback(
893
+ const handleChange = React.useCallback(
544
894
  (val) => {
545
895
  if (!isControlled) setUncontrolledValue(val);
546
896
  onValueChange?.(val);
@@ -549,7 +899,7 @@ function RadioGroup({
549
899
  );
550
900
  const labelId = label ? `${groupId}-label` : void 0;
551
901
  const errorId = error ? `${groupId}-error` : void 0;
552
- const ctxValue = react.useMemo(
902
+ const ctxValue = React.useMemo(
553
903
  () => ({ value: currentValue, onChange: handleChange, name, disabled, groupId }),
554
904
  [currentValue, handleChange, name, disabled, groupId]
555
905
  );
@@ -580,8 +930,8 @@ function RadioGroup({
580
930
  }
581
931
  function RadioItem({ value, disabled: itemDisabled, children, className }) {
582
932
  const { value: groupValue, onChange, name, disabled: groupDisabled, groupId } = useRadioGroup();
583
- const inputId = react.useId();
584
- const inputRef = react.useRef(null);
933
+ const inputId = React.useId();
934
+ const inputRef = React.useRef(null);
585
935
  const isDisabled = groupDisabled || itemDisabled;
586
936
  const isSelected = groupValue === value;
587
937
  const handleKeyDown = (e) => {
@@ -647,7 +997,7 @@ function RadioItem({ value, disabled: itemDisabled, children, className }) {
647
997
  }
648
998
  );
649
999
  }
650
- var sizeClass4 = {
1000
+ var sizeClass5 = {
651
1001
  sm: "h-3 w-3 border",
652
1002
  md: "h-4 w-4 border-2",
653
1003
  lg: "h-6 w-6 border-2"
@@ -656,7 +1006,7 @@ function Spinner({ className, size = "md", label }) {
656
1006
  return /* @__PURE__ */ jsxRuntime.jsx(
657
1007
  "span",
658
1008
  {
659
- className: cn("inline-block rounded-full border-white/15 border-t-primary animate-spin", sizeClass4[size], className),
1009
+ className: cn("inline-block rounded-full border-white/15 border-t-primary animate-spin", sizeClass5[size], className),
660
1010
  role: label ? "status" : void 0,
661
1011
  "aria-hidden": label ? void 0 : "true",
662
1012
  "aria-label": label || void 0
@@ -672,9 +1022,9 @@ function Skeleton({ className, circle }) {
672
1022
  }
673
1023
  );
674
1024
  }
675
- var TabsContext = react.createContext(null);
1025
+ var TabsContext = React.createContext(null);
676
1026
  function useTabsContext() {
677
- const ctx = react.useContext(TabsContext);
1027
+ const ctx = React.useContext(TabsContext);
678
1028
  if (!ctx) throw new Error("Tabs sub-components must be used inside <Tabs>");
679
1029
  return ctx;
680
1030
  }
@@ -686,18 +1036,18 @@ function Tabs({
686
1036
  children,
687
1037
  className
688
1038
  }) {
689
- const baseId = react.useId();
1039
+ const baseId = React.useId();
690
1040
  const isControlled = value !== void 0;
691
- const [internalValue, setInternalValue] = react.useState(defaultValue);
1041
+ const [internalValue, setInternalValue] = React.useState(defaultValue);
692
1042
  const activeValue = isControlled ? value ?? "" : internalValue;
693
- const setActiveValue = react.useCallback(
1043
+ const setActiveValue = React.useCallback(
694
1044
  (next) => {
695
1045
  if (!isControlled) setInternalValue(next);
696
1046
  onValueChange?.(next);
697
1047
  },
698
1048
  [isControlled, onValueChange]
699
1049
  );
700
- const ctxValue = react.useMemo(
1050
+ const ctxValue = React.useMemo(
701
1051
  () => ({ activeValue, setActiveValue, variant, baseId }),
702
1052
  [activeValue, setActiveValue, variant, baseId]
703
1053
  );
@@ -705,7 +1055,7 @@ function Tabs({
705
1055
  }
706
1056
  function TabList({ children, className }) {
707
1057
  const { variant } = useTabsContext();
708
- const listRef = react.useRef(null);
1058
+ const listRef = React.useRef(null);
709
1059
  const handleKeyDown = (e) => {
710
1060
  const list = listRef.current;
711
1061
  if (!list) return;
@@ -810,7 +1160,7 @@ function TabPanel({ value, children, className }) {
810
1160
  }
811
1161
  );
812
1162
  }
813
- var Card = react.forwardRef(function Card2({ hoverable, variant = "surface", className, ...props }, ref) {
1163
+ var Card = React.forwardRef(function Card2({ hoverable, variant = "surface", className, ...props }, ref) {
814
1164
  return /* @__PURE__ */ jsxRuntime.jsx(
815
1165
  "div",
816
1166
  {
@@ -850,9 +1200,9 @@ function Modal({
850
1200
  contentClassName,
851
1201
  zIndexClassName = "z-50"
852
1202
  }) {
853
- const dialogRef = react.useRef(null);
854
- const lastActiveElementRef = react.useRef(null);
855
- react.useEffect(() => {
1203
+ const dialogRef = React.useRef(null);
1204
+ const lastActiveElementRef = React.useRef(null);
1205
+ React.useEffect(() => {
856
1206
  if (!isOpen) return;
857
1207
  lastActiveElementRef.current = document.activeElement instanceof HTMLElement ? document.activeElement : null;
858
1208
  const raf = window.requestAnimationFrame(() => {
@@ -868,7 +1218,7 @@ function Modal({
868
1218
  if (lastActive?.isConnected) focusSafely(lastActive);
869
1219
  };
870
1220
  }, [isOpen]);
871
- react.useEffect(() => {
1221
+ React.useEffect(() => {
872
1222
  if (!isOpen) return;
873
1223
  lockScroll();
874
1224
  return () => unlockScroll();
@@ -961,7 +1311,7 @@ function ConfirmDialog({
961
1311
  variant = "danger",
962
1312
  isLoading = false
963
1313
  }) {
964
- const titleId = react.useId();
1314
+ const titleId = React.useId();
965
1315
  return /* @__PURE__ */ jsxRuntime.jsxs(
966
1316
  Modal,
967
1317
  {
@@ -1006,22 +1356,22 @@ function ConfirmDialog({
1006
1356
  );
1007
1357
  }
1008
1358
  function Tooltip({ content, delayMs = 500, placement = "top", className, children }) {
1009
- const tooltipId = react.useId();
1010
- const openTimerRef = react.useRef(null);
1011
- const anchorRef = react.useRef(null);
1012
- const [open, setOpen] = react.useState(false);
1013
- const [pos, setPos] = react.useState(null);
1014
- react.useMemo(() => {
1359
+ const tooltipId = React.useId();
1360
+ const openTimerRef = React.useRef(null);
1361
+ const anchorRef = React.useRef(null);
1362
+ const [open, setOpen] = React.useState(false);
1363
+ const [pos, setPos] = React.useState(null);
1364
+ React.useMemo(() => {
1015
1365
  if (typeof content === "string") return content.trim();
1016
1366
  return "";
1017
1367
  }, [content]);
1018
- const clearTimer = react.useCallback(() => {
1368
+ const clearTimer = React.useCallback(() => {
1019
1369
  if (openTimerRef.current !== null) {
1020
1370
  window.clearTimeout(openTimerRef.current);
1021
1371
  openTimerRef.current = null;
1022
1372
  }
1023
1373
  }, []);
1024
- const updatePosition = react.useCallback(() => {
1374
+ const updatePosition = React.useCallback(() => {
1025
1375
  const el = anchorRef.current;
1026
1376
  if (!el) return;
1027
1377
  const r = el.getBoundingClientRect();
@@ -1037,17 +1387,17 @@ function Tooltip({ content, delayMs = 500, placement = "top", className, childre
1037
1387
  placement: effPlacement
1038
1388
  });
1039
1389
  }, [placement]);
1040
- const scheduleOpen = react.useCallback(() => {
1390
+ const scheduleOpen = React.useCallback(() => {
1041
1391
  clearTimer();
1042
1392
  openTimerRef.current = window.setTimeout(() => {
1043
1393
  setOpen(true);
1044
1394
  }, Math.max(0, delayMs));
1045
1395
  }, [clearTimer, delayMs]);
1046
- const close = react.useCallback(() => {
1396
+ const close = React.useCallback(() => {
1047
1397
  clearTimer();
1048
1398
  setOpen(false);
1049
1399
  }, [clearTimer]);
1050
- react.useEffect(() => {
1400
+ React.useEffect(() => {
1051
1401
  if (!open) return;
1052
1402
  updatePosition();
1053
1403
  const onScroll = () => updatePosition();
@@ -1059,11 +1409,11 @@ function Tooltip({ content, delayMs = 500, placement = "top", className, childre
1059
1409
  window.removeEventListener("resize", onResize);
1060
1410
  };
1061
1411
  }, [open, updatePosition]);
1062
- react.useEffect(() => {
1412
+ React.useEffect(() => {
1063
1413
  return () => clearTimer();
1064
1414
  }, [clearTimer]);
1065
- if (!react.isValidElement(children)) return children;
1066
- const child = react.cloneElement(children, {
1415
+ if (!React.isValidElement(children)) return children;
1416
+ const child = React.cloneElement(children, {
1067
1417
  ref: (node) => {
1068
1418
  anchorRef.current = node;
1069
1419
  const childProps = children.props;
@@ -1128,8 +1478,8 @@ function EmptyState({ icon: Icon, title, description, actionLabel, onAction, chi
1128
1478
  ] });
1129
1479
  }
1130
1480
  function CollapsibleSection({ title, defaultOpen = true, children, right, className }) {
1131
- const [isOpen, setIsOpen] = react.useState(defaultOpen);
1132
- const contentId = react.useId();
1481
+ const [isOpen, setIsOpen] = React.useState(defaultOpen);
1482
+ const contentId = React.useId();
1133
1483
  const titleId = `${contentId}-title`;
1134
1484
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("rounded-xl ring-1 ring-white/10 bg-white/5 overflow-hidden", className), children: [
1135
1485
  /* @__PURE__ */ jsxRuntime.jsxs(
@@ -1176,21 +1526,21 @@ function CollapsibleSection({ title, defaultOpen = true, children, right, classN
1176
1526
  )
1177
1527
  ] });
1178
1528
  }
1179
- var DropdownContext = react.createContext(null);
1529
+ var DropdownContext = React.createContext(null);
1180
1530
  function useDropdownContext(component) {
1181
- const ctx = react.useContext(DropdownContext);
1531
+ const ctx = React.useContext(DropdownContext);
1182
1532
  if (!ctx) {
1183
1533
  throw new Error(`<${component}> must be rendered inside <Dropdown>`);
1184
1534
  }
1185
1535
  return ctx;
1186
1536
  }
1187
1537
  function Dropdown({ children, className }) {
1188
- const [open, setOpen] = react.useState(false);
1189
- const triggerId = react.useId();
1190
- const menuId = react.useId();
1191
- const triggerRef = react.useRef(null);
1192
- const toggleOpen = react.useCallback(() => setOpen((prev) => !prev), []);
1193
- const ctxValue = react.useMemo(
1538
+ const [open, setOpen] = React.useState(false);
1539
+ const triggerId = React.useId();
1540
+ const menuId = React.useId();
1541
+ const triggerRef = React.useRef(null);
1542
+ const toggleOpen = React.useCallback(() => setOpen((prev) => !prev), []);
1543
+ const ctxValue = React.useMemo(
1194
1544
  () => ({ open, setOpen, toggleOpen, triggerId, menuId, triggerRef }),
1195
1545
  [open, setOpen, toggleOpen, triggerId, menuId, triggerRef]
1196
1546
  );
@@ -1198,8 +1548,8 @@ function Dropdown({ children, className }) {
1198
1548
  }
1199
1549
  function DropdownTrigger({ children, className }) {
1200
1550
  const { open, toggleOpen, triggerId, menuId, triggerRef } = useDropdownContext("DropdownTrigger");
1201
- if (!react.isValidElement(children)) return children;
1202
- return react.cloneElement(children, {
1551
+ if (!React.isValidElement(children)) return children;
1552
+ return React.cloneElement(children, {
1203
1553
  id: triggerId,
1204
1554
  "aria-haspopup": "menu",
1205
1555
  "aria-expanded": open,
@@ -1221,10 +1571,10 @@ function DropdownTrigger({ children, className }) {
1221
1571
  }
1222
1572
  function DropdownMenu({ children, className, align = "left" }) {
1223
1573
  const { open, setOpen, menuId, triggerId, triggerRef } = useDropdownContext("DropdownMenu");
1224
- const menuRef = react.useRef(null);
1225
- const [pos, setPos] = react.useState(null);
1226
- const [visible, setVisible] = react.useState(false);
1227
- const updatePosition = react.useCallback(() => {
1574
+ const menuRef = React.useRef(null);
1575
+ const [pos, setPos] = React.useState(null);
1576
+ const [visible, setVisible] = React.useState(false);
1577
+ const updatePosition = React.useCallback(() => {
1228
1578
  const trigger = triggerRef.current;
1229
1579
  if (!trigger) return;
1230
1580
  const rect = trigger.getBoundingClientRect();
@@ -1234,7 +1584,7 @@ function DropdownMenu({ children, className, align = "left" }) {
1234
1584
  left: Math.round(left)
1235
1585
  });
1236
1586
  }, [align, triggerRef]);
1237
- react.useEffect(() => {
1587
+ React.useEffect(() => {
1238
1588
  if (!open) {
1239
1589
  setVisible(false);
1240
1590
  return;
@@ -1249,7 +1599,7 @@ function DropdownMenu({ children, className, align = "left" }) {
1249
1599
  });
1250
1600
  return () => window.cancelAnimationFrame(raf);
1251
1601
  }, [open, updatePosition]);
1252
- react.useEffect(() => {
1602
+ React.useEffect(() => {
1253
1603
  if (!open) return;
1254
1604
  function handlePointerDown(e) {
1255
1605
  const target = e.target;
@@ -1260,7 +1610,7 @@ function DropdownMenu({ children, className, align = "left" }) {
1260
1610
  document.addEventListener("pointerdown", handlePointerDown, true);
1261
1611
  return () => document.removeEventListener("pointerdown", handlePointerDown, true);
1262
1612
  }, [open, setOpen, triggerRef]);
1263
- react.useEffect(() => {
1613
+ React.useEffect(() => {
1264
1614
  if (!open) return;
1265
1615
  const onScroll = () => updatePosition();
1266
1616
  const onResize = () => updatePosition();
@@ -1336,7 +1686,7 @@ function DropdownMenu({ children, className, align = "left" }) {
1336
1686
  }
1337
1687
  function DropdownItem({ onSelect, disabled = false, children, className }) {
1338
1688
  const { setOpen, triggerRef } = useDropdownContext("DropdownItem");
1339
- const handleSelect = react.useCallback(() => {
1689
+ const handleSelect = React.useCallback(() => {
1340
1690
  if (disabled) return;
1341
1691
  setOpen(false);
1342
1692
  focusSafely(triggerRef.current);
@@ -1389,10 +1739,10 @@ function DropZone({
1389
1739
  className,
1390
1740
  "aria-label": ariaLabel = "File drop zone"
1391
1741
  }) {
1392
- const [isDragging, setIsDragging] = react.useState(false);
1393
- const inputRef = react.useRef(null);
1394
- const dragCounterRef = react.useRef(0);
1395
- const processFiles = react.useCallback(
1742
+ const [isDragging, setIsDragging] = React.useState(false);
1743
+ const inputRef = React.useRef(null);
1744
+ const dragCounterRef = React.useRef(0);
1745
+ const processFiles = React.useCallback(
1396
1746
  (fileList) => {
1397
1747
  if (!fileList || disabled) return;
1398
1748
  let files = Array.from(fileList);
@@ -1409,7 +1759,7 @@ function DropZone({
1409
1759
  },
1410
1760
  [accept, disabled, maxFiles, maxSize, onFilesDropped]
1411
1761
  );
1412
- const handleDragEnter = react.useCallback(
1762
+ const handleDragEnter = React.useCallback(
1413
1763
  (e) => {
1414
1764
  e.preventDefault();
1415
1765
  dragCounterRef.current++;
@@ -1417,18 +1767,18 @@ function DropZone({
1417
1767
  },
1418
1768
  [disabled]
1419
1769
  );
1420
- const handleDragOver = react.useCallback(
1770
+ const handleDragOver = React.useCallback(
1421
1771
  (e) => {
1422
1772
  e.preventDefault();
1423
1773
  },
1424
1774
  []
1425
1775
  );
1426
- const handleDragLeave = react.useCallback((e) => {
1776
+ const handleDragLeave = React.useCallback((e) => {
1427
1777
  e.preventDefault();
1428
1778
  dragCounterRef.current--;
1429
1779
  if (dragCounterRef.current === 0) setIsDragging(false);
1430
1780
  }, []);
1431
- const handleDrop = react.useCallback(
1781
+ const handleDrop = React.useCallback(
1432
1782
  (e) => {
1433
1783
  e.preventDefault();
1434
1784
  dragCounterRef.current = 0;
@@ -1438,10 +1788,10 @@ function DropZone({
1438
1788
  },
1439
1789
  [disabled, processFiles]
1440
1790
  );
1441
- const handleClick = react.useCallback(() => {
1791
+ const handleClick = React.useCallback(() => {
1442
1792
  if (!disabled) inputRef.current?.click();
1443
1793
  }, [disabled]);
1444
- const handleKeyDown = react.useCallback(
1794
+ const handleKeyDown = React.useCallback(
1445
1795
  (e) => {
1446
1796
  if (disabled) return;
1447
1797
  if (e.key === "Enter" || e.key === " ") {
@@ -1451,7 +1801,7 @@ function DropZone({
1451
1801
  },
1452
1802
  [disabled]
1453
1803
  );
1454
- const handleInputChange = react.useCallback(() => {
1804
+ const handleInputChange = React.useCallback(() => {
1455
1805
  processFiles(inputRef.current?.files ?? null);
1456
1806
  if (inputRef.current) inputRef.current.value = "";
1457
1807
  }, [processFiles]);
@@ -1519,97 +1869,798 @@ function DropZone({
1519
1869
  }
1520
1870
  );
1521
1871
  }
1522
- var maxWidthClass = {
1523
- sm: "max-w-2xl",
1524
- md: "max-w-4xl",
1525
- lg: "max-w-5xl",
1526
- xl: "max-w-7xl",
1527
- "2xl": "max-w-[92rem]",
1528
- full: "max-w-full"
1529
- };
1530
- function defaultBackground() {
1531
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { "aria-hidden": "true", className: "pointer-events-none absolute inset-0 overflow-hidden", children: [
1532
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute -top-32 -left-32 h-[600px] w-[600px] rounded-full bg-violet-600/20 blur-[140px]" }),
1533
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute top-20 -right-32 h-[500px] w-[500px] rounded-full bg-purple-500/[0.12] blur-[120px]" }),
1534
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute bottom-0 left-1/2 h-[400px] w-[500px] -translate-x-1/2 rounded-full bg-accent/[0.10] blur-[120px]" })
1872
+ function FormField({ label, error, helperText, children, className, id: idProp }) {
1873
+ const autoId = React.useId();
1874
+ const id = idProp ?? autoId;
1875
+ const descIds = [];
1876
+ const errorId = error ? `${id}-error` : void 0;
1877
+ const helperId = helperText ? `${id}-helper` : void 0;
1878
+ if (errorId) descIds.push(errorId);
1879
+ if (helperId) descIds.push(helperId);
1880
+ const describedBy = descIds.length > 0 ? descIds.join(" ") : void 0;
1881
+ const child = React.cloneElement(children, {
1882
+ id,
1883
+ ...describedBy ? { "aria-describedby": describedBy } : {},
1884
+ ...error ? { "aria-invalid": true } : {}
1885
+ });
1886
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex flex-col", className), children: [
1887
+ label ? /* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: id, className: "block text-sm text-white/70 mb-1.5", children: label }) : null,
1888
+ child,
1889
+ error ? /* @__PURE__ */ jsxRuntime.jsx("p", { id: errorId, className: "text-rose-400 text-xs mt-1", role: "alert", children: error }) : null,
1890
+ helperText && !error ? /* @__PURE__ */ jsxRuntime.jsx("p", { id: helperId, className: "text-white/40 text-xs mt-1", children: helperText }) : null
1535
1891
  ] });
1536
1892
  }
1537
- function PageShell({
1538
- header,
1539
- background,
1540
- variant = "plain",
1541
- className,
1542
- mainClassName,
1543
- containerClassName,
1544
- maxWidth = "xl",
1545
- children
1546
- }) {
1547
- const showDefaultBackground = variant !== "minimal" && !background;
1548
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("relative overflow-hidden flex-1 min-h-full flex flex-col", className), children: [
1549
- background,
1550
- showDefaultBackground ? defaultBackground() : null,
1551
- header,
1552
- /* @__PURE__ */ jsxRuntime.jsx(
1553
- "main",
1893
+ function Divider({ orientation = "horizontal", label, className }) {
1894
+ if (orientation === "vertical") {
1895
+ return /* @__PURE__ */ jsxRuntime.jsx(
1896
+ "div",
1554
1897
  {
1555
- className: cn(
1556
- "relative py-8 flex-1 w-full mx-auto px-4 sm:px-6 lg:px-8",
1557
- maxWidthClass[maxWidth],
1558
- containerClassName,
1559
- mainClassName
1560
- ),
1561
- children
1898
+ role: "separator",
1899
+ "aria-orientation": "vertical",
1900
+ className: cn("border-l border-white/10 h-full mx-3 self-stretch", className)
1562
1901
  }
1563
- )
1564
- ] });
1902
+ );
1903
+ }
1904
+ if (label) {
1905
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1906
+ "div",
1907
+ {
1908
+ role: "separator",
1909
+ "aria-orientation": "horizontal",
1910
+ className: cn("flex items-center gap-3 my-3 w-full", className),
1911
+ children: [
1912
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1 border-t border-white/10" }),
1913
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-white/40 leading-none select-none", children: label }),
1914
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1 border-t border-white/10" })
1915
+ ]
1916
+ }
1917
+ );
1918
+ }
1919
+ return /* @__PURE__ */ jsxRuntime.jsx(
1920
+ "hr",
1921
+ {
1922
+ role: "separator",
1923
+ "aria-orientation": "horizontal",
1924
+ className: cn("border-t border-white/10 w-full my-3", className)
1925
+ }
1926
+ );
1565
1927
  }
1566
- function Navbar({ logo, children, className, glass = true }) {
1567
- return /* @__PURE__ */ jsxRuntime.jsx("header", { className: cn("fixed top-0 w-full z-50", glass && "glass", className), children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-w-7xl mx-auto px-6 h-16 flex items-center justify-between", children: [
1568
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-3", children: logo ?? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-9 h-9 rounded-xl animated-gradient" }) }),
1569
- children && /* @__PURE__ */ jsxRuntime.jsx("nav", { "aria-label": "Main navigation", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-4", children }) })
1570
- ] }) });
1928
+ 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 }) }));
1929
+ Table.displayName = "Table";
1930
+ var TableHeader = React.forwardRef(
1931
+ ({ children, className }, ref) => /* @__PURE__ */ jsxRuntime.jsx("thead", { ref, className: cn("bg-white/5 border-b border-white/10", className), children })
1932
+ );
1933
+ TableHeader.displayName = "TableHeader";
1934
+ var TableBody = React.forwardRef(
1935
+ ({ children, className }, ref) => /* @__PURE__ */ jsxRuntime.jsx("tbody", { ref, className: cn("divide-y divide-white/[0.06]", className), children })
1936
+ );
1937
+ TableBody.displayName = "TableBody";
1938
+ var TableRow = React.forwardRef(
1939
+ ({ children, className, hoverable }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
1940
+ "tr",
1941
+ {
1942
+ ref,
1943
+ className: cn(hoverable && "hover:bg-white/[0.03] transition-colors", className),
1944
+ children
1945
+ }
1946
+ )
1947
+ );
1948
+ TableRow.displayName = "TableRow";
1949
+ var TableHead = React.forwardRef(
1950
+ ({ children, className }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
1951
+ "th",
1952
+ {
1953
+ ref,
1954
+ className: cn(
1955
+ "px-4 py-3 text-left text-xs font-semibold text-white/50 uppercase tracking-wider",
1956
+ className
1957
+ ),
1958
+ children
1959
+ }
1960
+ )
1961
+ );
1962
+ TableHead.displayName = "TableHead";
1963
+ var alignClass = {
1964
+ left: "text-left",
1965
+ center: "text-center",
1966
+ right: "text-right"
1967
+ };
1968
+ var TableCell = React.forwardRef(
1969
+ ({ children, className, align = "left" }, ref) => /* @__PURE__ */ jsxRuntime.jsx("td", { ref, className: cn("px-4 py-3 text-white/80", alignClass[align], className), children })
1970
+ );
1971
+ TableCell.displayName = "TableCell";
1972
+ function TrendIndicator({ trend }) {
1973
+ if (trend.value > 0) {
1974
+ return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center gap-1 text-xs text-emerald-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 9V3M3 6l3-3 3 3" }) }),
1976
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
1977
+ "+",
1978
+ trend.value,
1979
+ trend.label ? ` ${trend.label}` : ""
1980
+ ] })
1981
+ ] });
1982
+ }
1983
+ if (trend.value < 0) {
1984
+ return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center gap-1 text-xs text-rose-400", children: [
1985
+ /* @__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" }) }),
1986
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
1987
+ trend.value,
1988
+ trend.label ? ` ${trend.label}` : ""
1989
+ ] })
1990
+ ] });
1991
+ }
1992
+ return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center gap-1 text-xs text-white/40", children: [
1993
+ /* @__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" }) }),
1994
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
1995
+ trend.value,
1996
+ trend.label ? ` ${trend.label}` : ""
1997
+ ] })
1998
+ ] });
1571
1999
  }
1572
- function Sidebar({ children, collapsed = false, onToggle, className }) {
2000
+ function StatCard({ value, label, icon, trend, className }) {
1573
2001
  return /* @__PURE__ */ jsxRuntime.jsxs(
1574
- "aside",
2002
+ "div",
1575
2003
  {
1576
2004
  className: cn(
1577
- "glass h-full flex flex-col transition-[width] duration-200 overflow-hidden",
1578
- collapsed ? "w-16" : "w-64",
2005
+ "bg-white/5 ring-1 ring-white/10 rounded-xl p-4 flex items-start gap-3",
1579
2006
  className
1580
2007
  ),
1581
2008
  children: [
1582
- onToggle && /* @__PURE__ */ jsxRuntime.jsx(
1583
- "button",
1584
- {
1585
- type: "button",
1586
- onClick: onToggle,
1587
- className: "flex items-center justify-center w-full h-12 text-white/40 hover:text-white hover:bg-white/5 transition-colors",
1588
- "aria-label": collapsed ? "Expand sidebar" : "Collapse sidebar",
1589
- children: /* @__PURE__ */ jsxRuntime.jsx(
1590
- "svg",
1591
- {
1592
- className: cn("h-5 w-5 transition-transform duration-200", collapsed && "rotate-180"),
1593
- fill: "none",
1594
- viewBox: "0 0 24 24",
1595
- stroke: "currentColor",
1596
- strokeWidth: 2,
1597
- children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M11 19l-7-7 7-7m8 14l-7-7 7-7" })
1598
- }
1599
- )
1600
- }
1601
- ),
1602
- /* @__PURE__ */ jsxRuntime.jsx("nav", { className: "flex-1 overflow-y-auto py-2", children })
2009
+ 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 }),
2010
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-0.5 min-w-0", children: [
2011
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-2xl font-bold text-white tabular-nums leading-none", children: value }),
2012
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-white/50 truncate", children: label }),
2013
+ trend != null && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1", children: /* @__PURE__ */ jsxRuntime.jsx(TrendIndicator, { trend }) })
2014
+ ] })
1603
2015
  ]
1604
2016
  }
1605
2017
  );
1606
2018
  }
1607
- var maxWidthClass2 = {
1608
- sm: "max-w-2xl",
1609
- md: "max-w-4xl",
1610
- lg: "max-w-5xl",
1611
- xl: "max-w-7xl",
1612
- "2xl": "max-w-[92rem]",
2019
+ function getPageRange(page, totalPages, siblingCount) {
2020
+ if (totalPages <= 1) return [1];
2021
+ const siblingStart = Math.max(2, page - siblingCount);
2022
+ const siblingEnd = Math.min(totalPages - 1, page + siblingCount);
2023
+ const showLeftEllipsis = siblingStart > 2;
2024
+ const showRightEllipsis = siblingEnd < totalPages - 1;
2025
+ const items = [1];
2026
+ if (showLeftEllipsis) {
2027
+ items.push("...");
2028
+ } else {
2029
+ for (let i = 2; i < siblingStart; i++) {
2030
+ items.push(i);
2031
+ }
2032
+ }
2033
+ for (let i = siblingStart; i <= siblingEnd; i++) {
2034
+ items.push(i);
2035
+ }
2036
+ if (showRightEllipsis) {
2037
+ items.push("...");
2038
+ } else {
2039
+ for (let i = siblingEnd + 1; i < totalPages; i++) {
2040
+ items.push(i);
2041
+ }
2042
+ }
2043
+ if (totalPages > 1) {
2044
+ items.push(totalPages);
2045
+ }
2046
+ return items;
2047
+ }
2048
+ 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";
2049
+ var pageButton = cn(buttonBase, "bg-white/5 ring-1 ring-white/10 text-white/80 hover:bg-white/10 hover:text-white");
2050
+ var activeButton = cn(buttonBase, "bg-primary text-white ring-1 ring-primary/20");
2051
+ var navButton = cn(buttonBase, "bg-white/5 ring-1 ring-white/10 text-white/80 hover:bg-white/10 hover:text-white");
2052
+ var ChevronLeft = () => /* @__PURE__ */ jsxRuntime.jsx(
2053
+ "svg",
2054
+ {
2055
+ xmlns: "http://www.w3.org/2000/svg",
2056
+ width: "16",
2057
+ height: "16",
2058
+ viewBox: "0 0 24 24",
2059
+ fill: "none",
2060
+ stroke: "currentColor",
2061
+ strokeWidth: "2",
2062
+ strokeLinecap: "round",
2063
+ strokeLinejoin: "round",
2064
+ "aria-hidden": "true",
2065
+ children: /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "15 18 9 12 15 6" })
2066
+ }
2067
+ );
2068
+ var ChevronRight = () => /* @__PURE__ */ jsxRuntime.jsx(
2069
+ "svg",
2070
+ {
2071
+ xmlns: "http://www.w3.org/2000/svg",
2072
+ width: "16",
2073
+ height: "16",
2074
+ viewBox: "0 0 24 24",
2075
+ fill: "none",
2076
+ stroke: "currentColor",
2077
+ strokeWidth: "2",
2078
+ strokeLinecap: "round",
2079
+ strokeLinejoin: "round",
2080
+ "aria-hidden": "true",
2081
+ children: /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "9 18 15 12 9 6" })
2082
+ }
2083
+ );
2084
+ function Pagination({
2085
+ page,
2086
+ totalPages,
2087
+ onPageChange,
2088
+ siblingCount = 1,
2089
+ className
2090
+ }) {
2091
+ if (totalPages <= 1) return null;
2092
+ const items = getPageRange(page, totalPages, siblingCount);
2093
+ const isPrevDisabled = page <= 1;
2094
+ const isNextDisabled = page >= totalPages;
2095
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2096
+ "nav",
2097
+ {
2098
+ role: "navigation",
2099
+ "aria-label": "Pagination",
2100
+ className: cn("flex items-center gap-1", className),
2101
+ children: [
2102
+ /* @__PURE__ */ jsxRuntime.jsx(
2103
+ "button",
2104
+ {
2105
+ type: "button",
2106
+ onClick: () => onPageChange(page - 1),
2107
+ disabled: isPrevDisabled,
2108
+ "aria-label": "Previous page",
2109
+ className: cn(navButton, isPrevDisabled && "opacity-40 cursor-not-allowed pointer-events-none"),
2110
+ children: /* @__PURE__ */ jsxRuntime.jsx(ChevronLeft, {})
2111
+ }
2112
+ ),
2113
+ items.map(
2114
+ (item, index) => item === "..." ? /* @__PURE__ */ jsxRuntime.jsx(
2115
+ "span",
2116
+ {
2117
+ className: "inline-flex items-center justify-center px-3 py-2 text-sm text-white/40 select-none",
2118
+ "aria-hidden": "true",
2119
+ children: "\u2026"
2120
+ },
2121
+ `ellipsis-${index}`
2122
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
2123
+ "button",
2124
+ {
2125
+ type: "button",
2126
+ onClick: () => onPageChange(item),
2127
+ "aria-label": `Page ${item}`,
2128
+ "aria-current": item === page ? "page" : void 0,
2129
+ className: item === page ? activeButton : pageButton,
2130
+ children: item
2131
+ },
2132
+ item
2133
+ )
2134
+ ),
2135
+ /* @__PURE__ */ jsxRuntime.jsx(
2136
+ "button",
2137
+ {
2138
+ type: "button",
2139
+ onClick: () => onPageChange(page + 1),
2140
+ disabled: isNextDisabled,
2141
+ "aria-label": "Next page",
2142
+ className: cn(navButton, isNextDisabled && "opacity-40 cursor-not-allowed pointer-events-none"),
2143
+ children: /* @__PURE__ */ jsxRuntime.jsx(ChevronRight, {})
2144
+ }
2145
+ )
2146
+ ]
2147
+ }
2148
+ );
2149
+ }
2150
+ function Stepper({ steps, activeStep, className }) {
2151
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("flex items-start w-full", className), children: steps.map((step, index) => {
2152
+ const isCompleted = index < activeStep;
2153
+ const isActive = index === activeStep;
2154
+ return /* @__PURE__ */ jsxRuntime.jsxs(React__default.default.Fragment, { children: [
2155
+ /* @__PURE__ */ jsxRuntime.jsxs(
2156
+ "div",
2157
+ {
2158
+ className: "flex flex-col items-center",
2159
+ "aria-current": isActive ? "step" : void 0,
2160
+ children: [
2161
+ /* @__PURE__ */ jsxRuntime.jsx(
2162
+ "div",
2163
+ {
2164
+ className: cn(
2165
+ "w-8 h-8 rounded-full flex items-center justify-center text-sm font-semibold",
2166
+ isCompleted && "bg-emerald-600 text-white",
2167
+ isActive && "bg-primary text-white ring-2 ring-primary/40",
2168
+ !isCompleted && !isActive && "bg-white/10 text-white/40"
2169
+ ),
2170
+ children: isCompleted ? /* @__PURE__ */ jsxRuntime.jsx(
2171
+ "svg",
2172
+ {
2173
+ xmlns: "http://www.w3.org/2000/svg",
2174
+ viewBox: "0 0 20 20",
2175
+ fill: "currentColor",
2176
+ className: "w-4 h-4",
2177
+ "aria-hidden": "true",
2178
+ children: /* @__PURE__ */ jsxRuntime.jsx(
2179
+ "path",
2180
+ {
2181
+ fillRule: "evenodd",
2182
+ 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",
2183
+ clipRule: "evenodd"
2184
+ }
2185
+ )
2186
+ }
2187
+ ) : /* @__PURE__ */ jsxRuntime.jsx("span", { children: index + 1 })
2188
+ }
2189
+ ),
2190
+ /* @__PURE__ */ jsxRuntime.jsx(
2191
+ "span",
2192
+ {
2193
+ className: cn(
2194
+ "text-xs mt-2 text-center max-w-[6rem]",
2195
+ isActive ? "text-white/80" : "text-white/50"
2196
+ ),
2197
+ children: step.label
2198
+ }
2199
+ ),
2200
+ step.description && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs mt-0.5 text-center text-white/30 max-w-[6rem]", children: step.description })
2201
+ ]
2202
+ }
2203
+ ),
2204
+ index < steps.length - 1 && /* @__PURE__ */ jsxRuntime.jsx(
2205
+ "div",
2206
+ {
2207
+ className: cn(
2208
+ "h-0.5 flex-1 mx-2 mt-4 self-start",
2209
+ isCompleted ? "bg-emerald-600" : "bg-white/10"
2210
+ ),
2211
+ "aria-hidden": "true"
2212
+ }
2213
+ )
2214
+ ] }, index);
2215
+ }) });
2216
+ }
2217
+ var sizeClasses = {
2218
+ sm: "h-1",
2219
+ md: "h-2",
2220
+ lg: "h-3"
2221
+ };
2222
+ var variantClasses = {
2223
+ primary: "bg-primary",
2224
+ success: "bg-emerald-500",
2225
+ warning: "bg-amber-500",
2226
+ danger: "bg-rose-500"
2227
+ };
2228
+ function ProgressBar({
2229
+ value,
2230
+ max = 100,
2231
+ variant = "primary",
2232
+ label,
2233
+ showValue = false,
2234
+ size = "md",
2235
+ className
2236
+ }) {
2237
+ const percentage = Math.min(100, Math.max(0, value / max * 100));
2238
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("w-full", className), children: [
2239
+ (label || showValue) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between mb-1", children: [
2240
+ label && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-white/60", children: label }),
2241
+ showValue && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs text-white/60 ml-auto", children: [
2242
+ Math.round(percentage),
2243
+ "%"
2244
+ ] })
2245
+ ] }),
2246
+ /* @__PURE__ */ jsxRuntime.jsx(
2247
+ "div",
2248
+ {
2249
+ className: cn("w-full rounded-full bg-white/10", sizeClasses[size]),
2250
+ role: "progressbar",
2251
+ "aria-valuenow": value,
2252
+ "aria-valuemin": 0,
2253
+ "aria-valuemax": max,
2254
+ "aria-label": label,
2255
+ children: /* @__PURE__ */ jsxRuntime.jsx(
2256
+ "div",
2257
+ {
2258
+ className: cn(
2259
+ "rounded-full transition-[width] duration-300 ease-out",
2260
+ sizeClasses[size],
2261
+ variantClasses[variant]
2262
+ ),
2263
+ style: { width: `${percentage}%` }
2264
+ }
2265
+ )
2266
+ }
2267
+ )
2268
+ ] });
2269
+ }
2270
+ var sizeMap = {
2271
+ sm: "w-8 h-8 text-xs",
2272
+ md: "w-12 h-12 text-sm",
2273
+ lg: "w-16 h-16 text-base"
2274
+ };
2275
+ var strokeWidthMap = {
2276
+ sm: 3,
2277
+ md: 3.5,
2278
+ lg: 4
2279
+ };
2280
+ var RADIUS = 15.9155;
2281
+ var CIRCUMFERENCE = 2 * Math.PI * RADIUS;
2282
+ function CooldownRing({
2283
+ duration,
2284
+ remaining,
2285
+ size = "md",
2286
+ className
2287
+ }) {
2288
+ const fraction = duration > 0 ? Math.max(0, Math.min(1, remaining / duration)) : 0;
2289
+ const offset = CIRCUMFERENCE * (1 - fraction);
2290
+ const color = fraction > 0.5 ? "text-primary" : fraction > 0.25 ? "text-amber-500" : "text-rose-500";
2291
+ const pulse = remaining <= 10 && remaining > 0;
2292
+ const strokeWidth = strokeWidthMap[size];
2293
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("relative inline-flex items-center justify-center", sizeMap[size], className), children: [
2294
+ /* @__PURE__ */ jsxRuntime.jsxs(
2295
+ "svg",
2296
+ {
2297
+ viewBox: "0 0 36 36",
2298
+ className: cn("w-full h-full -rotate-90", color, pulse && "animate-pulse"),
2299
+ "aria-label": `Cooldown: ${remaining} seconds remaining`,
2300
+ role: "img",
2301
+ children: [
2302
+ /* @__PURE__ */ jsxRuntime.jsx(
2303
+ "circle",
2304
+ {
2305
+ cx: "18",
2306
+ cy: "18",
2307
+ r: RADIUS,
2308
+ fill: "none",
2309
+ stroke: "currentColor",
2310
+ strokeWidth,
2311
+ className: "text-white/10"
2312
+ }
2313
+ ),
2314
+ /* @__PURE__ */ jsxRuntime.jsx(
2315
+ "circle",
2316
+ {
2317
+ cx: "18",
2318
+ cy: "18",
2319
+ r: RADIUS,
2320
+ fill: "none",
2321
+ stroke: "currentColor",
2322
+ strokeWidth,
2323
+ strokeDasharray: `${CIRCUMFERENCE} ${CIRCUMFERENCE}`,
2324
+ strokeDashoffset: offset,
2325
+ strokeLinecap: "round",
2326
+ style: { transition: "stroke-dashoffset 0.6s ease" }
2327
+ }
2328
+ )
2329
+ ]
2330
+ }
2331
+ ),
2332
+ /* @__PURE__ */ jsxRuntime.jsx(
2333
+ "span",
2334
+ {
2335
+ className: "absolute font-semibold tabular-nums text-white select-none",
2336
+ style: { lineHeight: 1 },
2337
+ children: Math.max(0, Math.ceil(remaining))
2338
+ }
2339
+ )
2340
+ ] });
2341
+ }
2342
+ function StageProgress({ stages, activeStage, className }) {
2343
+ const clampedActive = Math.max(0, Math.min(activeStage, stages.length - 1));
2344
+ const fillPercent = stages.length <= 1 ? 100 : clampedActive / (stages.length - 1) * 100;
2345
+ const isComplete = clampedActive >= stages.length - 1;
2346
+ const isAnimating = !isComplete;
2347
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("w-full", className), children: [
2348
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-between", children: stages.map((stage, index) => {
2349
+ const isCompleted = index < clampedActive;
2350
+ const isActive = index === clampedActive;
2351
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2352
+ "div",
2353
+ {
2354
+ className: cn(
2355
+ "flex items-center gap-1.5 text-xs font-medium transition-colors duration-300",
2356
+ isCompleted && "text-emerald-400",
2357
+ isActive && "text-white",
2358
+ !isCompleted && !isActive && "text-white/40"
2359
+ ),
2360
+ children: [
2361
+ isCompleted ? (
2362
+ // Completed: emerald check circle
2363
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex h-3.5 w-3.5 items-center justify-center rounded-full bg-emerald-400/20", children: /* @__PURE__ */ jsxRuntime.jsx(
2364
+ "svg",
2365
+ {
2366
+ className: "h-2.5 w-2.5 text-emerald-400",
2367
+ viewBox: "0 0 10 10",
2368
+ fill: "none",
2369
+ xmlns: "http://www.w3.org/2000/svg",
2370
+ "aria-hidden": "true",
2371
+ children: /* @__PURE__ */ jsxRuntime.jsx(
2372
+ "path",
2373
+ {
2374
+ d: "M2 5.5L4 7.5L8 3",
2375
+ stroke: "currentColor",
2376
+ strokeWidth: "1.5",
2377
+ strokeLinecap: "round",
2378
+ strokeLinejoin: "round"
2379
+ }
2380
+ )
2381
+ }
2382
+ ) })
2383
+ ) : isActive ? (
2384
+ // Active: primary dot with ring
2385
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex h-3.5 w-3.5 items-center justify-center rounded-full ring-2 ring-[var(--ml-primary)] ring-offset-1 ring-offset-black/50", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "h-1.5 w-1.5 rounded-full bg-[var(--ml-primary)]" }) })
2386
+ ) : (
2387
+ // Upcoming: hollow dim dot
2388
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "h-3.5 w-3.5 rounded-full border border-white/20 bg-transparent" })
2389
+ ),
2390
+ stage
2391
+ ]
2392
+ },
2393
+ stage
2394
+ );
2395
+ }) }),
2396
+ /* @__PURE__ */ jsxRuntime.jsx(
2397
+ "div",
2398
+ {
2399
+ className: "relative mt-3 h-1.5 w-full overflow-hidden rounded-full bg-white/10",
2400
+ role: "progressbar",
2401
+ "aria-valuenow": clampedActive,
2402
+ "aria-valuemin": 0,
2403
+ "aria-valuemax": stages.length - 1,
2404
+ "aria-label": `Stage ${clampedActive + 1} of ${stages.length}: ${stages[clampedActive]}`,
2405
+ children: /* @__PURE__ */ jsxRuntime.jsx(
2406
+ "div",
2407
+ {
2408
+ className: "h-full rounded-full bg-gradient-to-r from-[var(--ml-accent)] to-[var(--ml-primary)] transition-[width] duration-500 ease-in-out",
2409
+ style: { width: `${fillPercent}%` },
2410
+ children: isAnimating && /* @__PURE__ */ jsxRuntime.jsx(
2411
+ "span",
2412
+ {
2413
+ className: "pointer-events-none absolute inset-0 -translate-x-full animate-[ml-shimmer_2s_ease-in-out_infinite] bg-gradient-to-r from-transparent via-white/30 to-transparent",
2414
+ "aria-hidden": "true"
2415
+ }
2416
+ )
2417
+ }
2418
+ )
2419
+ }
2420
+ )
2421
+ ] });
2422
+ }
2423
+ function getUrgencyClasses(remaining, max) {
2424
+ const ratio = max > 0 ? remaining / max : 0;
2425
+ if (ratio > 0.5) {
2426
+ return {
2427
+ filled: "bg-emerald-400",
2428
+ empty: "bg-emerald-400/30",
2429
+ label: "text-emerald-400"
2430
+ };
2431
+ }
2432
+ if (ratio > 0.25) {
2433
+ return {
2434
+ filled: "bg-amber-400",
2435
+ empty: "bg-amber-400/30",
2436
+ label: "text-amber-400"
2437
+ };
2438
+ }
2439
+ return {
2440
+ filled: "bg-rose-400",
2441
+ empty: "bg-rose-400/30",
2442
+ label: "text-rose-400"
2443
+ };
2444
+ }
2445
+ function DotIndicator({
2446
+ remaining,
2447
+ max,
2448
+ showLabel = false,
2449
+ labelFormat,
2450
+ className
2451
+ }) {
2452
+ const clampedRemaining = Math.max(0, Math.min(remaining, max));
2453
+ const used = max - clampedRemaining;
2454
+ const urgency = getUrgencyClasses(clampedRemaining, max);
2455
+ const defaultLabel = `${clampedRemaining}/${max}`;
2456
+ const label = labelFormat ? labelFormat(clampedRemaining, max) : defaultLabel;
2457
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("inline-flex items-center gap-2", className), children: [
2458
+ /* @__PURE__ */ jsxRuntime.jsx(
2459
+ "div",
2460
+ {
2461
+ className: "flex items-center gap-1",
2462
+ role: "meter",
2463
+ "aria-valuenow": clampedRemaining,
2464
+ "aria-valuemin": 0,
2465
+ "aria-valuemax": max,
2466
+ "aria-label": label,
2467
+ children: Array.from({ length: max }, (_, index) => {
2468
+ const isFilled = index < used;
2469
+ return /* @__PURE__ */ jsxRuntime.jsx(
2470
+ "span",
2471
+ {
2472
+ className: cn(
2473
+ "h-2 w-2 rounded-full transition-colors duration-300",
2474
+ isFilled ? urgency.filled : urgency.empty
2475
+ ),
2476
+ "aria-hidden": "true"
2477
+ },
2478
+ index
2479
+ );
2480
+ })
2481
+ }
2482
+ ),
2483
+ showLabel && /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("text-xs font-medium tabular-nums", urgency.label), children: label })
2484
+ ] });
2485
+ }
2486
+ function ActiveFilterPills({
2487
+ filters,
2488
+ onRemove,
2489
+ onClearAll,
2490
+ clearAllLabel = "Clear all",
2491
+ className
2492
+ }) {
2493
+ if (filters.length === 0) return null;
2494
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex flex-wrap items-center gap-1.5", className), children: [
2495
+ filters.map((filter) => /* @__PURE__ */ jsxRuntime.jsxs(
2496
+ "span",
2497
+ {
2498
+ className: "inline-flex items-center gap-1 rounded-full bg-white/10 px-2.5 py-1 text-xs text-white/80 ring-1 ring-white/10",
2499
+ children: [
2500
+ filter.label,
2501
+ /* @__PURE__ */ jsxRuntime.jsx(
2502
+ "button",
2503
+ {
2504
+ type: "button",
2505
+ onClick: () => onRemove(filter.key),
2506
+ className: "ml-0.5 text-white/50 transition-colors duration-150 hover:text-white focus:outline-none focus-visible:text-white",
2507
+ "aria-label": `Remove filter: ${filter.label}`,
2508
+ children: /* @__PURE__ */ jsxRuntime.jsx(
2509
+ "svg",
2510
+ {
2511
+ className: "h-3 w-3",
2512
+ viewBox: "0 0 12 12",
2513
+ fill: "none",
2514
+ xmlns: "http://www.w3.org/2000/svg",
2515
+ "aria-hidden": "true",
2516
+ children: /* @__PURE__ */ jsxRuntime.jsx(
2517
+ "path",
2518
+ {
2519
+ d: "M9 3L3 9M3 3L9 9",
2520
+ stroke: "currentColor",
2521
+ strokeWidth: "1.5",
2522
+ strokeLinecap: "round"
2523
+ }
2524
+ )
2525
+ }
2526
+ )
2527
+ }
2528
+ )
2529
+ ]
2530
+ },
2531
+ filter.key
2532
+ )),
2533
+ filters.length > 1 && onClearAll && /* @__PURE__ */ jsxRuntime.jsx(
2534
+ "button",
2535
+ {
2536
+ type: "button",
2537
+ onClick: onClearAll,
2538
+ className: "text-xs text-white/40 underline-offset-2 transition-colors duration-150 hover:text-white/70 focus:outline-none focus-visible:text-white/70",
2539
+ children: clearAllLabel
2540
+ }
2541
+ )
2542
+ ] });
2543
+ }
2544
+ function SectionCard({
2545
+ title,
2546
+ description,
2547
+ right,
2548
+ overlay,
2549
+ children,
2550
+ className
2551
+ }) {
2552
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2553
+ "div",
2554
+ {
2555
+ className: cn(
2556
+ "relative bg-white/5 ring-1 ring-white/10 rounded-xl overflow-hidden",
2557
+ className
2558
+ ),
2559
+ children: [
2560
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-3 px-5 py-4 border-b border-white/[0.06]", children: [
2561
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0", children: [
2562
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-semibold text-white", children: title }),
2563
+ description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-white/40 mt-0.5", children: description })
2564
+ ] }),
2565
+ right && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "shrink-0", children: right })
2566
+ ] }),
2567
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-5 py-4", children }),
2568
+ overlay
2569
+ ]
2570
+ }
2571
+ );
2572
+ }
2573
+ var maxWidthClass = {
2574
+ sm: "max-w-2xl",
2575
+ md: "max-w-4xl",
2576
+ lg: "max-w-5xl",
2577
+ xl: "max-w-7xl",
2578
+ "2xl": "max-w-[92rem]",
2579
+ full: "max-w-full"
2580
+ };
2581
+ function defaultBackground() {
2582
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { "aria-hidden": "true", className: "pointer-events-none absolute inset-0 overflow-hidden", children: [
2583
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute -top-32 -left-32 h-[600px] w-[600px] rounded-full bg-violet-600/20 blur-[140px]" }),
2584
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute top-20 -right-32 h-[500px] w-[500px] rounded-full bg-purple-500/[0.12] blur-[120px]" }),
2585
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute bottom-0 left-1/2 h-[400px] w-[500px] -translate-x-1/2 rounded-full bg-accent/[0.10] blur-[120px]" })
2586
+ ] });
2587
+ }
2588
+ function PageShell({
2589
+ header,
2590
+ background,
2591
+ variant = "plain",
2592
+ className,
2593
+ mainClassName,
2594
+ containerClassName,
2595
+ maxWidth = "xl",
2596
+ children
2597
+ }) {
2598
+ const showDefaultBackground = variant !== "minimal" && !background;
2599
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("relative overflow-hidden flex-1 min-h-full flex flex-col", className), children: [
2600
+ background,
2601
+ showDefaultBackground ? defaultBackground() : null,
2602
+ header,
2603
+ /* @__PURE__ */ jsxRuntime.jsx(
2604
+ "main",
2605
+ {
2606
+ className: cn(
2607
+ "relative py-8 flex-1 w-full mx-auto px-4 sm:px-6 lg:px-8",
2608
+ maxWidthClass[maxWidth],
2609
+ containerClassName,
2610
+ mainClassName
2611
+ ),
2612
+ children
2613
+ }
2614
+ )
2615
+ ] });
2616
+ }
2617
+ function Navbar({ logo, children, className, glass = true }) {
2618
+ return /* @__PURE__ */ jsxRuntime.jsx("header", { className: cn("fixed top-0 w-full z-50", glass && "glass", className), children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-w-7xl mx-auto px-6 h-16 flex items-center justify-between", children: [
2619
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-3", children: logo ?? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-9 h-9 rounded-xl animated-gradient" }) }),
2620
+ children && /* @__PURE__ */ jsxRuntime.jsx("nav", { "aria-label": "Main navigation", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-4", children }) })
2621
+ ] }) });
2622
+ }
2623
+ function Sidebar({ children, collapsed = false, onToggle, className }) {
2624
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2625
+ "aside",
2626
+ {
2627
+ className: cn(
2628
+ "glass h-full flex flex-col transition-[width] duration-200 overflow-hidden",
2629
+ collapsed ? "w-16" : "w-64",
2630
+ className
2631
+ ),
2632
+ children: [
2633
+ onToggle && /* @__PURE__ */ jsxRuntime.jsx(
2634
+ "button",
2635
+ {
2636
+ type: "button",
2637
+ onClick: onToggle,
2638
+ className: "flex items-center justify-center w-full h-12 text-white/40 hover:text-white hover:bg-white/5 transition-colors",
2639
+ "aria-label": collapsed ? "Expand sidebar" : "Collapse sidebar",
2640
+ children: /* @__PURE__ */ jsxRuntime.jsx(
2641
+ "svg",
2642
+ {
2643
+ className: cn("h-5 w-5 transition-transform duration-200", collapsed && "rotate-180"),
2644
+ fill: "none",
2645
+ viewBox: "0 0 24 24",
2646
+ stroke: "currentColor",
2647
+ strokeWidth: 2,
2648
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M11 19l-7-7 7-7m8 14l-7-7 7-7" })
2649
+ }
2650
+ )
2651
+ }
2652
+ ),
2653
+ /* @__PURE__ */ jsxRuntime.jsx("nav", { className: "flex-1 overflow-y-auto py-2", children })
2654
+ ]
2655
+ }
2656
+ );
2657
+ }
2658
+ var maxWidthClass2 = {
2659
+ sm: "max-w-2xl",
2660
+ md: "max-w-4xl",
2661
+ lg: "max-w-5xl",
2662
+ xl: "max-w-7xl",
2663
+ "2xl": "max-w-[92rem]",
1613
2664
  full: "max-w-full"
1614
2665
  };
1615
2666
  function DashboardLayout({ children, navbar, sidebar, className, mainClassName, maxWidth = "lg" }) {
@@ -1625,7 +2676,320 @@ function DashboardLayout({ children, navbar, sidebar, className, mainClassName,
1625
2676
  ] })
1626
2677
  ] });
1627
2678
  }
1628
- var ProgressButton = react.forwardRef(
2679
+ var variantBorderColor = {
2680
+ info: "border-blue-500",
2681
+ success: "border-emerald-500",
2682
+ warning: "border-amber-500",
2683
+ error: "border-rose-500"
2684
+ };
2685
+ var variantIconColor = {
2686
+ info: "text-blue-400",
2687
+ success: "text-emerald-400",
2688
+ warning: "text-amber-400",
2689
+ error: "text-rose-400"
2690
+ };
2691
+ function InfoIcon() {
2692
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2693
+ "svg",
2694
+ {
2695
+ "aria-hidden": "true",
2696
+ width: "18",
2697
+ height: "18",
2698
+ viewBox: "0 0 18 18",
2699
+ fill: "none",
2700
+ xmlns: "http://www.w3.org/2000/svg",
2701
+ children: [
2702
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "9", cy: "9", r: "7.5", stroke: "currentColor", strokeWidth: "1.5" }),
2703
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M9 8v5", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round" }),
2704
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "9", cy: "5.5", r: "0.875", fill: "currentColor" })
2705
+ ]
2706
+ }
2707
+ );
2708
+ }
2709
+ function SuccessIcon() {
2710
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2711
+ "svg",
2712
+ {
2713
+ "aria-hidden": "true",
2714
+ width: "18",
2715
+ height: "18",
2716
+ viewBox: "0 0 18 18",
2717
+ fill: "none",
2718
+ xmlns: "http://www.w3.org/2000/svg",
2719
+ children: [
2720
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "9", cy: "9", r: "7.5", stroke: "currentColor", strokeWidth: "1.5" }),
2721
+ /* @__PURE__ */ jsxRuntime.jsx(
2722
+ "path",
2723
+ {
2724
+ d: "M5.5 9.5l2.5 2.5 4.5-5",
2725
+ stroke: "currentColor",
2726
+ strokeWidth: "1.75",
2727
+ strokeLinecap: "round",
2728
+ strokeLinejoin: "round"
2729
+ }
2730
+ )
2731
+ ]
2732
+ }
2733
+ );
2734
+ }
2735
+ function WarningIcon() {
2736
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2737
+ "svg",
2738
+ {
2739
+ "aria-hidden": "true",
2740
+ width: "18",
2741
+ height: "18",
2742
+ viewBox: "0 0 18 18",
2743
+ fill: "none",
2744
+ xmlns: "http://www.w3.org/2000/svg",
2745
+ children: [
2746
+ /* @__PURE__ */ jsxRuntime.jsx(
2747
+ "path",
2748
+ {
2749
+ 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",
2750
+ stroke: "currentColor",
2751
+ strokeWidth: "1.5",
2752
+ strokeLinejoin: "round"
2753
+ }
2754
+ ),
2755
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M9 7v4", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round" }),
2756
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "9", cy: "12.5", r: "0.875", fill: "currentColor" })
2757
+ ]
2758
+ }
2759
+ );
2760
+ }
2761
+ function ErrorIcon() {
2762
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2763
+ "svg",
2764
+ {
2765
+ "aria-hidden": "true",
2766
+ width: "18",
2767
+ height: "18",
2768
+ viewBox: "0 0 18 18",
2769
+ fill: "none",
2770
+ xmlns: "http://www.w3.org/2000/svg",
2771
+ children: [
2772
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "9", cy: "9", r: "7.5", stroke: "currentColor", strokeWidth: "1.5" }),
2773
+ /* @__PURE__ */ jsxRuntime.jsx(
2774
+ "path",
2775
+ {
2776
+ d: "M6.5 6.5l5 5M11.5 6.5l-5 5",
2777
+ stroke: "currentColor",
2778
+ strokeWidth: "1.75",
2779
+ strokeLinecap: "round"
2780
+ }
2781
+ )
2782
+ ]
2783
+ }
2784
+ );
2785
+ }
2786
+ var variantIcon = {
2787
+ info: InfoIcon,
2788
+ success: SuccessIcon,
2789
+ warning: WarningIcon,
2790
+ error: ErrorIcon
2791
+ };
2792
+ function Alert({ variant = "info", title, children, onDismiss, className }) {
2793
+ const Icon = variantIcon[variant];
2794
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2795
+ "div",
2796
+ {
2797
+ role: "alert",
2798
+ className: cn(
2799
+ "flex items-start gap-3 rounded-xl bg-white/5 ring-1 ring-white/10",
2800
+ "border-l-4 pl-4 pr-3 py-3",
2801
+ variantBorderColor[variant],
2802
+ className
2803
+ ),
2804
+ children: [
2805
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("mt-0.5 shrink-0", variantIconColor[variant]), children: /* @__PURE__ */ jsxRuntime.jsx(Icon, {}) }),
2806
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0", children: [
2807
+ title && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-semibold text-white leading-snug mb-0.5", children: title }),
2808
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm text-white/70 leading-relaxed", children })
2809
+ ] }),
2810
+ onDismiss && /* @__PURE__ */ jsxRuntime.jsx(
2811
+ "button",
2812
+ {
2813
+ type: "button",
2814
+ "aria-label": "Dismiss",
2815
+ onClick: onDismiss,
2816
+ className: cn(
2817
+ "shrink-0 flex items-center justify-center h-6 w-6 rounded-lg mt-0.5",
2818
+ "text-white/40 transition-colors hover:bg-white/10 hover:text-white/80",
2819
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/40"
2820
+ ),
2821
+ children: /* @__PURE__ */ jsxRuntime.jsx(
2822
+ "svg",
2823
+ {
2824
+ "aria-hidden": "true",
2825
+ width: "10",
2826
+ height: "10",
2827
+ viewBox: "0 0 10 10",
2828
+ fill: "none",
2829
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M1 1l8 8M9 1L1 9", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" })
2830
+ }
2831
+ )
2832
+ }
2833
+ )
2834
+ ]
2835
+ }
2836
+ );
2837
+ }
2838
+ function CopyIcon() {
2839
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2840
+ "svg",
2841
+ {
2842
+ "aria-hidden": "true",
2843
+ width: "16",
2844
+ height: "16",
2845
+ viewBox: "0 0 16 16",
2846
+ fill: "none",
2847
+ xmlns: "http://www.w3.org/2000/svg",
2848
+ children: [
2849
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "5", y: "5", width: "9", height: "9", rx: "1.5", stroke: "currentColor", strokeWidth: "1.5" }),
2850
+ /* @__PURE__ */ jsxRuntime.jsx(
2851
+ "path",
2852
+ {
2853
+ 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",
2854
+ stroke: "currentColor",
2855
+ strokeWidth: "1.5",
2856
+ strokeLinecap: "round"
2857
+ }
2858
+ )
2859
+ ]
2860
+ }
2861
+ );
2862
+ }
2863
+ function CheckIcon() {
2864
+ return /* @__PURE__ */ jsxRuntime.jsx(
2865
+ "svg",
2866
+ {
2867
+ "aria-hidden": "true",
2868
+ width: "16",
2869
+ height: "16",
2870
+ viewBox: "0 0 16 16",
2871
+ fill: "none",
2872
+ xmlns: "http://www.w3.org/2000/svg",
2873
+ children: /* @__PURE__ */ jsxRuntime.jsx(
2874
+ "path",
2875
+ {
2876
+ d: "M3 8.5l3.5 3.5 6.5-7",
2877
+ stroke: "currentColor",
2878
+ strokeWidth: "1.75",
2879
+ strokeLinecap: "round",
2880
+ strokeLinejoin: "round"
2881
+ }
2882
+ )
2883
+ }
2884
+ );
2885
+ }
2886
+ function EyeIcon() {
2887
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2888
+ "svg",
2889
+ {
2890
+ "aria-hidden": "true",
2891
+ width: "16",
2892
+ height: "16",
2893
+ viewBox: "0 0 16 16",
2894
+ fill: "none",
2895
+ xmlns: "http://www.w3.org/2000/svg",
2896
+ children: [
2897
+ /* @__PURE__ */ jsxRuntime.jsx(
2898
+ "path",
2899
+ {
2900
+ 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",
2901
+ stroke: "currentColor",
2902
+ strokeWidth: "1.5",
2903
+ strokeLinejoin: "round"
2904
+ }
2905
+ ),
2906
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "8", cy: "8", r: "2", stroke: "currentColor", strokeWidth: "1.5" })
2907
+ ]
2908
+ }
2909
+ );
2910
+ }
2911
+ function EyeOffIcon() {
2912
+ return /* @__PURE__ */ jsxRuntime.jsx(
2913
+ "svg",
2914
+ {
2915
+ "aria-hidden": "true",
2916
+ width: "16",
2917
+ height: "16",
2918
+ viewBox: "0 0 16 16",
2919
+ fill: "none",
2920
+ xmlns: "http://www.w3.org/2000/svg",
2921
+ children: /* @__PURE__ */ jsxRuntime.jsx(
2922
+ "path",
2923
+ {
2924
+ 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",
2925
+ stroke: "currentColor",
2926
+ strokeWidth: "1.5",
2927
+ strokeLinecap: "round",
2928
+ strokeLinejoin: "round"
2929
+ }
2930
+ )
2931
+ }
2932
+ );
2933
+ }
2934
+ var iconButtonBase = cn(
2935
+ "flex items-center justify-center h-7 w-7 rounded-lg shrink-0",
2936
+ "text-white/40 transition-colors hover:bg-white/10 hover:text-white/80",
2937
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/40"
2938
+ );
2939
+ function CopyField({ value, label, masked = false, className, id: externalId }) {
2940
+ const generatedId = React.useId();
2941
+ const fieldId = externalId || generatedId;
2942
+ const { copy, copied } = useClipboard();
2943
+ const [revealed, setRevealed] = React.useState(false);
2944
+ const displayValue = masked && !revealed ? "\u2022".repeat(Math.min(value.length, 24)) : value;
2945
+ const field = /* @__PURE__ */ jsxRuntime.jsxs(
2946
+ "div",
2947
+ {
2948
+ className: cn(
2949
+ "flex items-center gap-1 w-full rounded-xl px-3 py-2.5",
2950
+ "bg-white/10 ring-1 ring-white/10",
2951
+ className
2952
+ ),
2953
+ children: [
2954
+ /* @__PURE__ */ jsxRuntime.jsx(
2955
+ "span",
2956
+ {
2957
+ id: fieldId,
2958
+ className: "flex-1 min-w-0 truncate text-sm text-white select-all font-mono",
2959
+ "aria-label": label,
2960
+ children: displayValue
2961
+ }
2962
+ ),
2963
+ masked && /* @__PURE__ */ jsxRuntime.jsx(
2964
+ "button",
2965
+ {
2966
+ type: "button",
2967
+ "aria-label": revealed ? "Hide value" : "Reveal value",
2968
+ onClick: () => setRevealed((v) => !v),
2969
+ className: iconButtonBase,
2970
+ children: revealed ? /* @__PURE__ */ jsxRuntime.jsx(EyeOffIcon, {}) : /* @__PURE__ */ jsxRuntime.jsx(EyeIcon, {})
2971
+ }
2972
+ ),
2973
+ /* @__PURE__ */ jsxRuntime.jsx(
2974
+ "button",
2975
+ {
2976
+ type: "button",
2977
+ "aria-label": copied ? "Copied!" : "Copy to clipboard",
2978
+ onClick: () => copy(value),
2979
+ className: cn(iconButtonBase, copied && "text-emerald-400 hover:text-emerald-400"),
2980
+ children: copied ? /* @__PURE__ */ jsxRuntime.jsx(CheckIcon, {}) : /* @__PURE__ */ jsxRuntime.jsx(CopyIcon, {})
2981
+ }
2982
+ )
2983
+ ]
2984
+ }
2985
+ );
2986
+ if (!label) return field;
2987
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2988
+ /* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: fieldId, className: "block text-sm text-white/70 mb-1.5", children: label }),
2989
+ field
2990
+ ] });
2991
+ }
2992
+ var ProgressButton = React.forwardRef(
1629
2993
  function ProgressButton2({ isLoading, loadingText, children, disabled, className, ...props }, ref) {
1630
2994
  return /* @__PURE__ */ jsxRuntime.jsx(
1631
2995
  Button,
@@ -1664,7 +3028,7 @@ function reducer(state, action) {
1664
3028
  return state;
1665
3029
  }
1666
3030
  }
1667
- var ToastContext = react.createContext(null);
3031
+ var ToastContext = React.createContext(null);
1668
3032
  var variantBarColor = {
1669
3033
  success: "bg-emerald-500",
1670
3034
  error: "bg-rose-500",
@@ -1683,7 +3047,7 @@ var variantIconLabel = {
1683
3047
  warning: "\u26A0",
1684
3048
  info: "i"
1685
3049
  };
1686
- var variantIconColor = {
3050
+ var variantIconColor2 = {
1687
3051
  success: "text-emerald-400",
1688
3052
  error: "text-rose-400",
1689
3053
  warning: "text-amber-400",
@@ -1697,13 +3061,13 @@ var positionClass = {
1697
3061
  };
1698
3062
  function ToastCard({ toast, onDismiss }) {
1699
3063
  const duration = toast.duration ?? 5e3;
1700
- const [visible, setVisible] = react.useState(false);
1701
- const [exiting, setExiting] = react.useState(false);
1702
- const [started, setStarted] = react.useState(false);
1703
- const dismissedRef = react.useRef(false);
1704
- const timerRef = react.useRef(null);
1705
- const exitTimerRef = react.useRef(null);
1706
- react.useEffect(() => {
3064
+ const [visible, setVisible] = React.useState(false);
3065
+ const [exiting, setExiting] = React.useState(false);
3066
+ const [started, setStarted] = React.useState(false);
3067
+ const dismissedRef = React.useRef(false);
3068
+ const timerRef = React.useRef(null);
3069
+ const exitTimerRef = React.useRef(null);
3070
+ React.useEffect(() => {
1707
3071
  let innerFrame;
1708
3072
  const frame = requestAnimationFrame(() => {
1709
3073
  setVisible(true);
@@ -1714,19 +3078,19 @@ function ToastCard({ toast, onDismiss }) {
1714
3078
  cancelAnimationFrame(innerFrame);
1715
3079
  };
1716
3080
  }, []);
1717
- react.useEffect(() => {
3081
+ React.useEffect(() => {
1718
3082
  return () => {
1719
3083
  if (exitTimerRef.current !== null) clearTimeout(exitTimerRef.current);
1720
3084
  };
1721
3085
  }, []);
1722
- const triggerDismiss = react.useCallback(() => {
3086
+ const triggerDismiss = React.useCallback(() => {
1723
3087
  if (dismissedRef.current) return;
1724
3088
  dismissedRef.current = true;
1725
3089
  if (timerRef.current !== null) clearTimeout(timerRef.current);
1726
3090
  setExiting(true);
1727
3091
  exitTimerRef.current = setTimeout(() => onDismiss(toast.id), 280);
1728
3092
  }, [onDismiss, toast.id]);
1729
- react.useEffect(() => {
3093
+ React.useEffect(() => {
1730
3094
  if (duration <= 0) return;
1731
3095
  timerRef.current = setTimeout(triggerDismiss, duration);
1732
3096
  return () => {
@@ -1759,7 +3123,7 @@ function ToastCard({ toast, onDismiss }) {
1759
3123
  "aria-hidden": "true",
1760
3124
  className: cn(
1761
3125
  "mt-0.5 flex h-5 w-5 shrink-0 items-center justify-center rounded-full text-[11px] font-bold ring-1",
1762
- variantIconColor[toast.variant],
3126
+ variantIconColor2[toast.variant],
1763
3127
  "ring-current/30"
1764
3128
  ),
1765
3129
  children: variantIconLabel[toast.variant]
@@ -1805,11 +3169,11 @@ function ToastCard({ toast, onDismiss }) {
1805
3169
  );
1806
3170
  }
1807
3171
  function ToastProvider({ children, position = "top-right", maxToasts = 5 }) {
1808
- const [toasts, dispatch] = react.useReducer(reducer, []);
1809
- const counterRef = react.useRef(0);
1810
- const maxToastsRef = react.useRef(maxToasts);
3172
+ const [toasts, dispatch] = React.useReducer(reducer, []);
3173
+ const counterRef = React.useRef(0);
3174
+ const maxToastsRef = React.useRef(maxToasts);
1811
3175
  maxToastsRef.current = maxToasts;
1812
- const toast = react.useCallback(
3176
+ const toast = React.useCallback(
1813
3177
  (options) => {
1814
3178
  const id = `toast-${++counterRef.current}`;
1815
3179
  const newToast = {
@@ -1824,13 +3188,13 @@ function ToastProvider({ children, position = "top-right", maxToasts = 5 }) {
1824
3188
  },
1825
3189
  []
1826
3190
  );
1827
- const dismiss = react.useCallback((id) => {
3191
+ const dismiss = React.useCallback((id) => {
1828
3192
  dispatch({ type: "REMOVE", id });
1829
3193
  }, []);
1830
- const dismissAll = react.useCallback(() => {
3194
+ const dismissAll = React.useCallback(() => {
1831
3195
  dispatch({ type: "REMOVE_ALL" });
1832
3196
  }, []);
1833
- const value = react.useMemo(() => ({ toast, dismiss, dismissAll }), [toast, dismiss, dismissAll]);
3197
+ const value = React.useMemo(() => ({ toast, dismiss, dismissAll }), [toast, dismiss, dismissAll]);
1834
3198
  const container = typeof document !== "undefined" ? reactDom.createPortal(
1835
3199
  /* @__PURE__ */ jsxRuntime.jsx(
1836
3200
  "div",
@@ -1848,20 +3212,140 @@ function ToastProvider({ children, position = "top-right", maxToasts = 5 }) {
1848
3212
  ] });
1849
3213
  }
1850
3214
  function useToast() {
1851
- const ctx = react.useContext(ToastContext);
3215
+ const ctx = React.useContext(ToastContext);
1852
3216
  if (!ctx) {
1853
3217
  throw new Error("useToast must be used inside <ToastProvider>");
1854
3218
  }
1855
3219
  return ctx;
1856
3220
  }
3221
+ function SavingIcon() {
3222
+ return /* @__PURE__ */ jsxRuntime.jsxs(
3223
+ "svg",
3224
+ {
3225
+ className: "h-5 w-5 animate-spin text-white/70",
3226
+ viewBox: "0 0 24 24",
3227
+ fill: "none",
3228
+ "aria-hidden": "true",
3229
+ children: [
3230
+ /* @__PURE__ */ jsxRuntime.jsx(
3231
+ "circle",
3232
+ {
3233
+ className: "opacity-25",
3234
+ cx: "12",
3235
+ cy: "12",
3236
+ r: "10",
3237
+ stroke: "currentColor",
3238
+ strokeWidth: "4"
3239
+ }
3240
+ ),
3241
+ /* @__PURE__ */ jsxRuntime.jsx(
3242
+ "path",
3243
+ {
3244
+ className: "opacity-75",
3245
+ fill: "currentColor",
3246
+ d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"
3247
+ }
3248
+ )
3249
+ ]
3250
+ }
3251
+ );
3252
+ }
3253
+ function SavedIcon() {
3254
+ return /* @__PURE__ */ jsxRuntime.jsxs(
3255
+ "svg",
3256
+ {
3257
+ className: "h-5 w-5 text-green-400",
3258
+ viewBox: "0 0 24 24",
3259
+ fill: "none",
3260
+ stroke: "currentColor",
3261
+ strokeWidth: 2,
3262
+ "aria-hidden": "true",
3263
+ children: [
3264
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "10", strokeOpacity: 0.4 }),
3265
+ /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M9 12l2 2 4-4" })
3266
+ ]
3267
+ }
3268
+ );
3269
+ }
3270
+ function ErrorIcon2() {
3271
+ return /* @__PURE__ */ jsxRuntime.jsxs(
3272
+ "svg",
3273
+ {
3274
+ className: "h-5 w-5 text-red-400",
3275
+ viewBox: "0 0 24 24",
3276
+ fill: "none",
3277
+ stroke: "currentColor",
3278
+ strokeWidth: 2,
3279
+ "aria-hidden": "true",
3280
+ children: [
3281
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "10", strokeOpacity: 0.4 }),
3282
+ /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M15 9l-6 6M9 9l6 6" })
3283
+ ]
3284
+ }
3285
+ );
3286
+ }
3287
+ var statusConfig = {
3288
+ saving: {
3289
+ icon: SavingIcon,
3290
+ defaultText: "Saving...",
3291
+ textClass: "text-white/70"
3292
+ },
3293
+ saved: {
3294
+ icon: SavedIcon,
3295
+ defaultText: "Saved",
3296
+ textClass: "text-green-400"
3297
+ },
3298
+ error: {
3299
+ icon: ErrorIcon2,
3300
+ defaultText: "Error",
3301
+ textClass: "text-red-400"
3302
+ }
3303
+ };
3304
+ function MutationOverlay({
3305
+ status,
3306
+ savingText,
3307
+ savedText,
3308
+ errorText,
3309
+ className
3310
+ }) {
3311
+ if (status === "idle") return null;
3312
+ const config = statusConfig[status];
3313
+ const Icon = config.icon;
3314
+ const text = status === "saving" ? savingText ?? config.defaultText : status === "saved" ? savedText ?? config.defaultText : errorText ?? config.defaultText;
3315
+ return /* @__PURE__ */ jsxRuntime.jsx(
3316
+ "div",
3317
+ {
3318
+ className: cn(
3319
+ "absolute inset-0 z-10 flex items-center justify-center",
3320
+ "bg-surface-50/80 backdrop-blur-sm",
3321
+ "transition-opacity duration-200",
3322
+ className
3323
+ ),
3324
+ role: "status",
3325
+ "aria-live": "polite",
3326
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
3327
+ /* @__PURE__ */ jsxRuntime.jsx(Icon, {}),
3328
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("text-sm font-medium", config.textClass), children: text })
3329
+ ] })
3330
+ }
3331
+ );
3332
+ }
1857
3333
 
3334
+ exports.ActiveFilterPills = ActiveFilterPills;
3335
+ exports.Alert = Alert;
3336
+ exports.Avatar = Avatar;
1858
3337
  exports.Badge = Badge;
1859
3338
  exports.Button = Button;
1860
3339
  exports.Card = Card;
1861
3340
  exports.Checkbox = Checkbox;
1862
3341
  exports.CollapsibleSection = CollapsibleSection;
3342
+ exports.ColorInput = ColorInput;
1863
3343
  exports.ConfirmDialog = ConfirmDialog;
3344
+ exports.CooldownRing = CooldownRing;
3345
+ exports.CopyField = CopyField;
1864
3346
  exports.DashboardLayout = DashboardLayout;
3347
+ exports.Divider = Divider;
3348
+ exports.DotIndicator = DotIndicator;
1865
3349
  exports.DropZone = DropZone;
1866
3350
  exports.Dropdown = Dropdown;
1867
3351
  exports.DropdownItem = DropdownItem;
@@ -1869,24 +3353,40 @@ exports.DropdownMenu = DropdownMenu;
1869
3353
  exports.DropdownSeparator = DropdownSeparator;
1870
3354
  exports.DropdownTrigger = DropdownTrigger;
1871
3355
  exports.EmptyState = EmptyState;
3356
+ exports.FormField = FormField;
1872
3357
  exports.IconButton = IconButton;
1873
3358
  exports.Input = Input;
1874
3359
  exports.Modal = Modal;
3360
+ exports.MutationOverlay = MutationOverlay;
1875
3361
  exports.Navbar = Navbar;
1876
3362
  exports.PageShell = PageShell;
3363
+ exports.Pagination = Pagination;
1877
3364
  exports.Pill = Pill;
3365
+ exports.ProgressBar = ProgressBar;
1878
3366
  exports.ProgressButton = ProgressButton;
1879
3367
  exports.RadioGroup = RadioGroup;
1880
3368
  exports.RadioItem = RadioItem;
1881
3369
  exports.SearchInput = SearchInput;
3370
+ exports.SectionCard = SectionCard;
1882
3371
  exports.Select = Select;
1883
3372
  exports.Sidebar = Sidebar;
1884
3373
  exports.Skeleton = Skeleton;
3374
+ exports.Slider = Slider;
1885
3375
  exports.Spinner = Spinner;
3376
+ exports.StageProgress = StageProgress;
3377
+ exports.StatCard = StatCard;
3378
+ exports.Stepper = Stepper;
1886
3379
  exports.Tab = Tab;
1887
3380
  exports.TabList = TabList;
1888
3381
  exports.TabPanel = TabPanel;
3382
+ exports.Table = Table;
3383
+ exports.TableBody = TableBody;
3384
+ exports.TableCell = TableCell;
3385
+ exports.TableHead = TableHead;
3386
+ exports.TableHeader = TableHeader;
3387
+ exports.TableRow = TableRow;
1889
3388
  exports.Tabs = Tabs;
3389
+ exports.TagInput = TagInput;
1890
3390
  exports.Textarea = Textarea;
1891
3391
  exports.ToastProvider = ToastProvider;
1892
3392
  exports.Toggle = Toggle;