@memelabui/ui 0.8.1 → 0.10.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,4 +1,4 @@
1
- import React, { forwardRef, useState, useId, useRef, useMemo, useEffect, createContext, useCallback, isValidElement, cloneElement, useReducer, useContext, Component } from 'react';
1
+ import React, { forwardRef, useState, useId, useRef, useMemo, useEffect, createContext, useCallback, isValidElement, cloneElement, useReducer, useContext, Fragment as Fragment$1, Component } from 'react';
2
2
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
3
3
  import { createPortal } from 'react-dom';
4
4
 
@@ -95,11 +95,11 @@ function useDisclosure(defaultOpen = false) {
95
95
  }
96
96
  function useMediaQuery(query) {
97
97
  const [matches, setMatches] = useState(() => {
98
- if (typeof window === "undefined") return false;
98
+ if (typeof window === "undefined" || typeof window.matchMedia !== "function") return false;
99
99
  return window.matchMedia(query).matches;
100
100
  });
101
101
  useEffect(() => {
102
- if (typeof window === "undefined") return;
102
+ if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
103
103
  const mediaQueryList = window.matchMedia(query);
104
104
  setMatches(mediaQueryList.matches);
105
105
  const handler = (event) => {
@@ -336,7 +336,7 @@ var sizeClass3 = {
336
336
  lg: "p-2.5 w-11 h-11"
337
337
  };
338
338
  var variantClass2 = {
339
- primary: "bg-primary text-white shadow-glow hover:brightness-[0.98]",
339
+ primary: "bg-primary text-white shadow-glow hover:shadow-glow-lg hover:scale-[1.02]",
340
340
  success: "bg-emerald-600 text-white shadow-lg shadow-emerald-600/20 hover:bg-emerald-700",
341
341
  warning: "bg-amber-600 text-white shadow-lg shadow-amber-600/20 hover:bg-amber-700",
342
342
  danger: "bg-rose-600 text-white shadow-lg shadow-rose-600/20 hover:bg-rose-700",
@@ -454,6 +454,765 @@ var SearchInput = forwardRef(function SearchInput2({ label, onClear, className,
454
454
  wrapper
455
455
  ] });
456
456
  });
457
+ var sizeClass4 = {
458
+ left: { sm: "w-64", md: "w-80", lg: "w-96", full: "w-screen" },
459
+ right: { sm: "w-64", md: "w-80", lg: "w-96", full: "w-screen" },
460
+ bottom: { sm: "h-1/4", md: "h-1/3", lg: "h-1/2", full: "h-screen" }
461
+ };
462
+ var positionClass = {
463
+ left: "inset-y-0 left-0",
464
+ right: "inset-y-0 right-0",
465
+ bottom: "inset-x-0 bottom-0"
466
+ };
467
+ var slideIn = {
468
+ left: "translate-x-0",
469
+ right: "translate-x-0",
470
+ bottom: "translate-y-0"
471
+ };
472
+ var slideOut = {
473
+ left: "-translate-x-full",
474
+ right: "translate-x-full",
475
+ bottom: "translate-y-full"
476
+ };
477
+ function Drawer({
478
+ isOpen,
479
+ onClose,
480
+ children,
481
+ side = "right",
482
+ size = "md",
483
+ ariaLabel,
484
+ closeOnBackdrop = true,
485
+ closeOnEsc = true,
486
+ className
487
+ }) {
488
+ const panelRef = useRef(null);
489
+ const lastActiveRef = useRef(null);
490
+ useEffect(() => {
491
+ if (!isOpen) return;
492
+ lastActiveRef.current = document.activeElement instanceof HTMLElement ? document.activeElement : null;
493
+ const raf = requestAnimationFrame(() => {
494
+ const el = panelRef.current;
495
+ if (!el) return;
496
+ const focusables = getFocusableElements(el);
497
+ focusSafely(focusables[0] ?? el);
498
+ });
499
+ return () => {
500
+ cancelAnimationFrame(raf);
501
+ const lastActive = lastActiveRef.current;
502
+ lastActiveRef.current = null;
503
+ if (lastActive?.isConnected) focusSafely(lastActive);
504
+ };
505
+ }, [isOpen]);
506
+ useScrollLock(isOpen);
507
+ if (!isOpen) return null;
508
+ return /* @__PURE__ */ jsxs("div", { className: "fixed inset-0 z-50", role: "presentation", children: [
509
+ /* @__PURE__ */ jsx(
510
+ "div",
511
+ {
512
+ className: "absolute inset-0 bg-black/40 backdrop-blur-sm transition-opacity duration-200",
513
+ "aria-hidden": "true",
514
+ onClick: closeOnBackdrop ? onClose : void 0
515
+ }
516
+ ),
517
+ /* @__PURE__ */ jsx(
518
+ "div",
519
+ {
520
+ ref: panelRef,
521
+ role: "dialog",
522
+ "aria-modal": "true",
523
+ "aria-label": ariaLabel,
524
+ tabIndex: -1,
525
+ className: cn(
526
+ "fixed flex flex-col bg-surface-50 shadow-2xl ring-1 ring-white/10 transition-transform duration-300 ease-out focus:outline-none",
527
+ positionClass[side],
528
+ sizeClass4[side][size],
529
+ isOpen ? slideIn[side] : slideOut[side],
530
+ className
531
+ ),
532
+ onKeyDownCapture: (e) => {
533
+ if (closeOnEsc && e.key === "Escape") {
534
+ e.preventDefault();
535
+ e.stopPropagation();
536
+ onClose();
537
+ return;
538
+ }
539
+ if (e.key !== "Tab") return;
540
+ const el = panelRef.current;
541
+ if (!el) return;
542
+ const focusables = getFocusableElements(el);
543
+ if (focusables.length === 0) {
544
+ e.preventDefault();
545
+ focusSafely(el);
546
+ return;
547
+ }
548
+ const active = document.activeElement;
549
+ const first = focusables[0];
550
+ const last = focusables[focusables.length - 1];
551
+ if (e.shiftKey) {
552
+ if (active === first) {
553
+ e.preventDefault();
554
+ focusSafely(last);
555
+ }
556
+ } else {
557
+ if (active === last) {
558
+ e.preventDefault();
559
+ focusSafely(first);
560
+ }
561
+ }
562
+ },
563
+ children
564
+ }
565
+ )
566
+ ] });
567
+ }
568
+ function Popover({
569
+ content,
570
+ children,
571
+ placement = "bottom",
572
+ closeOnClickOutside = true,
573
+ closeOnEsc = true,
574
+ open: controlledOpen,
575
+ onOpenChange,
576
+ offset = 8,
577
+ className
578
+ }) {
579
+ const popoverId = useId();
580
+ const anchorRef = useRef(null);
581
+ const popoverRef = useRef(null);
582
+ const [internalOpen, setInternalOpen] = useState(false);
583
+ const [pos, setPos] = useState(null);
584
+ const isControlled = controlledOpen !== void 0;
585
+ const isOpen = isControlled ? controlledOpen : internalOpen;
586
+ const setOpen = useCallback(
587
+ (value) => {
588
+ if (!isControlled) setInternalOpen(value);
589
+ onOpenChange?.(value);
590
+ },
591
+ [isControlled, onOpenChange]
592
+ );
593
+ const toggle = useCallback(() => setOpen(!isOpen), [isOpen, setOpen]);
594
+ const close = useCallback(() => setOpen(false), [setOpen]);
595
+ const updatePosition = useCallback(() => {
596
+ const el = anchorRef.current;
597
+ if (!el) return;
598
+ const r = el.getBoundingClientRect();
599
+ let left;
600
+ let top;
601
+ let effPlacement = placement;
602
+ if (placement === "bottom" || placement === "top") {
603
+ left = r.left + r.width / 2;
604
+ if (placement === "bottom") {
605
+ top = r.bottom + offset;
606
+ if (top + 200 > window.innerHeight && r.top - offset > 200) {
607
+ effPlacement = "top";
608
+ top = r.top - offset;
609
+ }
610
+ } else {
611
+ top = r.top - offset;
612
+ if (top < 8) {
613
+ effPlacement = "bottom";
614
+ top = r.bottom + offset;
615
+ }
616
+ }
617
+ } else {
618
+ top = r.top + r.height / 2;
619
+ if (placement === "right") {
620
+ left = r.right + offset;
621
+ } else {
622
+ left = r.left - offset;
623
+ }
624
+ }
625
+ setPos({ left: Math.round(left), top: Math.round(top), placement: effPlacement });
626
+ }, [placement, offset]);
627
+ useEffect(() => {
628
+ if (!isOpen) return;
629
+ updatePosition();
630
+ window.addEventListener("scroll", updatePosition, true);
631
+ window.addEventListener("resize", updatePosition);
632
+ return () => {
633
+ window.removeEventListener("scroll", updatePosition, true);
634
+ window.removeEventListener("resize", updatePosition);
635
+ };
636
+ }, [isOpen, updatePosition]);
637
+ useEffect(() => {
638
+ if (!isOpen || !closeOnClickOutside) return;
639
+ const handleClick = (e) => {
640
+ const target = e.target;
641
+ if (anchorRef.current?.contains(target) || popoverRef.current?.contains(target)) {
642
+ return;
643
+ }
644
+ close();
645
+ };
646
+ document.addEventListener("mousedown", handleClick);
647
+ return () => document.removeEventListener("mousedown", handleClick);
648
+ }, [isOpen, closeOnClickOutside, close]);
649
+ useEffect(() => {
650
+ if (!isOpen || !closeOnEsc) return;
651
+ const handleKey = (e) => {
652
+ if (e.key === "Escape") {
653
+ e.preventDefault();
654
+ close();
655
+ anchorRef.current?.focus();
656
+ }
657
+ };
658
+ document.addEventListener("keydown", handleKey);
659
+ return () => document.removeEventListener("keydown", handleKey);
660
+ }, [isOpen, closeOnEsc, close]);
661
+ if (!isValidElement(children)) return children;
662
+ const child = cloneElement(children, {
663
+ ref: (node) => {
664
+ anchorRef.current = node;
665
+ const childProps = children.props;
666
+ const prevRef = childProps.ref;
667
+ if (typeof prevRef === "function") prevRef(node);
668
+ else if (prevRef && typeof prevRef === "object") prevRef.current = node;
669
+ },
670
+ onClick: (e) => {
671
+ const childProps = children.props;
672
+ if (typeof childProps.onClick === "function") childProps.onClick(e);
673
+ toggle();
674
+ },
675
+ "aria-expanded": isOpen,
676
+ "aria-haspopup": "dialog",
677
+ "aria-controls": isOpen ? popoverId : void 0
678
+ });
679
+ const getTransform = () => {
680
+ if (!pos) return "translate(-9999px, -9999px)";
681
+ switch (pos.placement) {
682
+ case "top":
683
+ return "translate(-50%, -100%)";
684
+ case "bottom":
685
+ return "translate(-50%, 0%)";
686
+ case "left":
687
+ return "translate(-100%, -50%)";
688
+ case "right":
689
+ return "translate(0%, -50%)";
690
+ }
691
+ };
692
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
693
+ child,
694
+ isOpen && typeof document !== "undefined" ? createPortal(
695
+ /* @__PURE__ */ jsx(
696
+ "div",
697
+ {
698
+ ref: popoverRef,
699
+ id: popoverId,
700
+ role: "dialog",
701
+ className: cn(
702
+ "fixed z-[9999] rounded-xl shadow-xl ring-1 ring-white/10 bg-surface-50 backdrop-blur-md p-4",
703
+ className
704
+ ),
705
+ style: {
706
+ left: pos?.left ?? 0,
707
+ top: pos?.top ?? 0,
708
+ transform: getTransform()
709
+ },
710
+ children: content
711
+ }
712
+ ),
713
+ document.body
714
+ ) : null
715
+ ] });
716
+ }
717
+ var DAY_NAMES = ["Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"];
718
+ var DAY_IN_MS = 24 * 60 * 60 * 1e3;
719
+ function startOfDay(date) {
720
+ return new Date(date.getFullYear(), date.getMonth(), date.getDate());
721
+ }
722
+ function startOfMonth(date) {
723
+ return new Date(date.getFullYear(), date.getMonth(), 1);
724
+ }
725
+ function addDays(date, amount) {
726
+ return new Date(date.getFullYear(), date.getMonth(), date.getDate() + amount);
727
+ }
728
+ function addMonths(date, amount) {
729
+ return new Date(date.getFullYear(), date.getMonth() + amount, 1);
730
+ }
731
+ function getCalendarStart(date) {
732
+ const monthStart = startOfMonth(date);
733
+ const day = monthStart.getDay();
734
+ const diff = day === 0 ? 6 : day - 1;
735
+ return addDays(monthStart, -diff);
736
+ }
737
+ function isSameDay(a, b) {
738
+ if (!a || !b) return false;
739
+ return startOfDay(a).getTime() === startOfDay(b).getTime();
740
+ }
741
+ function isBetween(day, from, to) {
742
+ if (!from || !to) return false;
743
+ const current = startOfDay(day).getTime();
744
+ return current > startOfDay(from).getTime() && current < startOfDay(to).getTime();
745
+ }
746
+ function diffInDays(from, to) {
747
+ return Math.round((startOfDay(to).getTime() - startOfDay(from).getTime()) / DAY_IN_MS);
748
+ }
749
+ function pad(value) {
750
+ return String(value).padStart(2, "0");
751
+ }
752
+ function formatDate(date, pattern) {
753
+ return pattern.replace("dd", pad(date.getDate())).replace("MM", pad(date.getMonth() + 1)).replace("yyyy", String(date.getFullYear()));
754
+ }
755
+ function formatMonthLabel(date) {
756
+ return new Intl.DateTimeFormat(void 0, { month: "long", year: "numeric" }).format(date);
757
+ }
758
+ function formatFullDate(date) {
759
+ return new Intl.DateTimeFormat(void 0, {
760
+ year: "numeric",
761
+ month: "long",
762
+ day: "numeric"
763
+ }).format(date);
764
+ }
765
+ function parseDateInput(value) {
766
+ const trimmed = value.trim();
767
+ if (!trimmed) return null;
768
+ if (/^\d{4}-\d{2}-\d{2}$/.test(trimmed)) {
769
+ const [year2, month2, day2] = trimmed.split("-").map(Number);
770
+ const parsed2 = new Date(year2, month2 - 1, day2);
771
+ if (parsed2.getFullYear() === year2 && parsed2.getMonth() === month2 - 1 && parsed2.getDate() === day2) {
772
+ return startOfDay(parsed2);
773
+ }
774
+ return null;
775
+ }
776
+ const match = trimmed.match(/^(\d{1,2})[./-](\d{1,2})[./-](\d{4})$/);
777
+ if (!match) return null;
778
+ const day = Number(match[1]);
779
+ const month = Number(match[2]);
780
+ const year = Number(match[3]);
781
+ const parsed = new Date(year, month - 1, day);
782
+ if (parsed.getFullYear() !== year || parsed.getMonth() !== month - 1 || parsed.getDate() !== day) {
783
+ return null;
784
+ }
785
+ return startOfDay(parsed);
786
+ }
787
+ function getPlaceholder(placeholder, key, fallback) {
788
+ if (typeof placeholder === "string") {
789
+ return key === "trigger" ? placeholder : fallback;
790
+ }
791
+ return placeholder?.[key] ?? fallback;
792
+ }
793
+ function buildCalendarDays(month) {
794
+ const start = getCalendarStart(month);
795
+ return Array.from({ length: 42 }, (_, index) => addDays(start, index));
796
+ }
797
+ function getRangeSummary(range, formatPattern) {
798
+ if (range.from && range.to) {
799
+ return `${formatDate(range.from, formatPattern)} - ${formatDate(range.to, formatPattern)}`;
800
+ }
801
+ if (range.from) {
802
+ return `${formatDate(range.from, formatPattern)} - ...`;
803
+ }
804
+ return "No date range selected";
805
+ }
806
+ function normalizeRange(range) {
807
+ return {
808
+ from: range.from ? startOfDay(range.from) : null,
809
+ to: range.to ? startOfDay(range.to) : null
810
+ };
811
+ }
812
+ function clampRange(range, min, max, maxRangeDays) {
813
+ let nextFrom = range.from ? startOfDay(range.from) : null;
814
+ let nextTo = range.to ? startOfDay(range.to) : null;
815
+ if (min) {
816
+ const minDay = startOfDay(min);
817
+ if (nextFrom && nextFrom < minDay) nextFrom = minDay;
818
+ if (nextTo && nextTo < minDay) nextTo = minDay;
819
+ }
820
+ if (max) {
821
+ const maxDay = startOfDay(max);
822
+ if (nextFrom && nextFrom > maxDay) nextFrom = maxDay;
823
+ if (nextTo && nextTo > maxDay) nextTo = maxDay;
824
+ }
825
+ if (nextFrom && nextTo && nextFrom > nextTo) {
826
+ const swap = nextFrom;
827
+ nextFrom = nextTo;
828
+ nextTo = swap;
829
+ }
830
+ if (nextFrom && nextTo && maxRangeDays && diffInDays(nextFrom, nextTo) + 1 > maxRangeDays) {
831
+ nextTo = addDays(nextFrom, maxRangeDays - 1);
832
+ }
833
+ return { from: nextFrom, to: nextTo };
834
+ }
835
+ function isDateDisabled(day, range, min, max, maxRangeDays) {
836
+ const normalized = startOfDay(day);
837
+ const minDay = min ? startOfDay(min) : null;
838
+ const maxDay = max ? startOfDay(max) : null;
839
+ if (minDay && normalized < minDay) return true;
840
+ if (maxDay && normalized > maxDay) return true;
841
+ if (range.from && !range.to && maxRangeDays) {
842
+ return Math.abs(diffInDays(range.from, normalized)) + 1 > maxRangeDays;
843
+ }
844
+ return false;
845
+ }
846
+ function CalendarIcon() {
847
+ return /* @__PURE__ */ jsxs(
848
+ "svg",
849
+ {
850
+ "aria-hidden": "true",
851
+ className: "h-4 w-4",
852
+ viewBox: "0 0 20 20",
853
+ fill: "none",
854
+ xmlns: "http://www.w3.org/2000/svg",
855
+ children: [
856
+ /* @__PURE__ */ jsx("rect", { x: "3", y: "4", width: "14", height: "13", rx: "2.5", stroke: "currentColor", strokeWidth: "1.5" }),
857
+ /* @__PURE__ */ jsx("path", { d: "M6.5 2.75V5.5M13.5 2.75V5.5M3 8h14", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" })
858
+ ]
859
+ }
860
+ );
861
+ }
862
+ function ChevronIcon({ className }) {
863
+ return /* @__PURE__ */ jsx(
864
+ "svg",
865
+ {
866
+ "aria-hidden": "true",
867
+ className: cn("h-4 w-4", className),
868
+ viewBox: "0 0 20 20",
869
+ fill: "none",
870
+ xmlns: "http://www.w3.org/2000/svg",
871
+ children: /* @__PURE__ */ jsx("path", { d: "M6 8l4 4 4-4", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round", strokeLinejoin: "round" })
872
+ }
873
+ );
874
+ }
875
+ function CalendarMonth({
876
+ month,
877
+ viewMonth,
878
+ range,
879
+ formatPattern,
880
+ min,
881
+ max,
882
+ maxRangeDays,
883
+ onPrevMonth,
884
+ onNextMonth,
885
+ onSelectDay
886
+ }) {
887
+ const days = useMemo(() => buildCalendarDays(month), [month]);
888
+ return /* @__PURE__ */ jsxs("div", { className: "rounded-2xl border border-white/10 bg-white/[0.03] p-3", children: [
889
+ /* @__PURE__ */ jsxs("div", { className: "mb-3 flex items-center justify-between gap-2", children: [
890
+ /* @__PURE__ */ jsx(
891
+ "button",
892
+ {
893
+ type: "button",
894
+ onClick: onPrevMonth,
895
+ disabled: !onPrevMonth,
896
+ "aria-label": "Previous month",
897
+ className: cn(
898
+ "inline-flex h-8 w-8 items-center justify-center rounded-lg text-white/70 transition-colors",
899
+ onPrevMonth ? "hover:bg-white/10 hover:text-white" : "pointer-events-none opacity-0"
900
+ ),
901
+ children: /* @__PURE__ */ jsx("svg", { "aria-hidden": "true", className: "h-4 w-4", viewBox: "0 0 20 20", fill: "none", children: /* @__PURE__ */ jsx("path", { d: "M12 5l-5 5 5 5", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round", strokeLinejoin: "round" }) })
902
+ }
903
+ ),
904
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-medium capitalize text-white", children: formatMonthLabel(month) }),
905
+ /* @__PURE__ */ jsx(
906
+ "button",
907
+ {
908
+ type: "button",
909
+ onClick: onNextMonth,
910
+ disabled: !onNextMonth,
911
+ "aria-label": "Next month",
912
+ className: cn(
913
+ "inline-flex h-8 w-8 items-center justify-center rounded-lg text-white/70 transition-colors",
914
+ onNextMonth ? "hover:bg-white/10 hover:text-white" : "pointer-events-none opacity-0"
915
+ ),
916
+ children: /* @__PURE__ */ jsx("svg", { "aria-hidden": "true", className: "h-4 w-4", viewBox: "0 0 20 20", fill: "none", children: /* @__PURE__ */ jsx("path", { d: "M8 5l5 5-5 5", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round", strokeLinejoin: "round" }) })
917
+ }
918
+ )
919
+ ] }),
920
+ /* @__PURE__ */ jsx("div", { className: "mb-2 grid grid-cols-7 gap-1 text-center text-[11px] font-medium uppercase tracking-[0.14em] text-white/35", children: DAY_NAMES.map((day) => /* @__PURE__ */ jsx("span", { children: day }, day)) }),
921
+ /* @__PURE__ */ jsx("div", { className: "grid grid-cols-7 gap-1", children: days.map((day) => {
922
+ const inMonth = day.getMonth() === month.getMonth();
923
+ const disabled = isDateDisabled(day, range, min, max, maxRangeDays);
924
+ const selectedStart = isSameDay(day, range.from);
925
+ const selectedEnd = isSameDay(day, range.to);
926
+ const inRange = isBetween(day, range.from, range.to);
927
+ const isToday = isSameDay(day, /* @__PURE__ */ new Date());
928
+ const roundedClass = selectedStart && selectedEnd ? "rounded-xl" : selectedStart ? "rounded-l-xl rounded-r-md" : selectedEnd ? "rounded-r-xl rounded-l-md" : inRange ? "rounded-md" : "rounded-xl";
929
+ return /* @__PURE__ */ jsxs(
930
+ "button",
931
+ {
932
+ type: "button",
933
+ disabled,
934
+ onClick: () => onSelectDay(day),
935
+ "aria-label": formatFullDate(day),
936
+ "aria-pressed": selectedStart || selectedEnd || inRange,
937
+ className: cn(
938
+ "relative h-9 w-full text-sm tabular-nums transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/40",
939
+ roundedClass,
940
+ !inMonth && "text-white/25",
941
+ inMonth && !selectedStart && !selectedEnd && !inRange && "text-white/75",
942
+ (selectedStart || selectedEnd) && "bg-primary text-white shadow-glow",
943
+ inRange && !selectedStart && !selectedEnd && "bg-primary/15 text-white",
944
+ !selectedStart && !selectedEnd && !inRange && !disabled && "hover:bg-white/10 hover:text-white",
945
+ disabled && "cursor-not-allowed opacity-35"
946
+ ),
947
+ children: [
948
+ /* @__PURE__ */ jsx("span", { children: formatDate(day, "dd") }),
949
+ isToday && !selectedStart && !selectedEnd && !inRange ? /* @__PURE__ */ jsx("span", { className: "pointer-events-none absolute inset-x-2 bottom-1 h-0.5 rounded-full bg-primary/70" }) : null,
950
+ isSameDay(day, viewMonth) ? null : null
951
+ ]
952
+ },
953
+ day.toISOString()
954
+ );
955
+ }) }),
956
+ range.from || range.to ? /* @__PURE__ */ jsx("p", { className: "mt-3 text-xs text-white/45", children: getRangeSummary(range, formatPattern) }) : null
957
+ ] });
958
+ }
959
+ function DateRangePicker({
960
+ value,
961
+ onChange,
962
+ presets,
963
+ format = "dd.MM.yyyy",
964
+ placeholder,
965
+ min,
966
+ max,
967
+ maxRangeDays,
968
+ label,
969
+ helperText,
970
+ clearable = true,
971
+ disabled,
972
+ hasError,
973
+ error,
974
+ closeOnSelect = false,
975
+ compact = false,
976
+ className
977
+ }) {
978
+ const isMobile = useMediaQuery("(max-width: 767px)");
979
+ const [open, setOpen] = useState(false);
980
+ const normalizedValue = useMemo(() => normalizeRange(value), [value]);
981
+ const [viewMonth, setViewMonth] = useState(() => startOfMonth(normalizedValue.from ?? normalizedValue.to ?? /* @__PURE__ */ new Date()));
982
+ const [fromInput, setFromInput] = useState("");
983
+ const [toInput, setToInput] = useState("");
984
+ const showError = hasError || Boolean(error);
985
+ const hasValue = normalizedValue.from !== null || normalizedValue.to !== null;
986
+ const triggerPlaceholder = getPlaceholder(placeholder, "trigger", compact ? "Any date" : "Select date range");
987
+ const fromPlaceholder = getPlaceholder(placeholder, "from", "dd.mm.yyyy");
988
+ const toPlaceholder = getPlaceholder(placeholder, "to", "dd.mm.yyyy");
989
+ const monthsToRender = isMobile ? [viewMonth] : [viewMonth, addMonths(viewMonth, 1)];
990
+ useEffect(() => {
991
+ setFromInput(normalizedValue.from ? formatDate(normalizedValue.from, format) : "");
992
+ setToInput(normalizedValue.to ? formatDate(normalizedValue.to, format) : "");
993
+ }, [normalizedValue.from, normalizedValue.to, format]);
994
+ useEffect(() => {
995
+ if (!open) {
996
+ setViewMonth(startOfMonth(normalizedValue.from ?? normalizedValue.to ?? /* @__PURE__ */ new Date()));
997
+ }
998
+ }, [normalizedValue.from, normalizedValue.to, open]);
999
+ const selectedText = useMemo(() => {
1000
+ if (normalizedValue.from && normalizedValue.to) {
1001
+ return `${formatDate(normalizedValue.from, format)} - ${formatDate(normalizedValue.to, format)}`;
1002
+ }
1003
+ if (normalizedValue.from) {
1004
+ return `${formatDate(normalizedValue.from, format)} - ...`;
1005
+ }
1006
+ return triggerPlaceholder;
1007
+ }, [format, normalizedValue.from, normalizedValue.to, triggerPlaceholder]);
1008
+ const handleRangeChange = (nextRange) => {
1009
+ onChange(clampRange(nextRange, min, max, maxRangeDays));
1010
+ };
1011
+ const handleSelectDay = (day) => {
1012
+ if (isDateDisabled(day, normalizedValue, min, max, maxRangeDays)) {
1013
+ return;
1014
+ }
1015
+ const normalizedDay = startOfDay(day);
1016
+ if (!normalizedValue.from || normalizedValue.to) {
1017
+ handleRangeChange({ from: normalizedDay, to: null });
1018
+ return;
1019
+ }
1020
+ const nextRange = normalizedDay < normalizedValue.from ? { from: normalizedDay, to: normalizedValue.from } : { from: normalizedValue.from, to: normalizedDay };
1021
+ handleRangeChange(nextRange);
1022
+ if (closeOnSelect) {
1023
+ setOpen(false);
1024
+ }
1025
+ };
1026
+ const commitInput = (kind, rawValue) => {
1027
+ const parsed = parseDateInput(rawValue);
1028
+ if (!rawValue.trim()) {
1029
+ handleRangeChange({
1030
+ from: kind === "from" ? null : normalizedValue.from,
1031
+ to: kind === "to" ? null : normalizedValue.to
1032
+ });
1033
+ return;
1034
+ }
1035
+ if (!parsed || isDateDisabled(parsed, normalizedValue, min, max, maxRangeDays)) {
1036
+ return;
1037
+ }
1038
+ if (kind === "from") {
1039
+ handleRangeChange({ from: parsed, to: normalizedValue.to });
1040
+ setViewMonth(startOfMonth(parsed));
1041
+ return;
1042
+ }
1043
+ handleRangeChange({ from: normalizedValue.from, to: parsed });
1044
+ setViewMonth(startOfMonth(parsed));
1045
+ };
1046
+ const handleClear = () => {
1047
+ handleRangeChange({ from: null, to: null });
1048
+ setOpen(false);
1049
+ };
1050
+ const panel = /* @__PURE__ */ jsxs("div", { className: cn("space-y-4 p-4", isMobile ? "h-full overflow-y-auto" : "w-[min(42rem,calc(100vw-1.5rem))] max-w-[calc(100vw-1.5rem)]"), children: [
1051
+ /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-3", children: [
1052
+ /* @__PURE__ */ jsxs("div", { children: [
1053
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-semibold text-white", children: "Date range" }),
1054
+ /* @__PURE__ */ jsx("p", { className: "mt-1 text-xs text-white/50", children: "Pick a start and end date or use a preset." })
1055
+ ] }),
1056
+ !isMobile ? /* @__PURE__ */ jsx(Button, { size: "sm", variant: "ghost", onClick: () => setOpen(false), children: "Done" }) : null
1057
+ ] }),
1058
+ presets && presets.length > 0 ? /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-2", children: presets.map((preset) => {
1059
+ const presetRange = clampRange(preset.range, min, max, maxRangeDays);
1060
+ const active = isSameDay(presetRange.from, normalizedValue.from) && isSameDay(presetRange.to, normalizedValue.to);
1061
+ return /* @__PURE__ */ jsx(
1062
+ "button",
1063
+ {
1064
+ type: "button",
1065
+ onClick: () => {
1066
+ handleRangeChange(presetRange);
1067
+ if (closeOnSelect) {
1068
+ setOpen(false);
1069
+ }
1070
+ },
1071
+ className: cn(
1072
+ "rounded-xl border px-3 py-1.5 text-xs font-medium transition-colors",
1073
+ active ? "border-primary/60 bg-primary/15 text-white" : "border-white/10 bg-white/[0.03] text-white/70 hover:bg-white/10 hover:text-white"
1074
+ ),
1075
+ children: preset.label
1076
+ },
1077
+ preset.label
1078
+ );
1079
+ }) }) : null,
1080
+ /* @__PURE__ */ jsxs("div", { className: "grid gap-3 sm:grid-cols-2", children: [
1081
+ /* @__PURE__ */ jsx(
1082
+ Input,
1083
+ {
1084
+ label: "From",
1085
+ value: fromInput,
1086
+ placeholder: fromPlaceholder,
1087
+ onChange: (event) => setFromInput(event.target.value),
1088
+ onBlur: (event) => commitInput("from", event.target.value),
1089
+ onKeyDown: (event) => {
1090
+ if (event.key === "Enter") {
1091
+ event.preventDefault();
1092
+ commitInput("from", fromInput);
1093
+ }
1094
+ }
1095
+ }
1096
+ ),
1097
+ /* @__PURE__ */ jsx(
1098
+ Input,
1099
+ {
1100
+ label: "To",
1101
+ value: toInput,
1102
+ placeholder: toPlaceholder,
1103
+ onChange: (event) => setToInput(event.target.value),
1104
+ onBlur: (event) => commitInput("to", event.target.value),
1105
+ onKeyDown: (event) => {
1106
+ if (event.key === "Enter") {
1107
+ event.preventDefault();
1108
+ commitInput("to", toInput);
1109
+ }
1110
+ }
1111
+ }
1112
+ )
1113
+ ] }),
1114
+ /* @__PURE__ */ jsx("div", { className: cn("grid gap-4", isMobile ? "grid-cols-1" : "md:grid-cols-2"), children: monthsToRender.map((month, index) => /* @__PURE__ */ jsx(
1115
+ CalendarMonth,
1116
+ {
1117
+ month,
1118
+ viewMonth,
1119
+ range: normalizedValue,
1120
+ formatPattern: format,
1121
+ min,
1122
+ max,
1123
+ maxRangeDays,
1124
+ onPrevMonth: index === 0 ? () => setViewMonth((prev) => addMonths(prev, -1)) : void 0,
1125
+ onNextMonth: index === monthsToRender.length - 1 ? () => setViewMonth((prev) => addMonths(prev, 1)) : void 0,
1126
+ onSelectDay: handleSelectDay
1127
+ },
1128
+ month.toISOString()
1129
+ )) }),
1130
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3 border-t border-white/10 pt-3", children: [
1131
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-white/45", children: getRangeSummary(normalizedValue, format) }),
1132
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
1133
+ clearable ? /* @__PURE__ */ jsx(Button, { size: "sm", variant: "ghost", onClick: handleClear, children: "Clear" }) : null,
1134
+ isMobile ? /* @__PURE__ */ jsx(Button, { size: "sm", variant: "secondary", onClick: () => setOpen(false), children: "Done" }) : null
1135
+ ] })
1136
+ ] })
1137
+ ] });
1138
+ const triggerButton = /* @__PURE__ */ jsxs(
1139
+ "button",
1140
+ {
1141
+ type: "button",
1142
+ disabled,
1143
+ onClick: () => {
1144
+ if (isMobile) {
1145
+ setOpen(true);
1146
+ }
1147
+ },
1148
+ "aria-label": `Date range: ${selectedText}`,
1149
+ className: cn(
1150
+ "flex w-full items-center justify-between gap-3 rounded-xl bg-white/10 text-left text-white shadow-sm outline-none transition-shadow focus-visible:ring-2 focus-visible:ring-primary/40",
1151
+ compact ? "min-h-10 px-3 py-2 text-sm" : "min-h-11 px-3 py-2.5 text-sm",
1152
+ hasValue && clearable && "pr-16",
1153
+ showError && "ring-2 ring-rose-500/40 focus-visible:ring-rose-500/40",
1154
+ disabled && "cursor-not-allowed opacity-60",
1155
+ className
1156
+ ),
1157
+ children: [
1158
+ /* @__PURE__ */ jsxs("span", { className: "flex min-w-0 items-center gap-2", children: [
1159
+ /* @__PURE__ */ jsx("span", { className: cn(hasValue ? "text-primary" : "text-white/40"), children: /* @__PURE__ */ jsx(CalendarIcon, {}) }),
1160
+ /* @__PURE__ */ jsx("span", { className: cn("truncate", hasValue ? "text-white" : "text-white/40"), children: selectedText })
1161
+ ] }),
1162
+ /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-2 text-white/45", children: [
1163
+ normalizedValue.from && normalizedValue.to ? /* @__PURE__ */ jsxs("span", { className: "hidden rounded-full bg-white/10 px-2 py-0.5 text-[11px] text-white/60 sm:inline-flex", children: [
1164
+ diffInDays(normalizedValue.from, normalizedValue.to) + 1,
1165
+ "d"
1166
+ ] }) : null,
1167
+ /* @__PURE__ */ jsx(ChevronIcon, { className: cn(open && "rotate-180 transition-transform") })
1168
+ ] })
1169
+ ]
1170
+ }
1171
+ );
1172
+ return /* @__PURE__ */ jsxs("div", { children: [
1173
+ label ? /* @__PURE__ */ jsx("label", { className: "mb-1.5 block text-sm text-white/70", children: label }) : null,
1174
+ /* @__PURE__ */ jsxs("div", { className: "relative", children: [
1175
+ isMobile ? triggerButton : /* @__PURE__ */ jsx(
1176
+ Popover,
1177
+ {
1178
+ open,
1179
+ onOpenChange: setOpen,
1180
+ placement: "bottom",
1181
+ className: "overflow-hidden p-0",
1182
+ content: panel,
1183
+ children: triggerButton
1184
+ }
1185
+ ),
1186
+ clearable && hasValue ? /* @__PURE__ */ jsx(
1187
+ "button",
1188
+ {
1189
+ type: "button",
1190
+ onClick: (event) => {
1191
+ event.stopPropagation();
1192
+ handleClear();
1193
+ },
1194
+ "aria-label": "Clear date range",
1195
+ className: "absolute right-10 top-1/2 -translate-y-1/2 rounded-md p-1 text-white/35 transition-colors hover:bg-white/10 hover:text-white",
1196
+ children: /* @__PURE__ */ jsx("svg", { "aria-hidden": "true", className: "h-3.5 w-3.5", viewBox: "0 0 16 16", fill: "none", children: /* @__PURE__ */ jsx("path", { d: "M4 4l8 8M12 4l-8 8", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }) })
1197
+ }
1198
+ ) : null
1199
+ ] }),
1200
+ error ? /* @__PURE__ */ jsx("p", { className: "mt-1 text-xs text-rose-400", children: error }) : null,
1201
+ helperText && !error ? /* @__PURE__ */ jsx("p", { className: "mt-1 text-xs text-white/40", children: helperText }) : null,
1202
+ isMobile ? /* @__PURE__ */ jsx(
1203
+ Drawer,
1204
+ {
1205
+ isOpen: open,
1206
+ onClose: () => setOpen(false),
1207
+ side: "bottom",
1208
+ size: "full",
1209
+ ariaLabel: "Date range picker",
1210
+ className: "rounded-t-3xl",
1211
+ children: panel
1212
+ }
1213
+ ) : null
1214
+ ] });
1215
+ }
457
1216
  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";
