@hexdspace/react 0.1.30 → 0.1.32
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 +91 -58
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2740,7 +2740,27 @@ function Popover({
|
|
|
2740
2740
|
import { cva as cva7 } from "class-variance-authority";
|
|
2741
2741
|
import { AnimatePresence as AnimatePresence4, motion as motion4 } from "motion/react";
|
|
2742
2742
|
import { DropdownMenu as DropdownMenuPrimitive } from "radix-ui";
|
|
2743
|
+
import * as React13 from "react";
|
|
2744
|
+
|
|
2745
|
+
// src/ui/utils/refs.ts
|
|
2743
2746
|
import * as React12 from "react";
|
|
2747
|
+
function useComposedRefs(...refs) {
|
|
2748
|
+
return React12.useCallback(
|
|
2749
|
+
(node) => {
|
|
2750
|
+
for (const ref of refs) {
|
|
2751
|
+
if (!ref) continue;
|
|
2752
|
+
if (typeof ref === "function") {
|
|
2753
|
+
ref(node);
|
|
2754
|
+
} else if (ref) {
|
|
2755
|
+
ref.current = node;
|
|
2756
|
+
}
|
|
2757
|
+
}
|
|
2758
|
+
},
|
|
2759
|
+
[refs]
|
|
2760
|
+
);
|
|
2761
|
+
}
|
|
2762
|
+
|
|
2763
|
+
// src/ui/components/DropdownMenu.tsx
|
|
2744
2764
|
import { jsx as jsx19, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
2745
2765
|
var dropdownMenuContentVariants = cva7(
|
|
2746
2766
|
cn(
|
|
@@ -2809,14 +2829,14 @@ var dropdownMenuItemVariants = cva7(
|
|
|
2809
2829
|
}
|
|
2810
2830
|
);
|
|
2811
2831
|
function useWindowTimeout() {
|
|
2812
|
-
const timeoutRef =
|
|
2813
|
-
const clear =
|
|
2832
|
+
const timeoutRef = React13.useRef(null);
|
|
2833
|
+
const clear = React13.useCallback(() => {
|
|
2814
2834
|
if (timeoutRef.current !== null) {
|
|
2815
2835
|
window.clearTimeout(timeoutRef.current);
|
|
2816
2836
|
timeoutRef.current = null;
|
|
2817
2837
|
}
|
|
2818
2838
|
}, []);
|
|
2819
|
-
const set =
|
|
2839
|
+
const set = React13.useCallback(
|
|
2820
2840
|
(fn, ms) => {
|
|
2821
2841
|
clear();
|
|
2822
2842
|
timeoutRef.current = window.setTimeout(() => {
|
|
@@ -2826,9 +2846,27 @@ function useWindowTimeout() {
|
|
|
2826
2846
|
},
|
|
2827
2847
|
[clear]
|
|
2828
2848
|
);
|
|
2829
|
-
|
|
2849
|
+
React13.useEffect(() => clear, [clear]);
|
|
2830
2850
|
return { set, clear };
|
|
2831
2851
|
}
|
|
2852
|
+
function getFocusableElements() {
|
|
2853
|
+
const selector = [
|
|
2854
|
+
"a[href]",
|
|
2855
|
+
"button:not([disabled])",
|
|
2856
|
+
"textarea:not([disabled])",
|
|
2857
|
+
"input:not([disabled])",
|
|
2858
|
+
"select:not([disabled])",
|
|
2859
|
+
'[tabindex]:not([tabindex="-1"])'
|
|
2860
|
+
].join(",");
|
|
2861
|
+
return Array.from(document.querySelectorAll(selector));
|
|
2862
|
+
}
|
|
2863
|
+
function getNextFocusableElement(currentElement, reverse = false) {
|
|
2864
|
+
const focusableElements = getFocusableElements();
|
|
2865
|
+
const currentIndex = focusableElements.indexOf(currentElement);
|
|
2866
|
+
if (currentIndex === -1) return null;
|
|
2867
|
+
const nextIndex = reverse ? currentIndex - 1 : currentIndex + 1;
|
|
2868
|
+
return focusableElements[nextIndex] || null;
|
|
2869
|
+
}
|
|
2832
2870
|
function DropdownMenu({
|
|
2833
2871
|
trigger,
|
|
2834
2872
|
children,
|
|
@@ -2851,65 +2889,43 @@ function DropdownMenu({
|
|
|
2851
2889
|
style,
|
|
2852
2890
|
contentProps
|
|
2853
2891
|
}) {
|
|
2854
|
-
const [uncontrolledOpen, setUncontrolledOpen] =
|
|
2892
|
+
const [uncontrolledOpen, setUncontrolledOpen] = React13.useState(defaultOpen ?? false);
|
|
2855
2893
|
const isControlled = open2 !== void 0;
|
|
2856
2894
|
const resolvedOpen = isControlled ? open2 : uncontrolledOpen;
|
|
2857
2895
|
const motionDuration = useMotionDuration("--motion-fast", 0.14);
|
|
2858
|
-
const suppressDurationMs = Math.max(hoverCloseDelayMs, Math.round(motionDuration * 1e3) + 40);
|
|
2859
2896
|
const closeTimer = useWindowTimeout();
|
|
2860
|
-
const triggerRef =
|
|
2861
|
-
const contentRef =
|
|
2862
|
-
const openedByHoverRef =
|
|
2863
|
-
const
|
|
2864
|
-
const
|
|
2865
|
-
const isSuppressed = React12.useCallback(() => {
|
|
2866
|
-
if (!hoverOpen) return false;
|
|
2867
|
-
return Date.now() < suppressUntilRef.current;
|
|
2868
|
-
}, [hoverOpen]);
|
|
2869
|
-
const suppressReopen = React12.useCallback(() => {
|
|
2870
|
-
if (!hoverOpen) return;
|
|
2871
|
-
suppressUntilRef.current = Date.now() + suppressDurationMs;
|
|
2872
|
-
}, [hoverOpen, suppressDurationMs]);
|
|
2873
|
-
const handleOpenChange = React12.useCallback(
|
|
2897
|
+
const triggerRef = React13.useRef(null);
|
|
2898
|
+
const contentRef = React13.useRef(null);
|
|
2899
|
+
const openedByHoverRef = React13.useRef(false);
|
|
2900
|
+
const lastInputRef = React13.useRef("unknown");
|
|
2901
|
+
const handleOpenChange = React13.useCallback(
|
|
2874
2902
|
(nextOpen) => {
|
|
2875
2903
|
closeTimer.clear();
|
|
2876
2904
|
if (!nextOpen && hoverOpen && openedByHoverRef.current) {
|
|
2877
|
-
suppressReopen();
|
|
2878
2905
|
openedByHoverRef.current = false;
|
|
2879
2906
|
}
|
|
2880
2907
|
if (!isControlled) setUncontrolledOpen(nextOpen);
|
|
2881
2908
|
onOpenChange?.(nextOpen);
|
|
2882
2909
|
},
|
|
2883
|
-
[closeTimer, hoverOpen, isControlled, onOpenChange
|
|
2910
|
+
[closeTimer, hoverOpen, isControlled, onOpenChange]
|
|
2884
2911
|
);
|
|
2885
|
-
const isTargetInside =
|
|
2912
|
+
const isTargetInside = React13.useCallback((target) => {
|
|
2886
2913
|
if (!(target instanceof Node)) return false;
|
|
2887
2914
|
return Boolean(triggerRef.current?.contains(target) || contentRef.current?.contains(target));
|
|
2888
2915
|
}, []);
|
|
2889
|
-
const scheduleClose =
|
|
2916
|
+
const scheduleClose = React13.useCallback(() => {
|
|
2890
2917
|
if (!hoverOpen) return;
|
|
2891
2918
|
closeTimer.set(() => handleOpenChange(false), hoverCloseDelayMs);
|
|
2892
2919
|
}, [closeTimer, handleOpenChange, hoverCloseDelayMs, hoverOpen]);
|
|
2893
|
-
const setRef = (ref, node) => {
|
|
2894
|
-
if (typeof ref === "function") {
|
|
2895
|
-
ref(node);
|
|
2896
|
-
} else if (ref && typeof ref === "object") {
|
|
2897
|
-
ref.current = node;
|
|
2898
|
-
}
|
|
2899
|
-
};
|
|
2900
2920
|
const triggerElement = trigger;
|
|
2901
2921
|
const triggerProps = triggerElement.props;
|
|
2902
|
-
const
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
setRef(triggerProps.ref, node);
|
|
2906
|
-
},
|
|
2922
|
+
const composedTriggerRef = useComposedRefs(triggerRef, triggerProps.ref);
|
|
2923
|
+
const resolvedTrigger = hoverOpen ? React13.cloneElement(triggerElement, {
|
|
2924
|
+
ref: composedTriggerRef,
|
|
2907
2925
|
onPointerEnter: (event) => {
|
|
2908
2926
|
triggerProps.onPointerEnter?.(event);
|
|
2909
|
-
if (isSuppressed()) return;
|
|
2910
2927
|
openedByHoverRef.current = true;
|
|
2911
2928
|
lastInputRef.current = "pointer";
|
|
2912
|
-
suppressUntilRef.current = 0;
|
|
2913
2929
|
closeTimer.clear();
|
|
2914
2930
|
handleOpenChange(true);
|
|
2915
2931
|
},
|
|
@@ -2922,31 +2938,48 @@ function DropdownMenu({
|
|
|
2922
2938
|
if (isTargetInside(event.relatedTarget)) return;
|
|
2923
2939
|
scheduleClose();
|
|
2924
2940
|
},
|
|
2925
|
-
onFocus: (event) => {
|
|
2926
|
-
triggerProps.onFocus?.(event);
|
|
2927
|
-
if (lastInputRef.current === "pointer") return;
|
|
2928
|
-
if (isSuppressed()) return;
|
|
2929
|
-
openedByHoverRef.current = false;
|
|
2930
|
-
closeTimer.clear();
|
|
2931
|
-
handleOpenChange(true);
|
|
2932
|
-
},
|
|
2933
2941
|
onKeyDown: (event) => {
|
|
2934
2942
|
triggerProps.onKeyDown?.(event);
|
|
2935
2943
|
lastInputRef.current = "keyboard";
|
|
2936
2944
|
}
|
|
2937
2945
|
}) : trigger;
|
|
2938
2946
|
const contentPropsWithRef = contentProps;
|
|
2939
|
-
const {
|
|
2947
|
+
const {
|
|
2948
|
+
className: contentClassName,
|
|
2949
|
+
style: contentStyle,
|
|
2950
|
+
ref: contentPropRef,
|
|
2951
|
+
onKeyDown: userOnKeyDown,
|
|
2952
|
+
...restContentProps
|
|
2953
|
+
} = contentPropsWithRef ?? {};
|
|
2954
|
+
const composedContentRef = useComposedRefs(contentRef, contentPropRef);
|
|
2955
|
+
const handleContentKeyDown = React13.useCallback(
|
|
2956
|
+
(event) => {
|
|
2957
|
+
userOnKeyDown?.(event);
|
|
2958
|
+
if (event.key === "Tab" && !event.defaultPrevented) {
|
|
2959
|
+
event.preventDefault();
|
|
2960
|
+
const triggerElement2 = triggerRef.current;
|
|
2961
|
+
if (!triggerElement2) return;
|
|
2962
|
+
const reverse = event.shiftKey;
|
|
2963
|
+
const nextElement = getNextFocusableElement(triggerElement2, reverse);
|
|
2964
|
+
handleOpenChange(false);
|
|
2965
|
+
if (nextElement) {
|
|
2966
|
+
setTimeout(() => {
|
|
2967
|
+
nextElement.focus();
|
|
2968
|
+
}, 0);
|
|
2969
|
+
}
|
|
2970
|
+
}
|
|
2971
|
+
},
|
|
2972
|
+
[handleOpenChange, userOnKeyDown]
|
|
2973
|
+
);
|
|
2940
2974
|
const onPointerDownOutside = (event) => {
|
|
2941
2975
|
restContentProps.onPointerDownOutside?.(event);
|
|
2942
|
-
if (openedByHoverRef.current) suppressReopen();
|
|
2943
2976
|
};
|
|
2944
2977
|
const onInteractOutside = (event) => {
|
|
2945
2978
|
restContentProps.onInteractOutside?.(event);
|
|
2946
|
-
if (openedByHoverRef.current) suppressReopen();
|
|
2947
2979
|
};
|
|
2948
2980
|
const resolvedContentProps = hoverOpen ? {
|
|
2949
2981
|
...restContentProps,
|
|
2982
|
+
onKeyDown: handleContentKeyDown,
|
|
2950
2983
|
onPointerEnter: (event) => {
|
|
2951
2984
|
restContentProps.onPointerEnter?.(event);
|
|
2952
2985
|
closeTimer.clear();
|
|
@@ -2962,7 +2995,10 @@ function DropdownMenu({
|
|
|
2962
2995
|
},
|
|
2963
2996
|
onPointerDownOutside,
|
|
2964
2997
|
onInteractOutside
|
|
2965
|
-
} :
|
|
2998
|
+
} : {
|
|
2999
|
+
...restContentProps,
|
|
3000
|
+
onKeyDown: handleContentKeyDown
|
|
3001
|
+
};
|
|
2966
3002
|
return /* @__PURE__ */ jsxs11(DropdownMenuPrimitive.Root, { open: resolvedOpen, onOpenChange: handleOpenChange, modal, children: [
|
|
2967
3003
|
/* @__PURE__ */ jsx19(DropdownMenuPrimitive.Trigger, { asChild: true, children: resolvedTrigger }),
|
|
2968
3004
|
/* @__PURE__ */ jsx19(DropdownMenuPrimitive.Portal, { forceMount: true, container: portalContainer, children: /* @__PURE__ */ jsx19(AnimatePresence4, { children: resolvedOpen ? /* @__PURE__ */ jsx19(
|
|
@@ -2982,10 +3018,7 @@ function DropdownMenu({
|
|
|
2982
3018
|
motion4.div,
|
|
2983
3019
|
{
|
|
2984
3020
|
className: cn(dropdownMenuContentVariants({ chrome }), className, contentClassName),
|
|
2985
|
-
ref:
|
|
2986
|
-
contentRef.current = node;
|
|
2987
|
-
setRef(contentPropRef, node);
|
|
2988
|
-
},
|
|
3021
|
+
ref: composedContentRef,
|
|
2989
3022
|
initial: {
|
|
2990
3023
|
opacity: 0,
|
|
2991
3024
|
scale: 0.98,
|
|
@@ -3009,7 +3042,7 @@ function DropdownMenu({
|
|
|
3009
3042
|
) : null }) })
|
|
3010
3043
|
] });
|
|
3011
3044
|
}
|
|
3012
|
-
var DropdownMenuItem =
|
|
3045
|
+
var DropdownMenuItem = React13.forwardRef(
|
|
3013
3046
|
({ className, inset, destructive, ...props }, ref) => /* @__PURE__ */ jsx19(
|
|
3014
3047
|
DropdownMenuPrimitive.Item,
|
|
3015
3048
|
{
|
|
@@ -3020,13 +3053,13 @@ var DropdownMenuItem = React12.forwardRef(
|
|
|
3020
3053
|
)
|
|
3021
3054
|
);
|
|
3022
3055
|
DropdownMenuItem.displayName = "DropdownMenuItem";
|
|
3023
|
-
var DropdownMenuSeparator =
|
|
3056
|
+
var DropdownMenuSeparator = React13.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx19(DropdownMenuPrimitive.Separator, { ref, className: cn("my-1 h-px bg-(--divider)", className), ...props }));
|
|
3024
3057
|
DropdownMenuSeparator.displayName = "DropdownMenuSeparator";
|
|
3025
3058
|
|
|
3026
3059
|
// src/ui/components/Kbd.tsx
|
|
3027
|
-
import * as
|
|
3060
|
+
import * as React14 from "react";
|
|
3028
3061
|
import { jsx as jsx20 } from "react/jsx-runtime";
|
|
3029
|
-
var Kbd =
|
|
3062
|
+
var Kbd = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx20(
|
|
3030
3063
|
"span",
|
|
3031
3064
|
{
|
|
3032
3065
|
ref,
|