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