458
1217
  var Select = forwardRef(function Select2({ hasError, label, error, helperText, className, id: externalId, children, ...props }, ref) {
459
1218
  const generatedId = useId();
@@ -631,7 +1390,7 @@ var TagInput = forwardRef(
631
1390
  }
632
1391
  );
633
1392
  var base3 = "inline-flex items-center justify-center rounded-full font-semibold ring-1 ring-white/10";
634
- var sizeClass4 = {
1393
+ var sizeClass5 = {
635
1394
  sm: "text-xs px-2.5 py-1",
636
1395
  md: "text-sm px-3 py-1.5"
637
1396
  };
@@ -646,7 +1405,7 @@ var variantClass3 = {
646
1405
  accent: "bg-accent/15 text-accent-light ring-accent/20"
647
1406
  };
648
1407
  var Badge = forwardRef(function Badge2({ children, variant = "neutral", size = "sm", className, ...props }, ref) {
649
- return /* @__PURE__ */ jsx("span", { ref, ...props, className: cn(base3, sizeClass4[size], variantClass3[variant], className), children });
1408
+ return /* @__PURE__ */ jsx("span", { ref, ...props, className: cn(base3, sizeClass5[size], variantClass3[variant], className), children });
650
1409
  });
651
1410
  var Pill = Badge;
652
1411
  var trackSize = {
@@ -1096,7 +1855,7 @@ function RadioItem({ value, disabled: itemDisabled, children, className }) {
1096
1855
  }
1097
1856
  );
1098
1857
  }
1099
- var sizeClass5 = {
1858
+ var sizeClass6 = {
1100
1859
  sm: "h-3 w-3 border",
1101
1860
  md: "h-4 w-4 border-2",
1102
1861
  lg: "h-6 w-6 border-2"
@@ -1105,7 +1864,7 @@ function Spinner({ className, size = "md", label }) {
1105
1864
  return /* @__PURE__ */ jsx(
1106
1865
  "span",
1107
1866
  {
1108
- className: cn("inline-block rounded-full border-white/15 border-t-primary animate-spin", sizeClass5[size], className),
1867
+ className: cn("inline-block rounded-full border-white/15 border-t-primary animate-spin", sizeClass6[size], className),
1109
1868
  role: label ? "status" : void 0,
1110
1869
  "aria-hidden": label ? void 0 : "true",
1111
1870
  "aria-label": label || void 0
@@ -1280,6 +2039,7 @@ var Card = forwardRef(function Card2({ hoverable, variant = "surface", padding =
1280
2039
  }
1281
2040
  );
1282
2041
  });
2042
+ var EXIT_DURATION = 200;
1283
2043
  function Modal({
1284
2044
  isOpen,
1285
2045
  onClose,
@@ -1295,6 +2055,23 @@ function Modal({
1295
2055
  }) {
1296
2056
  const dialogRef = useRef(null);
1297
2057
  const lastActiveElementRef = useRef(null);
2058
+ const [mounted, setMounted] = useState(false);
2059
+ const [closing, setClosing] = useState(false);
2060
+ const closingTimerRef = useRef();
2061
+ useEffect(() => {
2062
+ if (isOpen) {
2063
+ setClosing(false);
2064
+ setMounted(true);
2065
+ clearTimeout(closingTimerRef.current);
2066
+ } else if (mounted) {
2067
+ setClosing(true);
2068
+ closingTimerRef.current = setTimeout(() => {
2069
+ setMounted(false);
2070
+ setClosing(false);
2071
+ }, EXIT_DURATION);
2072
+ }
2073
+ return () => clearTimeout(closingTimerRef.current);
2074
+ }, [isOpen]);
1298
2075
  useEffect(() => {
1299
2076
  if (!isOpen) return;
1300
2077
  lastActiveElementRef.current = document.activeElement instanceof HTMLElement ? document.activeElement : null;
@@ -1311,20 +2088,28 @@ function Modal({
1311
2088
  if (lastActive?.isConnected) focusSafely(lastActive);
1312
2089
  };
1313
2090
  }, [isOpen]);
1314
- useScrollLock(isOpen);
1315
- if (!isOpen) return null;
2091
+ useScrollLock(mounted);
2092
+ const handleClose = useCallback(() => {
2093
+ if (closing) return;
2094
+ onClose();
2095
+ }, [closing, onClose]);
2096
+ if (!mounted) return null;
1316
2097
  return /* @__PURE__ */ jsx(
1317
2098
  "div",
1318
2099
  {
2100
+ "data-closing": closing || void 0,
1319
2101
  className: cn(
1320
- "fixed inset-0 flex items-end sm:items-center justify-center p-4 pb-safe bg-black/25 backdrop-blur-sm animate-modal-backdrop",
2102
+ "fixed inset-0 flex items-end sm:items-center justify-center p-4 pb-safe bg-black/25 backdrop-blur-sm",
1321
2103
  zIndexClassName,
1322
2104
  overlayClassName
1323
2105
  ),
2106
+ style: {
2107
+ animation: closing ? `ml-modal-backdrop-out ${EXIT_DURATION}ms ease forwards` : "ml-modal-backdrop 200ms ease forwards"
2108
+ },
1324
2109
  role: "presentation",
1325
2110
  onMouseDown: (e) => {
1326
2111
  if (!closeOnBackdrop) return;
1327
- if (e.target === e.currentTarget) onClose();
2112
+ if (e.target === e.currentTarget) handleClose();
1328
2113
  },
1329
2114
  children: /* @__PURE__ */ jsx(
1330
2115
  "div",
@@ -1336,16 +2121,19 @@ function Modal({
1336
2121
  tabIndex: -1,
1337
2122
  ref: dialogRef,
1338
2123
  className: cn(
1339
- "w-full rounded-t-3xl sm:rounded-2xl shadow-xl ring-1 ring-white/10 animate-modal-pop focus:outline-none focus-visible:ring-2 focus-visible:ring-primary",
2124
+ "w-full rounded-t-3xl sm:rounded-2xl shadow-xl ring-1 ring-white/10 focus:outline-none focus-visible:ring-2 focus-visible:ring-primary",
1340
2125
  useGlass && "glass bg-surface-50/80",
1341
2126
  contentClassName
1342
2127
  ),
2128
+ style: {
2129
+ animation: closing ? `ml-modal-pop-out ${EXIT_DURATION}ms ease forwards` : "ml-modal-pop 200ms ease forwards"
2130
+ },
1343
2131
  onMouseDown: (e) => e.stopPropagation(),
1344
2132
  onKeyDownCapture: (e) => {
1345
2133
  if (closeOnEsc && e.key === "Escape") {
1346
2134
  e.preventDefault();
1347
2135
  e.stopPropagation();
1348
- onClose();
2136
+ handleClose();
1349
2137
  return;
1350
2138
  }
1351
2139
  if (e.key !== "Tab") return;
@@ -2025,93 +2813,203 @@ function Divider({ orientation = "horizontal", label, className }) {
2025
2813
  }
2026
2814
  );
2027
2815
  }
2028
- 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 }) }));
2029
- Table.displayName = "Table";
2030
- var TableHeader = forwardRef(
2031
- ({ children, className }, ref) => /* @__PURE__ */ jsx("thead", { ref, className: cn("bg-white/5 border-b border-white/10", className), children })
2032
- );
2033
- TableHeader.displayName = "TableHeader";
2034
- var TableBody = forwardRef(
2035
- ({ children, className }, ref) => /* @__PURE__ */ jsx("tbody", { ref, className: cn("divide-y divide-white/[0.06]", className), children })
2036
- );
2037
- TableBody.displayName = "TableBody";
2038
- var TableRow = forwardRef(
2039
- ({ children, className, hoverable }, ref) => /* @__PURE__ */ jsx(
2040
- "tr",
2041
- {
2042
- ref,
2043
- className: cn(hoverable && "hover:bg-white/[0.03] transition-colors", className),
2044
- children
2045
- }
2046
- )
2047
- );
2048
- TableRow.displayName = "TableRow";
2049
- var TableHead = forwardRef(
2050
- ({ children, className }, ref) => /* @__PURE__ */ jsx(
2051
- "th",
2816
+ var Table = forwardRef(function Table2({ children, className, ...props }, ref) {
2817
+ return /* @__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), ...props, children }) });
2818
+ });
2819
+ var TableHeader = forwardRef(function TableHeader2({ children, className, ...props }, ref) {
2820
+ return /* @__PURE__ */ jsx("thead", { ref, className: cn("bg-white/5 border-b border-white/10", className), ...props, children });
2821
+ });
2822
+ var TableBody = forwardRef(function TableBody2({ children, className, ...props }, ref) {
2823
+ return /* @__PURE__ */ jsx("tbody", { ref, className: cn("divide-y divide-white/[0.06]", className), ...props, children });
2824
+ });
2825
+ var TableRow = forwardRef(function TableRow2({ children, className, hoverable, ...props }, ref) {
2826
+ return /* @__PURE__ */ jsx(
2827
+ "tr",
2828
+ {
2829
+ ref,
2830
+ className: cn(hoverable && "hover:bg-white/[0.03] transition-colors", className),
2831
+ ...props,
2832
+ children
2833
+ }
2834
+ );
2835
+ });
2836
+ var TableHead = forwardRef(function TableHead2({ children, className, ...props }, ref) {
2837
+ return /* @__PURE__ */ jsx(
2838
+ "th",
2839
+ {
2840
+ ref,
2841
+ className: cn(
2842
+ "px-4 py-3 text-left text-xs font-semibold text-white/50 uppercase tracking-wider",
2843
+ className
2844
+ ),
2845
+ ...props,
2846
+ children
2847
+ }
2848
+ );
2849
+ });
2850
+ var alignClass = {
2851
+ left: "text-left",
2852
+ center: "text-center",
2853
+ right: "text-right"
2854
+ };
2855
+ var TableCell = forwardRef(function TableCell2({ children, className, align = "left", ...props }, ref) {
2856
+ return /* @__PURE__ */ jsx("td", { ref, className: cn("px-4 py-3 text-white/80", alignClass[align], className), ...props, children });
2857
+ });
2858
+ var variantBorderColor = {
2859
+ info: "border-blue-500",
2860
+ success: "border-emerald-500",
2861
+ warning: "border-amber-500",
2862
+ error: "border-rose-500"
2863
+ };
2864
+ var variantIconColor = {
2865
+ info: "text-blue-400",
2866
+ success: "text-emerald-400",
2867
+ warning: "text-amber-400",
2868
+ error: "text-rose-400"
2869
+ };
2870
+ function InfoIcon() {
2871
+ return /* @__PURE__ */ jsxs(
2872
+ "svg",
2873
+ {
2874
+ "aria-hidden": "true",
2875
+ width: "18",
2876
+ height: "18",
2877
+ viewBox: "0 0 18 18",
2878
+ fill: "none",
2879
+ xmlns: "http://www.w3.org/2000/svg",
2880
+ children: [
2881
+ /* @__PURE__ */ jsx("circle", { cx: "9", cy: "9", r: "7.5", stroke: "currentColor", strokeWidth: "1.5" }),
2882
+ /* @__PURE__ */ jsx("path", { d: "M9 8v5", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round" }),
2883
+ /* @__PURE__ */ jsx("circle", { cx: "9", cy: "5.5", r: "0.875", fill: "currentColor" })
2884
+ ]
2885
+ }
2886
+ );
2887
+ }
2888
+ function SuccessIcon() {
2889
+ return /* @__PURE__ */ jsxs(
2890
+ "svg",
2891
+ {
2892
+ "aria-hidden": "true",
2893
+ width: "18",
2894
+ height: "18",
2895
+ viewBox: "0 0 18 18",
2896
+ fill: "none",
2897
+ xmlns: "http://www.w3.org/2000/svg",
2898
+ children: [
2899
+ /* @__PURE__ */ jsx("circle", { cx: "9", cy: "9", r: "7.5", stroke: "currentColor", strokeWidth: "1.5" }),
2900
+ /* @__PURE__ */ jsx(
2901
+ "path",
2902
+ {
2903
+ d: "M5.5 9.5l2.5 2.5 4.5-5",
2904
+ stroke: "currentColor",
2905
+ strokeWidth: "1.75",
2906
+ strokeLinecap: "round",
2907
+ strokeLinejoin: "round"
2908
+ }
2909
+ )
2910
+ ]
2911
+ }
2912
+ );
2913
+ }
2914
+ function WarningIcon() {
2915
+ return /* @__PURE__ */ jsxs(
2916
+ "svg",
2917
+ {
2918
+ "aria-hidden": "true",
2919
+ width: "18",
2920
+ height: "18",
2921
+ viewBox: "0 0 18 18",
2922
+ fill: "none",
2923
+ xmlns: "http://www.w3.org/2000/svg",
2924
+ children: [
2925
+ /* @__PURE__ */ jsx(
2926
+ "path",
2927
+ {
2928
+ 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",
2929
+ stroke: "currentColor",
2930
+ strokeWidth: "1.5",
2931
+ strokeLinejoin: "round"
2932
+ }
2933
+ ),
2934
+ /* @__PURE__ */ jsx("path", { d: "M9 7v4", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round" }),
2935
+ /* @__PURE__ */ jsx("circle", { cx: "9", cy: "12.5", r: "0.875", fill: "currentColor" })
2936
+ ]
2937
+ }
2938
+ );
2939
+ }
2940
+ function ErrorIcon() {
2941
+ return /* @__PURE__ */ jsxs(
2942
+ "svg",
2052
2943
  {
2053
- ref,
2054
- className: cn(
2055
- "px-4 py-3 text-left text-xs font-semibold text-white/50 uppercase tracking-wider",
2056
- className
2057
- ),
2058
- children
2944
+ "aria-hidden": "true",
2945
+ width: "18",
2946
+ height: "18",
2947
+ viewBox: "0 0 18 18",
2948
+ fill: "none",
2949
+ xmlns: "http://www.w3.org/2000/svg",
2950
+ children: [
2951
+ /* @__PURE__ */ jsx("circle", { cx: "9", cy: "9", r: "7.5", stroke: "currentColor", strokeWidth: "1.5" }),
2952
+ /* @__PURE__ */ jsx(
2953
+ "path",
2954
+ {
2955
+ d: "M6.5 6.5l5 5M11.5 6.5l-5 5",
2956
+ stroke: "currentColor",
2957
+ strokeWidth: "1.75",
2958
+ strokeLinecap: "round"
2959
+ }
2960
+ )
2961
+ ]
2059
2962
  }
2060
- )
2061
- );
2062
- TableHead.displayName = "TableHead";
2063
- var alignClass = {
2064
- left: "text-left",
2065
- center: "text-center",
2066
- right: "text-right"
2067
- };
2068
- var TableCell = forwardRef(
2069
- ({ children, className, align = "left" }, ref) => /* @__PURE__ */ jsx("td", { ref, className: cn("px-4 py-3 text-white/80", alignClass[align], className), children })
2070
- );
2071
- TableCell.displayName = "TableCell";
2072
- function TrendIndicator({ trend }) {
2073
- if (trend.value > 0) {
2074
- return /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1 text-xs text-emerald-400", children: [
2075
- /* @__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" }) }),
2076
- /* @__PURE__ */ jsxs("span", { children: [
2077
- "+",
2078
- trend.value,
2079
- trend.label ? ` ${trend.label}` : ""
2080
- ] })
2081
- ] });
2082
- }
2083
- if (trend.value < 0) {
2084
- return /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1 text-xs text-rose-400", children: [
2085
- /* @__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" }) }),
2086
- /* @__PURE__ */ jsxs("span", { children: [
2087
- trend.value,
2088
- trend.label ? ` ${trend.label}` : ""
2089
- ] })
2090
- ] });
2091
- }
2092
- return /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1 text-xs text-white/40", children: [
2093
- /* @__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" }) }),
2094
- /* @__PURE__ */ jsxs("span", { children: [
2095
- trend.value,
2096
- trend.label ? ` ${trend.label}` : ""
2097
- ] })
2098
- ] });
2963
+ );
2099
2964
  }
2100
- function StatCard({ value, label, icon, trend, className }) {
2965
+ var variantIcon = {
2966
+ info: InfoIcon,
2967
+ success: SuccessIcon,
2968
+ warning: WarningIcon,
2969
+ error: ErrorIcon
2970
+ };
2971
+ function Alert({ variant = "info", title, children, onDismiss, className }) {
2972
+ const Icon = variantIcon[variant];
2101
2973
  return /* @__PURE__ */ jsxs(
2102
2974
  "div",
2103
2975
  {
2976
+ role: "alert",
2104
2977
  className: cn(
2105
- "glass rounded-xl p-4 flex items-start gap-3",
2978
+ "flex items-start gap-3 rounded-xl bg-white/5 ring-1 ring-white/10",
2979
+ "border-l-4 pl-4 pr-3 py-3",
2980
+ variantBorderColor[variant],
2106
2981
  className
2107
2982
  ),
2108
2983
  children: [
2109
- 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 }),
2110
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-0.5 min-w-0", children: [
2111
- /* @__PURE__ */ jsx("span", { className: "text-2xl font-bold text-white tabular-nums leading-none", children: value }),
2112
- /* @__PURE__ */ jsx("span", { className: "text-sm text-white/50 truncate", children: label }),
2113
- trend != null && /* @__PURE__ */ jsx("div", { className: "mt-1", children: /* @__PURE__ */ jsx(TrendIndicator, { trend }) })
2114
- ] })
2984
+ /* @__PURE__ */ jsx("span", { className: cn("mt-0.5 shrink-0", variantIconColor[variant]), children: /* @__PURE__ */ jsx(Icon, {}) }),
2985
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
2986
+ title && /* @__PURE__ */ jsx("p", { className: "text-sm font-semibold text-white leading-snug mb-0.5", children: title }),
2987
+ /* @__PURE__ */ jsx("div", { className: "text-sm text-white/70 leading-relaxed", children })
2988
+ ] }),
2989
+ onDismiss && /* @__PURE__ */ jsx(
2990
+ "button",
2991
+ {
2992
+ type: "button",
2993
+ "aria-label": "Dismiss",
2994
+ onClick: onDismiss,
2995
+ className: cn(
2996
+ "shrink-0 flex items-center justify-center h-6 w-6 rounded-lg mt-0.5",
2997
+ "text-white/40 transition-colors hover:bg-white/10 hover:text-white/80",
2998
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/40"
2999
+ ),
3000
+ children: /* @__PURE__ */ jsx(
3001
+ "svg",
3002
+ {
3003
+ "aria-hidden": "true",
3004
+ width: "10",
3005
+ height: "10",
3006
+ viewBox: "0 0 10 10",
3007
+ fill: "none",
3008
+ children: /* @__PURE__ */ jsx("path", { d: "M1 1l8 8M9 1L1 9", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" })
3009
+ }
3010
+ )
3011
+ }
3012
+ )
2115
3013
  ]
2116
3014
  }
2117
3015
  );
