@memelabui/ui 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/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 = {
@@ -420,6 +588,174 @@ var Toggle = forwardRef(function Toggle2({ checked, onChange, disabled, label, s
420
588
  label && /* @__PURE__ */ jsx("label", { htmlFor: toggleId, className: "text-sm text-white/60 cursor-pointer", children: label })
421
589
  ] });
422
590
  });
591
+ var Slider = forwardRef(function Slider2({
592
+ label,
593
+ showValue = false,
594
+ formatValue,
595
+ onChange,
596
+ disabled,
597
+ min = 0,
598
+ max = 100,
599
+ step = 1,
600
+ value,
601
+ defaultValue,
602
+ className,
603
+ id: externalId,
604
+ ...props
605
+ }, ref) {
606
+ const generatedId = useId();
607
+ const sliderId = externalId || generatedId;
608
+ const numericValue = useMemo(() => {
609
+ const raw = value !== void 0 ? value : defaultValue;
610
+ return raw !== void 0 ? Number(raw) : Number(min);
611
+ }, [value, defaultValue, min]);
612
+ const percentage = useMemo(() => {
613
+ const numMin = Number(min);
614
+ const numMax = Number(max);
615
+ if (numMax === numMin) return 0;
616
+ return Math.max(0, Math.min(100, (numericValue - numMin) / (numMax - numMin) * 100));
617
+ }, [numericValue, min, max]);
618
+ const trackGradient = `linear-gradient(to right, var(--ml-primary, #8b5cf6) ${percentage}%, rgba(255,255,255,0.1) ${percentage}%)`;
619
+ const displayValue = formatValue ? formatValue(numericValue) : String(numericValue);
620
+ const handleChange = (e) => {
621
+ onChange?.(Number(e.target.value));
622
+ };
623
+ const inputEl = /* @__PURE__ */ jsx(
624
+ "input",
625
+ {
626
+ ...props,
627
+ ref,
628
+ id: sliderId,
629
+ type: "range",
630
+ min,
631
+ max,
632
+ step,
633
+ value,
634
+ defaultValue: value === void 0 ? defaultValue ?? Number(min) : void 0,
635
+ disabled,
636
+ onChange: handleChange,
637
+ style: { background: trackGradient },
638
+ className: cn(
639
+ // Layout + reset
640
+ "w-full h-2 appearance-none rounded-full outline-none cursor-pointer",
641
+ // bg is set via inline style (trackGradient); keep transparent fallback for SSR
642
+ "bg-white/10",
643
+ // Webkit thumb
644
+ "[&::-webkit-slider-thumb]:appearance-none",
645
+ "[&::-webkit-slider-thumb]:w-4",
646
+ "[&::-webkit-slider-thumb]:h-4",
647
+ "[&::-webkit-slider-thumb]:rounded-full",
648
+ "[&::-webkit-slider-thumb]:bg-white",
649
+ "[&::-webkit-slider-thumb]:border-2",
650
+ "[&::-webkit-slider-thumb]:border-[var(--ml-primary,#8b5cf6)]",
651
+ "[&::-webkit-slider-thumb]:transition-shadow",
652
+ "[&::-webkit-slider-thumb]:duration-150",
653
+ // Moz thumb
654
+ "[&::-moz-range-thumb]:w-4",
655
+ "[&::-moz-range-thumb]:h-4",
656
+ "[&::-moz-range-thumb]:rounded-full",
657
+ "[&::-moz-range-thumb]:bg-white",
658
+ "[&::-moz-range-thumb]:border-2",
659
+ "[&::-moz-range-thumb]:border-[var(--ml-primary,#8b5cf6)]",
660
+ "[&::-moz-range-thumb]:transition-shadow",
661
+ "[&::-moz-range-thumb]:duration-150",
662
+ // Moz track — transparent so the gradient on the element shows through
663
+ "[&::-moz-range-track]:bg-transparent",
664
+ "[&::-moz-range-track]:rounded-full",
665
+ // Focus ring on thumb
666
+ "focus-visible:outline-none",
667
+ "focus-visible:[&::-webkit-slider-thumb]:ring-2",
668
+ "focus-visible:[&::-webkit-slider-thumb]:ring-primary/40",
669
+ "focus-visible:[&::-webkit-slider-thumb]:ring-offset-2",
670
+ "focus-visible:[&::-webkit-slider-thumb]:ring-offset-surface",
671
+ "focus-visible:[&::-moz-range-thumb]:ring-2",
672
+ "focus-visible:[&::-moz-range-thumb]:ring-primary/40",
673
+ // Disabled
674
+ disabled && "opacity-50 cursor-not-allowed",
675
+ className
676
+ )
677
+ }
678
+ );
679
+ if (!label && !showValue) return inputEl;
680
+ return /* @__PURE__ */ jsxs("div", { className: "w-full space-y-1.5", children: [
681
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2", children: [
682
+ label && /* @__PURE__ */ jsx("label", { htmlFor: sliderId, className: "text-sm text-white/70", children: label }),
683
+ showValue && /* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-white/90 tabular-nums ml-auto", children: displayValue })
684
+ ] }),
685
+ inputEl
686
+ ] });
687
+ });
688
+ var ColorInput = forwardRef(function ColorInput2({ value, onChange, label, disabled, className, id: idProp }, ref) {
689
+ const autoId = useId();
690
+ const id = idProp ?? autoId;
691
+ const nativePickerRef = useRef(null);
692
+ function handleSwatchClick() {
693
+ if (!disabled) {
694
+ nativePickerRef.current?.click();
695
+ }
696
+ }
697
+ function handleTextChange(e) {
698
+ onChange(e.target.value);
699
+ }
700
+ function handleNativeChange(e) {
701
+ onChange(e.target.value);
702
+ }
703
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-1.5", className), children: [
704
+ label ? /* @__PURE__ */ jsx("label", { htmlFor: id, className: "block text-sm text-white/70", children: label }) : null,
705
+ /* @__PURE__ */ jsxs(
706
+ "div",
707
+ {
708
+ className: cn(
709
+ "flex items-center gap-2 bg-white/10 rounded-xl ring-1 ring-white/10 px-3 py-2 transition-shadow",
710
+ "focus-within:ring-2 focus-within:ring-primary/40",
711
+ disabled && "opacity-60 pointer-events-none"
712
+ ),
713
+ children: [
714
+ /* @__PURE__ */ jsx(
715
+ "input",
716
+ {
717
+ type: "color",
718
+ ref: nativePickerRef,
719
+ value,
720
+ onChange: handleNativeChange,
721
+ disabled,
722
+ "aria-hidden": "true",
723
+ tabIndex: -1,
724
+ className: "sr-only"
725
+ }
726
+ ),
727
+ /* @__PURE__ */ jsx(
728
+ "button",
729
+ {
730
+ type: "button",
731
+ onClick: handleSwatchClick,
732
+ disabled,
733
+ "aria-label": "Open color picker",
734
+ className: cn(
735
+ "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"
736
+ ),
737
+ style: { backgroundColor: value }
738
+ }
739
+ ),
740
+ /* @__PURE__ */ jsx(
741
+ "input",
742
+ {
743
+ ref,
744
+ id,
745
+ type: "text",
746
+ value,
747
+ onChange: handleTextChange,
748
+ disabled,
749
+ spellCheck: false,
750
+ className: "flex-1 min-w-0 bg-transparent text-sm text-white placeholder:text-white/30 outline-none font-mono",
751
+ placeholder: "#000000"
752
+ }
753
+ )
754
+ ]
755
+ }
756
+ )
757
+ ] });
758
+ });
423
759
  var Checkbox = forwardRef(function Checkbox2({ label, error, indeterminate, className, id: externalId, disabled, checked, onChange, ...props }, ref) {
424
760
  const generatedId = useId();
425
761
  const inputId = externalId || generatedId;
@@ -645,7 +981,7 @@ function RadioItem({ value, disabled: itemDisabled, children, className }) {
645
981
  }
646
982
  );
647
983
  }
