@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.js CHANGED
@@ -1,5 +1,5 @@
1
- import { forwardRef, useId, useRef, useEffect, createContext, useState, useCallback, useMemo, isValidElement, cloneElement, useReducer, useContext } from 'react';
2
- import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
1
+ import React, { forwardRef, useState, useId, useMemo, useRef, useEffect, createContext, useCallback, isValidElement, cloneElement, useReducer, useContext } from 'react';
2
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
3
3
  import { createPortal } from 'react-dom';
4
4
 
5
5
  // src/utils/cn.ts
@@ -144,8 +144,56 @@ var colors = {
144
144
  warning: "#f59e0b",
145
145
  danger: "#f43f5e"
146
146
  };
147
- 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";
148
147
  var sizeClass = {
148
+ sm: "w-8 h-8 text-xs",
149
+ md: "w-10 h-10 text-sm",
150
+ lg: "w-12 h-12 text-base",
151
+ xl: "w-16 h-16 text-lg"
152
+ };
153
+ function getInitials(name) {
154
+ if (!name) return "";
155
+ const parts = name.trim().split(/\s+/);
156
+ const first = parts[0]?.[0] ?? "";
157
+ const second = parts[1]?.[0] ?? "";
158
+ return (first + second).toUpperCase();
159
+ }
160
+ var Avatar = forwardRef(function Avatar2({ src, alt, name, size = "md", className }, ref) {
161
+ const [imgError, setImgError] = useState(false);
162
+ const showFallback = !src || imgError;
163
+ const initials = getInitials(name);
164
+ return /* @__PURE__ */ jsxs(
165
+ "div",
166
+ {
167
+ ref,
168
+ className: cn(
169
+ "relative inline-flex items-center justify-center shrink-0 rounded-full overflow-hidden ring-1 ring-white/10",
170
+ sizeClass[size],
171
+ className
172
+ ),
173
+ children: [
174
+ !showFallback && /* @__PURE__ */ jsx(
175
+ "img",
176
+ {
177
+ src,
178
+ alt: alt ?? name ?? "",
179
+ onError: () => setImgError(true),
180
+ className: "w-full h-full object-cover"
181
+ }
182
+ ),
183
+ showFallback && /* @__PURE__ */ jsx(
184
+ "span",
185
+ {
186
+ "aria-label": name,
187
+ 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",
188
+ children: initials
189
+ }
190
+ )
191
+ ]
192
+ }
193
+ );
194
+ });
195
+ 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";
196
+ var sizeClass2 = {
149
197
  sm: "px-3 py-2 text-sm",
150
198
  md: "px-3.5 py-2.5 text-sm",
151
199
  lg: "px-4 py-3 text-base"
@@ -167,7 +215,7 @@ var Button = forwardRef(function Button2({ variant = "secondary", size = "md", l
167
215
  ...props,
168
216
  disabled: disabled || loading,
169
217
  ...loading ? { "aria-busy": true } : {},
170
- className: cn(base, sizeClass[size], variantClass[variant], className),
218
+ className: cn(base, sizeClass2[size], variantClass[variant], className),
171
219
  children: loading ? /* @__PURE__ */ jsxs("span", { className: "flex items-center justify-center gap-2", children: [
172
220
  /* @__PURE__ */ jsx("span", { className: "w-4 h-4 border-2 border-white/30 border-t-white rounded-full animate-spin" }),
173
221
  children
@@ -180,7 +228,7 @@ var Button = forwardRef(function Button2({ variant = "secondary", size = "md", l
180
228
  );
181
229
  });
182
230
  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";
183
- var sizeClass2 = {
231
+ var sizeClass3 = {
184
232
  sm: "p-1.5 w-7 h-7",
185
233
  md: "p-2 w-9 h-9",
186
234
  lg: "p-2.5 w-11 h-11"
@@ -201,7 +249,7 @@ var IconButton = forwardRef(function IconButton2({ icon, variant = "ghost", size
201
249
  type: type === "submit" ? "submit" : type === "reset" ? "reset" : "button",
202
250
  ...props,
203
251
  disabled,
204
- className: cn(base2, sizeClass2[size], variantClass2[variant], className),
252
+ className: cn(base2, sizeClass3[size], variantClass2[variant], className),
205
253
  children: /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: icon })
206
254
  }
207
255
  );
@@ -357,8 +405,128 @@ var Textarea = forwardRef(function Textarea2({ hasError, label, error, helperTex
357
405
  helperText && !error && /* @__PURE__ */ jsx("p", { id: helperId, className: "text-white/40 text-xs mt-1", children: helperText })
358
406
  ] });
359
407
  });
408
+ function TagInput({
409
+ value,
410
+ onChange,
411
+ placeholder,
412
+ disabled = false,
413
+ label,
414
+ error,
415
+ maxTags,
416
+ className,
417
+ id: externalId
418
+ }) {
419
+ const generatedId = useId();
420
+ const inputId = externalId ?? generatedId;
421
+ const errorId = error ? `${inputId}-error` : void 0;
422
+ const inputRef = useRef(null);
423
+ const atMax = maxTags !== void 0 && value.length >= maxTags;
424
+ function addTag(raw) {
425
+ const tag = raw.trim();
426
+ if (!tag || value.includes(tag) || atMax) return;
427
+ onChange([...value, tag]);
428
+ }
429
+ function removeTag(index) {
430
+ onChange(value.filter((_, i) => i !== index));
431
+ }
432
+ function handleKeyDown(e) {
433
+ const input = inputRef.current;
434
+ if (!input) return;
435
+ if (e.key === "Enter" || e.key === "," || e.key === "Tab") {
436
+ if (input.value) {
437
+ e.preventDefault();
438
+ addTag(input.value);
439
+ input.value = "";
440
+ }
441
+ return;
442
+ }
443
+ if (e.key === "Backspace" && !input.value && value.length > 0) {
444
+ removeTag(value.length - 1);
445
+ }
446
+ }
447
+ function handlePaste(e) {
448
+ const pasted = e.clipboardData.getData("text");
449
+ if (!pasted.includes(",")) return;
450
+ e.preventDefault();
451
+ const parts = pasted.split(",");
452
+ const next = [...value];
453
+ for (const part of parts) {
454
+ const tag = part.trim();
455
+ if (tag && !next.includes(tag)) {
456
+ if (maxTags !== void 0 && next.length >= maxTags) break;
457
+ next.push(tag);
458
+ }
459
+ }
460
+ onChange(next);
461
+ if (inputRef.current) inputRef.current.value = "";
462
+ }
463
+ const wrapper = /* @__PURE__ */ jsxs(
464
+ "div",
465
+ {
466
+ className: cn(
467
+ "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",
468
+ error && "ring-2 ring-rose-500/40 focus-within:ring-rose-500/40",
469
+ disabled && "opacity-50 cursor-not-allowed",
470
+ className
471
+ ),
472
+ onClick: () => inputRef.current?.focus(),
473
+ children: [
474
+ value.map((tag, i) => /* @__PURE__ */ jsxs(
475
+ "span",
476
+ {
477
+ 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",
478
+ children: [
479
+ tag,
480
+ !disabled && /* @__PURE__ */ jsx(
481
+ "button",
482
+ {
483
+ type: "button",
484
+ "aria-label": `Remove ${tag}`,
485
+ onClick: (e) => {
486
+ e.stopPropagation();
487
+ removeTag(i);
488
+ },
489
+ className: "text-white/50 hover:text-white/90 transition-colors leading-none",
490
+ children: "\u2715"
491
+ }
492
+ )
493
+ ]
494
+ },
495
+ `${tag}-${i}`
496
+ )),
497
+ /* @__PURE__ */ jsx(
498
+ "input",
499
+ {
500
+ ref: inputRef,
501
+ id: inputId,
502
+ type: "text",
503
+ disabled: disabled || atMax,
504
+ placeholder: value.length === 0 ? placeholder : void 0,
505
+ "aria-invalid": !!error || void 0,
506
+ "aria-describedby": errorId,
507
+ onKeyDown: handleKeyDown,
508
+ onPaste: handlePaste,
509
+ onBlur: (e) => {
510
+ if (e.target.value) {
511
+ addTag(e.target.value);
512
+ e.target.value = "";
513
+ }
514
+ },
515
+ className: "flex-1 min-w-[120px] bg-transparent text-sm text-white outline-none placeholder-white/30 disabled:cursor-not-allowed"
516
+ }
517
+ )
518
+ ]
519
+ }
520
+ );
521
+ if (!label && !error) return wrapper;
522
+ return /* @__PURE__ */ jsxs("div", { children: [
523
+ label && /* @__PURE__ */ jsx("label", { htmlFor: inputId, className: "block text-sm text-white/70 mb-1.5", children: label }),
524
+ wrapper,
525
+ error && /* @__PURE__ */ jsx("p", { id: errorId, className: "text-rose-400 text-xs mt-1", children: error })
526
+ ] });
527
+ }
360
528
  var base3 = "inline-flex items-center justify-center rounded-full font-semibold ring-1 ring-white/10";
361
- var sizeClass3 = {
529
+ var sizeClass4 = {
362
530
  sm: "text-xs px-2.5 py-1",
363
531
  md: "text-sm px-3 py-1.5"
364
532
  };
@@ -373,7 +541,7 @@ var variantClass3 = {
373
541
  accent: "bg-accent/15 text-accent-light ring-accent/20"
374
542
  };
375
543
  var Badge = forwardRef(function Badge2({ children, variant = "neutral", size = "sm", className, ...props }, ref) {
376
- return /* @__PURE__ */ jsx("span", { ref, ...props, className: cn(base3, sizeClass3[size], variantClass3[variant], className), children });
544
+ return /* @__PURE__ */ jsx("span", { ref, ...props, className: cn(base3, sizeClass4[size], variantClass3[variant], className), children });
377
545
  });
378
546
  var Pill = Badge;
379
547
  var trackSize = {
@@ -384,7 +552,7 @@ var thumbSize = {
384
552
  sm: { base: "w-4 h-4", translate: "translate-x-4" },
385
553
  md: { base: "w-5 h-5", translate: "translate-x-5" }
386
554
  };
387
- var Toggle = forwardRef(function Toggle2({ checked, onChange, disabled, label, size = "md", id: externalId, "aria-label": ariaLabel }, ref) {
555
+ var Toggle = forwardRef(function Toggle2({ checked, onChange, disabled, busy, label, size = "md", id: externalId, "aria-label": ariaLabel }, ref) {
388
556
  const generatedId = useId();
389
557
  const toggleId = externalId || generatedId;
390
558
  return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
@@ -397,7 +565,8 @@ var Toggle = forwardRef(function Toggle2({ checked, onChange, disabled, label, s
397
565
  role: "switch",
398
566
  "aria-checked": checked,
399
567
  "aria-label": ariaLabel || label,
400
- disabled,
568
+ disabled: disabled || busy,
569
+ "aria-busy": busy || void 0,
401
570
  onClick: () => onChange(!checked),
402
571
  className: cn(
403
572
  "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",
@@ -409,9 +578,18 @@ var Toggle = forwardRef(function Toggle2({ checked, onChange, disabled, label, s
409
578
  "span",
410
579
  {
411
580
  className: cn(
412
- "absolute top-0.5 left-0.5 rounded-full bg-white transition-transform duration-200",
581
+ "absolute top-0.5 left-0.5 rounded-full bg-white transition-transform duration-200 flex items-center justify-center",
413
582
  thumbSize[size].base,
414
583
  checked ? thumbSize[size].translate : "translate-x-0"
584
+ ),
585
+ children: busy && /* @__PURE__ */ jsx(
586
+ "span",
587
+ {
588
+ className: cn(
589
+ "border-2 border-primary/30 border-t-primary rounded-full animate-spin",
590
+ size === "sm" ? "w-2.5 h-2.5" : "w-3 h-3"
591
+ )
592
+ }
415
593
  )
416
594
  }
417
595
  )
@@ -420,6 +598,174 @@ var Toggle = forwardRef(function Toggle2({ checked, onChange, disabled, label, s
420
598
  label && /* @__PURE__ */ jsx("label", { htmlFor: toggleId, className: "text-sm text-white/60 cursor-pointer", children: label })
421
599
  ] });
422
600
  });
601
+ var Slider = forwardRef(function Slider2({
602
+ label,
603
+ showValue = false,
604
+ formatValue,
605
+ onChange,
606
+ disabled,
607
+ min = 0,
608
+ max = 100,
609
+ step = 1,
610
+ value,
611
+ defaultValue,
612
+ className,
613
+ id: externalId,
614
+ ...props
615
+ }, ref) {
616
+ const generatedId = useId();
617
+ const sliderId = externalId || generatedId;
618
+ const numericValue = useMemo(() => {
619
+ const raw = value !== void 0 ? value : defaultValue;
620
+ return raw !== void 0 ? Number(raw) : Number(min);
621
+ }, [value, defaultValue, min]);
622
+ const percentage = useMemo(() => {
623
+ const numMin = Number(min);
624
+ const numMax = Number(max);
625
+ if (numMax === numMin) return 0;
626
+ return Math.max(0, Math.min(100, (numericValue - numMin) / (numMax - numMin) * 100));
627
+ }, [numericValue, min, max]);
628
+ const trackGradient = `linear-gradient(to right, var(--ml-primary, #8b5cf6) ${percentage}%, rgba(255,255,255,0.1) ${percentage}%)`;
629
+ const displayValue = formatValue ? formatValue(numericValue) : String(numericValue);
630
+ const handleChange = (e) => {
631
+ onChange?.(Number(e.target.value));
632
+ };
633
+ const inputEl = /* @__PURE__ */ jsx(
634
+ "input",
635
+ {
636
+ ...props,
637
+ ref,
638
+ id: sliderId,
639
+ type: "range",
640
+ min,
641
+ max,
642
+ step,
643
+ value,
644
+ defaultValue: value === void 0 ? defaultValue ?? Number(min) : void 0,
645
+ disabled,
646
+ onChange: handleChange,
647
+ style: { background: trackGradient },
648
+ className: cn(
649
+ // Layout + reset
650
+ "w-full h-2 appearance-none rounded-full outline-none cursor-pointer",
651
+ // bg is set via inline style (trackGradient); keep transparent fallback for SSR
652
+ "bg-white/10",
653
+ // Webkit thumb
654
+ "[&::-webkit-slider-thumb]:appearance-none",
655
+ "[&::-webkit-slider-thumb]:w-4",
656
+ "[&::-webkit-slider-thumb]:h-4",
657
+ "[&::-webkit-slider-thumb]:rounded-full",
658
+ "[&::-webkit-slider-thumb]:bg-white",
659
+ "[&::-webkit-slider-thumb]:border-2",
660
+ "[&::-webkit-slider-thumb]:border-[var(--ml-primary,#8b5cf6)]",
661
+ "[&::-webkit-slider-thumb]:transition-shadow",
662
+ "[&::-webkit-slider-thumb]:duration-150",
663
+ // Moz thumb
664
+ "[&::-moz-range-thumb]:w-4",
665
+ "[&::-moz-range-thumb]:h-4",
666
+ "[&::-moz-range-thumb]:rounded-full",
667
+ "[&::-moz-range-thumb]:bg-white",
668
+ "[&::-moz-range-thumb]:border-2",
669
+ "[&::-moz-range-thumb]:border-[var(--ml-primary,#8b5cf6)]",
670
+ "[&::-moz-range-thumb]:transition-shadow",
671
+ "[&::-moz-range-thumb]:duration-150",
672
+ // Moz track — transparent so the gradient on the element shows through
673
+ "[&::-moz-range-track]:bg-transparent",
674
+ "[&::-moz-range-track]:rounded-full",
675
+ // Focus ring on thumb
676
+ "focus-visible:outline-none",
677
+ "focus-visible:[&::-webkit-slider-thumb]:ring-2",
678
+ "focus-visible:[&::-webkit-slider-thumb]:ring-primary/40",
679
+ "focus-visible:[&::-webkit-slider-thumb]:ring-offset-2",
680
+ "focus-visible:[&::-webkit-slider-thumb]:ring-offset-surface",
681
+ "focus-visible:[&::-moz-range-thumb]:ring-2",
682
+ "focus-visible:[&::-moz-range-thumb]:ring-primary/40",
683
+ // Disabled
684
+ disabled && "opacity-50 cursor-not-allowed",
685
+ className
686
+ )
687
+ }
688
+ );
689
+ if (!label && !showValue) return inputEl;
690
+ return /* @__PURE__ */ jsxs("div", { className: "w-full space-y-1.5", children: [
691
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2", children: [
692
+ label && /* @__PURE__ */ jsx("label", { htmlFor: sliderId, className: "text-sm text-white/70", children: label }),
693
+ showValue && /* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-white/90 tabular-nums ml-auto", children: displayValue })
694
+ ] }),
695
+ inputEl
696
+ ] });
697
+ });
698
+ var ColorInput = forwardRef(function ColorInput2({ value, onChange, label, disabled, className, id: idProp }, ref) {
699
+ const autoId = useId();
700
+ const id = idProp ?? autoId;
701
+ const nativePickerRef = useRef(null);
702
+ function handleSwatchClick() {
703
+ if (!disabled) {
704
+ nativePickerRef.current?.click();
705
+ }
706
+ }
707
+ function handleTextChange(e) {
708
+ onChange(e.target.value);
709
+ }
710
+ function handleNativeChange(e) {
711
+ onChange(e.target.value);
712
+ }
713
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-1.5", className), children: [
714
+ label ? /* @__PURE__ */ jsx("label", { htmlFor: id, className: "block text-sm text-white/70", children: label }) : null,
715
+ /* @__PURE__ */ jsxs(
716
+ "div",
717
+ {
718
+ className: cn(
719
+ "flex items-center gap-2 bg-white/10 rounded-xl ring-1 ring-white/10 px-3 py-2 transition-shadow",
720
+ "focus-within:ring-2 focus-within:ring-primary/40",
721
+ disabled && "opacity-60 pointer-events-none"
722
+ ),
723
+ children: [
724
+ /* @__PURE__ */ jsx(
725
+ "input",
726
+ {
727
+ type: "color",
728
+ ref: nativePickerRef,
729
+ value,
730
+ onChange: handleNativeChange,
731
+ disabled,
732
+ "aria-hidden": "true",
733
+ tabIndex: -1,
734
+ className: "sr-only"
735
+ }
736
+ ),
737
+ /* @__PURE__ */ jsx(
738
+ "button",
739
+ {
740
+ type: "button",
741
+ onClick: handleSwatchClick,
742
+ disabled,
743
+ "aria-label": "Open color picker",
744
+ className: cn(
745
+ "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"
746
+ ),
747
+ style: { backgroundColor: value }
748
+ }
749
+ ),
750
+ /* @__PURE__ */ jsx(
751
+ "input",
752
+ {
753
+ ref,
754
+ id,
755
+ type: "text",
756
+ value,
757
+ onChange: handleTextChange,
758
+ disabled,
759
+ spellCheck: false,
760
+ className: "flex-1 min-w-0 bg-transparent text-sm text-white placeholder:text-white/30 outline-none font-mono",
761
+ placeholder: "#000000"
762
+ }
763
+ )
764
+ ]
765
+ }
766
+ )
767
+ ] });
768
+ });
423
769
  var Checkbox = forwardRef(function Checkbox2({ label, error, indeterminate, className, id: externalId, disabled, checked, onChange, ...props }, ref) {
424
770
  const generatedId = useId();
425
771
  const inputId = externalId || generatedId;
@@ -645,7 +991,7 @@ function RadioItem({ value, disabled: itemDisabled, children, className }) {
645
991
  }
646
992
  );
647
993
  }
648
- var sizeClass4 = {
994
+ var sizeClass5 = {
649
995
  sm: "h-3 w-3 border",
650
996
  md: "h-4 w-4 border-2",
651
997
  lg: "h-6 w-6 border-2"
@@ -654,7 +1000,7 @@ function Spinner({ className, size = "md", label }) {
654
1000
  return /* @__PURE__ */ jsx(
655
1001
  "span",
656
1002
  {
657
- className: cn("inline-block rounded-full border-white/15 border-t-primary animate-spin", sizeClass4[size], className),
1003
+ className: cn("inline-block rounded-full border-white/15 border-t-primary animate-spin", sizeClass5[size], className),
658
1004
  role: label ? "status" : void 0,
659
1005
  "aria-hidden": label ? void 0 : "true",
660
1006
  "aria-label": label || void 0
@@ -1517,95 +1863,796 @@ function DropZone({
1517
1863
  }
1518
1864
  );
1519
1865
  }
1520
- var maxWidthClass = {
1521
- sm: "max-w-2xl",
1522
- md: "max-w-4xl",
1523
- lg: "max-w-5xl",
1524
- xl: "max-w-7xl",
1525
- "2xl": "max-w-[92rem]",
1526
- full: "max-w-full"
1527
- };
1528
- function defaultBackground() {
1529
- return /* @__PURE__ */ jsxs("div", { "aria-hidden": "true", className: "pointer-events-none absolute inset-0 overflow-hidden", children: [
1530
- /* @__PURE__ */ jsx("div", { className: "absolute -top-32 -left-32 h-[600px] w-[600px] rounded-full bg-violet-600/20 blur-[140px]" }),
1531
- /* @__PURE__ */ jsx("div", { className: "absolute top-20 -right-32 h-[500px] w-[500px] rounded-full bg-purple-500/[0.12] blur-[120px]" }),
1532
- /* @__PURE__ */ 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]" })
1866
+ function FormField({ label, error, helperText, children, className, id: idProp }) {
1867
+ const autoId = useId();
1868
+ const id = idProp ?? autoId;
1869
+ const descIds = [];
1870
+ const errorId = error ? `${id}-error` : void 0;
1871
+ const helperId = helperText ? `${id}-helper` : void 0;
1872
+ if (errorId) descIds.push(errorId);
1873
+ if (helperId) descIds.push(helperId);
1874
+ const describedBy = descIds.length > 0 ? descIds.join(" ") : void 0;
1875
+ const child = cloneElement(children, {
1876
+ id,
1877
+ ...describedBy ? { "aria-describedby": describedBy } : {},
1878
+ ...error ? { "aria-invalid": true } : {}
1879
+ });
1880
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col", className), children: [
1881
+ label ? /* @__PURE__ */ jsx("label", { htmlFor: id, className: "block text-sm text-white/70 mb-1.5", children: label }) : null,
1882
+ child,
1883
+ error ? /* @__PURE__ */ jsx("p", { id: errorId, className: "text-rose-400 text-xs mt-1", role: "alert", children: error }) : null,
1884
+ helperText && !error ? /* @__PURE__ */ jsx("p", { id: helperId, className: "text-white/40 text-xs mt-1", children: helperText }) : null
1533
1885
  ] });
1534
1886
  }
1535
- function PageShell({
1536
- header,
1537
- background,
1538
- variant = "plain",
1539
- className,
1540
- mainClassName,
1541
- containerClassName,
1542
- maxWidth = "xl",
1543
- children
1544
- }) {
1545
- const showDefaultBackground = variant !== "minimal" && !background;
1546
- return /* @__PURE__ */ jsxs("div", { className: cn("relative overflow-hidden flex-1 min-h-full flex flex-col", className), children: [
1547
- background,
1548
- showDefaultBackground ? defaultBackground() : null,
1549
- header,
1550
- /* @__PURE__ */ jsx(
1551
- "main",
1887
+ function Divider({ orientation = "horizontal", label, className }) {
1888
+ if (orientation === "vertical") {
1889
+ return /* @__PURE__ */ jsx(
1890
+ "div",
1552
1891
  {
1553
- className: cn(
1554
- "relative py-8 flex-1 w-full mx-auto px-4 sm:px-6 lg:px-8",
1555
- maxWidthClass[maxWidth],
1556
- containerClassName,
1557
- mainClassName
1558
- ),
1559
- children
1892
+ role: "separator",
1893
+ "aria-orientation": "vertical",
1894
+ className: cn("border-l border-white/10 h-full mx-3 self-stretch", className)
1560
1895
  }
1561
- )
1562
- ] });
1896
+ );
1897
+ }
1898
+ if (label) {
1899
+ return /* @__PURE__ */ jsxs(
1900
+ "div",
1901
+ {
1902
+ role: "separator",
1903
+ "aria-orientation": "horizontal",
1904
+ className: cn("flex items-center gap-3 my-3 w-full", className),
1905
+ children: [
1906
+ /* @__PURE__ */ jsx("span", { className: "flex-1 border-t border-white/10" }),
1907
+ /* @__PURE__ */ jsx("span", { className: "text-xs text-white/40 leading-none select-none", children: label }),
1908
+ /* @__PURE__ */ jsx("span", { className: "flex-1 border-t border-white/10" })
1909
+ ]
1910
+ }
1911
+ );
1912
+ }
1913
+ return /* @__PURE__ */ jsx(
1914
+ "hr",
1915
+ {
1916
+ role: "separator",
1917
+ "aria-orientation": "horizontal",
1918
+ className: cn("border-t border-white/10 w-full my-3", className)
1919
+ }
1920
+ );
1563
1921
  }
1564
- function Navbar({ logo, children, className, glass = true }) {
1565
- return /* @__PURE__ */ jsx("header", { className: cn("fixed top-0 w-full z-50", glass && "glass", className), children: /* @__PURE__ */ jsxs("div", { className: "max-w-7xl mx-auto px-6 h-16 flex items-center justify-between", children: [
1566
- /* @__PURE__ */ jsx("div", { className: "flex items-center gap-3", children: logo ?? /* @__PURE__ */ jsx("div", { className: "w-9 h-9 rounded-xl animated-gradient" }) }),
1567
- children && /* @__PURE__ */ jsx("nav", { "aria-label": "Main navigation", children: /* @__PURE__ */ jsx("div", { className: "flex items-center gap-4", children }) })
1568
- ] }) });
1922
+ var Table = forwardRef(({ children, className }, ref) => /* @__PURE__ */ jsx("div", { className: "rounded-xl ring-1 ring-white/10 overflow-hidden bg-white/5", children: /* @__PURE__ */ jsx("table", { ref, className: cn("w-full text-sm text-white", className), children }) }));
1923
+ Table.displayName = "Table";
1924
+ var TableHeader = forwardRef(
1925
+ ({ children, className }, ref) => /* @__PURE__ */ jsx("thead", { ref, className: cn("bg-white/5 border-b border-white/10", className), children })
1926
+ );
1927
+ TableHeader.displayName = "TableHeader";
1928
+ var TableBody = forwardRef(
1929
+ ({ children, className }, ref) => /* @__PURE__ */ jsx("tbody", { ref, className: cn("divide-y divide-white/[0.06]", className), children })
1930
+ );
1931
+ TableBody.displayName = "TableBody";
1932
+ var TableRow = forwardRef(
1933
+ ({ children, className, hoverable }, ref) => /* @__PURE__ */ jsx(
1934
+ "tr",
1935
+ {
1936
+ ref,
1937
+ className: cn(hoverable && "hover:bg-white/[0.03] transition-colors", className),
1938
+ children
1939
+ }
1940
+ )
1941
+ );
1942
+ TableRow.displayName = "TableRow";
1943
+ var TableHead = forwardRef(
1944
+ ({ children, className }, ref) => /* @__PURE__ */ jsx(
1945
+ "th",
1946
+ {
1947
+ ref,
1948
+ className: cn(
1949
+ "px-4 py-3 text-left text-xs font-semibold text-white/50 uppercase tracking-wider",
1950
+ className
1951
+ ),
1952
+ children
1953
+ }
1954
+ )
1955
+ );
1956
+ TableHead.displayName = "TableHead";
1957
+ var alignClass = {
1958
+ left: "text-left",
1959
+ center: "text-center",
1960
+ right: "text-right"
1961
+ };
1962
+ var TableCell = forwardRef(
1963
+ ({ children, className, align = "left" }, ref) => /* @__PURE__ */ jsx("td", { ref, className: cn("px-4 py-3 text-white/80", alignClass[align], className), children })
1964
+ );
1965
+ TableCell.displayName = "TableCell";
1966
+ function TrendIndicator({ trend }) {
1967
+ if (trend.value > 0) {
1968
+ return /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1 text-xs text-emerald-400", children: [
1969
+ /* @__PURE__ */ 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__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 9V3M3 6l3-3 3 3" }) }),
1970
+ /* @__PURE__ */ jsxs("span", { children: [
1971
+ "+",
1972
+ trend.value,
1973
+ trend.label ? ` ${trend.label}` : ""
1974
+ ] })
1975
+ ] });
1976
+ }
1977
+ if (trend.value < 0) {
1978
+ return /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1 text-xs text-rose-400", children: [
1979
+ /* @__PURE__ */ 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__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 3v6M3 6l3 3 3-3" }) }),
1980
+ /* @__PURE__ */ jsxs("span", { children: [
1981
+ trend.value,
1982
+ trend.label ? ` ${trend.label}` : ""
1983
+ ] })
1984
+ ] });
1985
+ }
1986
+ return /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1 text-xs text-white/40", children: [
1987
+ /* @__PURE__ */ 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__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M2 6h8" }) }),
1988
+ /* @__PURE__ */ jsxs("span", { children: [
1989
+ trend.value,
1990
+ trend.label ? ` ${trend.label}` : ""
1991
+ ] })
1992
+ ] });
1569
1993
  }
1570
- function Sidebar({ children, collapsed = false, onToggle, className }) {
1994
+ function StatCard({ value, label, icon, trend, className }) {
1571
1995
  return /* @__PURE__ */ jsxs(
1572
- "aside",
1996
+ "div",
1573
1997
  {
1574
1998
  className: cn(
1575
- "glass h-full flex flex-col transition-[width] duration-200 overflow-hidden",
1576
- collapsed ? "w-16" : "w-64",
1999
+ "bg-white/5 ring-1 ring-white/10 rounded-xl p-4 flex items-start gap-3",
1577
2000
  className
1578
2001
  ),
1579
2002
  children: [
1580
- onToggle && /* @__PURE__ */ jsx(
1581
- "button",
1582
- {
1583
- type: "button",
1584
- onClick: onToggle,
1585
- className: "flex items-center justify-center w-full h-12 text-white/40 hover:text-white hover:bg-white/5 transition-colors",
1586
- "aria-label": collapsed ? "Expand sidebar" : "Collapse sidebar",
1587
- children: /* @__PURE__ */ jsx(
1588
- "svg",
1589
- {
1590
- className: cn("h-5 w-5 transition-transform duration-200", collapsed && "rotate-180"),
1591
- fill: "none",
1592
- viewBox: "0 0 24 24",
1593
- stroke: "currentColor",
1594
- strokeWidth: 2,
1595
- children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M11 19l-7-7 7-7m8 14l-7-7 7-7" })
1596
- }
1597
- )
1598
- }
1599
- ),
1600
- /* @__PURE__ */ jsx("nav", { className: "flex-1 overflow-y-auto py-2", children })
2003
+ icon != null && /* @__PURE__ */ jsx("div", { className: "w-10 h-10 rounded-lg bg-white/10 flex items-center justify-center text-primary shrink-0", children: icon }),
2004
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-0.5 min-w-0", children: [
2005
+ /* @__PURE__ */ jsx("span", { className: "text-2xl font-bold text-white tabular-nums leading-none", children: value }),
2006
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-white/50 truncate", children: label }),
2007
+ trend != null && /* @__PURE__ */ jsx("div", { className: "mt-1", children: /* @__PURE__ */ jsx(TrendIndicator, { trend }) })
2008
+ ] })
1601
2009
  ]
1602
2010
  }
1603
2011
  );
1604
2012
  }
1605
- var maxWidthClass2 = {
1606
- sm: "max-w-2xl",
1607
- md: "max-w-4xl",
1608
- lg: "max-w-5xl",
2013
+ function getPageRange(page, totalPages, siblingCount) {
2014
+ if (totalPages <= 1) return [1];
2015
+ const siblingStart = Math.max(2, page - siblingCount);
2016
+ const siblingEnd = Math.min(totalPages - 1, page + siblingCount);
2017
+ const showLeftEllipsis = siblingStart > 2;
2018
+ const showRightEllipsis = siblingEnd < totalPages - 1;
2019
+ const items = [1];
2020
+ if (showLeftEllipsis) {
2021
+ items.push("...");
2022
+ } else {
2023
+ for (let i = 2; i < siblingStart; i++) {
2024
+ items.push(i);
2025
+ }
2026
+ }
2027
+ for (let i = siblingStart; i <= siblingEnd; i++) {
2028
+ items.push(i);
2029
+ }
2030
+ if (showRightEllipsis) {
2031
+ items.push("...");
2032
+ } else {
2033
+ for (let i = siblingEnd + 1; i < totalPages; i++) {
2034
+ items.push(i);
2035
+ }
2036
+ }
2037
+ if (totalPages > 1) {
2038
+ items.push(totalPages);
2039
+ }
2040
+ return items;
2041
+ }
2042
+ 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";
2043
+ var pageButton = cn(buttonBase, "bg-white/5 ring-1 ring-white/10 text-white/80 hover:bg-white/10 hover:text-white");
2044
+ var activeButton = cn(buttonBase, "bg-primary text-white ring-1 ring-primary/20");
2045
+ var navButton = cn(buttonBase, "bg-white/5 ring-1 ring-white/10 text-white/80 hover:bg-white/10 hover:text-white");
2046
+ var ChevronLeft = () => /* @__PURE__ */ jsx(
2047
+ "svg",
2048
+ {
2049
+ xmlns: "http://www.w3.org/2000/svg",
2050
+ width: "16",
2051
+ height: "16",
2052
+ viewBox: "0 0 24 24",
2053
+ fill: "none",
2054
+ stroke: "currentColor",
2055
+ strokeWidth: "2",
2056
+ strokeLinecap: "round",
2057
+ strokeLinejoin: "round",
2058
+ "aria-hidden": "true",
2059
+ children: /* @__PURE__ */ jsx("polyline", { points: "15 18 9 12 15 6" })
2060
+ }
2061
+ );
2062
+ var ChevronRight = () => /* @__PURE__ */ jsx(
2063
+ "svg",
2064
+ {
2065
+ xmlns: "http://www.w3.org/2000/svg",
2066
+ width: "16",
2067
+ height: "16",
2068
+ viewBox: "0 0 24 24",
2069
+ fill: "none",
2070
+ stroke: "currentColor",
2071
+ strokeWidth: "2",
2072
+ strokeLinecap: "round",
2073
+ strokeLinejoin: "round",
2074
+ "aria-hidden": "true",
2075
+ children: /* @__PURE__ */ jsx("polyline", { points: "9 18 15 12 9 6" })
2076
+ }
2077
+ );
2078
+ function Pagination({
2079
+ page,
2080
+ totalPages,
2081
+ onPageChange,
2082
+ siblingCount = 1,
2083
+ className
2084
+ }) {
2085
+ if (totalPages <= 1) return null;
2086
+ const items = getPageRange(page, totalPages, siblingCount);
2087
+ const isPrevDisabled = page <= 1;
2088
+ const isNextDisabled = page >= totalPages;
2089
+ return /* @__PURE__ */ jsxs(
2090
+ "nav",
2091
+ {
2092
+ role: "navigation",
2093
+ "aria-label": "Pagination",
2094
+ className: cn("flex items-center gap-1", className),
2095
+ children: [
2096
+ /* @__PURE__ */ jsx(
2097
+ "button",
2098
+ {
2099
+ type: "button",
2100
+ onClick: () => onPageChange(page - 1),
2101
+ disabled: isPrevDisabled,
2102
+ "aria-label": "Previous page",
2103
+ className: cn(navButton, isPrevDisabled && "opacity-40 cursor-not-allowed pointer-events-none"),
2104
+ children: /* @__PURE__ */ jsx(ChevronLeft, {})
2105
+ }
2106
+ ),
2107
+ items.map(
2108
+ (item, index) => item === "..." ? /* @__PURE__ */ jsx(
2109
+ "span",
2110
+ {
2111
+ className: "inline-flex items-center justify-center px-3 py-2 text-sm text-white/40 select-none",
2112
+ "aria-hidden": "true",
2113
+ children: "\u2026"
2114
+ },
2115
+ `ellipsis-${index}`
2116
+ ) : /* @__PURE__ */ jsx(
2117
+ "button",
2118
+ {
2119
+ type: "button",
2120
+ onClick: () => onPageChange(item),
2121
+ "aria-label": `Page ${item}`,
2122
+ "aria-current": item === page ? "page" : void 0,
2123
+ className: item === page ? activeButton : pageButton,
2124
+ children: item
2125
+ },
2126
+ item
2127
+ )
2128
+ ),
2129
+ /* @__PURE__ */ jsx(
2130
+ "button",
2131
+ {
2132
+ type: "button",
2133
+ onClick: () => onPageChange(page + 1),
2134
+ disabled: isNextDisabled,
2135
+ "aria-label": "Next page",
2136
+ className: cn(navButton, isNextDisabled && "opacity-40 cursor-not-allowed pointer-events-none"),
2137
+ children: /* @__PURE__ */ jsx(ChevronRight, {})
2138
+ }
2139
+ )
2140
+ ]
2141
+ }
2142
+ );
2143
+ }
2144
+ function Stepper({ steps, activeStep, className }) {
2145
+ return /* @__PURE__ */ jsx("div", { className: cn("flex items-start w-full", className), children: steps.map((step, index) => {
2146
+ const isCompleted = index < activeStep;
2147
+ const isActive = index === activeStep;
2148
+ return /* @__PURE__ */ jsxs(React.Fragment, { children: [
2149
+ /* @__PURE__ */ jsxs(
2150
+ "div",
2151
+ {
2152
+ className: "flex flex-col items-center",
2153
+ "aria-current": isActive ? "step" : void 0,
2154
+ children: [
2155
+ /* @__PURE__ */ jsx(
2156
+ "div",
2157
+ {
2158
+ className: cn(
2159
+ "w-8 h-8 rounded-full flex items-center justify-center text-sm font-semibold",
2160
+ isCompleted && "bg-emerald-600 text-white",
2161
+ isActive && "bg-primary text-white ring-2 ring-primary/40",
2162
+ !isCompleted && !isActive && "bg-white/10 text-white/40"
2163
+ ),
2164
+ children: isCompleted ? /* @__PURE__ */ jsx(
2165
+ "svg",
2166
+ {
2167
+ xmlns: "http://www.w3.org/2000/svg",
2168
+ viewBox: "0 0 20 20",
2169
+ fill: "currentColor",
2170
+ className: "w-4 h-4",
2171
+ "aria-hidden": "true",
2172
+ children: /* @__PURE__ */ jsx(
2173
+ "path",
2174
+ {
2175
+ fillRule: "evenodd",
2176
+ 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",
2177
+ clipRule: "evenodd"
2178
+ }
2179
+ )
2180
+ }
2181
+ ) : /* @__PURE__ */ jsx("span", { children: index + 1 })
2182
+ }
2183
+ ),
2184
+ /* @__PURE__ */ jsx(
2185
+ "span",
2186
+ {
2187
+ className: cn(
2188
+ "text-xs mt-2 text-center max-w-[6rem]",
2189
+ isActive ? "text-white/80" : "text-white/50"
2190
+ ),
2191
+ children: step.label
2192
+ }
2193
+ ),
2194
+ step.description && /* @__PURE__ */ jsx("span", { className: "text-xs mt-0.5 text-center text-white/30 max-w-[6rem]", children: step.description })
2195
+ ]
2196
+ }
2197
+ ),
2198
+ index < steps.length - 1 && /* @__PURE__ */ jsx(
2199
+ "div",
2200
+ {
2201
+ className: cn(
2202
+ "h-0.5 flex-1 mx-2 mt-4 self-start",
2203
+ isCompleted ? "bg-emerald-600" : "bg-white/10"
2204
+ ),
2205
+ "aria-hidden": "true"
2206
+ }
2207
+ )
2208
+ ] }, index);
2209
+ }) });
2210
+ }
2211
+ var sizeClasses = {
2212
+ sm: "h-1",
2213
+ md: "h-2",
2214
+ lg: "h-3"
2215
+ };
2216
+ var variantClasses = {
2217
+ primary: "bg-primary",
2218
+ success: "bg-emerald-500",
2219
+ warning: "bg-amber-500",
2220
+ danger: "bg-rose-500"
2221
+ };
2222
+ function ProgressBar({
2223
+ value,
2224
+ max = 100,
2225
+ variant = "primary",
2226
+ label,
2227
+ showValue = false,
2228
+ size = "md",
2229
+ className
2230
+ }) {
2231
+ const percentage = Math.min(100, Math.max(0, value / max * 100));
2232
+ return /* @__PURE__ */ jsxs("div", { className: cn("w-full", className), children: [
2233
+ (label || showValue) && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-1", children: [
2234
+ label && /* @__PURE__ */ jsx("span", { className: "text-xs text-white/60", children: label }),
2235
+ showValue && /* @__PURE__ */ jsxs("span", { className: "text-xs text-white/60 ml-auto", children: [
2236
+ Math.round(percentage),
2237
+ "%"
2238
+ ] })
2239
+ ] }),
2240
+ /* @__PURE__ */ jsx(
2241
+ "div",
2242
+ {
2243
+ className: cn("w-full rounded-full bg-white/10", sizeClasses[size]),
2244
+ role: "progressbar",
2245
+ "aria-valuenow": value,
2246
+ "aria-valuemin": 0,
2247
+ "aria-valuemax": max,
2248
+ "aria-label": label,
2249
+ children: /* @__PURE__ */ jsx(
2250
+ "div",
2251
+ {
2252
+ className: cn(
2253
+ "rounded-full transition-[width] duration-300 ease-out",
2254
+ sizeClasses[size],
2255
+ variantClasses[variant]
2256
+ ),
2257
+ style: { width: `${percentage}%` }
2258
+ }
2259
+ )
2260
+ }
2261
+ )
2262
+ ] });
2263
+ }
2264
+ var sizeMap = {
2265
+ sm: "w-8 h-8 text-xs",
2266
+ md: "w-12 h-12 text-sm",
2267
+ lg: "w-16 h-16 text-base"
2268
+ };
2269
+ var strokeWidthMap = {
2270
+ sm: 3,
2271
+ md: 3.5,
2272
+ lg: 4
2273
+ };
2274
+ var RADIUS = 15.9155;
2275
+ var CIRCUMFERENCE = 2 * Math.PI * RADIUS;
2276
+ function CooldownRing({
2277
+ duration,
2278
+ remaining,
2279
+ size = "md",
2280
+ className
2281
+ }) {
2282
+ const fraction = duration > 0 ? Math.max(0, Math.min(1, remaining / duration)) : 0;
2283
+ const offset = CIRCUMFERENCE * (1 - fraction);
2284
+ const color = fraction > 0.5 ? "text-primary" : fraction > 0.25 ? "text-amber-500" : "text-rose-500";
2285
+ const pulse = remaining <= 10 && remaining > 0;
2286
+ const strokeWidth = strokeWidthMap[size];
2287
+ return /* @__PURE__ */ jsxs("div", { className: cn("relative inline-flex items-center justify-center", sizeMap[size], className), children: [
2288
+ /* @__PURE__ */ jsxs(
2289
+ "svg",
2290
+ {
2291
+ viewBox: "0 0 36 36",
2292
+ className: cn("w-full h-full -rotate-90", color, pulse && "animate-pulse"),
2293
+ "aria-label": `Cooldown: ${remaining} seconds remaining`,
2294
+ role: "img",
2295
+ children: [
2296
+ /* @__PURE__ */ jsx(
2297
+ "circle",
2298
+ {
2299
+ cx: "18",
2300
+ cy: "18",
2301
+ r: RADIUS,
2302
+ fill: "none",
2303
+ stroke: "currentColor",
2304
+ strokeWidth,
2305
+ className: "text-white/10"
2306
+ }
2307
+ ),
2308
+ /* @__PURE__ */ jsx(
2309
+ "circle",
2310
+ {
2311
+ cx: "18",
2312
+ cy: "18",
2313
+ r: RADIUS,
2314
+ fill: "none",
2315
+ stroke: "currentColor",
2316
+ strokeWidth,
2317
+ strokeDasharray: `${CIRCUMFERENCE} ${CIRCUMFERENCE}`,
2318
+ strokeDashoffset: offset,
2319
+ strokeLinecap: "round",
2320
+ style: { transition: "stroke-dashoffset 0.6s ease" }
2321
+ }
2322
+ )
2323
+ ]
2324
+ }
2325
+ ),
2326
+ /* @__PURE__ */ jsx(
2327
+ "span",
2328
+ {
2329
+ className: "absolute font-semibold tabular-nums text-white select-none",
2330
+ style: { lineHeight: 1 },
2331
+ children: Math.max(0, Math.ceil(remaining))
2332
+ }
2333
+ )
2334
+ ] });
2335
+ }
2336
+ function StageProgress({ stages, activeStage, className }) {
2337
+ const clampedActive = Math.max(0, Math.min(activeStage, stages.length - 1));
2338
+ const fillPercent = stages.length <= 1 ? 100 : clampedActive / (stages.length - 1) * 100;
2339
+ const isComplete = clampedActive >= stages.length - 1;
2340
+ const isAnimating = !isComplete;
2341
+ return /* @__PURE__ */ jsxs("div", { className: cn("w-full", className), children: [
2342
+ /* @__PURE__ */ jsx("div", { className: "flex justify-between", children: stages.map((stage, index) => {
2343
+ const isCompleted = index < clampedActive;
2344
+ const isActive = index === clampedActive;
2345
+ return /* @__PURE__ */ jsxs(
2346
+ "div",
2347
+ {
2348
+ className: cn(
2349
+ "flex items-center gap-1.5 text-xs font-medium transition-colors duration-300",
2350
+ isCompleted && "text-emerald-400",
2351
+ isActive && "text-white",
2352
+ !isCompleted && !isActive && "text-white/40"
2353
+ ),
2354
+ children: [
2355
+ isCompleted ? (
2356
+ // Completed: emerald check circle
2357
+ /* @__PURE__ */ jsx("span", { className: "flex h-3.5 w-3.5 items-center justify-center rounded-full bg-emerald-400/20", children: /* @__PURE__ */ jsx(
2358
+ "svg",
2359
+ {
2360
+ className: "h-2.5 w-2.5 text-emerald-400",
2361
+ viewBox: "0 0 10 10",
2362
+ fill: "none",
2363
+ xmlns: "http://www.w3.org/2000/svg",
2364
+ "aria-hidden": "true",
2365
+ children: /* @__PURE__ */ jsx(
2366
+ "path",
2367
+ {
2368
+ d: "M2 5.5L4 7.5L8 3",
2369
+ stroke: "currentColor",
2370
+ strokeWidth: "1.5",
2371
+ strokeLinecap: "round",
2372
+ strokeLinejoin: "round"
2373
+ }
2374
+ )
2375
+ }
2376
+ ) })
2377
+ ) : isActive ? (
2378
+ // Active: primary dot with ring
2379
+ /* @__PURE__ */ 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__ */ jsx("span", { className: "h-1.5 w-1.5 rounded-full bg-[var(--ml-primary)]" }) })
2380
+ ) : (
2381
+ // Upcoming: hollow dim dot
2382
+ /* @__PURE__ */ jsx("span", { className: "h-3.5 w-3.5 rounded-full border border-white/20 bg-transparent" })
2383
+ ),
2384
+ stage
2385
+ ]
2386
+ },
2387
+ stage
2388
+ );
2389
+ }) }),
2390
+ /* @__PURE__ */ jsx(
2391
+ "div",
2392
+ {
2393
+ className: "relative mt-3 h-1.5 w-full overflow-hidden rounded-full bg-white/10",
2394
+ role: "progressbar",
2395
+ "aria-valuenow": clampedActive,
2396
+ "aria-valuemin": 0,
2397
+ "aria-valuemax": stages.length - 1,
2398
+ "aria-label": `Stage ${clampedActive + 1} of ${stages.length}: ${stages[clampedActive]}`,
2399
+ children: /* @__PURE__ */ jsx(
2400
+ "div",
2401
+ {
2402
+ className: "h-full rounded-full bg-gradient-to-r from-[var(--ml-accent)] to-[var(--ml-primary)] transition-[width] duration-500 ease-in-out",
2403
+ style: { width: `${fillPercent}%` },
2404
+ children: isAnimating && /* @__PURE__ */ jsx(
2405
+ "span",
2406
+ {
2407
+ 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",
2408
+ "aria-hidden": "true"
2409
+ }
2410
+ )
2411
+ }
2412
+ )
2413
+ }
2414
+ )
2415
+ ] });
2416
+ }
2417
+ function getUrgencyClasses(remaining, max) {
2418
+ const ratio = max > 0 ? remaining / max : 0;
2419
+ if (ratio > 0.5) {
2420
+ return {
2421
+ filled: "bg-emerald-400",
2422
+ empty: "bg-emerald-400/30",
2423
+ label: "text-emerald-400"
2424
+ };
2425
+ }
2426
+ if (ratio > 0.25) {
2427
+ return {
2428
+ filled: "bg-amber-400",
2429
+ empty: "bg-amber-400/30",
2430
+ label: "text-amber-400"
2431
+ };
2432
+ }
2433
+ return {
2434
+ filled: "bg-rose-400",
2435
+ empty: "bg-rose-400/30",
2436
+ label: "text-rose-400"
2437
+ };
2438
+ }
2439
+ function DotIndicator({
2440
+ remaining,
2441
+ max,
2442
+ showLabel = false,
2443
+ labelFormat,
2444
+ className
2445
+ }) {
2446
+ const clampedRemaining = Math.max(0, Math.min(remaining, max));
2447
+ const used = max - clampedRemaining;
2448
+ const urgency = getUrgencyClasses(clampedRemaining, max);
2449
+ const defaultLabel = `${clampedRemaining}/${max}`;
2450
+ const label = labelFormat ? labelFormat(clampedRemaining, max) : defaultLabel;
2451
+ return /* @__PURE__ */ jsxs("div", { className: cn("inline-flex items-center gap-2", className), children: [
2452
+ /* @__PURE__ */ jsx(
2453
+ "div",
2454
+ {
2455
+ className: "flex items-center gap-1",
2456
+ role: "meter",
2457
+ "aria-valuenow": clampedRemaining,
2458
+ "aria-valuemin": 0,
2459
+ "aria-valuemax": max,
2460
+ "aria-label": label,
2461
+ children: Array.from({ length: max }, (_, index) => {
2462
+ const isFilled = index < used;
2463
+ return /* @__PURE__ */ jsx(
2464
+ "span",
2465
+ {
2466
+ className: cn(
2467
+ "h-2 w-2 rounded-full transition-colors duration-300",
2468
+ isFilled ? urgency.filled : urgency.empty
2469
+ ),
2470
+ "aria-hidden": "true"
2471
+ },
2472
+ index
2473
+ );
2474
+ })
2475
+ }
2476
+ ),
2477
+ showLabel && /* @__PURE__ */ jsx("span", { className: cn("text-xs font-medium tabular-nums", urgency.label), children: label })
2478
+ ] });
2479
+ }
2480
+ function ActiveFilterPills({
2481
+ filters,
2482
+ onRemove,
2483
+ onClearAll,
2484
+ clearAllLabel = "Clear all",
2485
+ className
2486
+ }) {
2487
+ if (filters.length === 0) return null;
2488
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-wrap items-center gap-1.5", className), children: [
2489
+ filters.map((filter) => /* @__PURE__ */ jsxs(
2490
+ "span",
2491
+ {
2492
+ 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",
2493
+ children: [
2494
+ filter.label,
2495
+ /* @__PURE__ */ jsx(
2496
+ "button",
2497
+ {
2498
+ type: "button",
2499
+ onClick: () => onRemove(filter.key),
2500
+ className: "ml-0.5 text-white/50 transition-colors duration-150 hover:text-white focus:outline-none focus-visible:text-white",
2501
+ "aria-label": `Remove filter: ${filter.label}`,
2502
+ children: /* @__PURE__ */ jsx(
2503
+ "svg",
2504
+ {
2505
+ className: "h-3 w-3",
2506
+ viewBox: "0 0 12 12",
2507
+ fill: "none",
2508
+ xmlns: "http://www.w3.org/2000/svg",
2509
+ "aria-hidden": "true",
2510
+ children: /* @__PURE__ */ jsx(
2511
+ "path",
2512
+ {
2513
+ d: "M9 3L3 9M3 3L9 9",
2514
+ stroke: "currentColor",
2515
+ strokeWidth: "1.5",
2516
+ strokeLinecap: "round"
2517
+ }
2518
+ )
2519
+ }
2520
+ )
2521
+ }
2522
+ )
2523
+ ]
2524
+ },
2525
+ filter.key
2526
+ )),
2527
+ filters.length > 1 && onClearAll && /* @__PURE__ */ jsx(
2528
+ "button",
2529
+ {
2530
+ type: "button",
2531
+ onClick: onClearAll,
2532
+ 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",
2533
+ children: clearAllLabel
2534
+ }
2535
+ )
2536
+ ] });
2537
+ }
2538
+ function SectionCard({
2539
+ title,
2540
+ description,
2541
+ right,
2542
+ overlay,
2543
+ children,
2544
+ className
2545
+ }) {
2546
+ return /* @__PURE__ */ jsxs(
2547
+ "div",
2548
+ {
2549
+ className: cn(
2550
+ "relative bg-white/5 ring-1 ring-white/10 rounded-xl overflow-hidden",
2551
+ className
2552
+ ),
2553
+ children: [
2554
+ /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-3 px-5 py-4 border-b border-white/[0.06]", children: [
2555
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
2556
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-semibold text-white", children: title }),
2557
+ description && /* @__PURE__ */ jsx("p", { className: "text-xs text-white/40 mt-0.5", children: description })
2558
+ ] }),
2559
+ right && /* @__PURE__ */ jsx("div", { className: "shrink-0", children: right })
2560
+ ] }),
2561
+ /* @__PURE__ */ jsx("div", { className: "px-5 py-4", children }),
2562
+ overlay
2563
+ ]
2564
+ }
2565
+ );
2566
+ }
2567
+ var maxWidthClass = {
2568
+ sm: "max-w-2xl",
2569
+ md: "max-w-4xl",
2570
+ lg: "max-w-5xl",
2571
+ xl: "max-w-7xl",
2572
+ "2xl": "max-w-[92rem]",
2573
+ full: "max-w-full"
2574
+ };
2575
+ function defaultBackground() {
2576
+ return /* @__PURE__ */ jsxs("div", { "aria-hidden": "true", className: "pointer-events-none absolute inset-0 overflow-hidden", children: [
2577
+ /* @__PURE__ */ jsx("div", { className: "absolute -top-32 -left-32 h-[600px] w-[600px] rounded-full bg-violet-600/20 blur-[140px]" }),
2578
+ /* @__PURE__ */ jsx("div", { className: "absolute top-20 -right-32 h-[500px] w-[500px] rounded-full bg-purple-500/[0.12] blur-[120px]" }),
2579
+ /* @__PURE__ */ 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]" })
2580
+ ] });
2581
+ }
2582
+ function PageShell({
2583
+ header,
2584
+ background,
2585
+ variant = "plain",
2586
+ className,
2587
+ mainClassName,
2588
+ containerClassName,
2589
+ maxWidth = "xl",
2590
+ children
2591
+ }) {
2592
+ const showDefaultBackground = variant !== "minimal" && !background;
2593
+ return /* @__PURE__ */ jsxs("div", { className: cn("relative overflow-hidden flex-1 min-h-full flex flex-col", className), children: [
2594
+ background,
2595
+ showDefaultBackground ? defaultBackground() : null,
2596
+ header,
2597
+ /* @__PURE__ */ jsx(
2598
+ "main",
2599
+ {
2600
+ className: cn(
2601
+ "relative py-8 flex-1 w-full mx-auto px-4 sm:px-6 lg:px-8",
2602
+ maxWidthClass[maxWidth],
2603
+ containerClassName,
2604
+ mainClassName
2605
+ ),
2606
+ children
2607
+ }
2608
+ )
2609
+ ] });
2610
+ }
2611
+ function Navbar({ logo, children, className, glass = true }) {
2612
+ return /* @__PURE__ */ jsx("header", { className: cn("fixed top-0 w-full z-50", glass && "glass", className), children: /* @__PURE__ */ jsxs("div", { className: "max-w-7xl mx-auto px-6 h-16 flex items-center justify-between", children: [
2613
+ /* @__PURE__ */ jsx("div", { className: "flex items-center gap-3", children: logo ?? /* @__PURE__ */ jsx("div", { className: "w-9 h-9 rounded-xl animated-gradient" }) }),
2614
+ children && /* @__PURE__ */ jsx("nav", { "aria-label": "Main navigation", children: /* @__PURE__ */ jsx("div", { className: "flex items-center gap-4", children }) })
2615
+ ] }) });
2616
+ }
2617
+ function Sidebar({ children, collapsed = false, onToggle, className }) {
2618
+ return /* @__PURE__ */ jsxs(
2619
+ "aside",
2620
+ {
2621
+ className: cn(
2622
+ "glass h-full flex flex-col transition-[width] duration-200 overflow-hidden",
2623
+ collapsed ? "w-16" : "w-64",
2624
+ className
2625
+ ),
2626
+ children: [
2627
+ onToggle && /* @__PURE__ */ jsx(
2628
+ "button",
2629
+ {
2630
+ type: "button",
2631
+ onClick: onToggle,
2632
+ className: "flex items-center justify-center w-full h-12 text-white/40 hover:text-white hover:bg-white/5 transition-colors",
2633
+ "aria-label": collapsed ? "Expand sidebar" : "Collapse sidebar",
2634
+ children: /* @__PURE__ */ jsx(
2635
+ "svg",
2636
+ {
2637
+ className: cn("h-5 w-5 transition-transform duration-200", collapsed && "rotate-180"),
2638
+ fill: "none",
2639
+ viewBox: "0 0 24 24",
2640
+ stroke: "currentColor",
2641
+ strokeWidth: 2,
2642
+ children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M11 19l-7-7 7-7m8 14l-7-7 7-7" })
2643
+ }
2644
+ )
2645
+ }
2646
+ ),
2647
+ /* @__PURE__ */ jsx("nav", { className: "flex-1 overflow-y-auto py-2", children })
2648
+ ]
2649
+ }
2650
+ );
2651
+ }
2652
+ var maxWidthClass2 = {
2653
+ sm: "max-w-2xl",
2654
+ md: "max-w-4xl",
2655
+ lg: "max-w-5xl",
1609
2656
  xl: "max-w-7xl",
1610
2657
  "2xl": "max-w-[92rem]",
1611
2658
  full: "max-w-full"
@@ -1623,6 +2670,319 @@ function DashboardLayout({ children, navbar, sidebar, className, mainClassName,
1623
2670
  ] })
