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