648
- var sizeClass4 = {
984
+ var sizeClass5 = {
649
985
  sm: "h-3 w-3 border",
650
986
  md: "h-4 w-4 border-2",
651
987
  lg: "h-6 w-6 border-2"
@@ -654,7 +990,7 @@ function Spinner({ className, size = "md", label }) {
654
990
  return /* @__PURE__ */ jsx(
655
991
  "span",
656
992
  {
657
- className: cn("inline-block rounded-full border-white/15 border-t-primary animate-spin", sizeClass4[size], className),
993
+ className: cn("inline-block rounded-full border-white/15 border-t-primary animate-spin", sizeClass5[size], className),
658
994
  role: label ? "status" : void 0,
659
995
  "aria-hidden": label ? void 0 : "true",
660
996
  "aria-label": label || void 0
@@ -1517,6 +1853,404 @@ function DropZone({
1517
1853
  }
1518
1854
  );
1519
1855
  }
1856
+ function FormField({ label, error, helperText, children, className, id: idProp }) {
1857
+ const autoId = useId();
1858
+ const id = idProp ?? autoId;
1859
+ const descIds = [];
1860
+ const errorId = error ? `${id}-error` : void 0;
1861
+ const helperId = helperText ? `${id}-helper` : void 0;
1862
+ if (errorId) descIds.push(errorId);
1863
+ if (helperId) descIds.push(helperId);
1864
+ const describedBy = descIds.length > 0 ? descIds.join(" ") : void 0;
1865
+ const child = cloneElement(children, {
1866
+ id,
1867
+ ...describedBy ? { "aria-describedby": describedBy } : {},
1868
+ ...error ? { "aria-invalid": true } : {}
1869
+ });
1870
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col", className), children: [
1871
+ label ? /* @__PURE__ */ jsx("label", { htmlFor: id, className: "block text-sm text-white/70 mb-1.5", children: label }) : null,
1872
+ child,
1873
+ error ? /* @__PURE__ */ jsx("p", { id: errorId, className: "text-rose-400 text-xs mt-1", role: "alert", children: error }) : null,
1874
+ helperText && !error ? /* @__PURE__ */ jsx("p", { id: helperId, className: "text-white/40 text-xs mt-1", children: helperText }) : null
1875
+ ] });
1876
+ }
1877
+ function Divider({ orientation = "horizontal", label, className }) {
1878
+ if (orientation === "vertical") {
1879
+ return /* @__PURE__ */ jsx(
1880
+ "div",
1881
+ {
1882
+ role: "separator",
1883
+ "aria-orientation": "vertical",
1884
+ className: cn("border-l border-white/10 h-full mx-3 self-stretch", className)
1885
+ }
1886
+ );
1887
+ }
1888
+ if (label) {
1889
+ return /* @__PURE__ */ jsxs(
1890
+ "div",
1891
+ {
1892
+ role: "separator",
1893
+ "aria-orientation": "horizontal",
1894
+ className: cn("flex items-center gap-3 my-3 w-full", className),
1895
+ children: [
1896
+ /* @__PURE__ */ jsx("span", { className: "flex-1 border-t border-white/10" }),
1897
+ /* @__PURE__ */ jsx("span", { className: "text-xs text-white/40 leading-none select-none", children: label }),
1898
+ /* @__PURE__ */ jsx("span", { className: "flex-1 border-t border-white/10" })
1899
+ ]
1900
+ }
1901
+ );
1902
+ }
1903
+ return /* @__PURE__ */ jsx(
1904
+ "hr",
1905
+ {
1906
+ role: "separator",
1907
+ "aria-orientation": "horizontal",
1908
+ className: cn("border-t border-white/10 w-full my-3", className)
1909
+ }
1910
+ );
1911
+ }
1912
+ 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 }) }));
1913
+ Table.displayName = "Table";
1914
+ var TableHeader = forwardRef(
1915
+ ({ children, className }, ref) => /* @__PURE__ */ jsx("thead", { ref, className: cn("bg-white/5 border-b border-white/10", className), children })
1916
+ );
1917
+ TableHeader.displayName = "TableHeader";
1918
+ var TableBody = forwardRef(
1919
+ ({ children, className }, ref) => /* @__PURE__ */ jsx("tbody", { ref, className: cn("divide-y divide-white/[0.06]", className), children })
1920
+ );
1921
+ TableBody.displayName = "TableBody";
1922
+ var TableRow = forwardRef(
1923
+ ({ children, className, hoverable }, ref) => /* @__PURE__ */ jsx(
1924
+ "tr",
1925
+ {
1926
+ ref,
1927
+ className: cn(hoverable && "hover:bg-white/[0.03] transition-colors", className),
1928
+ children
1929
+ }
1930
+ )
1931
+ );
1932
+ TableRow.displayName = "TableRow";
1933
+ var TableHead = forwardRef(
1934
+ ({ children, className }, ref) => /* @__PURE__ */ jsx(
1935
+ "th",
1936
+ {
1937
+ ref,
1938
+ className: cn(
1939
+ "px-4 py-3 text-left text-xs font-semibold text-white/50 uppercase tracking-wider",
1940
+ className
1941
+ ),
1942
+ children
1943
+ }
1944
+ )
1945
+ );
1946
+ TableHead.displayName = "TableHead";
1947
+ var alignClass = {
1948
+ left: "text-left",
1949
+ center: "text-center",
1950
+ right: "text-right"
1951
+ };
1952
+ var TableCell = forwardRef(
1953
+ ({ children, className, align = "left" }, ref) => /* @__PURE__ */ jsx("td", { ref, className: cn("px-4 py-3 text-white/80", alignClass[align], className), children })
1954
+ );
1955
+ TableCell.displayName = "TableCell";
1956
+ function TrendIndicator({ trend }) {
1957
+ if (trend.value > 0) {
1958
+ return /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1 text-xs text-emerald-400", children: [
1959
+ /* @__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" }) }),
1960
+ /* @__PURE__ */ jsxs("span", { children: [
1961
+ "+",
1962
+ trend.value,
1963
+ trend.label ? ` ${trend.label}` : ""
1964
+ ] })
1965
+ ] });
1966
+ }
1967
+ if (trend.value < 0) {
1968
+ return /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1 text-xs text-rose-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 3v6M3 6l3 3 3-3" }) }),
1970
+ /* @__PURE__ */ jsxs("span", { children: [
1971
+ trend.value,
1972
+ trend.label ? ` ${trend.label}` : ""
1973
+ ] })
1974
+ ] });
1975
+ }
1976
+ return /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1 text-xs text-white/40", children: [
1977
+ /* @__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" }) }),
1978
+ /* @__PURE__ */ jsxs("span", { children: [
1979
+ trend.value,
1980
+ trend.label ? ` ${trend.label}` : ""
1981
+ ] })
1982
+ ] });
1983
+ }
1984
+ function StatCard({ value, label, icon, trend, className }) {
1985
+ return /* @__PURE__ */ jsxs(
1986
+ "div",
1987
+ {
1988
+ className: cn(
1989
+ "bg-white/5 ring-1 ring-white/10 rounded-xl p-4 flex items-start gap-3",
1990
+ className
1991
+ ),
1992
+ children: [
1993
+ 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 }),
1994
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-0.5 min-w-0", children: [
1995
+ /* @__PURE__ */ jsx("span", { className: "text-2xl font-bold text-white tabular-nums leading-none", children: value }),
1996
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-white/50 truncate", children: label }),
1997
+ trend != null && /* @__PURE__ */ jsx("div", { className: "mt-1", children: /* @__PURE__ */ jsx(TrendIndicator, { trend }) })
1998
+ ] })
1999
+ ]
2000
+ }
2001
+ );
2002
+ }
2003
+ function getPageRange(page, totalPages, siblingCount) {
2004
+ if (totalPages <= 1) return [1];
2005
+ const siblingStart = Math.max(2, page - siblingCount);
2006
+ const siblingEnd = Math.min(totalPages - 1, page + siblingCount);
2007
+ const showLeftEllipsis = siblingStart > 2;
2008
+ const showRightEllipsis = siblingEnd < totalPages - 1;
2009
+ const items = [1];
2010
+ if (showLeftEllipsis) {
2011
+ items.push("...");
2012
+ } else {
2013
+ for (let i = 2; i < siblingStart; i++) {
2014
+ items.push(i);
2015
+ }
2016
+ }
2017
+ for (let i = siblingStart; i <= siblingEnd; i++) {
2018
+ items.push(i);
2019
+ }
2020
+ if (showRightEllipsis) {
2021
+ items.push("...");
2022
+ } else {
2023
+ for (let i = siblingEnd + 1; i < totalPages; i++) {
2024
+ items.push(i);
2025
+ }
2026
+ }
2027
+ if (totalPages > 1) {
2028
+ items.push(totalPages);
2029
+ }
2030
+ return items;
2031
+ }
2032
+ 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";
2033
+ var pageButton = cn(buttonBase, "bg-white/5 ring-1 ring-white/10 text-white/80 hover:bg-white/10 hover:text-white");
2034
+ var activeButton = cn(buttonBase, "bg-primary text-white ring-1 ring-primary/20");
2035
+ var navButton = cn(buttonBase, "bg-white/5 ring-1 ring-white/10 text-white/80 hover:bg-white/10 hover:text-white");
2036
+ var ChevronLeft = () => /* @__PURE__ */ jsx(
2037
+ "svg",
2038
+ {
2039
+ xmlns: "http://www.w3.org/2000/svg",
2040
+ width: "16",
2041
+ height: "16",
2042
+ viewBox: "0 0 24 24",
2043
+ fill: "none",
2044
+ stroke: "currentColor",
2045
+ strokeWidth: "2",
2046
+ strokeLinecap: "round",
2047
+ strokeLinejoin: "round",
2048
+ "aria-hidden": "true",
2049
+ children: /* @__PURE__ */ jsx("polyline", { points: "15 18 9 12 15 6" })
2050
+ }
2051
+ );
2052
+ var ChevronRight = () => /* @__PURE__ */ 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__ */ jsx("polyline", { points: "9 18 15 12 9 6" })
2066
+ }
2067
+ );
2068
+ function Pagination({
2069
+ page,
2070
+ totalPages,
2071
+ onPageChange,
2072
+ siblingCount = 1,
2073
+ className
2074
+ }) {
2075
+ if (totalPages <= 1) return null;
2076
+ const items = getPageRange(page, totalPages, siblingCount);
2077
+ const isPrevDisabled = page <= 1;
2078
+ const isNextDisabled = page >= totalPages;
2079
+ return /* @__PURE__ */ jsxs(
2080
+ "nav",
2081
+ {
2082
+ role: "navigation",
2083
+ "aria-label": "Pagination",
2084
+ className: cn("flex items-center gap-1", className),
2085
+ children: [
2086
+ /* @__PURE__ */ jsx(
2087
+ "button",
2088
+ {
2089
+ type: "button",
2090
+ onClick: () => onPageChange(page - 1),
2091
+ disabled: isPrevDisabled,
2092
+ "aria-label": "Previous page",
2093
+ className: cn(navButton, isPrevDisabled && "opacity-40 cursor-not-allowed pointer-events-none"),
2094
+ children: /* @__PURE__ */ jsx(ChevronLeft, {})
2095
+ }
2096
+ ),
2097
+ items.map(
2098
+ (item, index) => item === "..." ? /* @__PURE__ */ jsx(
2099
+ "span",
2100
+ {
2101
+ className: "inline-flex items-center justify-center px-3 py-2 text-sm text-white/40 select-none",
2102
+ "aria-hidden": "true",
2103
+ children: "\u2026"
2104
+ },
2105
+ `ellipsis-${index}`
2106
+ ) : /* @__PURE__ */ jsx(
2107
+ "button",
2108
+ {
2109
+ type: "button",
2110
+ onClick: () => onPageChange(item),
2111
+ "aria-label": `Page ${item}`,
2112
+ "aria-current": item === page ? "page" : void 0,
2113
+ className: item === page ? activeButton : pageButton,
2114
+ children: item
2115
+ },
2116
+ item
2117
+ )
2118
+ ),
2119
+ /* @__PURE__ */ jsx(
2120
+ "button",
2121
+ {
2122
+ type: "button",
2123
+ onClick: () => onPageChange(page + 1),
2124
+ disabled: isNextDisabled,
2125
+ "aria-label": "Next page",
2126
+ className: cn(navButton, isNextDisabled && "opacity-40 cursor-not-allowed pointer-events-none"),
2127
+ children: /* @__PURE__ */ jsx(ChevronRight, {})
2128
+ }
2129
+ )
2130
+ ]
2131
+ }
2132
+ );
2133
+ }
2134
+ function Stepper({ steps, activeStep, className }) {
2135
+ return /* @__PURE__ */ jsx("div", { className: cn("flex items-start w-full", className), children: steps.map((step, index) => {
2136
+ const isCompleted = index < activeStep;
2137
+ const isActive = index === activeStep;
2138
+ return /* @__PURE__ */ jsxs(React.Fragment, { children: [
2139
+ /* @__PURE__ */ jsxs(
2140
+ "div",
2141
+ {
2142
+ className: "flex flex-col items-center",
2143
+ "aria-current": isActive ? "step" : void 0,
2144
+ children: [
2145
+ /* @__PURE__ */ jsx(
2146
+ "div",
2147
+ {
2148
+ className: cn(
2149
+ "w-8 h-8 rounded-full flex items-center justify-center text-sm font-semibold",
2150
+ isCompleted && "bg-emerald-600 text-white",
2151
+ isActive && "bg-primary text-white ring-2 ring-primary/40",
2152
+ !isCompleted && !isActive && "bg-white/10 text-white/40"
2153
+ ),
2154
+ children: isCompleted ? /* @__PURE__ */ jsx(
2155
+ "svg",
2156
+ {
2157
+ xmlns: "http://www.w3.org/2000/svg",
2158
+ viewBox: "0 0 20 20",
2159
+ fill: "currentColor",
2160
+ className: "w-4 h-4",
2161
+ "aria-hidden": "true",
2162
+ children: /* @__PURE__ */ jsx(
2163
+ "path",
2164
+ {
2165
+ fillRule: "evenodd",
2166
+ 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",
2167
+ clipRule: "evenodd"
2168
+ }
2169
+ )
2170
+ }
2171
+ ) : /* @__PURE__ */ jsx("span", { children: index + 1 })
2172
+ }
2173
+ ),
2174
+ /* @__PURE__ */ jsx(
2175
+ "span",
2176
+ {
2177
+ className: cn(
2178
+ "text-xs mt-2 text-center max-w-[6rem]",
2179
+ isActive ? "text-white/80" : "text-white/50"
2180
+ ),
2181
+ children: step.label
2182
+ }
2183
+ ),
2184
+ step.description && /* @__PURE__ */ jsx("span", { className: "text-xs mt-0.5 text-center text-white/30 max-w-[6rem]", children: step.description })
2185
+ ]
2186
+ }
2187
+ ),
2188
+ index < steps.length - 1 && /* @__PURE__ */ jsx(
2189
+ "div",
2190
+ {
2191
+ className: cn(
2192
+ "h-0.5 flex-1 mx-2 mt-4 self-start",
2193
+ isCompleted ? "bg-emerald-600" : "bg-white/10"
2194
+ ),
2195
+ "aria-hidden": "true"
2196
+ }
2197
+ )
2198
+ ] }, index);
2199
+ }) });
2200
+ }
2201
+ var sizeClasses = {
2202
+ sm: "h-1",
2203
+ md: "h-2",
2204
+ lg: "h-3"
2205
+ };
2206
+ var variantClasses = {
2207
+ primary: "bg-primary",
2208
+ success: "bg-emerald-500",
2209
+ warning: "bg-amber-500",
2210
+ danger: "bg-rose-500"
2211
+ };
2212
+ function ProgressBar({
2213
+ value,
2214
+ max = 100,
2215
+ variant = "primary",
2216
+ label,
2217
+ showValue = false,
2218
+ size = "md",
2219
+ className
2220
+ }) {
2221
+ const percentage = Math.min(100, Math.max(0, value / max * 100));
2222
+ return /* @__PURE__ */ jsxs("div", { className: cn("w-full", className), children: [
2223
+ (label || showValue) && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-1", children: [
2224
+ label && /* @__PURE__ */ jsx("span", { className: "text-xs text-white/60", children: label }),
2225
+ showValue && /* @__PURE__ */ jsxs("span", { className: "text-xs text-white/60 ml-auto", children: [
2226
+ Math.round(percentage),
2227
+ "%"
2228
+ ] })
2229
+ ] }),
2230
+ /* @__PURE__ */ jsx(
2231
+ "div",
2232
+ {
2233
+ className: cn("w-full rounded-full bg-white/10", sizeClasses[size]),
2234
+ role: "progressbar",
2235
+ "aria-valuenow": value,
2236
+ "aria-valuemin": 0,
2237
+ "aria-valuemax": max,
2238
+ "aria-label": label,
2239
+ children: /* @__PURE__ */ jsx(
2240
+ "div",
2241
+ {
2242
+ className: cn(
2243
+ "rounded-full transition-[width] duration-300 ease-out",
2244
+ sizeClasses[size],
2245
+ variantClasses[variant]
2246
+ ),
2247
+ style: { width: `${percentage}%` }
2248
+ }
2249
+ )
2250
+ }
2251
+ )
2252
+ ] });
2253
+ }
1520
2254
  var maxWidthClass = {
1521
2255
  sm: "max-w-2xl",
1522
2256
  md: "max-w-4xl",
@@ -1623,6 +2357,319 @@ function DashboardLayout({ children, navbar, sidebar, className, mainClassName,
1623
2357
  ] })