1624
2671
  ] });
1625
2672
  }
2673
+ var variantBorderColor = {
2674
+ info: "border-blue-500",
2675
+ success: "border-emerald-500",
2676
+ warning: "border-amber-500",
2677
+ error: "border-rose-500"
2678
+ };
2679
+ var variantIconColor = {
2680
+ info: "text-blue-400",
2681
+ success: "text-emerald-400",
2682
+ warning: "text-amber-400",
2683
+ error: "text-rose-400"
2684
+ };
2685
+ function InfoIcon() {
2686
+ return /* @__PURE__ */ jsxs(
2687
+ "svg",
2688
+ {
2689
+ "aria-hidden": "true",
2690
+ width: "18",
2691
+ height: "18",
2692
+ viewBox: "0 0 18 18",
2693
+ fill: "none",
2694
+ xmlns: "http://www.w3.org/2000/svg",
2695
+ children: [
2696
+ /* @__PURE__ */ jsx("circle", { cx: "9", cy: "9", r: "7.5", stroke: "currentColor", strokeWidth: "1.5" }),
2697
+ /* @__PURE__ */ jsx("path", { d: "M9 8v5", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round" }),
2698
+ /* @__PURE__ */ jsx("circle", { cx: "9", cy: "5.5", r: "0.875", fill: "currentColor" })
2699
+ ]
2700
+ }
2701
+ );
2702
+ }
2703
+ function SuccessIcon() {
2704
+ return /* @__PURE__ */ jsxs(
2705
+ "svg",
2706
+ {
2707
+ "aria-hidden": "true",
2708
+ width: "18",
2709
+ height: "18",
2710
+ viewBox: "0 0 18 18",
2711
+ fill: "none",
2712
+ xmlns: "http://www.w3.org/2000/svg",
2713
+ children: [
2714
+ /* @__PURE__ */ jsx("circle", { cx: "9", cy: "9", r: "7.5", stroke: "currentColor", strokeWidth: "1.5" }),
2715
+ /* @__PURE__ */ jsx(
2716
+ "path",
2717
+ {
2718
+ d: "M5.5 9.5l2.5 2.5 4.5-5",
2719
+ stroke: "currentColor",
2720
+ strokeWidth: "1.75",
2721
+ strokeLinecap: "round",
2722
+ strokeLinejoin: "round"
2723
+ }
2724
+ )
2725
+ ]
2726
+ }
2727
+ );
2728
+ }
2729
+ function WarningIcon() {
2730
+ return /* @__PURE__ */ jsxs(
2731
+ "svg",
2732
+ {
2733
+ "aria-hidden": "true",
2734
+ width: "18",
2735
+ height: "18",
2736
+ viewBox: "0 0 18 18",
2737
+ fill: "none",
2738
+ xmlns: "http://www.w3.org/2000/svg",
2739
+ children: [
2740
+ /* @__PURE__ */ jsx(
2741
+ "path",
2742
+ {
2743
+ 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",
2744
+ stroke: "currentColor",
2745
+ strokeWidth: "1.5",
2746
+ strokeLinejoin: "round"
2747
+ }
2748
+ ),
2749
+ /* @__PURE__ */ jsx("path", { d: "M9 7v4", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round" }),
2750
+ /* @__PURE__ */ jsx("circle", { cx: "9", cy: "12.5", r: "0.875", fill: "currentColor" })
2751
+ ]
2752
+ }
2753
+ );
2754
+ }
2755
+ function ErrorIcon() {
2756
+ return /* @__PURE__ */ jsxs(
2757
+ "svg",
2758
+ {
2759
+ "aria-hidden": "true",
2760
+ width: "18",
2761
+ height: "18",
2762
+ viewBox: "0 0 18 18",
2763
+ fill: "none",
2764
+ xmlns: "http://www.w3.org/2000/svg",
2765
+ children: [
2766
+ /* @__PURE__ */ jsx("circle", { cx: "9", cy: "9", r: "7.5", stroke: "currentColor", strokeWidth: "1.5" }),
2767
+ /* @__PURE__ */ jsx(
2768
+ "path",
2769
+ {
2770
+ d: "M6.5 6.5l5 5M11.5 6.5l-5 5",
2771
+ stroke: "currentColor",
2772
+ strokeWidth: "1.75",
2773
+ strokeLinecap: "round"
2774
+ }
2775
+ )
2776
+ ]
2777
+ }
2778
+ );
2779
+ }
2780
+ var variantIcon = {
2781
+ info: InfoIcon,
2782
+ success: SuccessIcon,
2783
+ warning: WarningIcon,
2784
+ error: ErrorIcon
2785
+ };
2786
+ function Alert({ variant = "info", title, children, onDismiss, className }) {
2787
+ const Icon = variantIcon[variant];
2788
+ return /* @__PURE__ */ jsxs(
2789
+ "div",
2790
+ {
2791
+ role: "alert",
2792
+ className: cn(
2793
+ "flex items-start gap-3 rounded-xl bg-white/5 ring-1 ring-white/10",
2794
+ "border-l-4 pl-4 pr-3 py-3",
2795
+ variantBorderColor[variant],
2796
+ className
2797
+ ),
2798
+ children: [
2799
+ /* @__PURE__ */ jsx("span", { className: cn("mt-0.5 shrink-0", variantIconColor[variant]), children: /* @__PURE__ */ jsx(Icon, {}) }),
2800
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
2801
+ title && /* @__PURE__ */ jsx("p", { className: "text-sm font-semibold text-white leading-snug mb-0.5", children: title }),
2802
+ /* @__PURE__ */ jsx("div", { className: "text-sm text-white/70 leading-relaxed", children })
2803
+ ] }),
2804
+ onDismiss && /* @__PURE__ */ jsx(
2805
+ "button",
2806
+ {
2807
+ type: "button",
2808
+ "aria-label": "Dismiss",
2809
+ onClick: onDismiss,
2810
+ className: cn(
2811
+ "shrink-0 flex items-center justify-center h-6 w-6 rounded-lg mt-0.5",
2812
+ "text-white/40 transition-colors hover:bg-white/10 hover:text-white/80",
2813
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/40"
2814
+ ),
2815
+ children: /* @__PURE__ */ jsx(
2816
+ "svg",
2817
+ {
2818
+ "aria-hidden": "true",
2819
+ width: "10",
2820
+ height: "10",
2821
+ viewBox: "0 0 10 10",
2822
+ fill: "none",
2823
+ children: /* @__PURE__ */ jsx("path", { d: "M1 1l8 8M9 1L1 9", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" })
2824
+ }
2825
+ )
2826
+ }
2827
+ )
2828
+ ]
2829
+ }
2830
+ );
2831
+ }
2832
+ function CopyIcon() {
2833
+ return /* @__PURE__ */ jsxs(
2834
+ "svg",
2835
+ {
2836
+ "aria-hidden": "true",
2837
+ width: "16",
2838
+ height: "16",
2839
+ viewBox: "0 0 16 16",
2840
+ fill: "none",
2841
+ xmlns: "http://www.w3.org/2000/svg",
2842
+ children: [
2843
+ /* @__PURE__ */ jsx("rect", { x: "5", y: "5", width: "9", height: "9", rx: "1.5", stroke: "currentColor", strokeWidth: "1.5" }),
2844
+ /* @__PURE__ */ jsx(
2845
+ "path",
2846
+ {
2847
+ 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",
2848
+ stroke: "currentColor",
2849
+ strokeWidth: "1.5",
2850
+ strokeLinecap: "round"
2851
+ }
2852
+ )
2853
+ ]
2854
+ }
2855
+ );
2856
+ }
2857
+ function CheckIcon() {
2858
+ return /* @__PURE__ */ jsx(
2859
+ "svg",
2860
+ {
2861
+ "aria-hidden": "true",
2862
+ width: "16",
2863
+ height: "16",
2864
+ viewBox: "0 0 16 16",
2865
+ fill: "none",
2866
+ xmlns: "http://www.w3.org/2000/svg",
2867
+ children: /* @__PURE__ */ jsx(
2868
+ "path",
2869
+ {
2870
+ d: "M3 8.5l3.5 3.5 6.5-7",
2871
+ stroke: "currentColor",
2872
+ strokeWidth: "1.75",
2873
+ strokeLinecap: "round",
2874
+ strokeLinejoin: "round"
2875
+ }
2876
+ )
2877
+ }
2878
+ );
2879
+ }
2880
+ function EyeIcon() {
2881
+ return /* @__PURE__ */ jsxs(
2882
+ "svg",
2883
+ {
2884
+ "aria-hidden": "true",
2885
+ width: "16",
2886
+ height: "16",
2887
+ viewBox: "0 0 16 16",
2888
+ fill: "none",
2889
+ xmlns: "http://www.w3.org/2000/svg",
2890
+ children: [
2891
+ /* @__PURE__ */ jsx(
2892
+ "path",
2893
+ {
2894
+ 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",
2895
+ stroke: "currentColor",
2896
+ strokeWidth: "1.5",
2897
+ strokeLinejoin: "round"
2898
+ }
2899
+ ),
2900
+ /* @__PURE__ */ jsx("circle", { cx: "8", cy: "8", r: "2", stroke: "currentColor", strokeWidth: "1.5" })
2901
+ ]
2902
+ }
2903
+ );
2904
+ }
2905
+ function EyeOffIcon() {
2906
+ return /* @__PURE__ */ jsx(
2907
+ "svg",
2908
+ {
2909
+ "aria-hidden": "true",
2910
+ width: "16",
2911
+ height: "16",
2912
+ viewBox: "0 0 16 16",
2913
+ fill: "none",
2914
+ xmlns: "http://www.w3.org/2000/svg",
2915
+ children: /* @__PURE__ */ jsx(
2916
+ "path",
2917
+ {
2918
+ 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",
2919
+ stroke: "currentColor",
2920
+ strokeWidth: "1.5",
2921
+ strokeLinecap: "round",
2922
+ strokeLinejoin: "round"
2923
+ }
2924
+ )
2925
+ }
2926
+ );
2927
+ }
2928
+ var iconButtonBase = cn(
2929
+ "flex items-center justify-center h-7 w-7 rounded-lg shrink-0",
2930
+ "text-white/40 transition-colors hover:bg-white/10 hover:text-white/80",
2931
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/40"
2932
+ );
2933
+ function CopyField({ value, label, masked = false, className, id: externalId }) {
2934
+ const generatedId = useId();
2935
+ const fieldId = externalId || generatedId;
2936
+ const { copy, copied } = useClipboard();
2937
+ const [revealed, setRevealed] = useState(false);
2938
+ const displayValue = masked && !revealed ? "\u2022".repeat(Math.min(value.length, 24)) : value;
2939
+ const field = /* @__PURE__ */ jsxs(
2940
+ "div",
2941
+ {
2942
+ className: cn(
2943
+ "flex items-center gap-1 w-full rounded-xl px-3 py-2.5",
2944
+ "bg-white/10 ring-1 ring-white/10",
2945
+ className
2946
+ ),
2947
+ children: [
2948
+ /* @__PURE__ */ jsx(
2949
+ "span",
2950
+ {
2951
+ id: fieldId,
2952
+ className: "flex-1 min-w-0 truncate text-sm text-white select-all font-mono",
2953
+ "aria-label": label,
2954
+ children: displayValue
2955
+ }
2956
+ ),
2957
+ masked && /* @__PURE__ */ jsx(
2958
+ "button",
2959
+ {
2960
+ type: "button",
2961
+ "aria-label": revealed ? "Hide value" : "Reveal value",
2962
+ onClick: () => setRevealed((v) => !v),
2963
+ className: iconButtonBase,
2964
+ children: revealed ? /* @__PURE__ */ jsx(EyeOffIcon, {}) : /* @__PURE__ */ jsx(EyeIcon, {})
2965
+ }
2966
+ ),
2967
+ /* @__PURE__ */ jsx(
2968
+ "button",
2969
+ {
2970
+ type: "button",
2971
+ "aria-label": copied ? "Copied!" : "Copy to clipboard",
2972
+ onClick: () => copy(value),
2973
+ className: cn(iconButtonBase, copied && "text-emerald-400 hover:text-emerald-400"),
2974
+ children: copied ? /* @__PURE__ */ jsx(CheckIcon, {}) : /* @__PURE__ */ jsx(CopyIcon, {})
2975
+ }
2976
+ )
2977
+ ]
2978
+ }
2979
+ );
2980
+ if (!label) return field;
2981
+ return /* @__PURE__ */ jsxs("div", { children: [
2982
+ /* @__PURE__ */ jsx("label", { htmlFor: fieldId, className: "block text-sm text-white/70 mb-1.5", children: label }),
2983
+ field
2984
+ ] });
2985
+ }
1626
2986
  var ProgressButton = forwardRef(
1627
2987
  function ProgressButton2({ isLoading, loadingText, children, disabled, className, ...props }, ref) {
1628
2988
  return /* @__PURE__ */ jsx(
@@ -1681,7 +3041,7 @@ var variantIconLabel = {
1681
3041
  warning: "\u26A0",
1682
3042
  info: "i"
1683
3043
  };
1684
- var variantIconColor = {
3044
+ var variantIconColor2 = {
1685
3045
  success: "text-emerald-400",
1686
3046
  error: "text-rose-400",
1687
3047
  warning: "text-amber-400",
@@ -1757,7 +3117,7 @@ function ToastCard({ toast, onDismiss }) {
1757
3117
  "aria-hidden": "true",
1758
3118
  className: cn(
1759
3119
  "mt-0.5 flex h-5 w-5 shrink-0 items-center justify-center rounded-full text-[11px] font-bold ring-1",
1760
- variantIconColor[toast.variant],
3120
+ variantIconColor2[toast.variant],
1761
3121
  "ring-current/30"
1762
3122
  ),
1763
3123
  children: variantIconLabel[toast.variant]
@@ -1852,5 +3212,117 @@ function useToast() {
1852
3212
  }
1853
3213
  return ctx;
1854
3214
  }
3215
+ function SavingIcon() {
3216
+ return /* @__PURE__ */ jsxs(
3217
+ "svg",
3218
+ {
3219
+ className: "h-5 w-5 animate-spin text-white/70",
3220
+ viewBox: "0 0 24 24",
3221
+ fill: "none",
3222
+ "aria-hidden": "true",
3223
+ children: [
3224
+ /* @__PURE__ */ jsx(
3225
+ "circle",
3226
+ {
3227
+ className: "opacity-25",
3228
+ cx: "12",
3229
+ cy: "12",
3230
+ r: "10",
3231
+ stroke: "currentColor",
3232
+ strokeWidth: "4"
3233
+ }
3234
+ ),
3235
+ /* @__PURE__ */ jsx(
3236
+ "path",
3237
+ {
3238
+ className: "opacity-75",
3239
+ fill: "currentColor",
3240
+ d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"
3241
+ }
3242
+ )
3243
+ ]
3244
+ }
3245
+ );
3246
+ }
3247
+ function SavedIcon() {
3248
+ return /* @__PURE__ */ jsxs(
3249
+ "svg",
3250
+ {
3251
+ className: "h-5 w-5 text-green-400",
3252
+ viewBox: "0 0 24 24",
3253
+ fill: "none",
3254
+ stroke: "currentColor",
3255
+ strokeWidth: 2,
3256
+ "aria-hidden": "true",
3257
+ children: [
3258
+ /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "10", strokeOpacity: 0.4 }),
3259
+ /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M9 12l2 2 4-4" })
3260
+ ]
3261
+ }
3262
+ );
3263
+ }
3264
+ function ErrorIcon2() {
3265
+ return /* @__PURE__ */ jsxs(
3266
+ "svg",
3267
+ {
3268
+ className: "h-5 w-5 text-red-400",
3269
+ viewBox: "0 0 24 24",
3270
+ fill: "none",
3271
+ stroke: "currentColor",
3272
+ strokeWidth: 2,
3273
+ "aria-hidden": "true",
3274
+ children: [
3275
+ /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "10", strokeOpacity: 0.4 }),
3276
+ /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M15 9l-6 6M9 9l6 6" })
3277
+ ]
3278
+ }
3279
+ );
3280
+ }
3281
+ var statusConfig = {
3282
+ saving: {
3283
+ icon: SavingIcon,
3284
+ defaultText: "Saving...",
3285
+ textClass: "text-white/70"
3286
+ },
3287
+ saved: {
3288
+ icon: SavedIcon,
3289
+ defaultText: "Saved",
3290
+ textClass: "text-green-400"
3291
+ },
3292
+ error: {
3293
+ icon: ErrorIcon2,
3294
+ defaultText: "Error",
3295
+ textClass: "text-red-400"
3296
+ }
3297
+ };
3298
+ function MutationOverlay({
3299
+ status,
3300
+ savingText,
3301
+ savedText,
3302
+ errorText,
3303
+ className
3304
+ }) {
3305
+ if (status === "idle") return null;
3306
+ const config = statusConfig[status];
3307
+ const Icon = config.icon;
3308
+ const text = status === "saving" ? savingText ?? config.defaultText : status === "saved" ? savedText ?? config.defaultText : errorText ?? config.defaultText;
3309
+ return /* @__PURE__ */ jsx(
3310
+ "div",
3311
+ {
3312
+ className: cn(
3313
+ "absolute inset-0 z-10 flex items-center justify-center",
3314
+ "bg-surface-50/80 backdrop-blur-sm",
3315
+ "transition-opacity duration-200",
3316
+ className
3317
+ ),
3318
+ role: "status",
3319
+ "aria-live": "polite",
3320
+ children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
3321
+ /* @__PURE__ */ jsx(Icon, {}),
3322
+ /* @__PURE__ */ jsx("span", { className: cn("text-sm font-medium", config.textClass), children: text })
3323
+ ] })
3324
+ }
3325
+ );
3326
+ }
1855
3327
 
1856
- export { Badge, Button, Card, Checkbox, CollapsibleSection, ConfirmDialog, DashboardLayout, DropZone, Dropdown, DropdownItem, DropdownMenu, DropdownSeparator, DropdownTrigger, EmptyState, IconButton, Input, Modal, Navbar, PageShell, Pill, ProgressButton, RadioGroup, RadioItem, SearchInput, Select, Sidebar, Skeleton, Spinner, Tab, TabList, TabPanel, Tabs, Textarea, ToastProvider, Toggle, Tooltip, cn, colors, focusSafely, getFocusableElements, useClipboard, useDebounce, useDisclosure, useMediaQuery, useToast };
3328
+ export { ActiveFilterPills, Alert, Avatar, Badge, Button, Card, Checkbox, CollapsibleSection, ColorInput, ConfirmDialog, CooldownRing, CopyField, DashboardLayout, Divider, DotIndicator, DropZone, Dropdown, DropdownItem, DropdownMenu, DropdownSeparator, DropdownTrigger, EmptyState, FormField, IconButton, Input, Modal, MutationOverlay, Navbar, PageShell, Pagination, Pill, ProgressBar, ProgressButton, RadioGroup, RadioItem, SearchInput, SectionCard, Select, Sidebar, Skeleton, Slider, Spinner, StageProgress, StatCard, Stepper, Tab, TabList, TabPanel, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, Tabs, TagInput, Textarea, ToastProvider, Toggle, Tooltip, cn, colors, focusSafely, getFocusableElements, useClipboard, useDebounce, useDisclosure, useMediaQuery, useToast };