@@ -2247,6 +3145,567 @@ function Pagination({
2247
3145
  }
2248
3146
  );
2249
3147
  }
3148
+ function useControllableState(controlledValue, defaultValue, onChange) {
3149
+ const [internalValue, setInternalValue] = useState(defaultValue);
3150
+ const value = controlledValue ?? internalValue;
3151
+ const setValue = (nextValue) => {
3152
+ const resolvedValue = typeof nextValue === "function" ? nextValue(value) : nextValue;
3153
+ if (controlledValue === void 0) {
3154
+ setInternalValue(resolvedValue);
3155
+ }
3156
+ onChange?.(resolvedValue);
3157
+ };
3158
+ return [value, setValue];
3159
+ }
3160
+ function startOfDay2(date) {
3161
+ return new Date(date.getFullYear(), date.getMonth(), date.getDate());
3162
+ }
3163
+ function endOfDay(date) {
3164
+ return new Date(date.getFullYear(), date.getMonth(), date.getDate(), 23, 59, 59, 999);
3165
+ }
3166
+ function isDateRangeValue(value) {
3167
+ return typeof value === "object" && value !== null && "from" in value && "to" in value;
3168
+ }
3169
+ function hasActiveDateRange(range) {
3170
+ return range.from !== null || range.to !== null;
3171
+ }
3172
+ function isFilterValueActive(value) {
3173
+ if (value == null) return false;
3174
+ if (typeof value === "string") return value.trim() !== "";
3175
+ if (Array.isArray(value)) return value.length > 0;
3176
+ if (isDateRangeValue(value)) return hasActiveDateRange(value);
3177
+ return true;
3178
+ }
3179
+ function getColumnValue(column, row) {
3180
+ if (column.accessorFn) {
3181
+ return column.accessorFn(row);
3182
+ }
3183
+ if (column.accessorKey) {
3184
+ return row[column.accessorKey];
3185
+ }
3186
+ return void 0;
3187
+ }
3188
+ function coerceDate(value) {
3189
+ if (value instanceof Date && !Number.isNaN(value.getTime())) {
3190
+ return value;
3191
+ }
3192
+ if (typeof value === "string" || typeof value === "number") {
3193
+ const parsed = new Date(value);
3194
+ return Number.isNaN(parsed.getTime()) ? null : parsed;
3195
+ }
3196
+ return null;
3197
+ }
3198
+ function compareValues(left, right) {
3199
+ if (left == null && right == null) return 0;
3200
+ if (left == null) return 1;
3201
+ if (right == null) return -1;
3202
+ if (left instanceof Date || right instanceof Date) {
3203
+ const leftDate = coerceDate(left);
3204
+ const rightDate = coerceDate(right);
3205
+ if (!leftDate && !rightDate) return 0;
3206
+ if (!leftDate) return 1;
3207
+ if (!rightDate) return -1;
3208
+ return leftDate.getTime() - rightDate.getTime();
3209
+ }
3210
+ if (typeof left === "number" && typeof right === "number") {
3211
+ return left - right;
3212
+ }
3213
+ return String(left).localeCompare(String(right), void 0, {
3214
+ numeric: true,
3215
+ sensitivity: "base"
3216
+ });
3217
+ }
3218
+ function matchColumnFilter(column, row, filterValue) {
3219
+ if (!isFilterValueActive(filterValue)) {
3220
+ return true;
3221
+ }
3222
+ const rawValue = getColumnValue(column, row);
3223
+ if (column.filterFn) {
3224
+ return column.filterFn(rawValue, row, filterValue);
3225
+ }
3226
+ if (typeof column.filter === "function") {
3227
+ return true;
3228
+ }
3229
+ switch (column.filter) {
3230
+ case "select":
3231
+ case "boolean":
3232
+ return String(rawValue ?? "") === String(filterValue);
3233
+ case "date-range": {
3234
+ if (!isDateRangeValue(filterValue)) return true;
3235
+ const dateValue = coerceDate(rawValue);
3236
+ if (!dateValue) return false;
3237
+ if (filterValue.from && dateValue < startOfDay2(filterValue.from)) return false;
3238
+ if (filterValue.to && dateValue > endOfDay(filterValue.to)) return false;
3239
+ return true;
3240
+ }
3241
+ case "text":
3242
+ default:
3243
+ return String(rawValue ?? "").toLowerCase().includes(String(filterValue).trim().toLowerCase());
3244
+ }
3245
+ }
3246
+ function defaultResultsLabel(meta) {
3247
+ return `Showing ${meta.from} - ${meta.to} of ${meta.total}`;
3248
+ }
3249
+ function SortIndicator({ active, desc }) {
3250
+ return /* @__PURE__ */ jsxs("span", { className: cn("inline-flex flex-col text-[10px] leading-none", active ? "text-white" : "text-white/25"), children: [
3251
+ /* @__PURE__ */ jsx("svg", { "aria-hidden": "true", className: cn("h-2.5 w-2.5", active && !desc && "text-primary"), viewBox: "0 0 16 16", fill: "none", children: /* @__PURE__ */ jsx("path", { d: "M4.5 9.5 8 6l3.5 3.5", stroke: "currentColor", strokeWidth: "1.6", strokeLinecap: "round", strokeLinejoin: "round" }) }),
3252
+ /* @__PURE__ */ jsx("svg", { "aria-hidden": "true", className: cn("h-2.5 w-2.5 -mt-0.5", active && desc && "text-primary"), viewBox: "0 0 16 16", fill: "none", children: /* @__PURE__ */ jsx("path", { d: "M4.5 6.5 8 10l3.5-3.5", stroke: "currentColor", strokeWidth: "1.6", strokeLinecap: "round", strokeLinejoin: "round" }) })
3253
+ ] });
3254
+ }
3255
+ function DataTable({
3256
+ data,
3257
+ columns,
3258
+ caption,
3259
+ searchValue,
3260
+ defaultSearchValue = "",
3261
+ onSearchValueChange,
3262
+ searchPlaceholder = "Search records...",
3263
+ enableSearch,
3264
+ sortBy,
3265
+ defaultSortBy = null,
3266
+ onSortChange,
3267
+ filters,
3268
+ defaultFilters = {},
3269
+ onFiltersChange,
3270
+ showFilters,
3271
+ defaultShowFilters = false,
3272
+ onShowFiltersChange,
3273
+ page,
3274
+ defaultPage = 1,
3275
+ onPageChange,
3276
+ pageSize,
3277
+ defaultPageSize = 25,
3278
+ onPageSizeChange,
3279
+ pageSizeOptions = [25, 50, 100],
3280
+ totalItems,
3281
+ loading,
3282
+ loadingRows = 5,
3283
+ error,
3284
+ onRetry,
3285
+ emptyState,
3286
+ emptyTitle = "Nothing to show yet",
3287
+ emptyDescription = "No rows matched the current filters.",
3288
+ filterToggleLabel = "Filters",
3289
+ clearFiltersLabel = "Clear",
3290
+ pageSizeLabel = "Rows",
3291
+ resultsLabel = defaultResultsLabel,
3292
+ toolbarActions,
3293
+ stickyHeader,
3294
+ dense,
3295
+ className,
3296
+ manualSorting,
3297
+ manualFiltering,
3298
+ manualPagination,
3299
+ onRowClick,
3300
+ rowHref,
3301
+ getRowId,
3302
+ getRowClassName
3303
+ }) {
3304
+ const visibleColumns = useMemo(() => columns.filter((column) => !column.hidden), [columns]);
3305
+ const [currentSearch, setCurrentSearch] = useControllableState(searchValue, defaultSearchValue, onSearchValueChange);
3306
+ const [currentSort, setCurrentSort] = useControllableState(sortBy, defaultSortBy, onSortChange);
3307
+ const [currentFilters, setCurrentFilters] = useControllableState(filters, defaultFilters, onFiltersChange);
3308
+ const [filtersVisible, setFiltersVisible] = useControllableState(showFilters, defaultShowFilters, onShowFiltersChange);
3309
+ const [currentPage, setCurrentPage] = useControllableState(page, defaultPage, onPageChange);
3310
+ const [currentPageSize, setCurrentPageSize] = useControllableState(pageSize, defaultPageSize, onPageSizeChange);
3311
+ const hasSearchControl = enableSearch || searchValue !== void 0 || defaultSearchValue !== "";
3312
+ const searchTerm = currentSearch.trim().toLowerCase();
3313
+ const searchableColumns = useMemo(
3314
+ () => visibleColumns.filter((column) => column.searchable !== false),
3315
+ [visibleColumns]
3316
+ );
3317
+ const filteredRows = useMemo(() => {
3318
+ if (manualFiltering) {
3319
+ return data;
3320
+ }
3321
+ return data.filter((row) => {
3322
+ const matchesSearch = !searchTerm || searchableColumns.some((column) => {
3323
+ const value = getColumnValue(column, row);
3324
+ return String(value ?? "").toLowerCase().includes(searchTerm);
3325
+ });
3326
+ if (!matchesSearch) {
3327
+ return false;
3328
+ }
3329
+ return visibleColumns.every((column) => matchColumnFilter(column, row, currentFilters[column.id]));
3330
+ });
3331
+ }, [currentFilters, data, manualFiltering, searchTerm, searchableColumns, visibleColumns]);
3332
+ const sortedRows = useMemo(() => {
3333
+ if (manualSorting || currentSort == null) {
3334
+ return filteredRows;
3335
+ }
3336
+ const sortColumn = visibleColumns.find((column) => column.id === currentSort.id);
3337
+ if (!sortColumn) {
3338
+ return filteredRows;
3339
+ }
3340
+ return [...filteredRows].sort((left, right) => {
3341
+ const result = compareValues(getColumnValue(sortColumn, left), getColumnValue(sortColumn, right));
3342
+ return currentSort.desc ? -result : result;
3343
+ });
3344
+ }, [currentSort, filteredRows, manualSorting, visibleColumns]);
3345
+ const derivedTotalItems = manualPagination ? totalItems ?? data.length : sortedRows.length;
3346
+ const totalPages = Math.max(1, Math.ceil(derivedTotalItems / currentPageSize));
3347
+ useEffect(() => {
3348
+ if (currentPage > totalPages) {
3349
+ setCurrentPage(totalPages);
3350
+ }
3351
+ }, [currentPage, setCurrentPage, totalPages]);
3352
+ const pagedRows = useMemo(() => {
3353
+ if (manualPagination) {
3354
+ return data;
3355
+ }
3356
+ const startIndex = (currentPage - 1) * currentPageSize;
3357
+ return sortedRows.slice(startIndex, startIndex + currentPageSize);
3358
+ }, [currentPage, currentPageSize, data, manualPagination, sortedRows]);
3359
+ const activeFilterCount = useMemo(
3360
+ () => Object.values(currentFilters).filter(isFilterValueActive).length + (searchTerm ? 1 : 0),
3361
+ [currentFilters, searchTerm]
3362
+ );
3363
+ const from = derivedTotalItems === 0 ? 0 : (currentPage - 1) * currentPageSize + 1;
3364
+ const to = derivedTotalItems === 0 ? 0 : manualPagination ? Math.min(from + pagedRows.length - 1, derivedTotalItems) : Math.min(currentPage * currentPageSize, derivedTotalItems);
3365
+ const handleSortToggle = (column) => {
3366
+ if (!column.sortable) return;
3367
+ setCurrentPage(1);
3368
+ setCurrentSort((previousSort) => {
3369
+ if (!previousSort || previousSort.id !== column.id) {
3370
+ return { id: column.id, desc: Boolean(column.sortDescFirst) };
3371
+ }
3372
+ if (previousSort.desc === Boolean(column.sortDescFirst)) {
3373
+ return { id: column.id, desc: !previousSort.desc };
3374
+ }
3375
+ return null;
3376
+ });
3377
+ };
3378
+ const handleFilterChange = (columnId, value) => {
3379
+ setCurrentPage(1);
3380
+ setCurrentFilters((previousFilters) => ({
3381
+ ...previousFilters,
3382
+ [columnId]: value
3383
+ }));
3384
+ };
3385
+ const handleClear = () => {
3386
+ setCurrentSearch("");
3387
+ setCurrentPage(1);
3388
+ setCurrentFilters({});
3389
+ };
3390
+ const handlePageSizeChange = (value) => {
3391
+ setCurrentPage(1);
3392
+ setCurrentPageSize(value);
3393
+ };
3394
+ const handleRowActivate = (row) => {
3395
+ onRowClick?.(row);
3396
+ const href = rowHref?.(row);
3397
+ if (href && typeof window !== "undefined") {
3398
+ window.location.assign(href);
3399
+ }
3400
+ };
3401
+ const renderFilterControl = (column) => {
3402
+ const filterValue = currentFilters[column.id];
3403
+ if (typeof column.filter === "function") {
3404
+ return column.filter({
3405
+ column,
3406
+ value: filterValue,
3407
+ onChange: (value) => handleFilterChange(column.id, value),
3408
+ data
3409
+ });
3410
+ }
3411
+ switch (column.filter) {
3412
+ case "select":
3413
+ case "boolean":
3414
+ return /* @__PURE__ */ jsxs(
3415
+ "select",
3416
+ {
3417
+ "aria-label": `Filter ${typeof column.header === "string" ? column.header : column.id}`,
3418
+ value: typeof filterValue === "string" ? filterValue : "",
3419
+ onChange: (event) => handleFilterChange(column.id, event.target.value),
3420
+ className: "w-full rounded-lg border border-white/10 bg-white/5 px-2.5 py-2 text-sm text-white outline-none focus-visible:ring-2 focus-visible:ring-primary/40",
3421
+ children: [
3422
+ /* @__PURE__ */ jsx("option", { value: "", children: "All" }),
3423
+ column.filterOptions?.map((option) => /* @__PURE__ */ jsx("option", { value: option.value, children: option.label }, option.value))
3424
+ ]
3425
+ }
3426
+ );
3427
+ case "date-range":
3428
+ return /* @__PURE__ */ jsx(
3429
+ DateRangePicker,
3430
+ {
3431
+ compact: true,
3432
+ value: isDateRangeValue(filterValue) ? filterValue : { from: null, to: null },
3433
+ onChange: (range) => handleFilterChange(column.id, range),
3434
+ placeholder: { trigger: "Any date" }
3435
+ }
3436
+ );
3437
+ case "text":
3438
+ default:
3439
+ return /* @__PURE__ */ jsx(
3440
+ "input",
3441
+ {
3442
+ "aria-label": `Filter ${typeof column.header === "string" ? column.header : column.id}`,
3443
+ type: "text",
3444
+ value: typeof filterValue === "string" ? filterValue : "",
3445
+ onChange: (event) => handleFilterChange(column.id, event.target.value),
3446
+ className: "w-full rounded-lg border border-white/10 bg-white/5 px-2.5 py-2 text-sm text-white outline-none placeholder:text-white/25 focus-visible:ring-2 focus-visible:ring-primary/40",
3447
+ placeholder: "Filter..."
3448
+ }
3449
+ );
3450
+ }
3451
+ };
3452
+ return /* @__PURE__ */ jsxs("div", { className: cn("space-y-4", className), children: [
3453
+ hasSearchControl || toolbarActions || visibleColumns.some((column) => column.filter) ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3 lg:flex-row lg:items-center lg:justify-between", children: [
3454
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-3", children: [
3455
+ /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2 text-sm text-white/60", children: [
3456
+ /* @__PURE__ */ jsx("span", { children: pageSizeLabel }),
3457
+ /* @__PURE__ */ jsx(
3458
+ "select",
3459
+ {
3460
+ "aria-label": "Rows per page",
3461
+ value: currentPageSize,
3462
+ onChange: (event) => handlePageSizeChange(Number(event.target.value)),
3463
+ className: "rounded-lg border border-white/10 bg-white/5 px-2.5 py-2 text-sm text-white outline-none focus-visible:ring-2 focus-visible:ring-primary/40",
3464
+ children: pageSizeOptions.map((option) => /* @__PURE__ */ jsx("option", { value: option, children: option }, option))
3465
+ }
3466
+ )
3467
+ ] }),
3468
+ visibleColumns.some((column) => column.filter) ? /* @__PURE__ */ jsxs(
3469
+ Button,
3470
+ {
3471
+ size: "sm",
3472
+ variant: filtersVisible ? "secondary" : "ghost",
3473
+ onClick: () => setFiltersVisible((previousValue) => !previousValue),
3474
+ children: [
3475
+ filterToggleLabel,
3476
+ activeFilterCount > 0 ? ` (${activeFilterCount})` : ""
3477
+ ]
3478
+ }
3479
+ ) : null,
3480
+ activeFilterCount > 0 ? /* @__PURE__ */ jsx(Button, { size: "sm", variant: "ghost", onClick: handleClear, children: clearFiltersLabel }) : null
3481
+ ] }),
3482
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-end", children: [
3483
+ hasSearchControl ? /* @__PURE__ */ jsx(
3484
+ SearchInput,
3485
+ {
3486
+ value: currentSearch,
3487
+ onChange: (event) => {
3488
+ setCurrentPage(1);
3489
+ setCurrentSearch(event.target.value);
3490
+ },
3491
+ onClear: () => {
3492
+ setCurrentPage(1);
3493
+ setCurrentSearch("");
3494
+ },
3495
+ placeholder: searchPlaceholder,
3496
+ className: "min-w-[16rem]"
3497
+ }
3498
+ ) : null,
3499
+ toolbarActions
3500
+ ] })
3501
+ ] }) : null,
3502
+ error ? /* @__PURE__ */ jsx(Alert, { variant: "error", title: "Unable to load table data", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between", children: [
3503
+ /* @__PURE__ */ jsx("span", { children: error }),
3504
+ onRetry ? /* @__PURE__ */ jsx(Button, { size: "sm", variant: "secondary", onClick: onRetry, children: "Retry" }) : null
3505
+ ] }) }) : null,
3506
+ /* @__PURE__ */ jsxs(Table, { className: "min-w-full", children: [
3507
+ caption ? /* @__PURE__ */ jsx("caption", { className: "sr-only", children: caption }) : null,
3508
+ /* @__PURE__ */ jsxs(TableHeader, { children: [
3509
+ /* @__PURE__ */ jsx(TableRow, { children: visibleColumns.map((column) => {
3510
+ const sorted = currentSort?.id === column.id ? currentSort : null;
3511
+ const ariaSort = column.sortable ? sorted ? sorted.desc ? "descending" : "ascending" : "none" : void 0;
3512
+ return /* @__PURE__ */ jsx(
3513
+ TableHead,
3514
+ {
3515
+ className: cn(
3516
+ stickyHeader && "sticky top-0 z-10 bg-[#121420] backdrop-blur-sm",
3517
+ column.headerClassName
3518
+ ),
3519
+ style: { width: column.width, minWidth: column.minWidth },
3520
+ "aria-sort": ariaSort,
3521
+ children: column.sortable ? /* @__PURE__ */ jsxs(
3522
+ "button",
3523
+ {
3524
+ type: "button",
3525
+ onClick: () => handleSortToggle(column),
3526
+ className: "flex w-full items-center gap-2 text-left transition-colors hover:text-white",
3527
+ children: [
3528
+ /* @__PURE__ */ jsx("span", { className: "truncate", children: typeof column.header === "function" ? column.header({ column, sort: sorted }) : column.header }),
3529
+ /* @__PURE__ */ jsx(SortIndicator, { active: sorted !== null, desc: sorted?.desc })
3530
+ ]
3531
+ }
3532
+ ) : typeof column.header === "function" ? column.header({ column, sort: sorted }) : column.header
3533
+ },
3534
+ column.id
3535
+ );
3536
+ }) }),
3537
+ filtersVisible ? /* @__PURE__ */ jsx(TableRow, { className: "bg-white/[0.025]", children: visibleColumns.map((column) => /* @__PURE__ */ jsx(
3538
+ TableHead,
3539
+ {
3540
+ className: "normal-case text-white/70 tracking-normal",
3541
+ style: { width: column.width, minWidth: column.minWidth },
3542
+ children: column.filter ? renderFilterControl(column) : null
3543
+ },
3544
+ `${column.id}-filter`
3545
+ )) }) : null
3546
+ ] }),
3547
+ /* @__PURE__ */ jsx(TableBody, { children: loading ? Array.from({ length: loadingRows }).map((_, rowIndex) => /* @__PURE__ */ jsx(TableRow, { children: visibleColumns.map((column) => /* @__PURE__ */ jsx(TableCell, { className: dense ? "py-2" : void 0, align: column.align, children: /* @__PURE__ */ jsx(Skeleton, { className: cn(column.align === "right" ? "ml-auto" : "", "h-5 w-full max-w-[12rem]") }) }, `${column.id}-${rowIndex}`)) }, `loading-${rowIndex}`)) : pagedRows.length === 0 ? /* @__PURE__ */ jsx(TableRow, { children: /* @__PURE__ */ jsx(TableCell, { colSpan: visibleColumns.length, className: "py-10", align: "center", children: emptyState ?? /* @__PURE__ */ jsx(
3548
+ EmptyState,
3549
+ {
3550
+ title: emptyTitle,
3551
+ description: emptyDescription
3552
+ }
3553
+ ) }) }) : pagedRows.map((row, rowIndex) => {
3554
+ const key = getRowId?.(row, rowIndex) ?? String(rowIndex);
3555
+ const href = rowHref?.(row);
3556
+ const interactive = Boolean(onRowClick || href);
3557
+ return /* @__PURE__ */ jsx(
3558
+ TableRow,
3559
+ {
3560
+ hoverable: interactive,
3561
+ className: cn(
3562
+ dense && "[&>td]:py-2",
3563
+ interactive && "cursor-pointer",
3564
+ getRowClassName?.(row, rowIndex)
3565
+ ),
3566
+ ...interactive ? {
3567
+ tabIndex: 0,
3568
+ onClick: () => handleRowActivate(row),
3569
+ onKeyDown: (event) => {
3570
+ if (event.key === "Enter" || event.key === " ") {
3571
+ event.preventDefault();
3572
+ handleRowActivate(row);
3573
+ }
3574
+ }
3575
+ } : {},
3576
+ children: visibleColumns.map((column) => {
3577
+ const value = getColumnValue(column, row);
3578
+ return /* @__PURE__ */ jsx(
3579
+ TableCell,
3580
+ {
3581
+ align: column.align,
3582
+ className: column.className,
3583
+ children: column.cell ? column.cell({ row, value, rowIndex, column }) : value == null ? "\u2014" : String(value)
3584
+ },
3585
+ column.id
3586
+ );
3587
+ })
3588
+ },
3589
+ key
3590
+ );
3591
+ }) })
3592
+ ] }),
3593
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3 border-t border-white/10 pt-3 sm:flex-row sm:items-center sm:justify-between", children: [
3594
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-white/50", children: resultsLabel({ from, to, total: derivedTotalItems }) }),
3595
+ /* @__PURE__ */ jsx(Pagination, { page: currentPage, totalPages, onPageChange: (nextPage) => setCurrentPage(nextPage) })
3596
+ ] })
3597
+ ] });
3598
+ }
3599
+ var sizeStyles = {
3600
+ sm: "p-3 gap-3",
3601
+ md: "p-4 gap-3",
3602
+ lg: "p-5 gap-4"
3603
+ };
3604
+ var valueStyles = {
3605
+ sm: "text-xl",
3606
+ md: "text-2xl",
3607
+ lg: "text-3xl"
3608
+ };
3609
+ var labelStyles = {
3610
+ sm: "text-[11px] uppercase tracking-[0.16em]",
3611
+ md: "text-sm",
3612
+ lg: "text-sm uppercase tracking-[0.18em]"
3613
+ };
3614
+ var iconStyles = {
3615
+ sm: "h-9 w-9 rounded-xl text-sm",
3616
+ md: "h-10 w-10 rounded-xl text-base",
3617
+ lg: "h-11 w-11 rounded-2xl text-base"
3618
+ };
3619
+ function getSignedValue(value) {
3620
+ if (value > 0) return `+${value}`;
3621
+ return `${value}`;
3622
+ }
3623
+ function getValueColorClass(valueColor, value) {
3624
+ if (valueColor === "default") return "text-white";
3625
+ if (valueColor === "success") return "text-emerald-400";
3626
+ if (valueColor === "danger") return "text-rose-400";
3627
+ if (valueColor === "warning") return "text-amber-400";
3628
+ const raw = typeof value === "number" ? value : Number(String(value).replace(/[%,$\s]/g, ""));
3629
+ if (!Number.isNaN(raw)) {
3630
+ if (raw > 0) return "text-emerald-400";
3631
+ if (raw < 0) return "text-rose-400";
3632
+ }
3633
+ const trimmed = String(value).trim();
3634
+ if (trimmed.startsWith("+")) return "text-emerald-400";
3635
+ if (trimmed.startsWith("-")) return "text-rose-400";
3636
+ return "text-white";
3637
+ }
3638
+ function TrendIndicator({ trend }) {
3639
+ const tone = trend.value > 0 ? "text-emerald-400" : trend.value < 0 ? "text-rose-400" : "text-white/40";
3640
+ const icon = trend.value > 0 ? /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 9V3M3 6l3-3 3 3" }) : trend.value < 0 ? /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 3v6M3 6l3 3 3-3" }) : /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M2 6h8" });
3641
+ const text = trend.format ? trend.format({ value: trend.value, percentValue: trend.percentValue }) : `${getSignedValue(trend.value)}${trend.percentValue != null ? ` (${getSignedValue(trend.percentValue)}%)` : ""}${trend.label ? ` ${trend.label}` : ""}`;
3642
+ return /* @__PURE__ */ jsxs("span", { className: cn("inline-flex items-center gap-1 text-xs", tone), children: [
3643
+ /* @__PURE__ */ jsx("svg", { "aria-hidden": "true", className: "h-3 w-3 shrink-0", fill: "none", viewBox: "0 0 12 12", stroke: "currentColor", strokeWidth: 2, children: icon }),
3644
+ /* @__PURE__ */ jsx("span", { children: text })
3645
+ ] });
3646
+ }
3647
+ function MetricContent({ value, label, trend, size, valueColor }) {
3648
+ return /* @__PURE__ */ jsxs("div", { className: "min-w-0 space-y-1", children: [
3649
+ /* @__PURE__ */ jsx("span", { className: cn("block font-bold leading-none tabular-nums", valueStyles[size], getValueColorClass(valueColor, value)), children: value }),
3650
+ /* @__PURE__ */ jsx("span", { className: cn("block truncate text-white/55", labelStyles[size]), children: label }),
3651
+ trend ? /* @__PURE__ */ jsx(TrendIndicator, { trend }) : null
3652
+ ] });
3653
+ }
3654
+ function ChevronIcon2() {
3655
+ return /* @__PURE__ */ jsx("svg", { "aria-hidden": "true", className: "h-4 w-4", viewBox: "0 0 20 20", fill: "none", children: /* @__PURE__ */ jsx("path", { d: "M8 5l5 5-5 5", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round", strokeLinejoin: "round" }) });
3656
+ }
3657
+ function StatCard({
3658
+ value,
3659
+ label,
3660
+ icon,
3661
+ trend,
3662
+ size = "md",
3663
+ valueColor = "default",
3664
+ href,
3665
+ onClick,
3666
+ loading,
3667
+ secondaryMetric,
3668
+ className
3669
+ }) {
3670
+ const clickable = Boolean(href || onClick);
3671
+ const rootClassName = cn(
3672
+ "glass rounded-xl transition-[transform,background-color,box-shadow,ring-color]",
3673
+ sizeStyles[size],
3674
+ clickable && "group hover:bg-white/[0.08] hover:-translate-y-0.5 hover:shadow-lg hover:shadow-black/20",
3675
+ className
3676
+ );
3677
+ const content = loading ? /* @__PURE__ */ jsxs("div", { className: "flex w-full items-start gap-3", children: [
3678
+ icon ? /* @__PURE__ */ jsx(Skeleton, { className: cn(iconStyles[size]) }) : null,
3679
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1 space-y-2", children: [
3680
+ /* @__PURE__ */ jsx(Skeleton, { className: cn("h-7 max-w-[8rem]", size === "lg" && "h-8 max-w-[10rem]") }),
3681
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-4 max-w-[11rem]" }),
3682
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-3 max-w-[9rem]" })
3683
+ ] })
3684
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
3685
+ icon ? /* @__PURE__ */ jsx("div", { className: cn("shrink-0 bg-white/10 flex items-center justify-center text-primary", iconStyles[size]), children: icon }) : null,
3686
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
3687
+ /* @__PURE__ */ jsx(MetricContent, { value, label, trend, size, valueColor }),
3688
+ secondaryMetric ? /* @__PURE__ */ jsx("div", { className: "mt-4 border-t border-white/10 pt-4", children: /* @__PURE__ */ jsx(
3689
+ MetricContent,
3690
+ {
3691
+ value: secondaryMetric.value,
3692
+ label: secondaryMetric.label,
3693
+ trend: secondaryMetric.trend,
3694
+ size: size === "lg" ? "md" : size,
3695
+ valueColor: "default"
3696
+ }
3697
+ ) }) : null
3698
+ ] }),
3699
+ clickable ? /* @__PURE__ */ jsx("span", { className: "mt-0.5 shrink-0 text-white/35 transition-colors group-hover:text-white/70", children: /* @__PURE__ */ jsx(ChevronIcon2, {}) }) : null
3700
+ ] });
3701
+ if (href) {
3702
+ return /* @__PURE__ */ jsx("a", { href, className: cn("flex items-start", rootClassName), children: content });
3703
+ }
3704
+ if (onClick) {
3705
+ return /* @__PURE__ */ jsx("button", { type: "button", onClick, className: cn("flex w-full items-start text-left", rootClassName), children: content });
3706
+ }
3707
+ return /* @__PURE__ */ jsx("div", { className: cn("flex items-start", rootClassName), children: content });
3708
+ }
2250
3709
  function Stepper({ steps, activeStep, className }) {
2251
3710
  return /* @__PURE__ */ jsx("div", { className: cn("flex items-start w-full", className), children: steps.map((step, index) => {
2252
3711
  const isCompleted = index < activeStep;
@@ -2579,8 +4038,221 @@ function DotIndicator({
2579
4038
  );
2580
4039
  })
2581
4040
  }
2582
- ),
2583
- showLabel && /* @__PURE__ */ jsx("span", { className: cn("text-xs font-medium tabular-nums", urgency.label), children: label })
4041
+ ),
4042
+ showLabel && /* @__PURE__ */ jsx("span", { className: cn("text-xs font-medium tabular-nums", urgency.label), children: label })
4043
+ ] });
4044
+ }
4045
+ var toneClass = {
4046
+ default: "text-white/55 bg-white/[0.04] ring-white/10",
4047
+ primary: "text-primary bg-primary/10 ring-primary/20",
4048
+ success: "text-emerald-400 bg-emerald-500/10 ring-emerald-500/20",
4049
+ warning: "text-amber-400 bg-amber-500/10 ring-amber-500/20",
4050
+ danger: "text-rose-400 bg-rose-500/10 ring-rose-500/20",
4051
+ accent: "text-accent-light bg-accent/10 ring-accent/20"
4052
+ };
4053
+ var variantStyles = {
4054
+ default: {
4055
+ gap: "gap-4",
4056
+ icon: "h-10 w-10 text-sm",
4057
+ textGap: "gap-2"
4058
+ },
4059
+ compact: {
4060
+ gap: "gap-3",
4061
+ icon: "h-8 w-8 text-xs",
4062
+ textGap: "gap-1.5"
4063
+ }
4064
+ };
4065
+ function toDate(value) {
4066
+ if (!value) return null;
4067
+ if (value instanceof Date) {
4068
+ return Number.isNaN(value.getTime()) ? null : value;
4069
+ }
4070
+ const parsed = new Date(value);
4071
+ return Number.isNaN(parsed.getTime()) ? null : parsed;
4072
+ }
4073
+ function formatTimestamp(value) {
4074
+ return new Intl.DateTimeFormat(void 0, {
4075
+ year: "numeric",
4076
+ month: "2-digit",
4077
+ day: "2-digit",
4078
+ hour: "2-digit",
4079
+ minute: "2-digit",
4080
+ second: "2-digit"
4081
+ }).format(value);
4082
+ }
4083
+ function formatGroupHeader(value, groupBy) {
4084
+ if (groupBy === "day") {
4085
+ return new Intl.DateTimeFormat(void 0, {
4086
+ year: "numeric",
4087
+ month: "long",
4088
+ day: "numeric"
4089
+ }).format(value);
4090
+ }
4091
+ if (groupBy === "month") {
4092
+ return new Intl.DateTimeFormat(void 0, {
4093
+ year: "numeric",
4094
+ month: "long"
4095
+ }).format(value);
4096
+ }
4097
+ return new Intl.DateTimeFormat(void 0, {
4098
+ year: "numeric"
4099
+ }).format(value);
4100
+ }
4101
+ function getGroupKey(value, groupBy) {
4102
+ const year = value.getFullYear();
4103
+ const month = String(value.getMonth() + 1).padStart(2, "0");
4104
+ const day = String(value.getDate()).padStart(2, "0");
4105
+ if (groupBy === "year") return `${year}`;
4106
+ if (groupBy === "month") return `${year}-${month}`;
4107
+ return `${year}-${month}-${day}`;
4108
+ }
4109
+ function DefaultIcon() {
4110
+ return /* @__PURE__ */ jsx("span", { className: "h-2.5 w-2.5 rounded-full bg-current", "aria-hidden": "true" });
4111
+ }
4112
+ function getToneStyle(iconColor) {
4113
+ if (!iconColor || iconColor in toneClass) {
4114
+ const tone = iconColor ?? "default";
4115
+ return { className: toneClass[tone] };
4116
+ }
4117
+ return {
4118
+ className: "bg-white/[0.04] ring-white/10",
4119
+ style: { color: iconColor }
4120
+ };
4121
+ }
4122
+ function getLineClass(lineStyle) {
4123
+ if (lineStyle === "dashed") {
4124
+ return "border-l border-dashed border-white/10";
4125
+ }
4126
+ if (lineStyle === "solid") {
4127
+ return "border-l border-white/10";
4128
+ }
4129
+ return "border-l border-transparent";
4130
+ }
4131
+ function LoadingTimeline({ variant }) {
4132
+ const styles = variantStyles[variant];
4133
+ return /* @__PURE__ */ jsx("div", { className: "space-y-4", children: Array.from({ length: 4 }).map((_, index) => /* @__PURE__ */ jsxs("div", { className: cn("flex items-start", styles.gap), children: [
4134
+ /* @__PURE__ */ jsx("div", { className: "relative flex w-10 shrink-0 justify-center", children: /* @__PURE__ */ jsx(Skeleton, { circle: true, className: styles.icon }) }),
4135
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1 space-y-2", children: [
4136
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-4 max-w-[12rem]" }),
4137
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-5 max-w-[14rem]" }),
4138
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-4 max-w-[18rem]" })
4139
+ ] })
4140
+ ] }, index)) });
4141
+ }
4142
+ function Timeline({
4143
+ events,
4144
+ timestampFormatter = formatTimestamp,
4145
+ timestampPosition = "above",
4146
+ groupBy = "none",
4147
+ groupHeaderFormatter = formatGroupHeader,
4148
+ variant = "default",
4149
+ lineStyle = "solid",
4150
+ order = "asc",
4151
+ maxVisible,
4152
+ onLoadMore,
4153
+ hasMore,
4154
+ loading,
4155
+ emptyState,
4156
+ className
4157
+ }) {
4158
+ const styles = variantStyles[variant];
4159
+ const orderedEvents = useMemo(() => {
4160
+ const nextEvents = [...events].map((event, index) => ({
4161
+ event,
4162
+ index,
4163
+ timestamp: toDate(event.timestamp)
4164
+ }));
4165
+ nextEvents.sort((left, right) => {
4166
+ const leftTime = left.timestamp?.getTime();
4167
+ const rightTime = right.timestamp?.getTime();
4168
+ if (leftTime == null && rightTime == null) return left.index - right.index;
4169
+ if (leftTime == null) return 1;
4170
+ if (rightTime == null) return -1;
4171
+ return order === "asc" ? leftTime - rightTime : rightTime - leftTime;
4172
+ });
4173
+ return nextEvents.map((entry) => entry.event);
4174
+ }, [events, order]);
4175
+ const visibleEvents = maxVisible ? orderedEvents.slice(0, maxVisible) : orderedEvents;
4176
+ const groupedEvents = useMemo(() => {
4177
+ if (groupBy === "none") {
4178
+ return [{ key: "all", date: null, items: visibleEvents }];
4179
+ }
4180
+ const groups = /* @__PURE__ */ new Map();
4181
+ visibleEvents.forEach((event) => {
4182
+ const timestamp = toDate(event.timestamp);
4183
+ const key = timestamp ? getGroupKey(timestamp, groupBy) : "ungrouped";
4184
+ const existing = groups.get(key);
4185
+ if (existing) {
4186
+ existing.items.push(event);
4187
+ return;
4188
+ }
4189
+ groups.set(key, {
4190
+ key,
4191
+ date: timestamp,
4192
+ items: [event]
4193
+ });
4194
+ });
4195
+ return Array.from(groups.values());
4196
+ }, [groupBy, visibleEvents]);
4197
+ const showLoadMore = Boolean(onLoadMore) && (hasMore ?? orderedEvents.length > visibleEvents.length);
4198
+ if (loading) {
4199
+ return /* @__PURE__ */ jsx(LoadingTimeline, { variant });
4200
+ }
4201
+ if (visibleEvents.length === 0) {
4202
+ return /* @__PURE__ */ jsx("div", { className, children: emptyState ?? /* @__PURE__ */ jsx(EmptyState, { title: "No events yet", description: "Timeline entries will appear here once activity starts." }) });
4203
+ }
4204
+ return /* @__PURE__ */ jsxs("div", { className: cn("space-y-6", className), children: [
4205
+ groupedEvents.map((group) => /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
4206
+ groupBy !== "none" && group.date ? /* @__PURE__ */ jsx("p", { className: "text-xs font-semibold uppercase tracking-[0.18em] text-white/35", children: groupHeaderFormatter(group.date, groupBy) }) : null,
4207
+ /* @__PURE__ */ jsx("ol", { className: "space-y-4", children: group.items.map((event, index) => {
4208
+ const timestamp = toDate(event.timestamp);
4209
+ const tone = getToneStyle(event.iconColor);
4210
+ const isLast = index === group.items.length - 1;
4211
+ const timestampNode = timestamp ? /* @__PURE__ */ jsx("time", { dateTime: timestamp.toISOString(), className: "text-xs text-white/45", children: timestampFormatter(timestamp) }) : null;
4212
+ return /* @__PURE__ */ jsxs("li", { className: cn(timestampPosition === "side" ? "grid gap-3 md:grid-cols-[11rem_1fr]" : ""), children: [
4213
+ timestampPosition === "side" ? /* @__PURE__ */ jsx("div", { className: "pt-1 text-xs text-white/45", children: timestampNode }) : null,
4214
+ /* @__PURE__ */ jsxs("div", { className: cn("flex items-start", styles.gap), "aria-label": timestamp ? `${timestampFormatter(timestamp)} ${String(event.title)}` : void 0, children: [
4215
+ /* @__PURE__ */ jsxs("div", { className: "relative flex w-10 shrink-0 justify-center", children: [
4216
+ lineStyle !== "none" && !isLast ? /* @__PURE__ */ jsx(
4217
+ "span",
4218
+ {
4219
+ "aria-hidden": "true",
4220
+ className: cn("absolute left-1/2 top-10 bottom-[-1rem] -translate-x-1/2", getLineClass(lineStyle))
4221
+ }
4222
+ ) : null,
4223
+ /* @__PURE__ */ jsx(
4224
+ "span",
4225
+ {
4226
+ className: cn(
4227
+ "relative z-[1] inline-flex shrink-0 items-center justify-center rounded-full ring-1",
4228
+ styles.icon,
4229
+ tone.className
4230
+ ),
4231
+ style: tone.style,
4232
+ "aria-hidden": "true",
4233
+ children: event.icon ?? /* @__PURE__ */ jsx(DefaultIcon, {})
4234
+ }
4235
+ )
4236
+ ] }),
4237
+ /* @__PURE__ */ jsxs("div", { className: cn("min-w-0 flex-1", styles.textGap, timestampPosition === "inline" ? "space-y-1.5" : "space-y-2"), children: [
4238
+ timestampPosition === "above" ? timestampNode : null,
4239
+ /* @__PURE__ */ jsxs("div", { className: cn(timestampPosition === "inline" ? "flex flex-wrap items-start justify-between gap-2" : "space-y-2"), children: [
4240
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 space-y-2", children: [
4241
+ /* @__PURE__ */ jsx("div", { className: "text-sm font-medium leading-relaxed text-white", children: event.title }),
4242
+ event.description ? /* @__PURE__ */ jsx("div", { className: "text-sm leading-relaxed text-white/60", children: event.description }) : null
4243
+ ] }),
4244
+ timestampPosition === "inline" ? timestampNode : null
4245
+ ] }),
4246
+ event.metadata && Object.keys(event.metadata).length > 0 ? /* @__PURE__ */ jsx("dl", { className: "grid gap-2 rounded-xl border border-white/10 bg-white/[0.03] p-3 sm:grid-cols-2", children: Object.entries(event.metadata).map(([key, value]) => /* @__PURE__ */ jsxs("div", { className: "min-w-0 space-y-1", children: [
4247
+ /* @__PURE__ */ jsx("dt", { className: "text-[11px] uppercase tracking-[0.14em] text-white/35", children: key }),
4248
+ /* @__PURE__ */ jsx("dd", { className: "text-sm text-white/70", children: value })
4249
+ ] }, key)) }) : null
4250
+ ] })
4251
+ ] })
4252
+ ] }, event.id);
4253
+ }) })
4254
+ ] }, group.key)),
4255
+ showLoadMore ? /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Button, { variant: "secondary", size: "sm", onClick: onLoadMore, children: "Load more" }) }) : null
2584
4256
  ] });