1624
2358
  ] });
1625
2359
  }
2360
+ var variantBorderColor = {
2361
+ info: "border-blue-500",
2362
+ success: "border-emerald-500",
2363
+ warning: "border-amber-500",
2364
+ error: "border-rose-500"
2365
+ };
2366
+ var variantIconColor = {
2367
+ info: "text-blue-400",
2368
+ success: "text-emerald-400",
2369
+ warning: "text-amber-400",
2370
+ error: "text-rose-400"
2371
+ };
2372
+ function InfoIcon() {
2373
+ return /* @__PURE__ */ jsxs(
2374
+ "svg",
2375
+ {
2376
+ "aria-hidden": "true",
2377
+ width: "18",
2378
+ height: "18",
2379
+ viewBox: "0 0 18 18",
2380
+ fill: "none",
2381
+ xmlns: "http://www.w3.org/2000/svg",
2382
+ children: [
2383
+ /* @__PURE__ */ jsx("circle", { cx: "9", cy: "9", r: "7.5", stroke: "currentColor", strokeWidth: "1.5" }),
2384
+ /* @__PURE__ */ jsx("path", { d: "M9 8v5", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round" }),
2385
+ /* @__PURE__ */ jsx("circle", { cx: "9", cy: "5.5", r: "0.875", fill: "currentColor" })
2386
+ ]
2387
+ }
2388
+ );
2389
+ }
2390
+ function SuccessIcon() {
2391
+ return /* @__PURE__ */ jsxs(
2392
+ "svg",
2393
+ {
2394
+ "aria-hidden": "true",
2395
+ width: "18",
2396
+ height: "18",
2397
+ viewBox: "0 0 18 18",
2398
+ fill: "none",
2399
+ xmlns: "http://www.w3.org/2000/svg",
2400
+ children: [
2401
+ /* @__PURE__ */ jsx("circle", { cx: "9", cy: "9", r: "7.5", stroke: "currentColor", strokeWidth: "1.5" }),
2402
+ /* @__PURE__ */ jsx(
2403
+ "path",
2404
+ {
2405
+ d: "M5.5 9.5l2.5 2.5 4.5-5",
2406
+ stroke: "currentColor",
2407
+ strokeWidth: "1.75",
2408
+ strokeLinecap: "round",
2409
+ strokeLinejoin: "round"
2410
+ }
2411
+ )
2412
+ ]
2413
+ }
2414
+ );
2415
+ }
2416
+ function WarningIcon() {
2417
+ return /* @__PURE__ */ jsxs(
2418
+ "svg",
2419
+ {
2420
+ "aria-hidden": "true",
2421
+ width: "18",
2422
+ height: "18",
2423
+ viewBox: "0 0 18 18",
2424
+ fill: "none",
2425
+ xmlns: "http://www.w3.org/2000/svg",
2426
+ children: [
2427
+ /* @__PURE__ */ jsx(
2428
+ "path",
2429
+ {
2430
+ 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",
2431
+ stroke: "currentColor",
2432
+ strokeWidth: "1.5",
2433
+ strokeLinejoin: "round"
2434
+ }
2435
+ ),
2436
+ /* @__PURE__ */ jsx("path", { d: "M9 7v4", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round" }),
2437
+ /* @__PURE__ */ jsx("circle", { cx: "9", cy: "12.5", r: "0.875", fill: "currentColor" })
2438
+ ]
2439
+ }
2440
+ );
2441
+ }
2442
+ function ErrorIcon() {
2443
+ return /* @__PURE__ */ jsxs(
2444
+ "svg",
2445
+ {
2446
+ "aria-hidden": "true",
2447
+ width: "18",
2448
+ height: "18",
2449
+ viewBox: "0 0 18 18",
2450
+ fill: "none",
2451
+ xmlns: "http://www.w3.org/2000/svg",
2452
+ children: [
2453
+ /* @__PURE__ */ jsx("circle", { cx: "9", cy: "9", r: "7.5", stroke: "currentColor", strokeWidth: "1.5" }),
2454
+ /* @__PURE__ */ jsx(
2455
+ "path",
2456
+ {
2457
+ d: "M6.5 6.5l5 5M11.5 6.5l-5 5",
2458
+ stroke: "currentColor",
2459
+ strokeWidth: "1.75",
2460
+ strokeLinecap: "round"
2461
+ }
2462
+ )
2463
+ ]
2464
+ }
2465
+ );
2466
+ }
2467
+ var variantIcon = {
2468
+ info: InfoIcon,
2469
+ success: SuccessIcon,
2470
+ warning: WarningIcon,
2471
+ error: ErrorIcon
2472
+ };
2473
+ function Alert({ variant = "info", title, children, onDismiss, className }) {
2474
+ const Icon = variantIcon[variant];
2475
+ return /* @__PURE__ */ jsxs(
2476
+ "div",
2477
+ {
2478
+ role: "alert",
2479
+ className: cn(
2480
+ "flex items-start gap-3 rounded-xl bg-white/5 ring-1 ring-white/10",
2481
+ "border-l-4 pl-4 pr-3 py-3",
2482
+ variantBorderColor[variant],
2483
+ className
2484
+ ),
2485
+ children: [
2486
+ /* @__PURE__ */ jsx("span", { className: cn("mt-0.5 shrink-0", variantIconColor[variant]), children: /* @__PURE__ */ jsx(Icon, {}) }),
2487
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
2488
+ title && /* @__PURE__ */ jsx("p", { className: "text-sm font-semibold text-white leading-snug mb-0.5", children: title }),
2489
+ /* @__PURE__ */ jsx("div", { className: "text-sm text-white/70 leading-relaxed", children })
2490
+ ] }),
2491
+ onDismiss && /* @__PURE__ */ jsx(
2492
+ "button",
2493
+ {
2494
+ type: "button",
2495
+ "aria-label": "Dismiss",
2496
+ onClick: onDismiss,
2497
+ className: cn(
2498
+ "shrink-0 flex items-center justify-center h-6 w-6 rounded-lg mt-0.5",
2499
+ "text-white/40 transition-colors hover:bg-white/10 hover:text-white/80",
2500
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/40"
2501
+ ),
2502
+ children: /* @__PURE__ */ jsx(
2503
+ "svg",
2504
+ {
2505
+ "aria-hidden": "true",
2506
+ width: "10",
2507
+ height: "10",
2508
+ viewBox: "0 0 10 10",
2509
+ fill: "none",
2510
+ children: /* @__PURE__ */ jsx("path", { d: "M1 1l8 8M9 1L1 9", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" })
2511
+ }
2512
+ )
2513
+ }
2514
+ )
2515
+ ]
2516
+ }
2517
+ );
2518
+ }
2519
+ function CopyIcon() {
2520
+ return /* @__PURE__ */ jsxs(
2521
+ "svg",
2522
+ {
2523
+ "aria-hidden": "true",
2524
+ width: "16",
2525
+ height: "16",
2526
+ viewBox: "0 0 16 16",
2527
+ fill: "none",
2528
+ xmlns: "http://www.w3.org/2000/svg",
2529
+ children: [
2530
+ /* @__PURE__ */ jsx("rect", { x: "5", y: "5", width: "9", height: "9", rx: "1.5", stroke: "currentColor", strokeWidth: "1.5" }),
2531
+ /* @__PURE__ */ jsx(
2532
+ "path",
2533
+ {
2534
+ 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",
2535
+ stroke: "currentColor",
2536
+ strokeWidth: "1.5",
2537
+ strokeLinecap: "round"
2538
+ }
2539
+ )
2540
+ ]
2541
+ }
2542
+ );
2543
+ }
2544
+ function CheckIcon() {
2545
+ return /* @__PURE__ */ jsx(
2546
+ "svg",
2547
+ {
2548
+ "aria-hidden": "true",
2549
+ width: "16",
2550
+ height: "16",
2551
+ viewBox: "0 0 16 16",
2552
+ fill: "none",
2553
+ xmlns: "http://www.w3.org/2000/svg",
2554
+ children: /* @__PURE__ */ jsx(
2555
+ "path",
2556
+ {
2557
+ d: "M3 8.5l3.5 3.5 6.5-7",
2558
+ stroke: "currentColor",
2559
+ strokeWidth: "1.75",
2560
+ strokeLinecap: "round",
2561
+ strokeLinejoin: "round"
2562
+ }
2563
+ )
2564
+ }
2565
+ );
2566
+ }
2567
+ function EyeIcon() {
2568
+ return /* @__PURE__ */ jsxs(
2569
+ "svg",
2570
+ {
2571
+ "aria-hidden": "true",
2572
+ width: "16",
2573
+ height: "16",
2574
+ viewBox: "0 0 16 16",
2575
+ fill: "none",
2576
+ xmlns: "http://www.w3.org/2000/svg",
2577
+ children: [
2578
+ /* @__PURE__ */ jsx(
2579
+ "path",
2580
+ {
2581
+ 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",
2582
+ stroke: "currentColor",
2583
+ strokeWidth: "1.5",
2584
+ strokeLinejoin: "round"
2585
+ }
2586
+ ),
2587
+ /* @__PURE__ */ jsx("circle", { cx: "8", cy: "8", r: "2", stroke: "currentColor", strokeWidth: "1.5" })
2588
+ ]
2589
+ }
2590
+ );
2591
+ }
2592
+ function EyeOffIcon() {
2593
+ return /* @__PURE__ */ jsx(
2594
+ "svg",
2595
+ {
2596
+ "aria-hidden": "true",
2597
+ width: "16",
2598
+ height: "16",
2599
+ viewBox: "0 0 16 16",
2600
+ fill: "none",
2601
+ xmlns: "http://www.w3.org/2000/svg",
2602
+ children: /* @__PURE__ */ jsx(
2603
+ "path",
2604
+ {
2605
+ 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",
2606
+ stroke: "currentColor",
2607
+ strokeWidth: "1.5",
2608
+ strokeLinecap: "round",
2609
+ strokeLinejoin: "round"
2610
+ }
2611
+ )
2612
+ }
2613
+ );
2614
+ }
2615
+ var iconButtonBase = cn(
2616
+ "flex items-center justify-center h-7 w-7 rounded-lg shrink-0",
2617
+ "text-white/40 transition-colors hover:bg-white/10 hover:text-white/80",
2618
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/40"
2619
+ );
2620
+ function CopyField({ value, label, masked = false, className, id: externalId }) {
2621
+ const generatedId = useId();
2622
+ const fieldId = externalId || generatedId;
2623
+ const { copy, copied } = useClipboard();
2624
+ const [revealed, setRevealed] = useState(false);
2625
+ const displayValue = masked && !revealed ? "\u2022".repeat(Math.min(value.length, 24)) : value;
2626
+ const field = /* @__PURE__ */ jsxs(
2627
+ "div",
2628
+ {
2629
+ className: cn(
2630
+ "flex items-center gap-1 w-full rounded-xl px-3 py-2.5",
2631
+ "bg-white/10 ring-1 ring-white/10",
2632
+ className
2633
+ ),
2634
+ children: [
2635
+ /* @__PURE__ */ jsx(
2636
+ "span",
2637
+ {
2638
+ id: fieldId,
2639
+ className: "flex-1 min-w-0 truncate text-sm text-white select-all font-mono",
2640
+ "aria-label": label,
2641
+ children: displayValue
2642
+ }
2643
+ ),
2644
+ masked && /* @__PURE__ */ jsx(
2645
+ "button",
2646
+ {
2647
+ type: "button",
2648
+ "aria-label": revealed ? "Hide value" : "Reveal value",
2649
+ onClick: () => setRevealed((v) => !v),
2650
+ className: iconButtonBase,
2651
+ children: revealed ? /* @__PURE__ */ jsx(EyeOffIcon, {}) : /* @__PURE__ */ jsx(EyeIcon, {})
2652
+ }
2653
+ ),
2654
+ /* @__PURE__ */ jsx(
2655
+ "button",
2656
+ {
2657
+ type: "button",
2658
+ "aria-label": copied ? "Copied!" : "Copy to clipboard",
2659
+ onClick: () => copy(value),
2660
+ className: cn(iconButtonBase, copied && "text-emerald-400 hover:text-emerald-400"),
2661
+ children: copied ? /* @__PURE__ */ jsx(CheckIcon, {}) : /* @__PURE__ */ jsx(CopyIcon, {})
2662
+ }
2663
+ )
2664
+ ]
2665
+ }
2666
+ );
2667
+ if (!label) return field;
2668
+ return /* @__PURE__ */ jsxs("div", { children: [
2669
+ /* @__PURE__ */ jsx("label", { htmlFor: fieldId, className: "block text-sm text-white/70 mb-1.5", children: label }),
2670
+ field
2671
+ ] });
2672
+ }
1626
2673
  var ProgressButton = forwardRef(
1627
2674
  function ProgressButton2({ isLoading, loadingText, children, disabled, className, ...props }, ref) {
1628
2675
  return /* @__PURE__ */ jsx(
@@ -1681,7 +2728,7 @@ var variantIconLabel = {
1681
2728
  warning: "\u26A0",
1682
2729
  info: "i"
1683
2730
  };
1684
- var variantIconColor = {
2731
+ var variantIconColor2 = {
1685
2732
  success: "text-emerald-400",
1686
2733
  error: "text-rose-400",
1687
2734
  warning: "text-amber-400",
@@ -1757,7 +2804,7 @@ function ToastCard({ toast, onDismiss }) {
1757
2804
  "aria-hidden": "true",
1758
2805
  className: cn(
1759
2806
  "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],
2807
+ variantIconColor2[toast.variant],
1761
2808
  "ring-current/30"
1762
2809
  ),
1763
2810
  children: variantIconLabel[toast.variant]
@@ -1853,4 +2900,4 @@ function useToast() {
1853
2900
  return ctx;
1854
2901
  }
1855
2902
 
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 };
2903
+ export { Alert, Avatar, Badge, Button, Card, Checkbox, CollapsibleSection, ColorInput, ConfirmDialog, CopyField, DashboardLayout, Divider, DropZone, Dropdown, DropdownItem, DropdownMenu, DropdownSeparator, DropdownTrigger, EmptyState, FormField, IconButton, Input, Modal, Navbar, PageShell, Pagination, Pill, ProgressBar, ProgressButton, RadioGroup, RadioItem, SearchInput, Select, Sidebar, Skeleton, Slider, Spinner, 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 };