@enonic/ui 0.12.0 → 0.12.1
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/enonic-ui.cjs +5 -4
- package/dist/enonic-ui.es.js +912 -349
- package/dist/styles/preset.css +1 -1
- package/dist/styles/style.css +1 -1
- package/dist/styles/tokens.css +1 -1
- package/dist/types/components/avatar/avatar.d.ts +36 -0
- package/dist/types/components/avatar/index.d.ts +1 -0
- package/dist/types/components/dialog/index.d.ts +1 -3
- package/dist/types/components/icon-button/icon-button.d.ts +1 -1
- package/dist/types/components/index.d.ts +5 -2
- package/dist/types/components/listbox/index.d.ts +1 -1
- package/dist/types/components/listbox/listbox.d.ts +34 -29
- package/dist/types/components/separator/index.d.ts +1 -2
- package/dist/types/providers/avatar-provider.d.ts +15 -0
- package/dist/types/providers/index.d.ts +2 -0
- package/dist/types/providers/listbox-provider.d.ts +22 -0
- package/package.json +1 -1
package/dist/enonic-ui.es.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { options, Fragment } from "preact";
|
|
2
|
-
import {
|
|
3
|
-
import { Root } from "@radix-ui/react-slot";
|
|
2
|
+
import { createContext, useContext, useId, forwardRef, useState, useCallback, useMemo, useEffect, createElement, useRef, isValidElement, Children, createPortal as createPortal$1 } from "react";
|
|
3
|
+
import { Slot, Root } from "@radix-ui/react-slot";
|
|
4
|
+
import { FocusTrap } from "focus-trap-react";
|
|
5
|
+
import { createPortal } from "react-dom";
|
|
4
6
|
import { useState as useState$1 } from "preact/hooks";
|
|
5
7
|
var f = 0;
|
|
6
8
|
function u(e, t, n, o, i, u2) {
|
|
@@ -11,6 +13,56 @@ function u(e, t, n, o, i, u2) {
|
|
|
11
13
|
if ("function" == typeof e && (a = e.defaultProps)) for (c in a) void 0 === p[c] && (p[c] = a[c]);
|
|
12
14
|
return options.vnode && options.vnode(l), l;
|
|
13
15
|
}
|
|
16
|
+
const AvatarContext = createContext(null);
|
|
17
|
+
const AvatarProvider = ({ value, children }) => {
|
|
18
|
+
return /* @__PURE__ */ u(AvatarContext.Provider, { value, children });
|
|
19
|
+
};
|
|
20
|
+
AvatarProvider.displayName = "AvatarProvider";
|
|
21
|
+
const useAvatar = () => {
|
|
22
|
+
const ctx = useContext(AvatarContext);
|
|
23
|
+
if (!ctx) {
|
|
24
|
+
throw new Error("useAvatar must be used within an Avatar");
|
|
25
|
+
}
|
|
26
|
+
return ctx;
|
|
27
|
+
};
|
|
28
|
+
const DialogContext = createContext(void 0);
|
|
29
|
+
const DialogProvider = ({ value, children }) => {
|
|
30
|
+
return /* @__PURE__ */ u(DialogContext.Provider, { value, children });
|
|
31
|
+
};
|
|
32
|
+
DialogProvider.displayName = "DialogProvider";
|
|
33
|
+
const useDialog = () => {
|
|
34
|
+
const context = useContext(DialogContext);
|
|
35
|
+
if (!context) {
|
|
36
|
+
throw new Error("useDialog must be used within a DialogProvider");
|
|
37
|
+
}
|
|
38
|
+
return context;
|
|
39
|
+
};
|
|
40
|
+
const IdContext = createContext(void 0);
|
|
41
|
+
const IdProvider = ({ children, prefix }) => {
|
|
42
|
+
return /* @__PURE__ */ u(IdContext.Provider, { value: { prefix }, children });
|
|
43
|
+
};
|
|
44
|
+
IdProvider.displayName = "IdProvider";
|
|
45
|
+
const usePrefixedId = (providedId) => {
|
|
46
|
+
const baseId = useId();
|
|
47
|
+
const context = useContext(IdContext);
|
|
48
|
+
if (providedId) {
|
|
49
|
+
return providedId;
|
|
50
|
+
}
|
|
51
|
+
const id = context?.prefix ? `${context.prefix}-${baseId}` : baseId;
|
|
52
|
+
return id;
|
|
53
|
+
};
|
|
54
|
+
const ListboxContext = createContext(null);
|
|
55
|
+
const ListboxProvider = ({ value, children }) => {
|
|
56
|
+
return /* @__PURE__ */ u(ListboxContext.Provider, { value, children });
|
|
57
|
+
};
|
|
58
|
+
ListboxProvider.displayName = "ListboxProvider";
|
|
59
|
+
const useListbox = () => {
|
|
60
|
+
const ctx = useContext(ListboxContext);
|
|
61
|
+
if (!ctx) {
|
|
62
|
+
throw new Error("useListbox must be used within a Listbox");
|
|
63
|
+
}
|
|
64
|
+
return ctx;
|
|
65
|
+
};
|
|
14
66
|
function r(e) {
|
|
15
67
|
var t, f2, n = "";
|
|
16
68
|
if ("string" == typeof e || "number" == typeof e) n += e;
|
|
@@ -3024,6 +3076,125 @@ const cva = (base, config) => (props) => {
|
|
|
3024
3076
|
}, []);
|
|
3025
3077
|
return cx(base, getVariantClassNames, getCompoundVariantClassNames, props === null || props === void 0 ? void 0 : props.class, props === null || props === void 0 ? void 0 : props.className);
|
|
3026
3078
|
};
|
|
3079
|
+
const avatarVariants = cva("relative flex shrink-0 overflow-hidden", {
|
|
3080
|
+
variants: {
|
|
3081
|
+
size: {
|
|
3082
|
+
sm: "w-6 h-6 text-xs",
|
|
3083
|
+
md: "w-8 h-8 text-sm",
|
|
3084
|
+
lg: "w-12 h-12 text-base"
|
|
3085
|
+
},
|
|
3086
|
+
shape: {
|
|
3087
|
+
circle: "rounded-full",
|
|
3088
|
+
square: "rounded-md"
|
|
3089
|
+
}
|
|
3090
|
+
},
|
|
3091
|
+
defaultVariants: {
|
|
3092
|
+
size: "md",
|
|
3093
|
+
shape: "circle"
|
|
3094
|
+
}
|
|
3095
|
+
});
|
|
3096
|
+
const AvatarRoot = forwardRef(
|
|
3097
|
+
({ children, className, size, shape, ...props }, ref) => {
|
|
3098
|
+
const [imageLoadingStatus, setImageLoadingStatus] = useState("idle");
|
|
3099
|
+
const handleImageLoadingStatusChange = useCallback((status) => {
|
|
3100
|
+
setImageLoadingStatus(status);
|
|
3101
|
+
}, []);
|
|
3102
|
+
const contextValue = useMemo(
|
|
3103
|
+
() => ({
|
|
3104
|
+
imageLoadingStatus,
|
|
3105
|
+
onImageLoadingStatusChange: handleImageLoadingStatusChange
|
|
3106
|
+
}),
|
|
3107
|
+
[imageLoadingStatus, handleImageLoadingStatusChange]
|
|
3108
|
+
);
|
|
3109
|
+
return /* @__PURE__ */ u(AvatarProvider, { value: contextValue, children: /* @__PURE__ */ u("span", { ref, className: cn(avatarVariants({ size, shape }), className), ...props, children }) });
|
|
3110
|
+
}
|
|
3111
|
+
);
|
|
3112
|
+
AvatarRoot.displayName = "AvatarRoot";
|
|
3113
|
+
const AvatarImage = forwardRef(
|
|
3114
|
+
({ src, alt, className, onLoadingStatusChange, ...props }, ref) => {
|
|
3115
|
+
const { imageLoadingStatus, onImageLoadingStatusChange } = useAvatar();
|
|
3116
|
+
const [hasError, setHasError] = useState(false);
|
|
3117
|
+
useEffect(() => {
|
|
3118
|
+
setHasError(false);
|
|
3119
|
+
if (!src) {
|
|
3120
|
+
return;
|
|
3121
|
+
}
|
|
3122
|
+
onImageLoadingStatusChange("loading");
|
|
3123
|
+
onLoadingStatusChange?.("loading");
|
|
3124
|
+
const img = new Image();
|
|
3125
|
+
const handleLoad = () => {
|
|
3126
|
+
onImageLoadingStatusChange("loaded");
|
|
3127
|
+
onLoadingStatusChange?.("loaded");
|
|
3128
|
+
};
|
|
3129
|
+
const handleError = () => {
|
|
3130
|
+
setHasError(true);
|
|
3131
|
+
onImageLoadingStatusChange("error");
|
|
3132
|
+
onLoadingStatusChange?.("error");
|
|
3133
|
+
};
|
|
3134
|
+
img.addEventListener("load", handleLoad);
|
|
3135
|
+
img.addEventListener("error", handleError);
|
|
3136
|
+
img.src = src;
|
|
3137
|
+
return () => {
|
|
3138
|
+
img.removeEventListener("load", handleLoad);
|
|
3139
|
+
img.removeEventListener("error", handleError);
|
|
3140
|
+
};
|
|
3141
|
+
}, [src, onImageLoadingStatusChange, onLoadingStatusChange]);
|
|
3142
|
+
if (!src || hasError || imageLoadingStatus === "error") {
|
|
3143
|
+
return null;
|
|
3144
|
+
}
|
|
3145
|
+
return /* @__PURE__ */ u(
|
|
3146
|
+
"img",
|
|
3147
|
+
{
|
|
3148
|
+
ref,
|
|
3149
|
+
src,
|
|
3150
|
+
alt,
|
|
3151
|
+
className: cn("aspect-square h-full w-full object-cover", className),
|
|
3152
|
+
...props
|
|
3153
|
+
}
|
|
3154
|
+
);
|
|
3155
|
+
}
|
|
3156
|
+
);
|
|
3157
|
+
AvatarImage.displayName = "AvatarImage";
|
|
3158
|
+
const AvatarFallback = forwardRef(
|
|
3159
|
+
({ children, className, delayMs = 0, ...props }, ref) => {
|
|
3160
|
+
const { imageLoadingStatus } = useAvatar();
|
|
3161
|
+
const [canRender, setCanRender] = useState(delayMs === 0);
|
|
3162
|
+
useEffect(() => {
|
|
3163
|
+
if (delayMs === 0) {
|
|
3164
|
+
return;
|
|
3165
|
+
}
|
|
3166
|
+
const timerId = setTimeout(() => {
|
|
3167
|
+
setCanRender(true);
|
|
3168
|
+
}, delayMs);
|
|
3169
|
+
return () => {
|
|
3170
|
+
clearTimeout(timerId);
|
|
3171
|
+
};
|
|
3172
|
+
}, [delayMs]);
|
|
3173
|
+
const shouldRender = canRender && (imageLoadingStatus === "idle" || imageLoadingStatus === "error");
|
|
3174
|
+
if (!shouldRender) {
|
|
3175
|
+
return null;
|
|
3176
|
+
}
|
|
3177
|
+
return /* @__PURE__ */ u(
|
|
3178
|
+
"span",
|
|
3179
|
+
{
|
|
3180
|
+
ref,
|
|
3181
|
+
className: cn(
|
|
3182
|
+
"flex h-full w-full items-center justify-center",
|
|
3183
|
+
"bg-surface-secondary text-alt font-medium uppercase cursor-default",
|
|
3184
|
+
className
|
|
3185
|
+
),
|
|
3186
|
+
...props,
|
|
3187
|
+
children
|
|
3188
|
+
}
|
|
3189
|
+
);
|
|
3190
|
+
}
|
|
3191
|
+
);
|
|
3192
|
+
AvatarFallback.displayName = "AvatarFallback";
|
|
3193
|
+
const Avatar = Object.assign(AvatarRoot, {
|
|
3194
|
+
Root: AvatarRoot,
|
|
3195
|
+
Image: AvatarImage,
|
|
3196
|
+
Fallback: AvatarFallback
|
|
3197
|
+
});
|
|
3027
3198
|
const buttonVariants = cva(
|
|
3028
3199
|
[
|
|
3029
3200
|
"inline-flex items-center justify-center",
|
|
@@ -3101,20 +3272,6 @@ const Button = forwardRef(
|
|
|
3101
3272
|
}
|
|
3102
3273
|
);
|
|
3103
3274
|
Button.displayName = "Button";
|
|
3104
|
-
const IdContext = createContext(void 0);
|
|
3105
|
-
const IdProvider = ({ children, prefix }) => {
|
|
3106
|
-
return /* @__PURE__ */ u(IdContext.Provider, { value: { prefix }, children });
|
|
3107
|
-
};
|
|
3108
|
-
IdProvider.displayName = "IdProvider";
|
|
3109
|
-
const usePrefixedId = (providedId) => {
|
|
3110
|
-
const baseId = useId();
|
|
3111
|
-
const context = useContext(IdContext);
|
|
3112
|
-
if (providedId) {
|
|
3113
|
-
return providedId;
|
|
3114
|
-
}
|
|
3115
|
-
const id = context?.prefix ? `${context.prefix}-${baseId}` : baseId;
|
|
3116
|
-
return id;
|
|
3117
|
-
};
|
|
3118
3275
|
/**
|
|
3119
3276
|
* @license lucide-react v0.545.0 - ISC
|
|
3120
3277
|
*
|
|
@@ -3487,6 +3644,324 @@ const IconButton = forwardRef(
|
|
|
3487
3644
|
}
|
|
3488
3645
|
);
|
|
3489
3646
|
IconButton.displayName = "IconButton";
|
|
3647
|
+
const useScrollLock = (lock, element) => {
|
|
3648
|
+
useEffect(() => {
|
|
3649
|
+
if (!lock) {
|
|
3650
|
+
return;
|
|
3651
|
+
}
|
|
3652
|
+
const target = element ?? document.body;
|
|
3653
|
+
const originalOverflow = target.style.overflow;
|
|
3654
|
+
target.style.overflow = "hidden";
|
|
3655
|
+
return () => {
|
|
3656
|
+
target.style.overflow = originalOverflow;
|
|
3657
|
+
};
|
|
3658
|
+
}, [lock, element]);
|
|
3659
|
+
};
|
|
3660
|
+
const DialogRoot = ({
|
|
3661
|
+
open: controlledOpen,
|
|
3662
|
+
defaultOpen = false,
|
|
3663
|
+
onOpenChange,
|
|
3664
|
+
children
|
|
3665
|
+
}) => {
|
|
3666
|
+
const isControlled = controlledOpen !== void 0;
|
|
3667
|
+
const [uncontrolledOpen, setUncontrolledOpen] = useState(defaultOpen);
|
|
3668
|
+
const open = isControlled ? controlledOpen : uncontrolledOpen;
|
|
3669
|
+
const setOpen = useCallback(
|
|
3670
|
+
(next) => {
|
|
3671
|
+
if (!isControlled) {
|
|
3672
|
+
setUncontrolledOpen(next);
|
|
3673
|
+
}
|
|
3674
|
+
onOpenChange?.(next);
|
|
3675
|
+
},
|
|
3676
|
+
[isControlled, onOpenChange]
|
|
3677
|
+
);
|
|
3678
|
+
const value = useMemo(() => ({ open, setOpen }), [open, setOpen]);
|
|
3679
|
+
return /* @__PURE__ */ u(DialogProvider, { value, children });
|
|
3680
|
+
};
|
|
3681
|
+
DialogRoot.displayName = "Dialog.Root";
|
|
3682
|
+
const DialogTrigger = forwardRef(
|
|
3683
|
+
({ children, onClick, ...props }, ref) => {
|
|
3684
|
+
const { setOpen } = useDialog();
|
|
3685
|
+
const handleClick = (e) => {
|
|
3686
|
+
onClick?.(e);
|
|
3687
|
+
setOpen(true);
|
|
3688
|
+
};
|
|
3689
|
+
return /* @__PURE__ */ u("button", { ref, type: "button", onClick: handleClick, ...props, children });
|
|
3690
|
+
}
|
|
3691
|
+
);
|
|
3692
|
+
DialogTrigger.displayName = "Dialog.Trigger";
|
|
3693
|
+
const DialogPortal = ({ children, container, forceMount }) => {
|
|
3694
|
+
const { open } = useDialog();
|
|
3695
|
+
const [mounted, setMounted] = useState(false);
|
|
3696
|
+
useEffect(() => {
|
|
3697
|
+
setMounted(true);
|
|
3698
|
+
}, []);
|
|
3699
|
+
if (!mounted || !forceMount && !open) {
|
|
3700
|
+
return null;
|
|
3701
|
+
}
|
|
3702
|
+
return createPortal(children, container ?? document.body);
|
|
3703
|
+
};
|
|
3704
|
+
DialogPortal.displayName = "Dialog.Portal";
|
|
3705
|
+
const DialogOverlay = forwardRef(
|
|
3706
|
+
({ className, forceMount, ...props }, ref) => {
|
|
3707
|
+
const { open } = useDialog();
|
|
3708
|
+
if (!forceMount && !open) {
|
|
3709
|
+
return null;
|
|
3710
|
+
}
|
|
3711
|
+
return /* @__PURE__ */ u(
|
|
3712
|
+
"div",
|
|
3713
|
+
{
|
|
3714
|
+
ref,
|
|
3715
|
+
"data-state": open ? "open" : "closed",
|
|
3716
|
+
className: cn(
|
|
3717
|
+
"fixed inset-0 z-30 bg-overlay backdrop-blur-xs",
|
|
3718
|
+
"data-[state=open]:animate-in data-[state=closed]:animate-out",
|
|
3719
|
+
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
3720
|
+
className
|
|
3721
|
+
),
|
|
3722
|
+
...props
|
|
3723
|
+
}
|
|
3724
|
+
);
|
|
3725
|
+
}
|
|
3726
|
+
);
|
|
3727
|
+
DialogOverlay.displayName = "Dialog.Overlay";
|
|
3728
|
+
const DialogContent = forwardRef(
|
|
3729
|
+
({
|
|
3730
|
+
children,
|
|
3731
|
+
className,
|
|
3732
|
+
forceMount,
|
|
3733
|
+
onEscapeKeyDown,
|
|
3734
|
+
onPointerDownOutside,
|
|
3735
|
+
onInteractOutside,
|
|
3736
|
+
onOpenAutoFocus,
|
|
3737
|
+
onCloseAutoFocus,
|
|
3738
|
+
...props
|
|
3739
|
+
}, ref) => {
|
|
3740
|
+
const { open, setOpen } = useDialog();
|
|
3741
|
+
const contentRef = useRef(null);
|
|
3742
|
+
const titleId = useId();
|
|
3743
|
+
const descriptionId = useId();
|
|
3744
|
+
useEffect(() => {
|
|
3745
|
+
if (typeof ref === "function") {
|
|
3746
|
+
ref(contentRef.current);
|
|
3747
|
+
} else if (ref) {
|
|
3748
|
+
ref.current = contentRef.current;
|
|
3749
|
+
}
|
|
3750
|
+
}, [ref]);
|
|
3751
|
+
useScrollLock(open);
|
|
3752
|
+
const handleEscapeKey = useCallback(
|
|
3753
|
+
(e) => {
|
|
3754
|
+
if (e.key === "Escape") {
|
|
3755
|
+
onEscapeKeyDown?.(e);
|
|
3756
|
+
if (!e.defaultPrevented) {
|
|
3757
|
+
setOpen(false);
|
|
3758
|
+
}
|
|
3759
|
+
}
|
|
3760
|
+
},
|
|
3761
|
+
[onEscapeKeyDown, setOpen]
|
|
3762
|
+
);
|
|
3763
|
+
useEffect(() => {
|
|
3764
|
+
if (!open) {
|
|
3765
|
+
return;
|
|
3766
|
+
}
|
|
3767
|
+
document.addEventListener("keydown", handleEscapeKey);
|
|
3768
|
+
return () => document.removeEventListener("keydown", handleEscapeKey);
|
|
3769
|
+
}, [open, handleEscapeKey]);
|
|
3770
|
+
const handlePointerDownOutside = useCallback(
|
|
3771
|
+
(e) => {
|
|
3772
|
+
const target = e.target;
|
|
3773
|
+
if (contentRef.current && !contentRef.current.contains(target)) {
|
|
3774
|
+
onPointerDownOutside?.(e);
|
|
3775
|
+
onInteractOutside?.(e);
|
|
3776
|
+
if (!e.defaultPrevented) {
|
|
3777
|
+
setOpen(false);
|
|
3778
|
+
}
|
|
3779
|
+
}
|
|
3780
|
+
},
|
|
3781
|
+
[onPointerDownOutside, onInteractOutside, setOpen]
|
|
3782
|
+
);
|
|
3783
|
+
useEffect(() => {
|
|
3784
|
+
if (!open) {
|
|
3785
|
+
return;
|
|
3786
|
+
}
|
|
3787
|
+
document.addEventListener("pointerdown", handlePointerDownOutside);
|
|
3788
|
+
return () => document.removeEventListener("pointerdown", handlePointerDownOutside);
|
|
3789
|
+
}, [open, handlePointerDownOutside]);
|
|
3790
|
+
if (!forceMount && !open) {
|
|
3791
|
+
return null;
|
|
3792
|
+
}
|
|
3793
|
+
return /* @__PURE__ */ u(
|
|
3794
|
+
FocusTrap,
|
|
3795
|
+
{
|
|
3796
|
+
active: open,
|
|
3797
|
+
focusTrapOptions: {
|
|
3798
|
+
initialFocus: false,
|
|
3799
|
+
fallbackFocus: () => contentRef.current ?? document.body,
|
|
3800
|
+
escapeDeactivates: false,
|
|
3801
|
+
clickOutsideDeactivates: false,
|
|
3802
|
+
returnFocusOnDeactivate: true,
|
|
3803
|
+
allowOutsideClick: true,
|
|
3804
|
+
preventScroll: false,
|
|
3805
|
+
onActivate: () => {
|
|
3806
|
+
requestAnimationFrame(() => {
|
|
3807
|
+
const event = new Event("openautofocus");
|
|
3808
|
+
onOpenAutoFocus?.(event);
|
|
3809
|
+
if (!event.defaultPrevented && contentRef.current) {
|
|
3810
|
+
contentRef.current.focus();
|
|
3811
|
+
}
|
|
3812
|
+
});
|
|
3813
|
+
},
|
|
3814
|
+
onDeactivate: () => {
|
|
3815
|
+
requestAnimationFrame(() => {
|
|
3816
|
+
const event = new Event("closeautofocus");
|
|
3817
|
+
onCloseAutoFocus?.(event);
|
|
3818
|
+
});
|
|
3819
|
+
}
|
|
3820
|
+
},
|
|
3821
|
+
children: /* @__PURE__ */ u("div", { className: "fixed inset-0 z-40 flex items-center justify-center p-4", children: /* @__PURE__ */ u(
|
|
3822
|
+
"div",
|
|
3823
|
+
{
|
|
3824
|
+
ref: contentRef,
|
|
3825
|
+
role: "dialog",
|
|
3826
|
+
"aria-modal": "true",
|
|
3827
|
+
"aria-labelledby": titleId,
|
|
3828
|
+
"aria-describedby": descriptionId,
|
|
3829
|
+
"data-state": open ? "open" : "closed",
|
|
3830
|
+
tabIndex: -1,
|
|
3831
|
+
className: cn(
|
|
3832
|
+
"relative rounded-lg shadow-xl bg-surface-neutral",
|
|
3833
|
+
"flex flex-col max-w-lg w-full max-h-[90vh] gap-10 p-10",
|
|
3834
|
+
"border border-bdr-subtle outline-none overflow-hidden",
|
|
3835
|
+
"data-[state=open]:animate-in data-[state=closed]:animate-out",
|
|
3836
|
+
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
3837
|
+
"data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
|
|
3838
|
+
className
|
|
3839
|
+
),
|
|
3840
|
+
...props,
|
|
3841
|
+
children
|
|
3842
|
+
}
|
|
3843
|
+
) })
|
|
3844
|
+
}
|
|
3845
|
+
);
|
|
3846
|
+
}
|
|
3847
|
+
);
|
|
3848
|
+
DialogContent.displayName = "Dialog.Content";
|
|
3849
|
+
const DialogHeader = forwardRef(
|
|
3850
|
+
({ className, children, ...props }, ref) => {
|
|
3851
|
+
return /* @__PURE__ */ u("header", { ref, className: cn("relative grid gap-2.5 self-stretch", className), ...props, children });
|
|
3852
|
+
}
|
|
3853
|
+
);
|
|
3854
|
+
DialogHeader.displayName = "Dialog.Header";
|
|
3855
|
+
const DialogClose = forwardRef(
|
|
3856
|
+
({ children, asChild, onClick, ...props }, ref) => {
|
|
3857
|
+
const { setOpen } = useDialog();
|
|
3858
|
+
const handleClick = useCallback(
|
|
3859
|
+
(e) => {
|
|
3860
|
+
onClick?.(e);
|
|
3861
|
+
if (!e.defaultPrevented) {
|
|
3862
|
+
setOpen(false);
|
|
3863
|
+
}
|
|
3864
|
+
},
|
|
3865
|
+
[onClick, setOpen]
|
|
3866
|
+
);
|
|
3867
|
+
const Comp = asChild ? Slot : "button";
|
|
3868
|
+
return /* @__PURE__ */ u(
|
|
3869
|
+
Comp,
|
|
3870
|
+
{
|
|
3871
|
+
ref,
|
|
3872
|
+
type: asChild ? void 0 : "button",
|
|
3873
|
+
onClick: handleClick,
|
|
3874
|
+
...props,
|
|
3875
|
+
children
|
|
3876
|
+
}
|
|
3877
|
+
);
|
|
3878
|
+
}
|
|
3879
|
+
);
|
|
3880
|
+
DialogClose.displayName = "Dialog.Close";
|
|
3881
|
+
const DialogTitle = forwardRef(
|
|
3882
|
+
({ children, className, asChild, ...props }, ref) => {
|
|
3883
|
+
const Comp = asChild ? Slot : "h2";
|
|
3884
|
+
return /* @__PURE__ */ u(
|
|
3885
|
+
Comp,
|
|
3886
|
+
{
|
|
3887
|
+
ref,
|
|
3888
|
+
className: cn("text-2xl font-semibold", className),
|
|
3889
|
+
...props,
|
|
3890
|
+
children
|
|
3891
|
+
}
|
|
3892
|
+
);
|
|
3893
|
+
}
|
|
3894
|
+
);
|
|
3895
|
+
DialogTitle.displayName = "Dialog.Title";
|
|
3896
|
+
const DialogDescription = forwardRef(
|
|
3897
|
+
({ children, className, asChild, ...props }, ref) => {
|
|
3898
|
+
const Comp = asChild ? Slot : "p";
|
|
3899
|
+
return /* @__PURE__ */ u(
|
|
3900
|
+
Comp,
|
|
3901
|
+
{
|
|
3902
|
+
ref,
|
|
3903
|
+
className: cn("", className),
|
|
3904
|
+
...props,
|
|
3905
|
+
children
|
|
3906
|
+
}
|
|
3907
|
+
);
|
|
3908
|
+
}
|
|
3909
|
+
);
|
|
3910
|
+
DialogDescription.displayName = "Dialog.Description";
|
|
3911
|
+
const DialogBody = forwardRef(
|
|
3912
|
+
({ className, children, ...props }, ref) => {
|
|
3913
|
+
return /* @__PURE__ */ u("div", { ref, className: cn("min-h-0 flex-1 overflow-y-auto", className), ...props, children });
|
|
3914
|
+
}
|
|
3915
|
+
);
|
|
3916
|
+
DialogBody.displayName = "Dialog.Body";
|
|
3917
|
+
const DialogFooter = forwardRef(
|
|
3918
|
+
({ className, children, ...props }, ref) => {
|
|
3919
|
+
return /* @__PURE__ */ u("footer", { ref, className: cn("flex justify-end gap-2.5", className), ...props, children });
|
|
3920
|
+
}
|
|
3921
|
+
);
|
|
3922
|
+
DialogFooter.displayName = "Dialog.Footer";
|
|
3923
|
+
const DialogDefaultClose = forwardRef((props, ref) => {
|
|
3924
|
+
return /* @__PURE__ */ u(DialogClose, { asChild: true, ref, ...props, children: /* @__PURE__ */ u(
|
|
3925
|
+
IconButton,
|
|
3926
|
+
{
|
|
3927
|
+
"aria-label": "Close",
|
|
3928
|
+
"data-area": "close",
|
|
3929
|
+
icon: X,
|
|
3930
|
+
size: "lg",
|
|
3931
|
+
iconSize: 36,
|
|
3932
|
+
iconStrokeWidth: 1,
|
|
3933
|
+
shape: "round",
|
|
3934
|
+
variant: "filled"
|
|
3935
|
+
}
|
|
3936
|
+
) });
|
|
3937
|
+
});
|
|
3938
|
+
DialogDefaultClose.displayName = "Dialog.DefaultClose";
|
|
3939
|
+
const DialogDefaultHeader = forwardRef(
|
|
3940
|
+
({ title, description, withClose, className, children, ...props }, ref) => {
|
|
3941
|
+
return /* @__PURE__ */ u(DialogHeader, { ref, className: cn(withClose && "grid-cols-[minmax(0,1fr)_auto]", className), ...props, children: [
|
|
3942
|
+
/* @__PURE__ */ u(DialogTitle, { className: cn(withClose && "col-start-1 row-start-1 min-w-0"), children: title }),
|
|
3943
|
+
withClose && /* @__PURE__ */ u(DialogDefaultClose, { className: "col-start-2 row-start-1 row-span-2 self-start justify-self-end" }),
|
|
3944
|
+
description && /* @__PURE__ */ u(DialogDescription, { className: cn(withClose && "row-start-2"), children: description }),
|
|
3945
|
+
children
|
|
3946
|
+
] });
|
|
3947
|
+
}
|
|
3948
|
+
);
|
|
3949
|
+
DialogDefaultHeader.displayName = "Dialog.DefaultHeader";
|
|
3950
|
+
const Dialog = Object.assign(DialogRoot, {
|
|
3951
|
+
Root: DialogRoot,
|
|
3952
|
+
Trigger: DialogTrigger,
|
|
3953
|
+
Portal: DialogPortal,
|
|
3954
|
+
Overlay: DialogOverlay,
|
|
3955
|
+
Content: DialogContent,
|
|
3956
|
+
Header: DialogHeader,
|
|
3957
|
+
Close: DialogClose,
|
|
3958
|
+
Title: DialogTitle,
|
|
3959
|
+
Description: DialogDescription,
|
|
3960
|
+
Body: DialogBody,
|
|
3961
|
+
Footer: DialogFooter,
|
|
3962
|
+
DefaultClose: DialogDefaultClose,
|
|
3963
|
+
DefaultHeader: DialogDefaultHeader
|
|
3964
|
+
});
|
|
3490
3965
|
const inputContainerVariants = cva(
|
|
3491
3966
|
[
|
|
3492
3967
|
"relative flex rounded-sm overflow-hidden",
|
|
@@ -3686,49 +4161,420 @@ const ListItem = Object.assign(ListItemRoot, {
|
|
|
3686
4161
|
DefaultContent: ListItemDefaultContent,
|
|
3687
4162
|
Right: ListItemRight
|
|
3688
4163
|
});
|
|
3689
|
-
|
|
3690
|
-
|
|
3691
|
-
|
|
3692
|
-
|
|
3693
|
-
|
|
3694
|
-
|
|
3695
|
-
|
|
3696
|
-
|
|
3697
|
-
readOnly,
|
|
3698
|
-
checked,
|
|
3699
|
-
defaultChecked,
|
|
3700
|
-
onCheckedChange,
|
|
3701
|
-
...props
|
|
3702
|
-
}) => {
|
|
3703
|
-
return /* @__PURE__ */ u(
|
|
3704
|
-
ListItem,
|
|
3705
|
-
{
|
|
3706
|
-
className: cn(!selected && "hover:bg-surface-primary-hover", className),
|
|
3707
|
-
selected,
|
|
3708
|
-
role: "row",
|
|
3709
|
-
"aria-selected": selected,
|
|
3710
|
-
...props,
|
|
3711
|
-
children: [
|
|
3712
|
-
/* @__PURE__ */ u(ListItem.Left, { children: /* @__PURE__ */ u(
|
|
3713
|
-
Checkbox,
|
|
3714
|
-
{
|
|
3715
|
-
checked,
|
|
3716
|
-
defaultChecked,
|
|
3717
|
-
onCheckedChange,
|
|
3718
|
-
readOnly
|
|
3719
|
-
}
|
|
3720
|
-
) }),
|
|
3721
|
-
/* @__PURE__ */ u(ListItem.DefaultContent, { label, description, metadata, icon }),
|
|
3722
|
-
/* @__PURE__ */ u(ListItem.Right, { children })
|
|
3723
|
-
]
|
|
4164
|
+
function setRef(ref, value) {
|
|
4165
|
+
if (!ref) return;
|
|
4166
|
+
if (typeof ref === "function") {
|
|
4167
|
+
ref(value);
|
|
4168
|
+
} else {
|
|
4169
|
+
try {
|
|
4170
|
+
ref.current = value;
|
|
4171
|
+
} catch {
|
|
3724
4172
|
}
|
|
3725
|
-
|
|
3726
|
-
}
|
|
3727
|
-
|
|
3728
|
-
|
|
3729
|
-
|
|
3730
|
-
|
|
3731
|
-
|
|
4173
|
+
}
|
|
4174
|
+
}
|
|
4175
|
+
function useComposedRefs(...refs) {
|
|
4176
|
+
return useCallback((node) => {
|
|
4177
|
+
refs.forEach((ref) => setRef(ref, node));
|
|
4178
|
+
}, refs);
|
|
4179
|
+
}
|
|
4180
|
+
const EMPTY_SELECTION = [];
|
|
4181
|
+
const listboxItemVariants = cva("flex w-full items-center px-4.5 py-1 gap-x-2.5 cursor-pointer", {
|
|
4182
|
+
variants: {
|
|
4183
|
+
selected: {
|
|
4184
|
+
true: "bg-surface-primary-selected text-alt hover:bg-surface-primary-selected-hover",
|
|
4185
|
+
false: "hover:bg-surface-primary-hover"
|
|
4186
|
+
},
|
|
4187
|
+
active: {
|
|
4188
|
+
true: "bg-surface-primary-hover",
|
|
4189
|
+
false: ""
|
|
4190
|
+
}
|
|
4191
|
+
},
|
|
4192
|
+
compoundVariants: [
|
|
4193
|
+
{
|
|
4194
|
+
selected: true,
|
|
4195
|
+
active: true,
|
|
4196
|
+
class: "bg-surface-primary-selected-hover"
|
|
4197
|
+
}
|
|
4198
|
+
],
|
|
4199
|
+
defaultVariants: {
|
|
4200
|
+
selected: false,
|
|
4201
|
+
active: false
|
|
4202
|
+
}
|
|
4203
|
+
});
|
|
4204
|
+
const ListboxRoot = ({
|
|
4205
|
+
selection: controlledSelection,
|
|
4206
|
+
defaultSelection = EMPTY_SELECTION,
|
|
4207
|
+
onSelectionChange,
|
|
4208
|
+
active: controlledActive,
|
|
4209
|
+
defaultActive,
|
|
4210
|
+
setActive,
|
|
4211
|
+
selectionMode = "single",
|
|
4212
|
+
disabled,
|
|
4213
|
+
children
|
|
4214
|
+
}) => {
|
|
4215
|
+
const listboxId = usePrefixedId();
|
|
4216
|
+
const [uncontrolledSelection, setUncontrolledSelection] = useState(() => new Set(defaultSelection));
|
|
4217
|
+
const isSelectionControlled = controlledSelection !== void 0;
|
|
4218
|
+
const selectionSet = useMemo(
|
|
4219
|
+
() => isSelectionControlled ? new Set(controlledSelection) : uncontrolledSelection,
|
|
4220
|
+
[isSelectionControlled, controlledSelection, uncontrolledSelection]
|
|
4221
|
+
);
|
|
4222
|
+
const [uncontrolledActive, setUncontrolledActive] = useState(defaultActive);
|
|
4223
|
+
const isActiveControlled = controlledActive !== void 0;
|
|
4224
|
+
const active = isActiveControlled ? controlledActive : uncontrolledActive;
|
|
4225
|
+
const updateActive = useCallback(
|
|
4226
|
+
(id) => {
|
|
4227
|
+
if (!isActiveControlled) {
|
|
4228
|
+
setUncontrolledActive(id);
|
|
4229
|
+
}
|
|
4230
|
+
setActive?.(id);
|
|
4231
|
+
},
|
|
4232
|
+
[isActiveControlled, setActive]
|
|
4233
|
+
);
|
|
4234
|
+
const itemsRef = useRef(/* @__PURE__ */ new Set());
|
|
4235
|
+
const registerItem = useCallback((value) => {
|
|
4236
|
+
itemsRef.current.add(value);
|
|
4237
|
+
}, []);
|
|
4238
|
+
const unregisterItem = useCallback((value) => {
|
|
4239
|
+
itemsRef.current.delete(value);
|
|
4240
|
+
}, []);
|
|
4241
|
+
const getItems = useCallback(() => Array.from(itemsRef.current), []);
|
|
4242
|
+
const toggleValue = useCallback(
|
|
4243
|
+
(value) => {
|
|
4244
|
+
const isSelected = selectionSet.has(value);
|
|
4245
|
+
const newSet = new Set(selectionSet);
|
|
4246
|
+
if (selectionMode === "single") {
|
|
4247
|
+
newSet.clear();
|
|
4248
|
+
if (!isSelected) {
|
|
4249
|
+
newSet.add(value);
|
|
4250
|
+
}
|
|
4251
|
+
} else {
|
|
4252
|
+
if (isSelected) {
|
|
4253
|
+
newSet.delete(value);
|
|
4254
|
+
} else {
|
|
4255
|
+
newSet.add(value);
|
|
4256
|
+
}
|
|
4257
|
+
}
|
|
4258
|
+
if (!isSelectionControlled) {
|
|
4259
|
+
setUncontrolledSelection(newSet);
|
|
4260
|
+
}
|
|
4261
|
+
onSelectionChange?.(Array.from(newSet));
|
|
4262
|
+
updateActive(value);
|
|
4263
|
+
},
|
|
4264
|
+
[selectionSet, selectionMode, isSelectionControlled, onSelectionChange, updateActive]
|
|
4265
|
+
);
|
|
4266
|
+
const contextValue = useMemo(
|
|
4267
|
+
() => ({
|
|
4268
|
+
active,
|
|
4269
|
+
selection: selectionSet,
|
|
4270
|
+
selectionMode,
|
|
4271
|
+
disabled,
|
|
4272
|
+
setActive: updateActive,
|
|
4273
|
+
toggleValue,
|
|
4274
|
+
registerItem,
|
|
4275
|
+
unregisterItem,
|
|
4276
|
+
getItems,
|
|
4277
|
+
listboxId
|
|
4278
|
+
}),
|
|
4279
|
+
[
|
|
4280
|
+
active,
|
|
4281
|
+
selectionSet,
|
|
4282
|
+
selectionMode,
|
|
4283
|
+
disabled,
|
|
4284
|
+
updateActive,
|
|
4285
|
+
toggleValue,
|
|
4286
|
+
registerItem,
|
|
4287
|
+
unregisterItem,
|
|
4288
|
+
getItems,
|
|
4289
|
+
listboxId
|
|
4290
|
+
]
|
|
4291
|
+
);
|
|
4292
|
+
return /* @__PURE__ */ u(ListboxProvider, { value: contextValue, children });
|
|
4293
|
+
};
|
|
4294
|
+
ListboxRoot.displayName = "ListboxRoot";
|
|
4295
|
+
const ListboxContent = forwardRef(
|
|
4296
|
+
({ className, label, children, ...props }, ref) => {
|
|
4297
|
+
const { active, disabled, getItems, setActive, toggleValue, listboxId } = useListbox();
|
|
4298
|
+
const innerRef = useRef(null);
|
|
4299
|
+
const moveActive = useCallback(
|
|
4300
|
+
(delta) => {
|
|
4301
|
+
const items = getItems();
|
|
4302
|
+
if (!items.length) {
|
|
4303
|
+
return;
|
|
4304
|
+
}
|
|
4305
|
+
const currentIndex = active ? items.indexOf(active) : -1;
|
|
4306
|
+
const newIndex = Math.max(0, Math.min(items.length - 1, currentIndex + delta));
|
|
4307
|
+
setActive(items[newIndex]);
|
|
4308
|
+
},
|
|
4309
|
+
[getItems, active, setActive]
|
|
4310
|
+
);
|
|
4311
|
+
const handleKeyDown = useCallback(
|
|
4312
|
+
(e) => {
|
|
4313
|
+
if (disabled) {
|
|
4314
|
+
return;
|
|
4315
|
+
}
|
|
4316
|
+
const items = getItems();
|
|
4317
|
+
if (!items.length) {
|
|
4318
|
+
return;
|
|
4319
|
+
}
|
|
4320
|
+
if (e.key === "ArrowDown") {
|
|
4321
|
+
e.preventDefault();
|
|
4322
|
+
moveActive(1);
|
|
4323
|
+
} else if (e.key === "ArrowUp") {
|
|
4324
|
+
e.preventDefault();
|
|
4325
|
+
moveActive(-1);
|
|
4326
|
+
} else if (e.key === "Home") {
|
|
4327
|
+
e.preventDefault();
|
|
4328
|
+
setActive(items[0]);
|
|
4329
|
+
} else if (e.key === "End") {
|
|
4330
|
+
e.preventDefault();
|
|
4331
|
+
setActive(items[items.length - 1]);
|
|
4332
|
+
} else if (e.key === " " || e.key === "Enter") {
|
|
4333
|
+
e.preventDefault();
|
|
4334
|
+
if (active) {
|
|
4335
|
+
toggleValue(active);
|
|
4336
|
+
}
|
|
4337
|
+
}
|
|
4338
|
+
},
|
|
4339
|
+
[disabled, getItems, active, moveActive, toggleValue, setActive]
|
|
4340
|
+
);
|
|
4341
|
+
useEffect(() => {
|
|
4342
|
+
if (!active || !innerRef.current) {
|
|
4343
|
+
return;
|
|
4344
|
+
}
|
|
4345
|
+
const el = innerRef.current.querySelector(`#${listboxId}-option-${active}`);
|
|
4346
|
+
if (el) {
|
|
4347
|
+
el.scrollIntoView({
|
|
4348
|
+
block: "nearest",
|
|
4349
|
+
behavior: "auto"
|
|
4350
|
+
});
|
|
4351
|
+
}
|
|
4352
|
+
}, [active, listboxId]);
|
|
4353
|
+
return /* @__PURE__ */ u(
|
|
4354
|
+
"div",
|
|
4355
|
+
{
|
|
4356
|
+
ref: useComposedRefs(ref, innerRef),
|
|
4357
|
+
id: listboxId,
|
|
4358
|
+
className: cn(
|
|
4359
|
+
"flex flex-col items-start grow shrink-0 basis-0",
|
|
4360
|
+
"max-h-100 overflow-y-auto",
|
|
4361
|
+
"focus-within:outline-none focus-within:ring-3 focus-within:ring-ring/50",
|
|
4362
|
+
disabled && "pointer-events-none select-none opacity-30",
|
|
4363
|
+
className
|
|
4364
|
+
),
|
|
4365
|
+
role: "listbox",
|
|
4366
|
+
"aria-disabled": disabled,
|
|
4367
|
+
"aria-label": label,
|
|
4368
|
+
"aria-activedescendant": active ? `${listboxId}-option-${active}` : void 0,
|
|
4369
|
+
tabIndex: disabled ? -1 : 0,
|
|
4370
|
+
onKeyDown: handleKeyDown,
|
|
4371
|
+
...props,
|
|
4372
|
+
children
|
|
4373
|
+
}
|
|
4374
|
+
);
|
|
4375
|
+
}
|
|
4376
|
+
);
|
|
4377
|
+
ListboxContent.displayName = "ListboxContent";
|
|
4378
|
+
const ListboxItem = ({ value, children, className, ...props }) => {
|
|
4379
|
+
const ctx = useListbox();
|
|
4380
|
+
const { disabled, toggleValue, registerItem, unregisterItem, listboxId } = ctx;
|
|
4381
|
+
const isSelected = ctx.selection.has(value);
|
|
4382
|
+
const isActive = ctx.active === value;
|
|
4383
|
+
useEffect(() => {
|
|
4384
|
+
registerItem(value);
|
|
4385
|
+
return () => {
|
|
4386
|
+
unregisterItem(value);
|
|
4387
|
+
};
|
|
4388
|
+
}, [value, registerItem, unregisterItem]);
|
|
4389
|
+
const handleClick = useCallback(() => {
|
|
4390
|
+
if (!disabled) {
|
|
4391
|
+
toggleValue(value);
|
|
4392
|
+
}
|
|
4393
|
+
}, [disabled, toggleValue, value]);
|
|
4394
|
+
return (
|
|
4395
|
+
// ARIA listbox pattern: options are not individually focusable
|
|
4396
|
+
// Parent listbox handles all keyboard interactions via aria-activedescendant
|
|
4397
|
+
// eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/interactive-supports-focus
|
|
4398
|
+
/* @__PURE__ */ u(
|
|
4399
|
+
"div",
|
|
4400
|
+
{
|
|
4401
|
+
id: `${listboxId}-option-${value}`,
|
|
4402
|
+
className: cn(listboxItemVariants({ selected: isSelected, active: isActive }), className),
|
|
4403
|
+
role: "option",
|
|
4404
|
+
"aria-selected": isSelected,
|
|
4405
|
+
"data-value": value,
|
|
4406
|
+
"data-active": isActive || void 0,
|
|
4407
|
+
onClick: handleClick,
|
|
4408
|
+
...props,
|
|
4409
|
+
children
|
|
4410
|
+
}
|
|
4411
|
+
)
|
|
4412
|
+
);
|
|
4413
|
+
};
|
|
4414
|
+
ListboxItem.displayName = "ListboxItem";
|
|
4415
|
+
const Listbox = Object.assign(ListboxRoot, {
|
|
4416
|
+
Root: ListboxRoot,
|
|
4417
|
+
Content: ListboxContent,
|
|
4418
|
+
Item: ListboxItem
|
|
4419
|
+
});
|
|
4420
|
+
const SearchInput = forwardRef(
|
|
4421
|
+
({
|
|
4422
|
+
className,
|
|
4423
|
+
id,
|
|
4424
|
+
value,
|
|
4425
|
+
defaultValue = "",
|
|
4426
|
+
placeholder = "Search",
|
|
4427
|
+
clearLabel = "Clear",
|
|
4428
|
+
onChange,
|
|
4429
|
+
disabled,
|
|
4430
|
+
readOnly,
|
|
4431
|
+
...props
|
|
4432
|
+
}, ref) => {
|
|
4433
|
+
const inputId = usePrefixedId(unwrap(id));
|
|
4434
|
+
const [uncontrolledValue, setUncontrolledValue] = useState$1(defaultValue);
|
|
4435
|
+
const isControlled = value !== void 0;
|
|
4436
|
+
const inputValue = isControlled ? value : uncontrolledValue;
|
|
4437
|
+
const isValueSet = inputValue.length > 0;
|
|
4438
|
+
const canClear = isValueSet && !disabled && !readOnly;
|
|
4439
|
+
const handleChange = (e) => {
|
|
4440
|
+
const newValue = e.currentTarget.value;
|
|
4441
|
+
if (!isControlled) {
|
|
4442
|
+
setUncontrolledValue(newValue);
|
|
4443
|
+
}
|
|
4444
|
+
onChange?.(newValue);
|
|
4445
|
+
};
|
|
4446
|
+
const inputRef = useRef(null);
|
|
4447
|
+
const handleClear = () => {
|
|
4448
|
+
const newValue = "";
|
|
4449
|
+
if (!isControlled) {
|
|
4450
|
+
setUncontrolledValue(newValue);
|
|
4451
|
+
}
|
|
4452
|
+
onChange?.(newValue);
|
|
4453
|
+
inputRef.current?.focus();
|
|
4454
|
+
};
|
|
4455
|
+
return /* @__PURE__ */ u(
|
|
4456
|
+
"div",
|
|
4457
|
+
{
|
|
4458
|
+
className: cn(
|
|
4459
|
+
"relative flex rounded-sm overflow-hidden",
|
|
4460
|
+
"h-12 border border-bdr-subtle focus-within:border-bdr-strong",
|
|
4461
|
+
"focus-within:outline-none focus-within:ring-3 focus-within:ring-ring/50 focus-within:ring-offset-0",
|
|
4462
|
+
"transition-highlight",
|
|
4463
|
+
disabled && "pointer-events-none select-none opacity-30",
|
|
4464
|
+
className
|
|
4465
|
+
),
|
|
4466
|
+
children: [
|
|
4467
|
+
/* @__PURE__ */ u(
|
|
4468
|
+
Search,
|
|
4469
|
+
{
|
|
4470
|
+
className: "absolute left-4.5 top-1/2 -translate-y-1/2 mt-0.25 text-subtle pointer-events-none",
|
|
4471
|
+
size: 20,
|
|
4472
|
+
strokeWidth: 1.5
|
|
4473
|
+
}
|
|
4474
|
+
),
|
|
4475
|
+
/* @__PURE__ */ u(
|
|
4476
|
+
"input",
|
|
4477
|
+
{
|
|
4478
|
+
ref: useComposedRefs(ref, inputRef),
|
|
4479
|
+
id: inputId,
|
|
4480
|
+
className: cn(
|
|
4481
|
+
"w-full text-base pr-1 px-12 border-0",
|
|
4482
|
+
"text-main bg-surface-neutral",
|
|
4483
|
+
"placeholder:text-subtle",
|
|
4484
|
+
"focus:outline-none",
|
|
4485
|
+
"read-only:bg-surface-primary"
|
|
4486
|
+
),
|
|
4487
|
+
value: inputValue,
|
|
4488
|
+
onChange: handleChange,
|
|
4489
|
+
readOnly,
|
|
4490
|
+
disabled,
|
|
4491
|
+
placeholder,
|
|
4492
|
+
"aria-label": "Search",
|
|
4493
|
+
"aria-disabled": disabled,
|
|
4494
|
+
...props
|
|
4495
|
+
}
|
|
4496
|
+
),
|
|
4497
|
+
canClear && /* @__PURE__ */ u(
|
|
4498
|
+
IconButton,
|
|
4499
|
+
{
|
|
4500
|
+
className: "absolute right-3 top-1/2 -translate-y-1/2 w-8 h-8 text-subtle",
|
|
4501
|
+
size: "lg",
|
|
4502
|
+
icon: X,
|
|
4503
|
+
title: clearLabel,
|
|
4504
|
+
onClick: handleClear,
|
|
4505
|
+
disabled
|
|
4506
|
+
}
|
|
4507
|
+
)
|
|
4508
|
+
]
|
|
4509
|
+
}
|
|
4510
|
+
);
|
|
4511
|
+
}
|
|
4512
|
+
);
|
|
4513
|
+
SearchInput.displayName = "SearchInput";
|
|
4514
|
+
const SelectableListItem = ({
|
|
4515
|
+
className,
|
|
4516
|
+
selected,
|
|
4517
|
+
children,
|
|
4518
|
+
label,
|
|
4519
|
+
description,
|
|
4520
|
+
metadata,
|
|
4521
|
+
icon,
|
|
4522
|
+
readOnly,
|
|
4523
|
+
checked,
|
|
4524
|
+
defaultChecked,
|
|
4525
|
+
onCheckedChange,
|
|
4526
|
+
...props
|
|
4527
|
+
}) => {
|
|
4528
|
+
return /* @__PURE__ */ u(
|
|
4529
|
+
ListItem,
|
|
4530
|
+
{
|
|
4531
|
+
className: cn(!selected && "hover:bg-surface-primary-hover", className),
|
|
4532
|
+
selected,
|
|
4533
|
+
role: "row",
|
|
4534
|
+
"aria-selected": selected,
|
|
4535
|
+
...props,
|
|
4536
|
+
children: [
|
|
4537
|
+
/* @__PURE__ */ u(ListItem.Left, { children: /* @__PURE__ */ u(
|
|
4538
|
+
Checkbox,
|
|
4539
|
+
{
|
|
4540
|
+
checked,
|
|
4541
|
+
defaultChecked,
|
|
4542
|
+
onCheckedChange,
|
|
4543
|
+
readOnly
|
|
4544
|
+
}
|
|
4545
|
+
) }),
|
|
4546
|
+
/* @__PURE__ */ u(ListItem.DefaultContent, { label, description, metadata, icon }),
|
|
4547
|
+
/* @__PURE__ */ u(ListItem.Right, { children })
|
|
4548
|
+
]
|
|
4549
|
+
}
|
|
4550
|
+
);
|
|
4551
|
+
};
|
|
4552
|
+
SelectableListItem.displayName = "SelectableListItem";
|
|
4553
|
+
const Separator = ({ className, label, decorative = false, ...props }) => {
|
|
4554
|
+
const ariaHidden = decorative ? "true" : void 0;
|
|
4555
|
+
if (!label) {
|
|
4556
|
+
return /* @__PURE__ */ u("hr", { "aria-hidden": ariaHidden, className: cn("w-full border-bdr-subtle", className) });
|
|
4557
|
+
}
|
|
4558
|
+
return /* @__PURE__ */ u(
|
|
4559
|
+
"div",
|
|
4560
|
+
{
|
|
4561
|
+
role: "separator",
|
|
4562
|
+
"aria-orientation": "horizontal",
|
|
4563
|
+
"aria-hidden": ariaHidden,
|
|
4564
|
+
className: cn("inline-flex w-full gap-2.5", className),
|
|
4565
|
+
...props,
|
|
4566
|
+
children: [
|
|
4567
|
+
/* @__PURE__ */ u("span", { className: "min-w-0 truncate text-subtle uppercase", children: label }),
|
|
4568
|
+
/* @__PURE__ */ u("span", { className: "min-w-6 flex-1 border-b-1 border-bdr-subtle" })
|
|
4569
|
+
]
|
|
4570
|
+
}
|
|
4571
|
+
);
|
|
4572
|
+
};
|
|
4573
|
+
Separator.displayName = "Separator";
|
|
4574
|
+
const oppositeSide = {
|
|
4575
|
+
top: "bottom",
|
|
4576
|
+
bottom: "top",
|
|
4577
|
+
left: "right",
|
|
3732
4578
|
right: "left"
|
|
3733
4579
|
};
|
|
3734
4580
|
function useTooltipPosition(isOpen, side, triggerRef, tooltipRef) {
|
|
@@ -3924,7 +4770,7 @@ function Tooltip({
|
|
|
3924
4770
|
children
|
|
3925
4771
|
}
|
|
3926
4772
|
),
|
|
3927
|
-
isOpen && hasContent && createPortal(
|
|
4773
|
+
isOpen && hasContent && createPortal$1(
|
|
3928
4774
|
/* @__PURE__ */ u(
|
|
3929
4775
|
TooltipContent,
|
|
3930
4776
|
{
|
|
@@ -3939,299 +4785,12 @@ function Tooltip({
|
|
|
3939
4785
|
)
|
|
3940
4786
|
] });
|
|
3941
4787
|
}
|
|
3942
|
-
const DialogContext = createContext(void 0);
|
|
3943
|
-
const DialogProvider = ({ value, children }) => {
|
|
3944
|
-
return /* @__PURE__ */ u(DialogContext.Provider, { value, children });
|
|
3945
|
-
};
|
|
3946
|
-
DialogProvider.displayName = "DialogProvider";
|
|
3947
|
-
const useDialog = () => {
|
|
3948
|
-
const context = useContext(DialogContext);
|
|
3949
|
-
if (!context) {
|
|
3950
|
-
throw new Error("useDialog must be used within a DialogProvider");
|
|
3951
|
-
}
|
|
3952
|
-
return context;
|
|
3953
|
-
};
|
|
3954
|
-
function setRef(ref, value) {
|
|
3955
|
-
if (!ref) return;
|
|
3956
|
-
if (typeof ref === "function") {
|
|
3957
|
-
ref(value);
|
|
3958
|
-
} else {
|
|
3959
|
-
try {
|
|
3960
|
-
ref.current = value;
|
|
3961
|
-
} catch {
|
|
3962
|
-
}
|
|
3963
|
-
}
|
|
3964
|
-
}
|
|
3965
|
-
function useComposedRefs(...refs) {
|
|
3966
|
-
return useCallback((node) => {
|
|
3967
|
-
refs.forEach((ref) => setRef(ref, node));
|
|
3968
|
-
}, refs);
|
|
3969
|
-
}
|
|
3970
|
-
const SearchInput = forwardRef(
|
|
3971
|
-
({
|
|
3972
|
-
className,
|
|
3973
|
-
id,
|
|
3974
|
-
value,
|
|
3975
|
-
defaultValue = "",
|
|
3976
|
-
placeholder = "Search",
|
|
3977
|
-
clearLabel = "Clear",
|
|
3978
|
-
onChange,
|
|
3979
|
-
disabled,
|
|
3980
|
-
readOnly,
|
|
3981
|
-
...props
|
|
3982
|
-
}, ref) => {
|
|
3983
|
-
const inputId = usePrefixedId(unwrap(id));
|
|
3984
|
-
const [uncontrolledValue, setUncontrolledValue] = useState$1(defaultValue);
|
|
3985
|
-
const isControlled = value !== void 0;
|
|
3986
|
-
const inputValue = isControlled ? value : uncontrolledValue;
|
|
3987
|
-
const isValueSet = inputValue.length > 0;
|
|
3988
|
-
const canClear = isValueSet && !disabled && !readOnly;
|
|
3989
|
-
const handleChange = (e) => {
|
|
3990
|
-
const newValue = e.currentTarget.value;
|
|
3991
|
-
if (!isControlled) {
|
|
3992
|
-
setUncontrolledValue(newValue);
|
|
3993
|
-
}
|
|
3994
|
-
onChange?.(newValue);
|
|
3995
|
-
};
|
|
3996
|
-
const inputRef = useRef(null);
|
|
3997
|
-
const handleClear = () => {
|
|
3998
|
-
const newValue = "";
|
|
3999
|
-
if (!isControlled) {
|
|
4000
|
-
setUncontrolledValue(newValue);
|
|
4001
|
-
}
|
|
4002
|
-
onChange?.(newValue);
|
|
4003
|
-
inputRef.current?.focus();
|
|
4004
|
-
};
|
|
4005
|
-
return /* @__PURE__ */ u(
|
|
4006
|
-
"div",
|
|
4007
|
-
{
|
|
4008
|
-
className: cn(
|
|
4009
|
-
"relative flex rounded-sm overflow-hidden",
|
|
4010
|
-
"h-12 border border-bdr-subtle focus-within:border-bdr-strong",
|
|
4011
|
-
"focus-within:outline-none focus-within:ring-3 focus-within:ring-ring/50 focus-within:ring-offset-0",
|
|
4012
|
-
"transition-highlight",
|
|
4013
|
-
disabled && "pointer-events-none select-none opacity-30",
|
|
4014
|
-
className
|
|
4015
|
-
),
|
|
4016
|
-
children: [
|
|
4017
|
-
/* @__PURE__ */ u(
|
|
4018
|
-
Search,
|
|
4019
|
-
{
|
|
4020
|
-
className: "absolute left-4.5 top-1/2 -translate-y-1/2 mt-0.25 text-subtle pointer-events-none",
|
|
4021
|
-
size: 20,
|
|
4022
|
-
strokeWidth: 1.5
|
|
4023
|
-
}
|
|
4024
|
-
),
|
|
4025
|
-
/* @__PURE__ */ u(
|
|
4026
|
-
"input",
|
|
4027
|
-
{
|
|
4028
|
-
ref: useComposedRefs(ref, inputRef),
|
|
4029
|
-
id: inputId,
|
|
4030
|
-
className: cn(
|
|
4031
|
-
"w-full text-base pr-1 px-12 border-0",
|
|
4032
|
-
"text-main bg-surface-neutral",
|
|
4033
|
-
"placeholder:text-subtle",
|
|
4034
|
-
"focus:outline-none",
|
|
4035
|
-
"read-only:bg-surface-primary"
|
|
4036
|
-
),
|
|
4037
|
-
value: inputValue,
|
|
4038
|
-
onChange: handleChange,
|
|
4039
|
-
readOnly,
|
|
4040
|
-
disabled,
|
|
4041
|
-
placeholder,
|
|
4042
|
-
"aria-label": "Search",
|
|
4043
|
-
"aria-disabled": disabled,
|
|
4044
|
-
...props
|
|
4045
|
-
}
|
|
4046
|
-
),
|
|
4047
|
-
canClear && /* @__PURE__ */ u(
|
|
4048
|
-
IconButton,
|
|
4049
|
-
{
|
|
4050
|
-
className: "absolute right-3 top-1/2 -translate-y-1/2 w-8 h-8 text-subtle",
|
|
4051
|
-
size: "lg",
|
|
4052
|
-
icon: X,
|
|
4053
|
-
title: clearLabel,
|
|
4054
|
-
onClick: handleClear,
|
|
4055
|
-
disabled
|
|
4056
|
-
}
|
|
4057
|
-
)
|
|
4058
|
-
]
|
|
4059
|
-
}
|
|
4060
|
-
);
|
|
4061
|
-
}
|
|
4062
|
-
);
|
|
4063
|
-
SearchInput.displayName = "SearchInput";
|
|
4064
|
-
function ListboxImpl({
|
|
4065
|
-
className,
|
|
4066
|
-
selection: controlledSelection,
|
|
4067
|
-
selectionMode = "single",
|
|
4068
|
-
disabled = false,
|
|
4069
|
-
defaultSelection = /* @__PURE__ */ new Set(),
|
|
4070
|
-
setSelection,
|
|
4071
|
-
active: controlledActive,
|
|
4072
|
-
defaultActive,
|
|
4073
|
-
onActiveChange,
|
|
4074
|
-
items,
|
|
4075
|
-
renderItem,
|
|
4076
|
-
getValue,
|
|
4077
|
-
...props
|
|
4078
|
-
}, ref) {
|
|
4079
|
-
const listboxId = usePrefixedId();
|
|
4080
|
-
const innerRef = useRef(null);
|
|
4081
|
-
const [uncontrolledSelection, setUncontrolledSelection] = useState(defaultSelection);
|
|
4082
|
-
const isSelectionControlled = controlledSelection !== void 0;
|
|
4083
|
-
const selection = isSelectionControlled ? controlledSelection : uncontrolledSelection;
|
|
4084
|
-
const [uncontrolledActive, setUncontrolledActive] = useState(
|
|
4085
|
-
defaultActive ?? (items[0] ? getValue(items[0]) : void 0)
|
|
4086
|
-
);
|
|
4087
|
-
const isActiveControlled = controlledActive !== void 0;
|
|
4088
|
-
const active = isActiveControlled ? controlledActive : uncontrolledActive;
|
|
4089
|
-
const valueToIndexMap = useMemo(() => {
|
|
4090
|
-
return new Map(items.map((item, idx) => [getValue(item), idx]));
|
|
4091
|
-
}, [items, getValue]);
|
|
4092
|
-
const updateActive = useCallback(
|
|
4093
|
-
(newActive) => {
|
|
4094
|
-
if (!isActiveControlled) {
|
|
4095
|
-
setUncontrolledActive(newActive);
|
|
4096
|
-
}
|
|
4097
|
-
onActiveChange?.(newActive);
|
|
4098
|
-
},
|
|
4099
|
-
[isActiveControlled, onActiveChange]
|
|
4100
|
-
);
|
|
4101
|
-
useEffect(() => {
|
|
4102
|
-
if (!active || !items.some((item) => getValue(item) === active)) {
|
|
4103
|
-
updateActive(items[0] ? getValue(items[0]) : void 0);
|
|
4104
|
-
}
|
|
4105
|
-
}, [items, getValue, active, updateActive]);
|
|
4106
|
-
useEffect(() => {
|
|
4107
|
-
if (!active || !innerRef.current) return;
|
|
4108
|
-
const el = innerRef.current.querySelector(`#${listboxId}-option-${active}`);
|
|
4109
|
-
el?.scrollIntoView({ block: "nearest", behavior: "auto" });
|
|
4110
|
-
}, [active, listboxId]);
|
|
4111
|
-
const handleToggleValue = (value) => {
|
|
4112
|
-
const isAlreadySelected = selection.has(value);
|
|
4113
|
-
let newSelection;
|
|
4114
|
-
if (selectionMode === "single") {
|
|
4115
|
-
newSelection = isAlreadySelected ? /* @__PURE__ */ new Set() : /* @__PURE__ */ new Set([value]);
|
|
4116
|
-
} else {
|
|
4117
|
-
newSelection = new Set(selection);
|
|
4118
|
-
if (isAlreadySelected) {
|
|
4119
|
-
newSelection.delete(value);
|
|
4120
|
-
} else {
|
|
4121
|
-
newSelection.add(value);
|
|
4122
|
-
}
|
|
4123
|
-
}
|
|
4124
|
-
if (!isSelectionControlled) {
|
|
4125
|
-
setUncontrolledSelection(newSelection);
|
|
4126
|
-
}
|
|
4127
|
-
setSelection?.(newSelection);
|
|
4128
|
-
updateActive(value);
|
|
4129
|
-
};
|
|
4130
|
-
const handleClickItem = ({ target }) => {
|
|
4131
|
-
const li = target instanceof Element ? target.closest("li") : null;
|
|
4132
|
-
const value = li?.getAttribute("data-value");
|
|
4133
|
-
if (value) {
|
|
4134
|
-
handleToggleValue(value);
|
|
4135
|
-
}
|
|
4136
|
-
};
|
|
4137
|
-
const moveActive = (delta) => {
|
|
4138
|
-
const activeIndex = active ? valueToIndexMap.get(active) ?? 0 : 0;
|
|
4139
|
-
const newIndex = Math.max(0, Math.min(items.length - 1, activeIndex + delta));
|
|
4140
|
-
updateActive(getValue(items[newIndex]));
|
|
4141
|
-
};
|
|
4142
|
-
const handleKeyDown = (e) => {
|
|
4143
|
-
if (disabled) {
|
|
4144
|
-
return;
|
|
4145
|
-
}
|
|
4146
|
-
if (e.key === "ArrowDown") {
|
|
4147
|
-
e.preventDefault();
|
|
4148
|
-
moveActive(1);
|
|
4149
|
-
} else if (e.key === "ArrowUp") {
|
|
4150
|
-
e.preventDefault();
|
|
4151
|
-
moveActive(-1);
|
|
4152
|
-
} else if (e.key === "Home") {
|
|
4153
|
-
e.preventDefault();
|
|
4154
|
-
const firstItem = items[0];
|
|
4155
|
-
updateActive(firstItem && getValue(firstItem));
|
|
4156
|
-
} else if (e.key === "End") {
|
|
4157
|
-
e.preventDefault();
|
|
4158
|
-
const lastItem = items.at(-1);
|
|
4159
|
-
updateActive(lastItem && getValue(lastItem));
|
|
4160
|
-
} else if (e.key === " " || e.key === "Enter") {
|
|
4161
|
-
e.preventDefault();
|
|
4162
|
-
if (active) {
|
|
4163
|
-
handleToggleValue(active);
|
|
4164
|
-
}
|
|
4165
|
-
}
|
|
4166
|
-
};
|
|
4167
|
-
return /* @__PURE__ */ u(
|
|
4168
|
-
"ul",
|
|
4169
|
-
{
|
|
4170
|
-
id: listboxId,
|
|
4171
|
-
ref: useComposedRefs(ref, innerRef),
|
|
4172
|
-
tabIndex: disabled ? -1 : 0,
|
|
4173
|
-
className: cn(
|
|
4174
|
-
"flex flex-col items-start grow-1 shrink-0 basis-0",
|
|
4175
|
-
"max-h-100 px-0 overflow-y-auto",
|
|
4176
|
-
"focus-within:border-bdr-solid focus-within:outline-none focus-within:ring-3 focus-within:ring-ring/50 focus-within:ring-offset-0",
|
|
4177
|
-
"focus-within:[&>li[data-active=true]]:bg-surface-primary-hover",
|
|
4178
|
-
"focus-within:[&>li[data-active=true][aria-selected=true]]:bg-surface-primary-selected-hover",
|
|
4179
|
-
"transition-highlight",
|
|
4180
|
-
disabled && "pointer-events-none select-none opacity-30",
|
|
4181
|
-
className
|
|
4182
|
-
),
|
|
4183
|
-
role: "listbox",
|
|
4184
|
-
"aria-activedescendant": active ? `${listboxId}-option-${active}` : void 0,
|
|
4185
|
-
"aria-disabled": disabled,
|
|
4186
|
-
"aria-multiselectable": selectionMode === "multiple",
|
|
4187
|
-
"aria-label": props.label ?? void 0,
|
|
4188
|
-
"aria-orientation": "vertical",
|
|
4189
|
-
onKeyDown: handleKeyDown,
|
|
4190
|
-
onClick: handleClickItem,
|
|
4191
|
-
children: items.map((item) => {
|
|
4192
|
-
const value = getValue(item);
|
|
4193
|
-
const selected = selection.has(value);
|
|
4194
|
-
const isActive = value === active;
|
|
4195
|
-
return /* @__PURE__ */ u(
|
|
4196
|
-
"li",
|
|
4197
|
-
{
|
|
4198
|
-
id: `${listboxId}-option-${value}`,
|
|
4199
|
-
"data-value": value,
|
|
4200
|
-
"data-active": isActive ? "true" : "false",
|
|
4201
|
-
tabIndex: -1,
|
|
4202
|
-
className: cn(
|
|
4203
|
-
"flex items-center w-full px-4.5 py-1 gap-x-2.5",
|
|
4204
|
-
!disabled && "cursor-pointer",
|
|
4205
|
-
selected ? "bg-surface-primary-selected text-alt hover:bg-surface-primary-selected-hover" : "hover:bg-surface-primary-hover"
|
|
4206
|
-
),
|
|
4207
|
-
role: "option",
|
|
4208
|
-
"aria-selected": selected,
|
|
4209
|
-
children: renderItem(item, selected, isActive)
|
|
4210
|
-
},
|
|
4211
|
-
value
|
|
4212
|
-
);
|
|
4213
|
-
})
|
|
4214
|
-
}
|
|
4215
|
-
);
|
|
4216
|
-
}
|
|
4217
|
-
const Listbox = forwardRef(ListboxImpl);
|
|
4218
|
-
Listbox.displayName = "Listbox";
|
|
4219
|
-
const useScrollLock = (lock, element) => {
|
|
4220
|
-
useEffect(() => {
|
|
4221
|
-
if (!lock) {
|
|
4222
|
-
return;
|
|
4223
|
-
}
|
|
4224
|
-
const target = element ?? document.body;
|
|
4225
|
-
const originalOverflow = target.style.overflow;
|
|
4226
|
-
target.style.overflow = "hidden";
|
|
4227
|
-
return () => {
|
|
4228
|
-
target.style.overflow = originalOverflow;
|
|
4229
|
-
};
|
|
4230
|
-
}, [lock, element]);
|
|
4231
|
-
};
|
|
4232
4788
|
export {
|
|
4789
|
+
Avatar,
|
|
4790
|
+
AvatarProvider,
|
|
4233
4791
|
Button,
|
|
4234
4792
|
Checkbox,
|
|
4793
|
+
Dialog,
|
|
4235
4794
|
DialogProvider,
|
|
4236
4795
|
IconButton,
|
|
4237
4796
|
IdProvider,
|
|
@@ -4239,12 +4798,16 @@ export {
|
|
|
4239
4798
|
Link,
|
|
4240
4799
|
ListItem,
|
|
4241
4800
|
Listbox,
|
|
4801
|
+
ListboxProvider,
|
|
4242
4802
|
SearchInput,
|
|
4243
4803
|
SelectableListItem,
|
|
4804
|
+
Separator,
|
|
4244
4805
|
Tooltip,
|
|
4245
4806
|
cn,
|
|
4246
4807
|
unwrap,
|
|
4808
|
+
useAvatar,
|
|
4247
4809
|
useDialog,
|
|
4810
|
+
useListbox,
|
|
4248
4811
|
usePrefixedId,
|
|
4249
4812
|
useScrollLock
|
|
4250
4813
|
};
|