2585
4257
  }
2586
4258
  function ActiveFilterPills({
@@ -2755,7 +4427,7 @@ function Sidebar({ children, collapsed = false, onToggle, className }) {
2755
4427
  }
2756
4428
  );
2757
4429
  }
2758
- var maxWidthClass2 = {
4430
+ var widthClass = {
2759
4431
  sm: "max-w-2xl",
2760
4432
  md: "max-w-4xl",
2761
4433
  lg: "max-w-5xl",
@@ -2763,309 +4435,247 @@ var maxWidthClass2 = {
2763
4435
  "2xl": "max-w-[92rem]",
2764
4436
  full: "max-w-full"
2765
4437
  };
2766
- function DashboardLayout({ children, navbar, sidebar, className, mainClassName, maxWidth = "lg" }) {
2767
- return /* @__PURE__ */ jsxs("div", { className: cn("min-h-screen bg-surface relative overflow-hidden", className), children: [
2768
- /* @__PURE__ */ jsxs("div", { "aria-hidden": "true", className: "pointer-events-none fixed inset-0", children: [
2769
- /* @__PURE__ */ jsx("div", { className: "orb orb-purple w-[400px] h-[400px] -top-[150px] -left-[150px] opacity-15" }),
2770
- /* @__PURE__ */ jsx("div", { className: "orb orb-blue w-[300px] h-[300px] top-[60%] -right-[100px] opacity-10" })
2771
- ] }),
2772
- navbar,
2773
- /* @__PURE__ */ jsxs("div", { className: cn("flex", navbar && "pt-16"), children: [
2774
- sidebar,
2775
- /* @__PURE__ */ jsx("main", { className: cn("flex-1 min-w-0 py-8 px-6", mainClassName), children: /* @__PURE__ */ jsx("div", { className: cn("mx-auto", maxWidthClass2[maxWidth]), children }) })
2776
- ] })
2777
- ] });
2778
- }
2779
- var variantBorderColor = {
2780
- info: "border-blue-500",
2781
- success: "border-emerald-500",
2782
- warning: "border-amber-500",
2783
- error: "border-rose-500"
2784
- };
2785
- var variantIconColor = {
2786
- info: "text-blue-400",
2787
- success: "text-emerald-400",
2788
- warning: "text-amber-400",
2789
- error: "text-rose-400"
2790
- };
2791
- function InfoIcon() {
2792
- return /* @__PURE__ */ jsxs(
2793
- "svg",
2794
- {
2795
- "aria-hidden": "true",
2796
- width: "18",
2797
- height: "18",
2798
- viewBox: "0 0 18 18",
2799
- fill: "none",
2800
- xmlns: "http://www.w3.org/2000/svg",
2801
- children: [
2802
- /* @__PURE__ */ jsx("circle", { cx: "9", cy: "9", r: "7.5", stroke: "currentColor", strokeWidth: "1.5" }),
2803
- /* @__PURE__ */ jsx("path", { d: "M9 8v5", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round" }),
2804
- /* @__PURE__ */ jsx("circle", { cx: "9", cy: "5.5", r: "0.875", fill: "currentColor" })
2805
- ]
2806
- }
2807
- );
4438
+ function getItemKey(item, index) {
4439
+ if (item.key) return item.key;
4440
+ if (item.href) return item.href;
4441
+ return `dashboard-nav-item-${index}`;
2808
4442
  }
2809
- function SuccessIcon() {
2810
- return /* @__PURE__ */ jsxs(
2811
- "svg",
2812
- {
2813
- "aria-hidden": "true",
2814
- width: "18",
2815
- height: "18",
2816
- viewBox: "0 0 18 18",
2817
- fill: "none",
2818
- xmlns: "http://www.w3.org/2000/svg",
2819
- children: [
2820
- /* @__PURE__ */ jsx("circle", { cx: "9", cy: "9", r: "7.5", stroke: "currentColor", strokeWidth: "1.5" }),
2821
- /* @__PURE__ */ jsx(
2822
- "path",
2823
- {
2824
- d: "M5.5 9.5l2.5 2.5 4.5-5",
2825
- stroke: "currentColor",
2826
- strokeWidth: "1.75",
2827
- strokeLinecap: "round",
2828
- strokeLinejoin: "round"
2829
- }
2830
- )
2831
- ]
2832
- }
4443
+ function getDesktopNavItemClass(item) {
4444
+ return cn(
4445
+ "flex items-center gap-3 rounded-lg px-4 py-2.5 text-sm transition-all duration-200",
4446
+ item.active ? "bg-accent/20 text-accent" : "text-white/60 hover:bg-white/5 hover:text-white",
4447
+ item.disabled && "pointer-events-none opacity-50"
2833
4448
  );
2834
4449
  }
2835
- function WarningIcon() {
2836
- return /* @__PURE__ */ jsxs(
2837
- "svg",
2838
- {
2839
- "aria-hidden": "true",
2840
- width: "18",
2841
- height: "18",
2842
- viewBox: "0 0 18 18",
2843
- fill: "none",
2844
- xmlns: "http://www.w3.org/2000/svg",
2845
- children: [
2846
- /* @__PURE__ */ jsx(
2847
- "path",
2848
- {
2849
- 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",
2850
- stroke: "currentColor",
2851
- strokeWidth: "1.5",
2852
- strokeLinejoin: "round"
2853
- }
2854
- ),
2855
- /* @__PURE__ */ jsx("path", { d: "M9 7v4", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round" }),
2856
- /* @__PURE__ */ jsx("circle", { cx: "9", cy: "12.5", r: "0.875", fill: "currentColor" })
2857
- ]
2858
- }
4450
+ function getMobileNavItemClass(item) {
4451
+ return cn(
4452
+ "flex flex-col items-center px-3 py-2 text-xs transition-colors",
4453
+ item.active ? "text-accent" : "text-white/50",
4454
+ item.disabled && "pointer-events-none opacity-50"
2859
4455
  );
2860
4456
  }
2861
- function ErrorIcon() {
2862
- return /* @__PURE__ */ jsxs(
2863
- "svg",
4457
+ function renderDefaultNavItem(item, context) {
4458
+ const content = /* @__PURE__ */ jsxs(Fragment, { children: [
4459
+ item.icon ? /* @__PURE__ */ jsx("span", { className: context.type === "mobile" ? "text-lg" : void 0, children: item.icon }) : null,
4460
+ /* @__PURE__ */ jsx("span", { className: cn("min-w-0 truncate", context.type === "desktop" && item.badge && "flex-1"), children: item.label }),
4461
+ context.type === "desktop" && item.badge ? /* @__PURE__ */ jsx("span", { className: "shrink-0", children: item.badge }) : null
4462
+ ] });
4463
+ if (item.href) {
4464
+ return /* @__PURE__ */ jsx(
4465
+ "a",
4466
+ {
4467
+ href: item.href,
4468
+ target: item.target,
4469
+ rel: item.rel,
4470
+ "aria-current": item.active ? "page" : void 0,
4471
+ className: context.className,
4472
+ children: content
4473
+ }
4474
+ );
4475
+ }
4476
+ return /* @__PURE__ */ jsx(
4477
+ "button",
2864
4478
  {
2865
- "aria-hidden": "true",
2866
- width: "18",
2867
- height: "18",
2868
- viewBox: "0 0 18 18",
2869
- fill: "none",
2870
- xmlns: "http://www.w3.org/2000/svg",
2871
- children: [
2872
- /* @__PURE__ */ jsx("circle", { cx: "9", cy: "9", r: "7.5", stroke: "currentColor", strokeWidth: "1.5" }),
2873
- /* @__PURE__ */ jsx(
2874
- "path",
2875
- {
2876
- d: "M6.5 6.5l5 5M11.5 6.5l-5 5",
2877
- stroke: "currentColor",
2878
- strokeWidth: "1.75",
2879
- strokeLinecap: "round"
2880
- }
2881
- )
2882
- ]
4479
+ type: "button",
4480
+ onClick: item.onClick,
4481
+ disabled: item.disabled,
4482
+ "aria-current": item.active ? "page" : void 0,
4483
+ className: context.className,
4484
+ children: content
2883
4485
  }
2884
4486
  );
2885
4487
  }
2886
- var variantIcon = {
2887
- info: InfoIcon,
2888
- success: SuccessIcon,
2889
- warning: WarningIcon,
2890
- error: ErrorIcon
2891
- };
2892
- function Alert({ variant = "info", title, children, onDismiss, className }) {
2893
- const Icon = variantIcon[variant];
2894
- return /* @__PURE__ */ jsxs(
4488
+ function DashboardLayout({
4489
+ children,
4490
+ navbar,
4491
+ sidebar,
4492
+ brand,
4493
+ user,
4494
+ headerActions,
4495
+ navItems,
4496
+ renderNavItem,
4497
+ navigationLabel = "Main navigation",
4498
+ mobileNavigationLabel = "Mobile navigation",
4499
+ shellClassName,
4500
+ shellWidth = "xl",
4501
+ className,
4502
+ mainClassName,
4503
+ maxWidth = "lg"
4504
+ }) {
4505
+ const hasGeneratedHeader = !navbar && Boolean(brand || user || headerActions);
4506
+ const hasGeneratedNavigation = !sidebar && Boolean(navItems?.length);
4507
+ const hasGeneratedShell = hasGeneratedHeader || hasGeneratedNavigation;
4508
+ const renderNav = renderNavItem ?? renderDefaultNavItem;
4509
+ const generatedHeader = hasGeneratedHeader ? /* @__PURE__ */ jsx("header", { className: "sticky top-0 z-40 glass border-b border-white/10", children: /* @__PURE__ */ jsxs(
2895
4510
  "div",
2896
4511
  {
2897
- role: "alert",
2898
4512
  className: cn(
2899
- "flex items-start gap-3 rounded-xl bg-white/5 ring-1 ring-white/10",
2900
- "border-l-4 pl-4 pr-3 py-3",
2901
- variantBorderColor[variant],
2902
- className
4513
+ "mx-auto flex h-16 items-center justify-between gap-4 px-4 sm:px-6 lg:px-8",
4514
+ widthClass[shellWidth]
2903
4515
  ),
2904
4516
  children: [
2905
- /* @__PURE__ */ jsx("span", { className: cn("mt-0.5 shrink-0", variantIconColor[variant]), children: /* @__PURE__ */ jsx(Icon, {}) }),
2906
- /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
2907
- title && /* @__PURE__ */ jsx("p", { className: "text-sm font-semibold text-white leading-snug mb-0.5", children: title }),
2908
- /* @__PURE__ */ jsx("div", { className: "text-sm text-white/70 leading-relaxed", children })
2909
- ] }),
2910
- onDismiss && /* @__PURE__ */ jsx(
2911
- "button",
2912
- {
2913
- type: "button",
2914
- "aria-label": "Dismiss",
2915
- onClick: onDismiss,
2916
- className: cn(
2917
- "shrink-0 flex items-center justify-center h-6 w-6 rounded-lg mt-0.5",
2918
- "text-white/40 transition-colors hover:bg-white/10 hover:text-white/80",
2919
- "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/40"
2920
- ),
2921
- children: /* @__PURE__ */ jsx(
2922
- "svg",
2923
- {
2924
- "aria-hidden": "true",
2925
- width: "10",
2926
- height: "10",
2927
- viewBox: "0 0 10 10",
2928
- fill: "none",
2929
- children: /* @__PURE__ */ jsx("path", { d: "M1 1l8 8M9 1L1 9", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" })
2930
- }
2931
- )
2932
- }
2933
- )
2934
- ]
2935
- }
2936
- );
2937
- }
2938
- function CopyIcon() {
2939
- return /* @__PURE__ */ jsxs(
2940
- "svg",
2941
- {
2942
- "aria-hidden": "true",
2943
- width: "16",
2944
- height: "16",
2945
- viewBox: "0 0 16 16",
2946
- fill: "none",
2947
- xmlns: "http://www.w3.org/2000/svg",
2948
- children: [
2949
- /* @__PURE__ */ jsx("rect", { x: "5", y: "5", width: "9", height: "9", rx: "1.5", stroke: "currentColor", strokeWidth: "1.5" }),
2950
- /* @__PURE__ */ jsx(
2951
- "path",
2952
- {
2953
- 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",
2954
- stroke: "currentColor",
2955
- strokeWidth: "1.5",
2956
- strokeLinecap: "round"
2957
- }
2958
- )
4517
+ /* @__PURE__ */ jsx("div", { className: "min-w-0 flex items-center gap-3", children: brand }),
4518
+ (user || headerActions) && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-4", children: [
4519
+ user,
4520
+ headerActions
4521
+ ] })
2959
4522
  ]
2960
4523
  }
2961
- );
2962
- }
2963
- function CheckIcon() {
2964
- return /* @__PURE__ */ jsx(
2965
- "svg",
4524
+ ) }) : null;
4525
+ const generatedSidebar = hasGeneratedNavigation ? /* @__PURE__ */ jsx("nav", { className: "hidden w-56 shrink-0 md:block", "aria-label": navigationLabel, children: /* @__PURE__ */ jsx("div", { className: "glass sticky top-24 rounded-xl p-3", children: navItems.map((item, index) => {
4526
+ const navContext = {
4527
+ type: "desktop",
4528
+ className: getDesktopNavItemClass(item)
4529
+ };
4530
+ return /* @__PURE__ */ jsx("div", { children: renderNav(item, navContext) }, getItemKey(item, index));
4531
+ }) }) }) : null;
4532
+ const generatedMobileNavigation = hasGeneratedNavigation ? /* @__PURE__ */ jsx(
4533
+ "nav",
2966
4534
  {
2967
- "aria-hidden": "true",
2968
- width: "16",
2969
- height: "16",
2970
- viewBox: "0 0 16 16",
2971
- fill: "none",
2972
- xmlns: "http://www.w3.org/2000/svg",
2973
- children: /* @__PURE__ */ jsx(
2974
- "path",
2975
- {
2976
- d: "M3 8.5l3.5 3.5 6.5-7",
2977
- stroke: "currentColor",
2978
- strokeWidth: "1.75",
2979
- strokeLinecap: "round",
2980
- strokeLinejoin: "round"
2981
- }
2982
- )
4535
+ className: "glass pb-safe fixed bottom-0 left-0 right-0 z-40 border-t border-white/10 px-2 py-1 md:hidden",
4536
+ "aria-label": mobileNavigationLabel,
4537
+ children: /* @__PURE__ */ jsx("div", { className: "flex justify-around", children: navItems.map((item, index) => {
4538
+ const navContext = {
4539
+ type: "mobile",
4540
+ className: getMobileNavItemClass(item)
4541
+ };
4542
+ return /* @__PURE__ */ jsx("div", { children: renderNav(item, navContext) }, getItemKey(item, index));
4543
+ }) })
2983
4544
  }
2984
- );
2985
- }
2986
- function EyeIcon() {
2987
- return /* @__PURE__ */ jsxs(
2988
- "svg",
2989
- {
2990
- "aria-hidden": "true",
2991
- width: "16",
2992
- height: "16",
2993
- viewBox: "0 0 16 16",
2994
- fill: "none",
2995
- xmlns: "http://www.w3.org/2000/svg",
2996
- children: [
2997
- /* @__PURE__ */ jsx(
2998
- "path",
2999
- {
3000
- 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",
3001
- stroke: "currentColor",
3002
- strokeWidth: "1.5",
3003
- strokeLinejoin: "round"
3004
- }
3005
- ),
3006
- /* @__PURE__ */ jsx("circle", { cx: "8", cy: "8", r: "2", stroke: "currentColor", strokeWidth: "1.5" })
3007
- ]
4545
+ ) : null;
4546
+ return /* @__PURE__ */ jsxs("div", { className: cn("min-h-screen bg-surface relative overflow-hidden", className), children: [
4547
+ /* @__PURE__ */ jsxs("div", { "aria-hidden": "true", className: "pointer-events-none fixed inset-0", children: [
4548
+ /* @__PURE__ */ jsx("div", { className: "orb orb-purple w-[400px] h-[400px] -top-[150px] -left-[150px] opacity-15" }),
4549
+ /* @__PURE__ */ jsx("div", { className: "orb orb-blue w-[300px] h-[300px] top-[60%] -right-[100px] opacity-10" })
4550
+ ] }),
4551
+ generatedHeader ?? navbar,
4552
+ hasGeneratedShell ? /* @__PURE__ */ jsxs(Fragment, { children: [
4553
+ /* @__PURE__ */ jsxs("div", { className: cn("mx-auto flex gap-6 px-4 py-6 sm:px-6 lg:px-8", widthClass[shellWidth], shellClassName), children: [
4554
+ generatedSidebar ?? sidebar,
4555
+ /* @__PURE__ */ jsx("main", { className: cn("flex-1 min-w-0", hasGeneratedNavigation && "pb-20 md:pb-0", mainClassName), children: /* @__PURE__ */ jsx("div", { className: cn("mx-auto", widthClass[maxWidth]), children }) })
4556
+ ] }),
4557
+ generatedMobileNavigation
4558
+ ] }) : /* @__PURE__ */ jsxs("div", { className: cn("flex", navbar && "pt-16", shellClassName), children: [
4559
+ sidebar,
4560
+ /* @__PURE__ */ jsx("main", { className: cn("flex-1 min-w-0 py-8 px-6", mainClassName), children: /* @__PURE__ */ jsx("div", { className: cn("mx-auto", widthClass[maxWidth]), children }) })
4561
+ ] })
4562
+ ] });
4563
+ }
4564
+ function CopyIcon() {
4565
+ return /* @__PURE__ */ jsxs("svg", { "aria-hidden": "true", width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
4566
+ /* @__PURE__ */ jsx("rect", { x: "5", y: "5", width: "9", height: "9", rx: "1.5", stroke: "currentColor", strokeWidth: "1.5" }),
4567
+ /* @__PURE__ */ jsx(
4568
+ "path",
4569
+ {
4570
+ 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",
4571
+ stroke: "currentColor",
4572
+ strokeWidth: "1.5",
4573
+ strokeLinecap: "round"
4574
+ }
4575
+ )
4576
+ ] });
4577
+ }
4578
+ function CheckIcon() {
4579
+ return /* @__PURE__ */ jsx("svg", { "aria-hidden": "true", width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsx(
4580
+ "path",
4581
+ {
4582
+ d: "M3 8.5l3.5 3.5 6.5-7",
4583
+ stroke: "currentColor",
4584
+ strokeWidth: "1.75",
4585
+ strokeLinecap: "round",
4586
+ strokeLinejoin: "round"
3008
4587
  }
3009
- );
4588
+ ) });
4589
+ }
4590
+ function EyeIcon() {
4591
+ return /* @__PURE__ */ jsxs("svg", { "aria-hidden": "true", width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
4592
+ /* @__PURE__ */ jsx(
4593
+ "path",
4594
+ {
4595
+ 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",
4596
+ stroke: "currentColor",
4597
+ strokeWidth: "1.5",
4598
+ strokeLinejoin: "round"
4599
+ }
4600
+ ),
4601
+ /* @__PURE__ */ jsx("circle", { cx: "8", cy: "8", r: "2", stroke: "currentColor", strokeWidth: "1.5" })
4602
+ ] });
3010
4603
  }
3011
4604
  function EyeOffIcon() {
3012
- return /* @__PURE__ */ jsx(
3013
- "svg",
4605
+ return /* @__PURE__ */ jsx("svg", { "aria-hidden": "true", width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsx(
4606
+ "path",
3014
4607
  {
3015
- "aria-hidden": "true",
3016
- width: "16",
3017
- height: "16",
3018
- viewBox: "0 0 16 16",
3019
- fill: "none",
3020
- xmlns: "http://www.w3.org/2000/svg",
3021
- children: /* @__PURE__ */ jsx(
3022
- "path",
3023
- {
3024
- 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",
3025
- stroke: "currentColor",
3026
- strokeWidth: "1.5",
3027
- strokeLinecap: "round",
3028
- strokeLinejoin: "round"
3029
- }
3030
- )
4608
+ 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",
4609
+ stroke: "currentColor",
4610
+ strokeWidth: "1.5",
4611
+ strokeLinecap: "round",
4612
+ strokeLinejoin: "round"
3031
4613
  }
3032
- );
4614
+ ) });
3033
4615
  }
3034
4616
  var iconButtonBase = cn(
3035
4617
  "flex items-center justify-center h-7 w-7 rounded-lg shrink-0",
3036
4618
  "text-white/40 transition-colors hover:bg-white/10 hover:text-white/80",
3037
4619
  "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/40"
3038
4620
  );
3039
- function CopyField({ value, label, masked = false, className, id: externalId }) {
4621
+ function defaultMaskFormatter(rawValue) {
4622
+ return "\u2022".repeat(Math.min(rawValue.length, 24));
4623
+ }
4624
+ function CopyField({
4625
+ value,
4626
+ label,
4627
+ description,
4628
+ masked = false,
4629
+ emptyText = "\u2014",
4630
+ rightActions,
4631
+ copyOnClick = false,
4632
+ maskFormatter = defaultMaskFormatter,
4633
+ className,
4634
+ id: externalId
4635
+ }) {
3040
4636
  const generatedId = useId();
3041
4637
  const fieldId = externalId || generatedId;
4638
+ const labelId = label ? `${fieldId}-label` : void 0;
3042
4639
  const { copy, copied } = useClipboard();
3043
4640
  const [revealed, setRevealed] = useState(false);
3044
- const displayValue = masked && !revealed ? "\u2022".repeat(Math.min(value.length, 24)) : value;
4641
+ const hasValue = value.trim().length > 0;
4642
+ const displayValue = !hasValue ? emptyText : masked && !revealed ? maskFormatter(value) : value;
4643
+ const handleCopy = () => {
4644
+ if (!hasValue) return;
4645
+ void copy(value);
4646
+ };
3045
4647
  const field = /* @__PURE__ */ jsxs(
3046
4648
  "div",
3047
4649
  {
3048
4650
  className: cn(
3049
4651
  "flex items-center gap-1 w-full rounded-xl px-3 py-2.5",
3050
4652
  "bg-white/10 ring-1 ring-white/10",
4653
+ copyOnClick && hasValue && "cursor-pointer hover:bg-white/15 focus-within:ring-primary/30",
4654
+ copyOnClick && !hasValue && "cursor-not-allowed opacity-70",
3051
4655
  className
3052
4656
  ),
4657
+ "aria-labelledby": labelId,
4658
+ role: copyOnClick && hasValue ? "button" : void 0,
4659
+ tabIndex: copyOnClick && hasValue ? 0 : void 0,
4660
+ onClick: copyOnClick ? handleCopy : void 0,
4661
+ onKeyDown: copyOnClick && hasValue ? (event) => {
4662
+ if (event.key === "Enter" || event.key === " ") {
4663
+ event.preventDefault();
4664
+ handleCopy();
4665
+ }
4666
+ } : void 0,
3053
4667
  children: [
3054
- /* @__PURE__ */ jsx(
3055
- "span",
3056
- {
3057
- id: fieldId,
3058
- className: "flex-1 min-w-0 truncate text-sm text-white select-all font-mono",
3059
- "aria-label": label,
3060
- children: displayValue
3061
- }
3062
- ),
3063
- masked && /* @__PURE__ */ jsx(
4668
+ /* @__PURE__ */ jsx("span", { id: fieldId, className: "flex-1 min-w-0 truncate text-sm text-white select-all font-mono", children: displayValue }),
4669
+ rightActions,
4670
+ masked && hasValue && /* @__PURE__ */ jsx(
3064
4671
  "button",
3065
4672
  {
3066
4673
  type: "button",
3067
4674
  "aria-label": revealed ? "Hide value" : "Reveal value",
3068
- onClick: () => setRevealed((v) => !v),
4675
+ onClick: (event) => {
4676
+ event.stopPropagation();
4677
+ setRevealed((currentValue) => !currentValue);
4678
+ },
3069
4679
  className: iconButtonBase,
3070
4680
  children: revealed ? /* @__PURE__ */ jsx(EyeOffIcon, {}) : /* @__PURE__ */ jsx(EyeIcon, {})
3071
4681
  }
@@ -3075,7 +4685,11 @@ function CopyField({ value, label, masked = false, className, id: externalId })
3075
4685
  {
3076
4686
  type: "button",
3077
4687
  "aria-label": copied ? "Copied!" : "Copy to clipboard",
3078
- onClick: () => copy(value),
4688
+ onClick: (event) => {
4689
+ event.stopPropagation();
4690
+ handleCopy();
4691
+ },
4692
+ disabled: !hasValue,
3079
4693
  className: cn(iconButtonBase, copied && "text-emerald-400 hover:text-emerald-400"),
3080
4694
  children: copied ? /* @__PURE__ */ jsx(CheckIcon, {}) : /* @__PURE__ */ jsx(CopyIcon, {})
3081
4695
  }
@@ -3085,8 +4699,9 @@ function CopyField({ value, label, masked = false, className, id: externalId })
3085
4699
  );
3086
4700
  if (!label) return field;
3087
4701
  return /* @__PURE__ */ jsxs("div", { children: [
3088
- /* @__PURE__ */ jsx("label", { htmlFor: fieldId, className: "block text-sm text-white/70 mb-1.5", children: label }),
3089
- field
4702
+ /* @__PURE__ */ jsx("div", { id: labelId, className: "block text-sm text-white/70 mb-1.5", children: label }),
4703
+ field,
4704
+ description ? /* @__PURE__ */ jsx("div", { className: "mt-1.5 text-xs text-white/50", children: description }) : null
3090
4705
  ] });
3091
4706
  }
3092
4707
  var ProgressButton = forwardRef(
@@ -3153,7 +4768,7 @@ var variantIconColor2 = {
3153
4768
  warning: "text-amber-400",
3154
4769
  info: "text-primary"
3155
4770
  };
3156
- var positionClass = {
4771
+ var positionClass2 = {
3157
4772
  "top-right": "top-4 right-4 items-end",
3158
4773
  "top-center": "top-4 left-1/2 -translate-x-1/2 items-center",
3159
4774
  "bottom-right": "bottom-4 right-4 items-end",
@@ -3299,8 +4914,11 @@ function ToastProvider({ children, position = "top-right", maxToasts = 5 }) {
3299
4914
  /* @__PURE__ */ jsx(
3300
4915
  "div",
3301
4916
  {
4917
+ role: "region",
3302
4918
  "aria-label": "Notifications",
3303
- className: cn("fixed z-[9999] flex flex-col gap-3 pointer-events-none", positionClass[position]),
4919
+ "aria-live": "polite",
4920
+ "aria-relevant": "additions text",
4921
+ className: cn("fixed z-[9999] flex flex-col gap-3 pointer-events-none", positionClass2[position]),
3304
4922
  children: toasts.map((t) => /* @__PURE__ */ jsx("div", { className: "pointer-events-auto", children: /* @__PURE__ */ jsx(ToastCard, { toast: t, onDismiss: dismiss }) }, t.id))
3305
4923
  }
3306
4924
  ),
@@ -3430,7 +5048,7 @@ function MutationOverlay({
3430
5048
  }
3431
5049
  );
3432
5050
  }
3433
- var sizeClass6 = {
5051
+ var sizeClass7 = {
3434
5052
  sm: "w-8 h-8",
3435
5053
  md: "w-10 h-10",
3436
5054
  lg: "w-12 h-12"
@@ -3448,503 +5066,345 @@ var badgeSizeClass = {
3448
5066
  var DefaultBellIcon = ({ className }) => /* @__PURE__ */ jsxs(
3449
5067
  "svg",
3450
5068
  {
3451
- xmlns: "http://www.w3.org/2000/svg",
3452
- viewBox: "0 0 24 24",
3453
- fill: "none",
3454
- stroke: "currentColor",
3455
- strokeWidth: 2,
3456
- strokeLinecap: "round",
3457
- strokeLinejoin: "round",
3458
- className,
3459
- "aria-hidden": "true",
3460
- children: [
3461
- /* @__PURE__ */ jsx("path", { d: "M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9" }),
3462
- /* @__PURE__ */ jsx("path", { d: "M10.3 21a1.94 1.94 0 0 0 3.4 0" })
3463
- ]
3464
- }
3465
- );
3466
- var NotificationBell = forwardRef(
3467
- function NotificationBell2({ icon, count, maxCount = 99, size = "md", ping, className, disabled, ...props }, ref) {
3468
- const displayCount = count && count > maxCount ? `${maxCount}+` : count;
3469
- const hasCount = count !== void 0 && count > 0;
3470
- return /* @__PURE__ */ jsxs(
3471
- "button",
3472
- {
3473
- ref,
3474
- type: "button",
3475
- ...props,
3476
- disabled,
3477
- "aria-label": props["aria-label"] || `Notifications${hasCount ? ` (${count})` : ""}`,
3478
- className: cn(
3479
- "relative inline-flex items-center justify-center rounded-xl text-white/70 transition-colors hover:text-white hover:bg-white/10 focus-visible:ring-2 focus-visible:ring-primary/40 focus-visible:ring-offset-2 focus-visible:ring-offset-transparent disabled:opacity-60 disabled:pointer-events-none",
3480
- sizeClass6[size],
3481
- className
3482
- ),
3483
- children: [
3484
- icon ? /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: icon }) : /* @__PURE__ */ jsx(DefaultBellIcon, { className: iconSizeClass[size] }),
3485
- hasCount && /* @__PURE__ */ jsxs(
3486
- "span",
3487
- {
3488
- className: cn(
3489
- "absolute top-0 right-0 flex items-center justify-center rounded-full bg-rose-500 text-white font-semibold leading-none",
3490
- badgeSizeClass[size]
3491
- ),
3492
- children: [
3493
- ping && /* @__PURE__ */ jsx("span", { className: "absolute inset-0 rounded-full bg-rose-500 animate-ping opacity-75" }),
3494
- /* @__PURE__ */ jsx("span", { className: "relative", children: displayCount })
3495
- ]
3496
- }
3497
- )
3498
- ]
3499
- }
3500
- );
3501
- }
3502
- );
3503
- var sizeClass7 = {
3504
- xs: "text-sm font-semibold",
3505
- sm: "text-base font-semibold",
3506
- md: "text-lg font-bold",
3507
- lg: "text-xl font-bold",
3508
- xl: "text-2xl font-bold tracking-tight",
3509
- "2xl": "text-3xl font-bold tracking-tight sm:text-4xl"
3510
- };
3511
- var levelToSize = {
3512
- 1: "2xl",
3513
- 2: "xl",
3514
- 3: "lg",
3515
- 4: "md",
3516
- 5: "sm",
3517
- 6: "xs"
3518
- };
3519
- var colorClass = {
3520
- default: "text-white",
3521
- muted: "text-white/70",
3522
- gradient: "text-gradient"
3523
- };
3524
- var Heading = forwardRef(function Heading2({ level = 2, size, color = "default", className, ...props }, ref) {
3525
- const Tag = `h${level}`;
3526
- const effectiveSize = size ?? levelToSize[level];
3527
- return /* @__PURE__ */ jsx(
3528
- Tag,
3529
- {
3530
- ref,
3531
- ...props,
3532
- className: cn(sizeClass7[effectiveSize], colorClass[color], className)
3533
- }
3534
- );
3535
- });
3536
- var sizeMap2 = {
3537
- xs: "text-xs",
3538
- sm: "text-sm",
3539
- md: "text-base",
3540
- lg: "text-lg"
3541
- };
3542
- var colorMap = {
3543
- default: "text-white/90",
3544
- muted: "text-white/70",
3545
- dimmed: "text-white/50",
3546
- primary: "text-primary-light",
3547
- success: "text-emerald-400",
3548
- warning: "text-amber-400",
3549
- danger: "text-rose-400"
3550
- };
3551
- var weightMap = {
3552
- normal: "font-normal",
3553
- medium: "font-medium",
3554
- semibold: "font-semibold",
3555
- bold: "font-bold"
3556
- };
3557
- var Text = forwardRef(function Text2({ size = "md", color = "default", weight = "normal", inline = false, truncate = false, className, ...props }, ref) {
3558
- const Tag = inline ? "span" : "p";
3559
- return /* @__PURE__ */ jsx(
3560
- Tag,
3561
- {
3562
- ref,
3563
- ...props,
3564
- className: cn(
3565
- sizeMap2[size],
3566
- colorMap[color],
3567
- weightMap[weight],
3568
- truncate && "truncate",
3569
- className
3570
- )
3571
- }
3572
- );
3573
- });
3574
- var gapClass = {
3575
- 0: "gap-0",
3576
- 1: "gap-1",
3577
- 2: "gap-2",
3578
- 3: "gap-3",
3579
- 4: "gap-4",
3580
- 5: "gap-5",
3581
- 6: "gap-6",
3582
- 8: "gap-8",
3583
- 10: "gap-10",
3584
- 12: "gap-12"
3585
- };
3586
- var alignClass2 = {
3587
- start: "items-start",
3588
- center: "items-center",
3589
- end: "items-end",
3590
- stretch: "items-stretch",
3591
- baseline: "items-baseline"
3592
- };
3593
- var justifyClass = {
3594
- start: "justify-start",
3595
- center: "justify-center",
3596
- end: "justify-end",
3597
- between: "justify-between",
3598
- around: "justify-around",
3599
- evenly: "justify-evenly"
3600
- };
3601
- var Stack = forwardRef(function Stack2({ children, direction = "vertical", gap = 4, align = "stretch", justify = "start", wrap = false, className, ...props }, ref) {
3602
- return /* @__PURE__ */ jsx(
3603
- "div",
3604
- {
3605
- ref,
3606
- ...props,
3607
- className: cn(
3608
- "flex",
3609
- direction === "vertical" ? "flex-col" : "flex-row",
3610
- gapClass[gap],
3611
- alignClass2[align],
3612
- justifyClass[justify],
3613
- wrap && "flex-wrap",
3614
- className
3615
- ),
3616
- children
3617
- }
3618
- );
3619
- });
3620
- var ScrollArea = forwardRef(function ScrollArea2({ children, maxHeight, hideScrollbar = false, orientation = "vertical", className, style, ...props }, ref) {
3621
- const overflowClass = {
3622
- vertical: "overflow-y-auto overflow-x-hidden",
3623
- horizontal: "overflow-x-auto overflow-y-hidden",
3624
- both: "overflow-auto"
3625
- }[orientation];
3626
- return /* @__PURE__ */ jsx(
3627
- "div",
3628
- {
3629
- ref,
3630
- ...props,
3631
- tabIndex: 0,
3632
- className: cn(
3633
- overflowClass,
3634
- // Custom dark scrollbar styling
3635
- "[&::-webkit-scrollbar]:w-1.5 [&::-webkit-scrollbar]:h-1.5",
3636
- "[&::-webkit-scrollbar-track]:bg-transparent",
3637
- "[&::-webkit-scrollbar-thumb]:rounded-full [&::-webkit-scrollbar-thumb]:bg-white/15 hover:[&::-webkit-scrollbar-thumb]:bg-white/25",
3638
- hideScrollbar && "no-scrollbar",
3639
- "focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-primary/30 focus-visible:ring-inset",
3640
- className
3641
- ),
3642
- style: {
3643
- maxHeight: typeof maxHeight === "number" ? `${maxHeight}px` : maxHeight,
3644
- ...style
3645
- },
3646
- children
3647
- }
3648
- );
3649
- });
3650
- var defaultSeparator = /* @__PURE__ */ jsx(
3651
- "svg",
3652
- {
3653
- className: "w-3.5 h-3.5 text-white/30 flex-shrink-0",
3654
- viewBox: "0 0 16 16",
5069
+ xmlns: "http://www.w3.org/2000/svg",
5070
+ viewBox: "0 0 24 24",
3655
5071
  fill: "none",
3656
5072
  stroke: "currentColor",
3657
- strokeWidth: "2",
5073
+ strokeWidth: 2,
3658
5074
  strokeLinecap: "round",
5075
+ strokeLinejoin: "round",
5076
+ className,
3659
5077
  "aria-hidden": "true",
3660
- children: /* @__PURE__ */ jsx("path", { d: "M6 4l4 4-4 4" })
5078
+ children: [
5079
+ /* @__PURE__ */ jsx("path", { d: "M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9" }),
5080
+ /* @__PURE__ */ jsx("path", { d: "M10.3 21a1.94 1.94 0 0 0 3.4 0" })
5081
+ ]
3661
5082
  }
3662
5083
  );
3663
- function Breadcrumbs({ items, separator = defaultSeparator, className }) {
3664
- if (items.length === 0) return null;
3665
- return /* @__PURE__ */ jsx("nav", { "aria-label": "Breadcrumb", className: cn("flex items-center", className), children: /* @__PURE__ */ jsx("ol", { className: "flex items-center gap-1.5 text-sm", children: items.map((item, index) => {
3666
- const isLast = index === items.length - 1;
3667
- return /* @__PURE__ */ jsxs("li", { className: "flex items-center gap-1.5", children: [
3668
- index > 0 && separator,
3669
- isLast ? /* @__PURE__ */ jsx("span", { className: "text-white font-medium", "aria-current": "page", children: item.label }) : item.href ? /* @__PURE__ */ jsx(
3670
- "a",
3671
- {
3672
- href: item.href,
3673
- onClick: item.onClick,
3674
- className: "text-white/50 hover:text-white/80 transition-colors",
3675
- children: item.label
3676
- }
3677
- ) : item.onClick ? /* @__PURE__ */ jsx(
3678
- "button",
3679
- {
3680
- type: "button",
3681
- onClick: item.onClick,
3682
- className: "text-white/50 hover:text-white/80 transition-colors",
3683
- children: item.label
3684
- }
3685
- ) : /* @__PURE__ */ jsx("span", { className: "text-white/50", children: item.label })
3686
- ] }, index);
3687
- }) }) });
3688
- }
3689
- function Popover({
3690
- content,
3691
- children,
3692
- placement = "bottom",
3693
- closeOnClickOutside = true,
3694
- closeOnEsc = true,
3695
- open: controlledOpen,
3696
- onOpenChange,
3697
- offset = 8,
3698
- className
3699
- }) {
3700
- const popoverId = useId();
3701
- const anchorRef = useRef(null);
3702
- const popoverRef = useRef(null);
3703
- const [internalOpen, setInternalOpen] = useState(false);
3704
- const [pos, setPos] = useState(null);
3705
- const isControlled = controlledOpen !== void 0;
3706
- const isOpen = isControlled ? controlledOpen : internalOpen;
3707
- const setOpen = useCallback(
3708
- (value) => {
3709
- if (!isControlled) setInternalOpen(value);
3710
- onOpenChange?.(value);
3711
- },
3712
- [isControlled, onOpenChange]
3713
- );
3714
- const toggle = useCallback(() => setOpen(!isOpen), [isOpen, setOpen]);
3715
- const close = useCallback(() => setOpen(false), [setOpen]);
3716
- const updatePosition = useCallback(() => {
3717
- const el = anchorRef.current;
3718
- if (!el) return;
3719
- const r = el.getBoundingClientRect();
3720
- let left;
3721
- let top;
3722
- let effPlacement = placement;
3723
- if (placement === "bottom" || placement === "top") {
3724
- left = r.left + r.width / 2;
3725
- if (placement === "bottom") {
3726
- top = r.bottom + offset;
3727
- if (top + 200 > window.innerHeight && r.top - offset > 200) {
3728
- effPlacement = "top";
3729
- top = r.top - offset;
3730
- }
3731
- } else {
3732
- top = r.top - offset;
3733
- if (top < 8) {
3734
- effPlacement = "bottom";
3735
- top = r.bottom + offset;
3736
- }
3737
- }
3738
- } else {
3739
- top = r.top + r.height / 2;
3740
- if (placement === "right") {
3741
- left = r.right + offset;
3742
- } else {
3743
- left = r.left - offset;
3744
- }
3745
- }
3746
- setPos({ left: Math.round(left), top: Math.round(top), placement: effPlacement });
3747
- }, [placement, offset]);
3748
- useEffect(() => {
3749
- if (!isOpen) return;
3750
- updatePosition();
3751
- window.addEventListener("scroll", updatePosition, true);
3752
- window.addEventListener("resize", updatePosition);
3753
- return () => {
3754
- window.removeEventListener("scroll", updatePosition, true);
3755
- window.removeEventListener("resize", updatePosition);
3756
- };
3757
- }, [isOpen, updatePosition]);
3758
- useEffect(() => {
3759
- if (!isOpen || !closeOnClickOutside) return;
3760
- const handleClick = (e) => {
3761
- const target = e.target;
3762
- if (anchorRef.current?.contains(target) || popoverRef.current?.contains(target)) {
3763
- return;
3764
- }
3765
- close();
3766
- };
3767
- document.addEventListener("mousedown", handleClick);
3768
- return () => document.removeEventListener("mousedown", handleClick);
3769
- }, [isOpen, closeOnClickOutside, close]);
3770
- useEffect(() => {
3771
- if (!isOpen || !closeOnEsc) return;
3772
- const handleKey = (e) => {
3773
- if (e.key === "Escape") {
3774
- e.preventDefault();
3775
- close();
3776
- anchorRef.current?.focus();
5084
+ var NotificationBell = forwardRef(
5085
+ function NotificationBell2({ icon, count, maxCount = 99, size = "md", ping, className, disabled, ...props }, ref) {
5086
+ const displayCount = count && count > maxCount ? `${maxCount}+` : count;
5087
+ const hasCount = count !== void 0 && count > 0;
5088
+ return /* @__PURE__ */ jsxs(
5089
+ "button",
5090
+ {
5091
+ ref,
5092
+ type: "button",
5093
+ ...props,
5094
+ disabled,
5095
+ "aria-label": props["aria-label"] || `Notifications${hasCount ? ` (${count})` : ""}`,
5096
+ className: cn(
5097
+ "relative inline-flex items-center justify-center rounded-xl text-white/70 transition-colors hover:text-white hover:bg-white/10 focus-visible:ring-2 focus-visible:ring-primary/40 focus-visible:ring-offset-2 focus-visible:ring-offset-transparent disabled:opacity-60 disabled:pointer-events-none",
5098
+ sizeClass7[size],
5099
+ className
5100
+ ),
5101
+ children: [
5102
+ icon ? /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: icon }) : /* @__PURE__ */ jsx(DefaultBellIcon, { className: iconSizeClass[size] }),
5103
+ hasCount && /* @__PURE__ */ jsxs(
5104
+ "span",
5105
+ {
5106
+ className: cn(
5107
+ "absolute top-0 right-0 flex items-center justify-center rounded-full bg-rose-500 text-white font-semibold leading-none",
5108
+ badgeSizeClass[size]
5109
+ ),
5110
+ children: [
5111
+ ping && /* @__PURE__ */ jsx("span", { className: "absolute inset-0 rounded-full bg-rose-500 animate-ping opacity-75" }),
5112
+ /* @__PURE__ */ jsx("span", { className: "relative", children: displayCount })
5113
+ ]
5114
+ }
5115
+ )
5116
+ ]
3777
5117
  }
3778
- };
3779
- document.addEventListener("keydown", handleKey);
3780
- return () => document.removeEventListener("keydown", handleKey);
3781
- }, [isOpen, closeOnEsc, close]);
3782
- if (!isValidElement(children)) return children;
3783
- const child = cloneElement(children, {
3784
- ref: (node) => {
3785
- anchorRef.current = node;
3786
- const childProps = children.props;
3787
- const prevRef = childProps.ref;
3788
- if (typeof prevRef === "function") prevRef(node);
3789
- else if (prevRef && typeof prevRef === "object") prevRef.current = node;
3790
- },
3791
- onClick: (e) => {
3792
- const childProps = children.props;
3793
- if (typeof childProps.onClick === "function") childProps.onClick(e);
3794
- toggle();
3795
- },
3796
- "aria-expanded": isOpen,
3797
- "aria-haspopup": "dialog",
3798
- "aria-controls": isOpen ? popoverId : void 0
3799
- });
3800
- const getTransform = () => {
3801
- if (!pos) return "translate(-9999px, -9999px)";
3802
- switch (pos.placement) {
3803
- case "top":
3804
- return "translate(-50%, -100%)";
3805
- case "bottom":
3806
- return "translate(-50%, 0%)";
3807
- case "left":
3808
- return "translate(-100%, -50%)";
3809
- case "right":
3810
- return "translate(0%, -50%)";
3811
- }
3812
- };
3813
- return /* @__PURE__ */ jsxs(Fragment, { children: [
3814
- child,
3815
- isOpen && typeof document !== "undefined" ? createPortal(
3816
- /* @__PURE__ */ jsx(
3817
- "div",
3818
- {
3819
- ref: popoverRef,
3820
- id: popoverId,
3821
- role: "dialog",
3822
- className: cn(
3823
- "fixed z-[9999] rounded-xl shadow-xl ring-1 ring-white/10 bg-surface-50 backdrop-blur-md p-4",
3824
- className
3825
- ),
3826
- style: {
3827
- left: pos?.left ?? 0,
3828
- top: pos?.top ?? 0,
3829
- transform: getTransform()
3830
- },
3831
- children: content
3832
- }
3833
- ),
3834
- document.body
3835
- ) : null
3836
- ] });
3837
- }
5118
+ );
5119
+ }
5120
+ );
3838
5121
  var sizeClass8 = {
3839
- left: { sm: "w-64", md: "w-80", lg: "w-96", full: "w-screen" },
3840
- right: { sm: "w-64", md: "w-80", lg: "w-96", full: "w-screen" },
3841
- bottom: { sm: "h-1/4", md: "h-1/3", lg: "h-1/2", full: "h-screen" }
5122
+ xs: "text-sm font-semibold",
5123
+ sm: "text-base font-semibold",
5124
+ md: "text-lg font-bold",
5125
+ lg: "text-xl font-bold",
5126
+ xl: "text-2xl font-bold tracking-tight",
5127
+ "2xl": "text-3xl font-bold tracking-tight sm:text-4xl"
5128
+ };
5129
+ var levelToSize = {
5130
+ 1: "2xl",
5131
+ 2: "xl",
5132
+ 3: "lg",
5133
+ 4: "md",
5134
+ 5: "sm",
5135
+ 6: "xs"
5136
+ };
5137
+ var colorClass = {
5138
+ default: "text-white",
5139
+ muted: "text-white/70",
5140
+ gradient: "text-gradient"
5141
+ };
5142
+ var Heading = forwardRef(function Heading2({ level = 2, size, color = "default", className, ...props }, ref) {
5143
+ const Tag = `h${level}`;
5144
+ const effectiveSize = size ?? levelToSize[level];
5145
+ return /* @__PURE__ */ jsx(
5146
+ Tag,
5147
+ {
5148
+ ref,
5149
+ ...props,
5150
+ className: cn(sizeClass8[effectiveSize], colorClass[color], className)
5151
+ }
5152
+ );
5153
+ });
5154
+ var sizeMap2 = {
5155
+ xs: "text-xs",
5156
+ sm: "text-sm",
5157
+ md: "text-base",
5158
+ lg: "text-lg"
5159
+ };
5160
+ var colorMap = {
5161
+ default: "text-white/90",
5162
+ muted: "text-white/70",
5163
+ dimmed: "text-white/50",
5164
+ primary: "text-primary-light",
5165
+ success: "text-emerald-400",
5166
+ warning: "text-amber-400",
5167
+ danger: "text-rose-400"
3842
5168
  };
3843
- var positionClass2 = {
3844
- left: "inset-y-0 left-0",
3845
- right: "inset-y-0 right-0",
3846
- bottom: "inset-x-0 bottom-0"
5169
+ var weightMap = {
5170
+ normal: "font-normal",
5171
+ medium: "font-medium",
5172
+ semibold: "font-semibold",
5173
+ bold: "font-bold"
3847
5174
  };
3848
- var slideIn = {
3849
- left: "translate-x-0",
3850
- right: "translate-x-0",
3851
- bottom: "translate-y-0"
5175
+ var Text = forwardRef(function Text2({ size = "md", color = "default", weight = "normal", inline = false, truncate = false, className, ...props }, ref) {
5176
+ const Tag = inline ? "span" : "p";
5177
+ return /* @__PURE__ */ jsx(
5178
+ Tag,
5179
+ {
5180
+ ref,
5181
+ ...props,
5182
+ className: cn(
5183
+ sizeMap2[size],
5184
+ colorMap[color],
5185
+ weightMap[weight],
5186
+ truncate && "truncate",
5187
+ className
5188
+ )
5189
+ }
5190
+ );
5191
+ });
5192
+ var gapClass = {
5193
+ 0: "gap-0",
5194
+ 1: "gap-1",
5195
+ 2: "gap-2",
5196
+ 3: "gap-3",
5197
+ 4: "gap-4",
5198
+ 5: "gap-5",
5199
+ 6: "gap-6",
5200
+ 8: "gap-8",
5201
+ 10: "gap-10",
5202
+ 12: "gap-12"
3852
5203
  };
3853
- var slideOut = {
3854
- left: "-translate-x-full",
3855
- right: "translate-x-full",
3856
- bottom: "translate-y-full"
5204
+ var alignClass2 = {
5205
+ start: "items-start",
5206
+ center: "items-center",
5207
+ end: "items-end",
5208
+ stretch: "items-stretch",
5209
+ baseline: "items-baseline"
3857
5210
  };
3858
- function Drawer({
3859
- isOpen,
3860
- onClose,
3861
- children,
3862
- side = "right",
3863
- size = "md",
3864
- ariaLabel,
3865
- closeOnBackdrop = true,
3866
- closeOnEsc = true,
5211
+ var justifyClass = {
5212
+ start: "justify-start",
5213
+ center: "justify-center",
5214
+ end: "justify-end",
5215
+ between: "justify-between",
5216
+ around: "justify-around",
5217
+ evenly: "justify-evenly"
5218
+ };
5219
+ var Stack = forwardRef(function Stack2({ children, direction = "vertical", gap = 4, align = "stretch", justify = "start", wrap = false, className, ...props }, ref) {
5220
+ return /* @__PURE__ */ jsx(
5221
+ "div",
5222
+ {
5223
+ ref,
5224
+ ...props,
5225
+ className: cn(
5226
+ "flex",
5227
+ direction === "vertical" ? "flex-col" : "flex-row",
5228
+ gapClass[gap],
5229
+ alignClass2[align],
5230
+ justifyClass[justify],
5231
+ wrap && "flex-wrap",
5232
+ className
5233
+ ),
5234
+ children
5235
+ }
5236
+ );
5237
+ });
5238
+ var ScrollArea = forwardRef(function ScrollArea2({ children, maxHeight, hideScrollbar = false, orientation = "vertical", className, style, ...props }, ref) {
5239
+ const overflowClass = {
5240
+ vertical: "overflow-y-auto overflow-x-hidden",
5241
+ horizontal: "overflow-x-auto overflow-y-hidden",
5242
+ both: "overflow-auto"
5243
+ }[orientation];
5244
+ return /* @__PURE__ */ jsx(
5245
+ "div",
5246
+ {
5247
+ ref,
5248
+ ...props,
5249
+ tabIndex: 0,
5250
+ className: cn(
5251
+ overflowClass,
5252
+ // Custom dark scrollbar styling
5253
+ "[&::-webkit-scrollbar]:w-1.5 [&::-webkit-scrollbar]:h-1.5",
5254
+ "[&::-webkit-scrollbar-track]:bg-transparent",
5255
+ "[&::-webkit-scrollbar-thumb]:rounded-full [&::-webkit-scrollbar-thumb]:bg-white/15 hover:[&::-webkit-scrollbar-thumb]:bg-white/25",
5256
+ hideScrollbar && "no-scrollbar",
5257
+ "focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-primary/30 focus-visible:ring-inset",
5258
+ className
5259
+ ),
5260
+ style: {
5261
+ maxHeight: typeof maxHeight === "number" ? `${maxHeight}px` : maxHeight,
5262
+ ...style
5263
+ },
5264
+ children
5265
+ }
5266
+ );
5267
+ });
5268
+ var defaultSeparator = /* @__PURE__ */ jsx(
5269
+ "svg",
5270
+ {
5271
+ className: "w-3.5 h-3.5 text-white/30 flex-shrink-0",
5272
+ viewBox: "0 0 16 16",
5273
+ fill: "none",
5274
+ stroke: "currentColor",
5275
+ strokeWidth: "2",
5276
+ strokeLinecap: "round",
5277
+ "aria-hidden": "true",
5278
+ children: /* @__PURE__ */ jsx("path", { d: "M6 4l4 4-4 4" })
5279
+ }
5280
+ );
5281
+ function DotsIcon() {
5282
+ return /* @__PURE__ */ jsxs("svg", { "aria-hidden": "true", className: "h-4 w-4", viewBox: "0 0 16 16", fill: "currentColor", children: [
5283
+ /* @__PURE__ */ jsx("circle", { cx: "3", cy: "8", r: "1.25" }),
5284
+ /* @__PURE__ */ jsx("circle", { cx: "8", cy: "8", r: "1.25" }),
5285
+ /* @__PURE__ */ jsx("circle", { cx: "13", cy: "8", r: "1.25" })
5286
+ ] });
5287
+ }
5288
+ function renderItemContent(item) {
5289
+ return /* @__PURE__ */ jsxs("span", { className: "inline-flex min-w-0 items-center gap-1.5", children: [
5290
+ item.icon ? /* @__PURE__ */ jsx("span", { className: "shrink-0 text-white/45", children: item.icon }) : null,
5291
+ /* @__PURE__ */ jsx("span", { className: "truncate", children: item.label })
5292
+ ] });
5293
+ }
5294
+ function getVisibleItems(items, maxItems, itemsBeforeCollapse = 1, itemsAfterCollapse = 1) {
5295
+ if (!maxItems || items.length <= maxItems) {
5296
+ return items.map((item, index) => ({ type: "item", item, originalIndex: index }));
5297
+ }
5298
+ const before = Math.max(1, itemsBeforeCollapse);
5299
+ const after = Math.max(1, itemsAfterCollapse);
5300
+ if (before + after >= items.length) {
5301
+ return items.map((item, index) => ({ type: "item", item, originalIndex: index }));
5302
+ }
5303
+ const collapsedItems = items.slice(before, items.length - after);
5304
+ const startItems = items.slice(0, before).map((item, index) => ({ type: "item", item, originalIndex: index }));
5305
+ const endItems = items.slice(items.length - after).map((item, index) => ({
5306
+ type: "item",
5307
+ item,
5308
+ originalIndex: items.length - after + index
5309
+ }));
5310
+ return [
5311
+ ...startItems,
5312
+ { type: "collapse", items: collapsedItems },
5313
+ ...endItems
5314
+ ];
5315
+ }
5316
+ function Breadcrumbs({
5317
+ items,
5318
+ separator = defaultSeparator,
5319
+ maxItems,
5320
+ itemsBeforeCollapse = 1,
5321
+ itemsAfterCollapse = 1,
5322
+ renderLink,
3867
5323
  className
3868
5324
  }) {
3869
- const panelRef = useRef(null);
3870
- const lastActiveRef = useRef(null);
3871
- useEffect(() => {
3872
- if (!isOpen) return;
3873
- lastActiveRef.current = document.activeElement instanceof HTMLElement ? document.activeElement : null;
3874
- const raf = requestAnimationFrame(() => {
3875
- const el = panelRef.current;
3876
- if (!el) return;
3877
- const focusables = getFocusableElements(el);
3878
- focusSafely(focusables[0] ?? el);
3879
- });
3880
- return () => {
3881
- cancelAnimationFrame(raf);
3882
- const lastActive = lastActiveRef.current;
3883
- lastActiveRef.current = null;
3884
- if (lastActive?.isConnected) focusSafely(lastActive);
3885
- };
3886
- }, [isOpen]);
3887
- useScrollLock(isOpen);
3888
- if (!isOpen) return null;
3889
- return /* @__PURE__ */ jsxs("div", { className: "fixed inset-0 z-50", role: "presentation", children: [
3890
- /* @__PURE__ */ jsx(
3891
- "div",
3892
- {
3893
- className: "absolute inset-0 bg-black/40 backdrop-blur-sm transition-opacity duration-200",
3894
- "aria-hidden": "true",
3895
- onClick: closeOnBackdrop ? onClose : void 0
3896
- }
3897
- ),
3898
- /* @__PURE__ */ jsx(
3899
- "div",
3900
- {
3901
- ref: panelRef,
3902
- role: "dialog",
3903
- "aria-modal": "true",
3904
- "aria-label": ariaLabel,
3905
- tabIndex: -1,
3906
- className: cn(
3907
- "fixed flex flex-col bg-surface-50 shadow-2xl ring-1 ring-white/10 transition-transform duration-300 ease-out focus:outline-none",
3908
- positionClass2[side],
3909
- sizeClass8[side][size],
3910
- isOpen ? slideIn[side] : slideOut[side],
3911
- className
3912
- ),
3913
- onKeyDownCapture: (e) => {
3914
- if (closeOnEsc && e.key === "Escape") {
3915
- e.preventDefault();
3916
- e.stopPropagation();
3917
- onClose();
3918
- return;
3919
- }
3920
- if (e.key !== "Tab") return;
3921
- const el = panelRef.current;
3922
- if (!el) return;
3923
- const focusables = getFocusableElements(el);
3924
- if (focusables.length === 0) {
3925
- e.preventDefault();
3926
- focusSafely(el);
3927
- return;
3928
- }
3929
- const active = document.activeElement;
3930
- const first = focusables[0];
3931
- const last = focusables[focusables.length - 1];
3932
- if (e.shiftKey) {
3933
- if (active === first) {
3934
- e.preventDefault();
3935
- focusSafely(last);
3936
- }
3937
- } else {
3938
- if (active === last) {
3939
- e.preventDefault();
3940
- focusSafely(first);
3941
- }
5325
+ if (items.length === 0) return null;
5326
+ const visibleItems = getVisibleItems(items, maxItems, itemsBeforeCollapse, itemsAfterCollapse);
5327
+ const lastItemIndex = items.length - 1;
5328
+ const renderLinkNode = (item, classNameValue) => {
5329
+ const content = renderItemContent(item);
5330
+ if (!item.href) {
5331
+ return content;
5332
+ }
5333
+ if (renderLink) {
5334
+ return renderLink({
5335
+ href: item.href,
5336
+ onClick: item.onClick,
5337
+ className: classNameValue,
5338
+ children: content,
5339
+ item
5340
+ });
5341
+ }
5342
+ return /* @__PURE__ */ jsx("a", { href: item.href, onClick: item.onClick, className: classNameValue, children: content });
5343
+ };
5344
+ return /* @__PURE__ */ jsx("nav", { "aria-label": "Breadcrumb", className: cn("flex items-center", className), children: /* @__PURE__ */ jsx("ol", { className: "flex min-w-0 items-center gap-1.5 text-sm", children: visibleItems.map((entry, index) => {
5345
+ if (entry.type === "collapse") {
5346
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [
5347
+ index > 0 ? /* @__PURE__ */ jsx("li", { className: "flex items-center", children: separator }) : null,
5348
+ /* @__PURE__ */ jsx("li", { className: "flex items-center", children: /* @__PURE__ */ jsx(
5349
+ Popover,
5350
+ {
5351
+ placement: "bottom",
5352
+ className: "min-w-[12rem] p-2",
5353
+ content: /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-1", children: entry.items.map((item2, hiddenIndex) => /* @__PURE__ */ jsx("div", { children: item2.href ? renderLink ? renderLink({
5354
+ href: item2.href,
5355
+ onClick: item2.onClick,
5356
+ className: "flex w-full items-center rounded-lg px-3 py-2 text-sm text-white/75 transition-colors hover:bg-white/10 hover:text-white",
5357
+ children: renderItemContent(item2),
5358
+ item: item2
5359
+ }) : /* @__PURE__ */ jsx(
5360
+ "a",
5361
+ {
5362
+ href: item2.href,
5363
+ onClick: item2.onClick,
5364
+ className: "flex w-full items-center rounded-lg px-3 py-2 text-sm text-white/75 transition-colors hover:bg-white/10 hover:text-white",
5365
+ children: renderItemContent(item2)
5366
+ }
5367
+ ) : item2.onClick ? /* @__PURE__ */ jsx(
5368
+ "button",
5369
+ {
5370
+ type: "button",
5371
+ onClick: item2.onClick,
5372
+ className: "flex w-full items-center rounded-lg px-3 py-2 text-left text-sm text-white/75 transition-colors hover:bg-white/10 hover:text-white",
5373
+ children: renderItemContent(item2)
5374
+ }
5375
+ ) : /* @__PURE__ */ jsx("div", { className: "flex w-full items-center rounded-lg px-3 py-2 text-sm text-white/55", children: renderItemContent(item2) }) }, `${hiddenIndex}-${String(item2.href ?? item2.label)}`)) }),
5376
+ children: /* @__PURE__ */ jsx(
5377
+ "button",
5378
+ {
5379
+ type: "button",
5380
+ "aria-label": "Show hidden breadcrumbs",
5381
+ className: "inline-flex h-8 w-8 items-center justify-center rounded-lg text-white/45 transition-colors hover:bg-white/10 hover:text-white focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/40",
5382
+ children: /* @__PURE__ */ jsx(DotsIcon, {})
5383
+ }
5384
+ )
3942
5385
  }
3943
- },
3944
- children
3945
- }
3946
- )
3947
- ] });
5386
+ ) })
5387
+ ] }, `collapse-${index}`);
5388
+ }
5389
+ const isLast = entry.originalIndex === lastItemIndex;
5390
+ const item = entry.item;
5391
+ const interactiveClassName = "text-white/50 hover:text-white/80 transition-colors";
5392
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [
5393
+ index > 0 ? /* @__PURE__ */ jsx("li", { className: "flex items-center", children: separator }) : null,
5394
+ /* @__PURE__ */ jsx("li", { className: "flex min-w-0 items-center", children: isLast ? /* @__PURE__ */ jsxs("span", { className: "inline-flex min-w-0 items-center gap-1.5 text-white font-medium", "aria-current": "page", children: [
5395
+ item.icon ? /* @__PURE__ */ jsx("span", { className: "shrink-0 text-white/55", children: item.icon }) : null,
5396
+ /* @__PURE__ */ jsx("span", { className: "truncate", children: item.label })
5397
+ ] }) : item.href ? renderLinkNode(item, interactiveClassName) : item.onClick ? /* @__PURE__ */ jsx(
5398
+ "button",
5399
+ {
5400
+ type: "button",
5401
+ onClick: item.onClick,
5402
+ className: cn("min-w-0", interactiveClassName),
5403
+ children: renderItemContent(item)
5404
+ }
5405
+ ) : /* @__PURE__ */ jsx("span", { className: "text-white/50", children: renderItemContent(item) }) })
5406
+ ] }, `${entry.originalIndex}-${String(item.href ?? item.label)}`);
5407
+ }) }) });
3948
5408
  }
3949
5409
  var defaultFilter = (opt, q) => opt.label.toLowerCase().includes(q.toLowerCase());
3950
5410
  var Combobox = forwardRef(function Combobox2({
@@ -4267,6 +5727,12 @@ function VisuallyHidden({ children, as: Tag = "span", style, ...props }) {
4267
5727
  }
4268
5728
  );
4269
5729
  }
5730
+ function didResetKeysChange(previous, next) {
5731
+ if (!previous && !next) return false;
5732
+ if (!previous || !next) return true;
5733
+ if (previous.length !== next.length) return true;
5734
+ return previous.some((value, index) => !Object.is(value, next[index]));
5735
+ }
4270
5736
  var ErrorBoundary = class extends Component {
4271
5737
  constructor() {
4272
5738
  super(...arguments);
@@ -4281,6 +5747,12 @@ var ErrorBoundary = class extends Component {
4281
5747
  componentDidCatch(error, errorInfo) {
4282
5748
  this.props.onError?.(error, errorInfo);
4283
5749
  }
5750
+ componentDidUpdate(prevProps) {
5751
+ if (!this.state.error) return;
5752
+ if (!Object.is(prevProps.resetKey, this.props.resetKey) || didResetKeysChange(prevProps.resetKeys, this.props.resetKeys)) {
5753
+ this.reset();
5754
+ }
5755
+ }
4284
5756
  render() {
4285
5757
  const { error } = this.state;
4286
5758
  if (!error) return this.props.children;
@@ -4291,19 +5763,40 @@ var ErrorBoundary = class extends Component {
4291
5763
  if (fallback !== void 0) {
4292
5764
  return fallback;
4293
5765
  }
4294
- return /* @__PURE__ */ jsxs("div", { role: "alert", className: cn("glass rounded-xl p-6 text-center"), children: [
4295
- /* @__PURE__ */ jsx("h2", { className: "text-lg font-semibold text-white mb-2", children: "Something went wrong" }),
4296
- /* @__PURE__ */ jsx("p", { className: "text-sm text-white/60 mb-4", children: error.message }),
4297
- /* @__PURE__ */ jsx(
4298
- "button",
4299
- {
4300
- type: "button",
4301
- onClick: this.reset,
4302
- className: "inline-flex items-center justify-center gap-2 rounded-xl font-semibold leading-none px-3.5 py-2.5 text-sm bg-gradient-to-r from-violet-600 to-purple-600 text-white shadow-glow hover:shadow-glow-lg hover:scale-[1.02] transition-[transform,background-color,box-shadow,opacity] active:translate-y-[0.5px]",
4303
- children: "Try again"
4304
- }
4305
- )
4306
- ] });
5766
+ const {
5767
+ actionLabel = "Try again",
5768
+ description,
5769
+ fullScreen = false,
5770
+ onAction,
5771
+ title = "Something went wrong"
5772
+ } = this.props;
5773
+ const descriptionContent = typeof description === "function" ? description(error) : description ?? error.message;
5774
+ const handleAction = () => {
5775
+ if (onAction) {
5776
+ onAction({ error, reset: this.reset });
5777
+ return;
5778
+ }
5779
+ this.reset();
5780
+ };
5781
+ const content = /* @__PURE__ */ jsxs(
5782
+ "div",
5783
+ {
5784
+ role: "alert",
5785
+ className: cn(
5786
+ "glass rounded-xl p-6 text-center",
5787
+ fullScreen && "w-full max-w-md rounded-2xl p-8 shadow-surface"
5788
+ ),
5789
+ children: [
5790
+ /* @__PURE__ */ jsx("h2", { className: "text-lg font-semibold text-white mb-2", children: title }),
5791
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-white/60 mb-4", children: descriptionContent }),
5792
+ /* @__PURE__ */ jsx(Button, { type: "button", variant: "primary", onClick: handleAction, children: actionLabel })
5793
+ ]
5794
+ }
5795
+ );
5796
+ if (fullScreen) {
5797
+ return /* @__PURE__ */ jsx("div", { className: "min-h-screen bg-surface flex items-center justify-center p-6", children: content });
5798
+ }
5799
+ return content;
4307
5800
  }
4308
5801
  };
4309
5802
  function LoadingScreen({ message, size = "lg", className }) {
@@ -4323,4 +5816,4 @@ function LoadingScreen({ message, size = "lg", className }) {
4323
5816
  );
4324
5817
  }
4325
5818
 
4326
- export { ActiveFilterPills, Alert, Avatar, Badge, Breadcrumbs, Button, Card, Checkbox, CollapsibleSection, ColorInput, Combobox, ConfirmDialog, CooldownRing, CopyField, DashboardLayout, Divider, DotIndicator, Drawer, DropZone, Dropdown, DropdownItem, DropdownMenu, DropdownSeparator, DropdownTrigger, EmptyState, ErrorBoundary, FormField, Heading, IconButton, Input, LoadingScreen, Modal, MutationOverlay, Navbar, NotificationBell, PageShell, Pagination, Pill, Popover, ProgressBar, ProgressButton, RadioGroup, RadioItem, ScrollArea, SearchInput, SectionCard, Select, Sidebar, Skeleton, Slider, Spinner, Stack, StageProgress, StatCard, Stepper, Tab, TabList, TabPanel, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, Tabs, TagInput, Text, Textarea, ToastProvider, Toggle, Tooltip, Transition, VisuallyHidden, cn, colors, focusSafely, getFocusableElements, useClipboard, useDebounce, useDisclosure, useHotkeys, useIntersectionObserver, useMediaQuery, useScrollLock, useSharedNow, useToast };
5819
+ export { ActiveFilterPills, Alert, Avatar, Badge, Breadcrumbs, Button, Card, Checkbox, CollapsibleSection, ColorInput, Combobox, ConfirmDialog, CooldownRing, CopyField, DashboardLayout, DataTable, DateRangePicker, Divider, DotIndicator, Drawer, DropZone, Dropdown, DropdownItem, DropdownMenu, DropdownSeparator, DropdownTrigger, EmptyState, ErrorBoundary, FormField, Heading, IconButton, Input, LoadingScreen, Modal, MutationOverlay, Navbar, NotificationBell, PageShell, Pagination, Pill, Popover, ProgressBar, ProgressButton, RadioGroup, RadioItem, ScrollArea, SearchInput, SectionCard, Select, Sidebar, Skeleton, Slider, Spinner, Stack, StageProgress, StatCard, Stepper, Tab, TabList, TabPanel, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, Tabs, TagInput, Text, Textarea, Timeline, ToastProvider, Toggle, Tooltip, Transition, VisuallyHidden, cn, colors, focusSafely, getFocusableElements, useClipboard, useDebounce, useDisclosure, useHotkeys, useIntersectionObserver, useMediaQuery, useScrollLock, useSharedNow, useToast };