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