@memelabui/ui 0.5.1 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -3470,5 +3470,793 @@ var NotificationBell = forwardRef(
3470
3470
  );
3471
3471
  }
3472
3472
  );
3473
+ var sizeClass7 = {
3474
+ xs: "text-sm font-semibold",
3475
+ sm: "text-base font-semibold",
3476
+ md: "text-lg font-bold",
3477
+ lg: "text-xl font-bold",
3478
+ xl: "text-2xl font-bold tracking-tight",
3479
+ "2xl": "text-3xl font-bold tracking-tight sm:text-4xl"
3480
+ };
3481
+ var levelToSize = {
3482
+ 1: "2xl",
3483
+ 2: "xl",
3484
+ 3: "lg",
3485
+ 4: "md",
3486
+ 5: "sm",
3487
+ 6: "xs"
3488
+ };
3489
+ var colorClass = {
3490
+ default: "text-white",
3491
+ muted: "text-white/70",
3492
+ gradient: "text-gradient"
3493
+ };
3494
+ var Heading = forwardRef(function Heading2({ level = 2, size, color = "default", className, ...props }, ref) {
3495
+ const Tag = `h${level}`;
3496
+ const effectiveSize = size ?? levelToSize[level];
3497
+ return /* @__PURE__ */ jsx(
3498
+ Tag,
3499
+ {
3500
+ ref,
3501
+ ...props,
3502
+ className: cn(sizeClass7[effectiveSize], colorClass[color], className)
3503
+ }
3504
+ );
3505
+ });
3506
+ var sizeMap2 = {
3507
+ xs: "text-xs",
3508
+ sm: "text-sm",
3509
+ md: "text-base",
3510
+ lg: "text-lg"
3511
+ };
3512
+ var colorMap = {
3513
+ default: "text-white/90",
3514
+ muted: "text-white/70",
3515
+ dimmed: "text-white/50",
3516
+ primary: "text-primary-light",
3517
+ success: "text-emerald-400",
3518
+ warning: "text-amber-400",
3519
+ danger: "text-rose-400"
3520
+ };
3521
+ var weightMap = {
3522
+ normal: "font-normal",
3523
+ medium: "font-medium",
3524
+ semibold: "font-semibold",
3525
+ bold: "font-bold"
3526
+ };
3527
+ var Text = forwardRef(function Text2({ size = "md", color = "default", weight = "normal", inline = false, truncate = false, className, ...props }, ref) {
3528
+ const Tag = inline ? "span" : "p";
3529
+ return /* @__PURE__ */ jsx(
3530
+ Tag,
3531
+ {
3532
+ ref,
3533
+ ...props,
3534
+ className: cn(
3535
+ sizeMap2[size],
3536
+ colorMap[color],
3537
+ weightMap[weight],
3538
+ truncate && "truncate",
3539
+ className
3540
+ )
3541
+ }
3542
+ );
3543
+ });
3544
+ var gapClass = {
3545
+ 0: "gap-0",
3546
+ 1: "gap-1",
3547
+ 2: "gap-2",
3548
+ 3: "gap-3",
3549
+ 4: "gap-4",
3550
+ 5: "gap-5",
3551
+ 6: "gap-6",
3552
+ 8: "gap-8",
3553
+ 10: "gap-10",
3554
+ 12: "gap-12"
3555
+ };
3556
+ var alignClass2 = {
3557
+ start: "items-start",
3558
+ center: "items-center",
3559
+ end: "items-end",
3560
+ stretch: "items-stretch",
3561
+ baseline: "items-baseline"
3562
+ };
3563
+ var justifyClass = {
3564
+ start: "justify-start",
3565
+ center: "justify-center",
3566
+ end: "justify-end",
3567
+ between: "justify-between",
3568
+ around: "justify-around",
3569
+ evenly: "justify-evenly"
3570
+ };
3571
+ var Stack = forwardRef(function Stack2({ children, direction = "vertical", gap = 4, align = "stretch", justify = "start", wrap = false, className, ...props }, ref) {
3572
+ return /* @__PURE__ */ jsx(
3573
+ "div",
3574
+ {
3575
+ ref,
3576
+ ...props,
3577
+ className: cn(
3578
+ "flex",
3579
+ direction === "vertical" ? "flex-col" : "flex-row",
3580
+ gapClass[gap],
3581
+ alignClass2[align],
3582
+ justifyClass[justify],
3583
+ wrap && "flex-wrap",
3584
+ className
3585
+ ),
3586
+ children
3587
+ }
3588
+ );
3589
+ });
3590
+ var ScrollArea = forwardRef(function ScrollArea2({ children, maxHeight, hideScrollbar = false, orientation = "vertical", className, style, ...props }, ref) {
3591
+ const overflowClass = {
3592
+ vertical: "overflow-y-auto overflow-x-hidden",
3593
+ horizontal: "overflow-x-auto overflow-y-hidden",
3594
+ both: "overflow-auto"
3595
+ }[orientation];
3596
+ return /* @__PURE__ */ jsx(
3597
+ "div",
3598
+ {
3599
+ ref,
3600
+ ...props,
3601
+ tabIndex: 0,
3602
+ className: cn(
3603
+ overflowClass,
3604
+ // Custom dark scrollbar styling
3605
+ "[&::-webkit-scrollbar]:w-1.5 [&::-webkit-scrollbar]:h-1.5",
3606
+ "[&::-webkit-scrollbar-track]:bg-transparent",
3607
+ "[&::-webkit-scrollbar-thumb]:rounded-full [&::-webkit-scrollbar-thumb]:bg-white/15 hover:[&::-webkit-scrollbar-thumb]:bg-white/25",
3608
+ hideScrollbar && "no-scrollbar",
3609
+ "focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-primary/30 focus-visible:ring-inset",
3610
+ className
3611
+ ),
3612
+ style: {
3613
+ maxHeight: typeof maxHeight === "number" ? `${maxHeight}px` : maxHeight,
3614
+ ...style
3615
+ },
3616
+ children
3617
+ }
3618
+ );
3619
+ });
3620
+ var defaultSeparator = /* @__PURE__ */ jsx(
3621
+ "svg",
3622
+ {
3623
+ className: "w-3.5 h-3.5 text-white/30 flex-shrink-0",
3624
+ viewBox: "0 0 16 16",
3625
+ fill: "none",
3626
+ stroke: "currentColor",
3627
+ strokeWidth: "2",
3628
+ strokeLinecap: "round",
3629
+ "aria-hidden": "true",
3630
+ children: /* @__PURE__ */ jsx("path", { d: "M6 4l4 4-4 4" })
3631
+ }
3632
+ );
3633
+ function Breadcrumbs({ items, separator = defaultSeparator, className }) {
3634
+ if (items.length === 0) return null;
3635
+ return /* @__PURE__ */ jsx("nav", { "aria-label": "Breadcrumb", className: cn("flex items-center", className), children: /* @__PURE__ */ jsx("ol", { className: "flex items-center gap-1.5 text-sm", children: items.map((item, index) => {
3636
+ const isLast = index === items.length - 1;
3637
+ return /* @__PURE__ */ jsxs("li", { className: "flex items-center gap-1.5", children: [
3638
+ index > 0 && separator,
3639
+ isLast ? /* @__PURE__ */ jsx("span", { className: "text-white font-medium", "aria-current": "page", children: item.label }) : item.href ? /* @__PURE__ */ jsx(
3640
+ "a",
3641
+ {
3642
+ href: item.href,
3643
+ onClick: item.onClick,
3644
+ className: "text-white/50 hover:text-white/80 transition-colors",
3645
+ children: item.label
3646
+ }
3647
+ ) : item.onClick ? /* @__PURE__ */ jsx(
3648
+ "button",
3649
+ {
3650
+ type: "button",
3651
+ onClick: item.onClick,
3652
+ className: "text-white/50 hover:text-white/80 transition-colors",
3653
+ children: item.label
3654
+ }
3655
+ ) : /* @__PURE__ */ jsx("span", { className: "text-white/50", children: item.label })
3656
+ ] }, index);
3657
+ }) }) });
3658
+ }
3659
+ function Popover({
3660
+ content,
3661
+ children,
3662
+ placement = "bottom",
3663
+ closeOnClickOutside = true,
3664
+ closeOnEsc = true,
3665
+ open: controlledOpen,
3666
+ onOpenChange,
3667
+ offset = 8,
3668
+ className
3669
+ }) {
3670
+ const popoverId = useId();
3671
+ const anchorRef = useRef(null);
3672
+ const popoverRef = useRef(null);
3673
+ const [internalOpen, setInternalOpen] = useState(false);
3674
+ const [pos, setPos] = useState(null);
3675
+ const isControlled = controlledOpen !== void 0;
3676
+ const isOpen = isControlled ? controlledOpen : internalOpen;
3677
+ const setOpen = useCallback(
3678
+ (value) => {
3679
+ if (!isControlled) setInternalOpen(value);
3680
+ onOpenChange?.(value);
3681
+ },
3682
+ [isControlled, onOpenChange]
3683
+ );
3684
+ const toggle = useCallback(() => setOpen(!isOpen), [isOpen, setOpen]);
3685
+ const close = useCallback(() => setOpen(false), [setOpen]);
3686
+ const updatePosition = useCallback(() => {
3687
+ const el = anchorRef.current;
3688
+ if (!el) return;
3689
+ const r = el.getBoundingClientRect();
3690
+ let left;
3691
+ let top;
3692
+ let effPlacement = placement;
3693
+ if (placement === "bottom" || placement === "top") {
3694
+ left = r.left + r.width / 2;
3695
+ if (placement === "bottom") {
3696
+ top = r.bottom + offset;
3697
+ if (top + 200 > window.innerHeight && r.top - offset > 200) {
3698
+ effPlacement = "top";
3699
+ top = r.top - offset;
3700
+ }
3701
+ } else {
3702
+ top = r.top - offset;
3703
+ if (top < 8) {
3704
+ effPlacement = "bottom";
3705
+ top = r.bottom + offset;
3706
+ }
3707
+ }
3708
+ } else {
3709
+ top = r.top + r.height / 2;
3710
+ if (placement === "right") {
3711
+ left = r.right + offset;
3712
+ } else {
3713
+ left = r.left - offset;
3714
+ }
3715
+ }
3716
+ setPos({ left: Math.round(left), top: Math.round(top), placement: effPlacement });
3717
+ }, [placement, offset]);
3718
+ useEffect(() => {
3719
+ if (!isOpen) return;
3720
+ updatePosition();
3721
+ window.addEventListener("scroll", updatePosition, true);
3722
+ window.addEventListener("resize", updatePosition);
3723
+ return () => {
3724
+ window.removeEventListener("scroll", updatePosition, true);
3725
+ window.removeEventListener("resize", updatePosition);
3726
+ };
3727
+ }, [isOpen, updatePosition]);
3728
+ useEffect(() => {
3729
+ if (!isOpen || !closeOnClickOutside) return;
3730
+ const handleClick = (e) => {
3731
+ const target = e.target;
3732
+ if (anchorRef.current?.contains(target) || popoverRef.current?.contains(target)) {
3733
+ return;
3734
+ }
3735
+ close();
3736
+ };
3737
+ document.addEventListener("mousedown", handleClick);
3738
+ return () => document.removeEventListener("mousedown", handleClick);
3739
+ }, [isOpen, closeOnClickOutside, close]);
3740
+ useEffect(() => {
3741
+ if (!isOpen || !closeOnEsc) return;
3742
+ const handleKey = (e) => {
3743
+ if (e.key === "Escape") {
3744
+ e.preventDefault();
3745
+ close();
3746
+ anchorRef.current?.focus();
3747
+ }
3748
+ };
3749
+ document.addEventListener("keydown", handleKey);
3750
+ return () => document.removeEventListener("keydown", handleKey);
3751
+ }, [isOpen, closeOnEsc, close]);
3752
+ if (!isValidElement(children)) return children;
3753
+ const child = cloneElement(children, {
3754
+ ref: (node) => {
3755
+ anchorRef.current = node;
3756
+ const childProps = children.props;
3757
+ const prevRef = childProps.ref;
3758
+ if (typeof prevRef === "function") prevRef(node);
3759
+ else if (prevRef && typeof prevRef === "object") prevRef.current = node;
3760
+ },
3761
+ onClick: (e) => {
3762
+ const childProps = children.props;
3763
+ if (typeof childProps.onClick === "function") childProps.onClick(e);
3764
+ toggle();
3765
+ },
3766
+ "aria-expanded": isOpen,
3767
+ "aria-haspopup": "dialog",
3768
+ "aria-controls": isOpen ? popoverId : void 0
3769
+ });
3770
+ const getTransform = () => {
3771
+ if (!pos) return "translate(-9999px, -9999px)";
3772
+ switch (pos.placement) {
3773
+ case "top":
3774
+ return "translate(-50%, -100%)";
3775
+ case "bottom":
3776
+ return "translate(-50%, 0%)";
3777
+ case "left":
3778
+ return "translate(-100%, -50%)";
3779
+ case "right":
3780
+ return "translate(0%, -50%)";
3781
+ }
3782
+ };
3783
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
3784
+ child,
3785
+ isOpen && typeof document !== "undefined" ? createPortal(
3786
+ /* @__PURE__ */ jsx(
3787
+ "div",
3788
+ {
3789
+ ref: popoverRef,
3790
+ id: popoverId,
3791
+ role: "dialog",
3792
+ className: cn(
3793
+ "fixed z-[9999] rounded-xl shadow-xl ring-1 ring-white/10 bg-surface-50 backdrop-blur-md p-4",
3794
+ className
3795
+ ),
3796
+ style: {
3797
+ left: pos?.left ?? 0,
3798
+ top: pos?.top ?? 0,
3799
+ transform: getTransform()
3800
+ },
3801
+ children: content
3802
+ }
3803
+ ),
3804
+ document.body
3805
+ ) : null
3806
+ ] });
3807
+ }
3808
+ var scrollLockCount2 = 0;
3809
+ var savedOverflow2 = "";
3810
+ function lockScroll2() {
3811
+ if (typeof document === "undefined") return;
3812
+ if (scrollLockCount2 === 0) {
3813
+ savedOverflow2 = document.body.style.overflow;
3814
+ document.body.style.overflow = "hidden";
3815
+ }
3816
+ scrollLockCount2++;
3817
+ }
3818
+ function unlockScroll2() {
3819
+ if (typeof document === "undefined") return;
3820
+ scrollLockCount2 = Math.max(0, scrollLockCount2 - 1);
3821
+ if (scrollLockCount2 === 0) {
3822
+ document.body.style.overflow = savedOverflow2;
3823
+ }
3824
+ }
3825
+ var sizeClass8 = {
3826
+ left: { sm: "w-64", md: "w-80", lg: "w-96", full: "w-screen" },
3827
+ right: { sm: "w-64", md: "w-80", lg: "w-96", full: "w-screen" },
3828
+ bottom: { sm: "h-1/4", md: "h-1/3", lg: "h-1/2", full: "h-screen" }
3829
+ };
3830
+ var positionClass2 = {
3831
+ left: "inset-y-0 left-0",
3832
+ right: "inset-y-0 right-0",
3833
+ bottom: "inset-x-0 bottom-0"
3834
+ };
3835
+ var slideIn = {
3836
+ left: "translate-x-0",
3837
+ right: "translate-x-0",
3838
+ bottom: "translate-y-0"
3839
+ };
3840
+ var slideOut = {
3841
+ left: "-translate-x-full",
3842
+ right: "translate-x-full",
3843
+ bottom: "translate-y-full"
3844
+ };
3845
+ function Drawer({
3846
+ isOpen,
3847
+ onClose,
3848
+ children,
3849
+ side = "right",
3850
+ size = "md",
3851
+ ariaLabel,
3852
+ closeOnBackdrop = true,
3853
+ closeOnEsc = true,
3854
+ className
3855
+ }) {
3856
+ const panelRef = useRef(null);
3857
+ const lastActiveRef = useRef(null);
3858
+ useEffect(() => {
3859
+ if (!isOpen) return;
3860
+ lastActiveRef.current = document.activeElement instanceof HTMLElement ? document.activeElement : null;
3861
+ const raf = requestAnimationFrame(() => {
3862
+ const el = panelRef.current;
3863
+ if (!el) return;
3864
+ const focusables = getFocusableElements(el);
3865
+ focusSafely(focusables[0] ?? el);
3866
+ });
3867
+ return () => {
3868
+ cancelAnimationFrame(raf);
3869
+ const lastActive = lastActiveRef.current;
3870
+ lastActiveRef.current = null;
3871
+ if (lastActive?.isConnected) focusSafely(lastActive);
3872
+ };
3873
+ }, [isOpen]);
3874
+ useEffect(() => {
3875
+ if (!isOpen) return;
3876
+ lockScroll2();
3877
+ return () => unlockScroll2();
3878
+ }, [isOpen]);
3879
+ if (!isOpen) return null;
3880
+ return /* @__PURE__ */ jsxs("div", { className: "fixed inset-0 z-50", role: "presentation", children: [
3881
+ /* @__PURE__ */ jsx(
3882
+ "div",
3883
+ {
3884
+ className: "absolute inset-0 bg-black/40 backdrop-blur-sm transition-opacity duration-200",
3885
+ "aria-hidden": "true",
3886
+ onClick: closeOnBackdrop ? onClose : void 0
3887
+ }
3888
+ ),
3889
+ /* @__PURE__ */ jsx(
3890
+ "div",
3891
+ {
3892
+ ref: panelRef,
3893
+ role: "dialog",
3894
+ "aria-modal": "true",
3895
+ "aria-label": ariaLabel,
3896
+ tabIndex: -1,
3897
+ className: cn(
3898
+ "fixed flex flex-col bg-surface-50 shadow-2xl ring-1 ring-white/10 transition-transform duration-300 ease-out focus:outline-none",
3899
+ positionClass2[side],
3900
+ sizeClass8[side][size],
3901
+ isOpen ? slideIn[side] : slideOut[side],
3902
+ className
3903
+ ),
3904
+ onKeyDownCapture: (e) => {
3905
+ if (closeOnEsc && e.key === "Escape") {
3906
+ e.preventDefault();
3907
+ e.stopPropagation();
3908
+ onClose();
3909
+ return;
3910
+ }
3911
+ if (e.key !== "Tab") return;
3912
+ const el = panelRef.current;
3913
+ if (!el) return;
3914
+ const focusables = getFocusableElements(el);
3915
+ if (focusables.length === 0) {
3916
+ e.preventDefault();
3917
+ focusSafely(el);
3918
+ return;
3919
+ }
3920
+ const active = document.activeElement;
3921
+ const first = focusables[0];
3922
+ const last = focusables[focusables.length - 1];
3923
+ if (e.shiftKey) {
3924
+ if (active === first) {
3925
+ e.preventDefault();
3926
+ focusSafely(last);
3927
+ }
3928
+ } else {
3929
+ if (active === last) {
3930
+ e.preventDefault();
3931
+ focusSafely(first);
3932
+ }
3933
+ }
3934
+ },
3935
+ children
3936
+ }
3937
+ )
3938
+ ] });
3939
+ }
3940
+ var defaultFilter = (opt, q) => opt.label.toLowerCase().includes(q.toLowerCase());
3941
+ var Combobox = forwardRef(function Combobox2({
3942
+ options,
3943
+ value,
3944
+ onChange,
3945
+ placeholder,
3946
+ label,
3947
+ error,
3948
+ allowCustom = false,
3949
+ filterFn = defaultFilter,
3950
+ emptyContent,
3951
+ disabled,
3952
+ className,
3953
+ id: externalId
3954
+ }, ref) {
3955
+ const generatedId = useId();
3956
+ const inputId = externalId || generatedId;
3957
+ const listboxId = `${inputId}-listbox`;
3958
+ const [query, setQuery] = useState("");
3959
+ const [open, setOpen] = useState(false);
3960
+ const [activeIndex, setActiveIndex] = useState(-1);
3961
+ const inputRef = useRef(null);
3962
+ const listRef = useRef(null);
3963
+ const containerRef = useRef(null);
3964
+ const [listPos, setListPos] = useState(null);
3965
+ useEffect(() => {
3966
+ if (value !== void 0) {
3967
+ const opt = options.find((o) => o.value === value);
3968
+ setQuery(opt ? opt.label : value);
3969
+ }
3970
+ }, [value, options]);
3971
+ const filtered = useMemo(() => {
3972
+ if (!query) return options;
3973
+ return options.filter((opt) => filterFn(opt, query));
3974
+ }, [options, query, filterFn]);
3975
+ const enabledFiltered = useMemo(
3976
+ () => filtered.filter((o) => !o.disabled),
3977
+ [filtered]
3978
+ );
3979
+ const updatePosition = useCallback(() => {
3980
+ const el = containerRef.current;
3981
+ if (!el) return;
3982
+ const r = el.getBoundingClientRect();
3983
+ setListPos({
3984
+ left: r.left,
3985
+ top: r.bottom + 4,
3986
+ width: r.width
3987
+ });
3988
+ }, []);
3989
+ useEffect(() => {
3990
+ if (!open) return;
3991
+ updatePosition();
3992
+ window.addEventListener("scroll", updatePosition, true);
3993
+ window.addEventListener("resize", updatePosition);
3994
+ return () => {
3995
+ window.removeEventListener("scroll", updatePosition, true);
3996
+ window.removeEventListener("resize", updatePosition);
3997
+ };
3998
+ }, [open, updatePosition]);
3999
+ useEffect(() => {
4000
+ if (!open) return;
4001
+ const handleClick = (e) => {
4002
+ const target = e.target;
4003
+ if (containerRef.current?.contains(target) || listRef.current?.contains(target)) return;
4004
+ setOpen(false);
4005
+ };
4006
+ document.addEventListener("mousedown", handleClick);
4007
+ return () => document.removeEventListener("mousedown", handleClick);
4008
+ }, [open]);
4009
+ const selectOption = useCallback(
4010
+ (opt) => {
4011
+ setQuery(opt.label);
4012
+ onChange?.(opt.value);
4013
+ setOpen(false);
4014
+ setActiveIndex(-1);
4015
+ inputRef.current?.focus();
4016
+ },
4017
+ [onChange]
4018
+ );
4019
+ const handleInputChange = (e) => {
4020
+ const v = e.target.value;
4021
+ setQuery(v);
4022
+ setOpen(true);
4023
+ setActiveIndex(-1);
4024
+ if (allowCustom) onChange?.(v);
4025
+ };
4026
+ const handleKeyDown = (e) => {
4027
+ if (e.key === "ArrowDown") {
4028
+ e.preventDefault();
4029
+ if (!open) {
4030
+ setOpen(true);
4031
+ return;
4032
+ }
4033
+ setActiveIndex((i) => {
4034
+ const next = i + 1;
4035
+ return next >= enabledFiltered.length ? 0 : next;
4036
+ });
4037
+ } else if (e.key === "ArrowUp") {
4038
+ e.preventDefault();
4039
+ if (!open) {
4040
+ setOpen(true);
4041
+ return;
4042
+ }
4043
+ setActiveIndex((i) => {
4044
+ const prev = i - 1;
4045
+ return prev < 0 ? enabledFiltered.length - 1 : prev;
4046
+ });
4047
+ } else if (e.key === "Enter") {
4048
+ e.preventDefault();
4049
+ if (open && activeIndex >= 0 && enabledFiltered[activeIndex]) {
4050
+ selectOption(enabledFiltered[activeIndex]);
4051
+ }
4052
+ } else if (e.key === "Escape") {
4053
+ if (open) {
4054
+ e.preventDefault();
4055
+ setOpen(false);
4056
+ setActiveIndex(-1);
4057
+ }
4058
+ }
4059
+ };
4060
+ useEffect(() => {
4061
+ if (activeIndex < 0 || !listRef.current) return;
4062
+ const items = listRef.current.querySelectorAll('[role="option"]:not([aria-disabled="true"])');
4063
+ const item = items[activeIndex];
4064
+ if (item && typeof item.scrollIntoView === "function") {
4065
+ item.scrollIntoView({ block: "nearest" });
4066
+ }
4067
+ }, [activeIndex]);
4068
+ const activeOptionId = activeIndex >= 0 ? `${inputId}-opt-${activeIndex}` : void 0;
4069
+ return /* @__PURE__ */ jsxs("div", { className: cn("w-full", className), children: [
4070
+ label && /* @__PURE__ */ jsx("label", { htmlFor: inputId, className: "block text-sm text-white/70 mb-1.5", children: label }),
4071
+ /* @__PURE__ */ jsxs("div", { ref: containerRef, className: "relative", children: [
4072
+ /* @__PURE__ */ jsx(
4073
+ "input",
4074
+ {
4075
+ ref: (node) => {
4076
+ inputRef.current = node;
4077
+ if (typeof ref === "function") ref(node);
4078
+ else if (ref) ref.current = node;
4079
+ },
4080
+ id: inputId,
4081
+ type: "text",
4082
+ role: "combobox",
4083
+ "aria-expanded": open,
4084
+ "aria-controls": listboxId,
4085
+ "aria-activedescendant": activeOptionId,
4086
+ "aria-autocomplete": "list",
4087
+ autoComplete: "off",
4088
+ disabled,
4089
+ placeholder,
4090
+ value: query,
4091
+ onChange: handleInputChange,
4092
+ onFocus: () => setOpen(true),
4093
+ onKeyDown: handleKeyDown,
4094
+ className: cn(
4095
+ "w-full rounded-xl px-3 py-2.5 text-sm bg-white/10 text-white shadow-sm outline-none placeholder-white/30 focus-visible:ring-2 focus-visible:ring-primary/40 transition-shadow",
4096
+ error && "ring-1 ring-rose-500/50",
4097
+ disabled && "opacity-50 cursor-not-allowed"
4098
+ )
4099
+ }
4100
+ ),
4101
+ /* @__PURE__ */ jsx(
4102
+ "button",
4103
+ {
4104
+ type: "button",
4105
+ tabIndex: -1,
4106
+ "aria-hidden": "true",
4107
+ onClick: () => {
4108
+ if (!disabled) {
4109
+ setOpen(!open);
4110
+ inputRef.current?.focus();
4111
+ }
4112
+ },
4113
+ className: "absolute right-2 top-1/2 -translate-y-1/2 text-white/40 hover:text-white/60 p-1",
4114
+ children: /* @__PURE__ */ jsx("svg", { className: "w-4 h-4", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", children: /* @__PURE__ */ jsx("path", { d: "M4 6l4 4 4-4" }) })
4115
+ }
4116
+ )
4117
+ ] }),
4118
+ error && /* @__PURE__ */ jsx("p", { className: "mt-1 text-xs text-rose-400", children: error }),
4119
+ open && typeof document !== "undefined" ? createPortal(
4120
+ /* @__PURE__ */ jsx(
4121
+ "ul",
4122
+ {
4123
+ ref: listRef,
4124
+ id: listboxId,
4125
+ role: "listbox",
4126
+ className: "fixed z-[9999] max-h-60 overflow-auto rounded-xl bg-surface-50 shadow-xl ring-1 ring-white/10 py-1 backdrop-blur-md",
4127
+ style: {
4128
+ left: listPos?.left ?? 0,
4129
+ top: listPos?.top ?? 0,
4130
+ width: listPos?.width ?? 0
4131
+ },
4132
+ children: filtered.length === 0 ? /* @__PURE__ */ jsx("li", { className: "px-3 py-2 text-sm text-white/40", children: emptyContent ?? "No results" }) : filtered.map((opt) => {
4133
+ const enabledIndex = enabledFiltered.indexOf(opt);
4134
+ const isActive = enabledIndex === activeIndex;
4135
+ return /* @__PURE__ */ jsx(
4136
+ "li",
4137
+ {
4138
+ id: isActive ? activeOptionId : void 0,
4139
+ role: "option",
4140
+ "aria-selected": opt.value === value,
4141
+ "aria-disabled": opt.disabled || void 0,
4142
+ className: cn(
4143
+ "px-3 py-2 text-sm cursor-pointer transition-colors",
4144
+ isActive && "bg-white/10",
4145
+ opt.value === value && "text-primary-light",
4146
+ opt.disabled && "opacity-40 cursor-not-allowed",
4147
+ !opt.disabled && !isActive && "text-white hover:bg-white/5"
4148
+ ),
4149
+ onMouseDown: (e) => {
4150
+ e.preventDefault();
4151
+ if (!opt.disabled) selectOption(opt);
4152
+ },
4153
+ onMouseEnter: () => {
4154
+ if (!opt.disabled) setActiveIndex(enabledIndex);
4155
+ },
4156
+ children: opt.label
4157
+ },
4158
+ opt.value
4159
+ );
4160
+ })
4161
+ }
4162
+ ),
4163
+ document.body
4164
+ ) : null
4165
+ ] });
4166
+ });
4167
+ var presetStyles = {
4168
+ fade: {
4169
+ enter: "opacity-100",
4170
+ exit: "opacity-0"
4171
+ },
4172
+ "fade-up": {
4173
+ enter: "opacity-100 translate-y-0",
4174
+ exit: "opacity-0 translate-y-2"
4175
+ },
4176
+ "fade-down": {
4177
+ enter: "opacity-100 translate-y-0",
4178
+ exit: "opacity-0 -translate-y-2"
4179
+ },
4180
+ scale: {
4181
+ enter: "opacity-100 scale-100",
4182
+ exit: "opacity-0 scale-95"
4183
+ },
4184
+ "slide-right": {
4185
+ enter: "translate-x-0",
4186
+ exit: "translate-x-full"
4187
+ },
4188
+ "slide-left": {
4189
+ enter: "translate-x-0",
4190
+ exit: "-translate-x-full"
4191
+ }
4192
+ };
4193
+ function Transition({
4194
+ show,
4195
+ children,
4196
+ preset = "fade",
4197
+ duration = 200,
4198
+ unmountOnHide = true,
4199
+ className
4200
+ }) {
4201
+ const [mounted, setMounted] = useState(show);
4202
+ const [entering, setEntering] = useState(false);
4203
+ const timerRef = useRef(null);
4204
+ useEffect(() => {
4205
+ if (timerRef.current !== null) clearTimeout(timerRef.current);
4206
+ if (show) {
4207
+ setMounted(true);
4208
+ requestAnimationFrame(() => {
4209
+ requestAnimationFrame(() => setEntering(true));
4210
+ });
4211
+ } else {
4212
+ setEntering(false);
4213
+ if (unmountOnHide) {
4214
+ timerRef.current = setTimeout(() => {
4215
+ setMounted(false);
4216
+ timerRef.current = null;
4217
+ }, duration);
4218
+ }
4219
+ }
4220
+ return () => {
4221
+ if (timerRef.current !== null) clearTimeout(timerRef.current);
4222
+ };
4223
+ }, [show, duration, unmountOnHide]);
4224
+ if (!mounted) return null;
4225
+ const styles = presetStyles[preset];
4226
+ return /* @__PURE__ */ jsx(
4227
+ "div",
4228
+ {
4229
+ className: cn(
4230
+ "transition-all",
4231
+ entering ? styles.enter : styles.exit,
4232
+ className
4233
+ ),
4234
+ style: { transitionDuration: `${duration}ms` },
4235
+ "aria-hidden": !show,
4236
+ children
4237
+ }
4238
+ );
4239
+ }
4240
+ function VisuallyHidden({ children, as: Tag = "span", style, ...props }) {
4241
+ return /* @__PURE__ */ jsx(
4242
+ Tag,
4243
+ {
4244
+ ...props,
4245
+ style: {
4246
+ position: "absolute",
4247
+ width: 1,
4248
+ height: 1,
4249
+ padding: 0,
4250
+ margin: -1,
4251
+ overflow: "hidden",
4252
+ clip: "rect(0,0,0,0)",
4253
+ whiteSpace: "nowrap",
4254
+ borderWidth: 0,
4255
+ ...style
4256
+ },
4257
+ children
4258
+ }
4259
+ );
4260
+ }
3473
4261
 
3474
- export { ActiveFilterPills, Alert, Avatar, Badge, Button, Card, Checkbox, CollapsibleSection, ColorInput, ConfirmDialog, CooldownRing, CopyField, DashboardLayout, Divider, DotIndicator, DropZone, Dropdown, DropdownItem, DropdownMenu, DropdownSeparator, DropdownTrigger, EmptyState, FormField, IconButton, Input, Modal, MutationOverlay, Navbar, NotificationBell, PageShell, Pagination, Pill, ProgressBar, ProgressButton, RadioGroup, RadioItem, SearchInput, SectionCard, Select, Sidebar, Skeleton, Slider, Spinner, StageProgress, StatCard, Stepper, Tab, TabList, TabPanel, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, Tabs, TagInput, Textarea, ToastProvider, Toggle, Tooltip, cn, colors, focusSafely, getFocusableElements, useClipboard, useDebounce, useDisclosure, useHotkeys, useIntersectionObserver, useMediaQuery, useSharedNow, useToast };
4262
+ export { ActiveFilterPills, Alert, Avatar, Badge, Breadcrumbs, Button, Card, Checkbox, CollapsibleSection, ColorInput, Combobox, ConfirmDialog, CooldownRing, CopyField, DashboardLayout, Divider, DotIndicator, Drawer, DropZone, Dropdown, DropdownItem, DropdownMenu, DropdownSeparator, DropdownTrigger, EmptyState, FormField, Heading, IconButton, Input, Modal, MutationOverlay, Navbar, NotificationBell, PageShell, Pagination, Pill, Popover, ProgressBar, ProgressButton, RadioGroup, RadioItem, ScrollArea, SearchInput, SectionCard, Select, Sidebar, Skeleton, Slider, Spinner, Stack, StageProgress, StatCard, Stepper, Tab, TabList, TabPanel, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, Tabs, TagInput, Text, Textarea, ToastProvider, Toggle, Tooltip, Transition, VisuallyHidden, cn, colors, focusSafely, getFocusableElements, useClipboard, useDebounce, useDisclosure, useHotkeys, useIntersectionObserver, useMediaQuery, useSharedNow, useToast };