@underverse-ui/underverse 1.0.160 → 1.0.161
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/api-reference.json +1 -1
- package/dist/index.cjs +53 -26
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +53 -26
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -7593,6 +7593,23 @@ var DropdownMenu = ({
|
|
|
7593
7593
|
const itemsRef = React25.useRef([]);
|
|
7594
7594
|
const [activeIndex, setActiveIndex] = useResettingIndex(open);
|
|
7595
7595
|
const parentMenu = React25.useContext(DropdownMenuContext);
|
|
7596
|
+
const closeMenu = React25.useCallback(() => {
|
|
7597
|
+
setOpen(false);
|
|
7598
|
+
parentMenu?.closeMenu();
|
|
7599
|
+
}, [parentMenu, setOpen]);
|
|
7600
|
+
const getEnabledMenuItems = React25.useCallback(() => {
|
|
7601
|
+
const menuEl = menuRef.current;
|
|
7602
|
+
if (!menuEl) return [];
|
|
7603
|
+
return Array.from(menuEl.querySelectorAll("[data-dropdown-menu-item]")).filter((el) => !el.disabled);
|
|
7604
|
+
}, []);
|
|
7605
|
+
const focusMenuItem = React25.useCallback((index) => {
|
|
7606
|
+
const enabled = getEnabledMenuItems();
|
|
7607
|
+
const item = enabled[index];
|
|
7608
|
+
if (!item) return;
|
|
7609
|
+
setActiveIndex(index);
|
|
7610
|
+
item.focus();
|
|
7611
|
+
item.scrollIntoView({ block: "nearest" });
|
|
7612
|
+
}, [getEnabledMenuItems, setActiveIndex]);
|
|
7596
7613
|
useShadCNAnimations();
|
|
7597
7614
|
React25.useEffect(() => {
|
|
7598
7615
|
if (!open) return;
|
|
@@ -7603,38 +7620,34 @@ var DropdownMenu = ({
|
|
|
7603
7620
|
if (!active || !triggerEl || !menuEl) return;
|
|
7604
7621
|
const isInMenu = menuEl.contains(active);
|
|
7605
7622
|
const isOnTrigger = triggerEl.contains(active);
|
|
7606
|
-
|
|
7607
|
-
const enabled = itemsRef.current.filter((el) => el && !el.disabled);
|
|
7623
|
+
const enabled = getEnabledMenuItems();
|
|
7608
7624
|
if (enabled.length === 0) return;
|
|
7625
|
+
const currentIndex = enabled.findIndex((el) => el === active);
|
|
7626
|
+
const baseIndex = currentIndex >= 0 ? currentIndex : activeIndex;
|
|
7609
7627
|
if (e.key === "ArrowDown") {
|
|
7610
7628
|
e.preventDefault();
|
|
7611
|
-
const next = (
|
|
7612
|
-
|
|
7613
|
-
enabled[next]?.focus();
|
|
7629
|
+
const next = (baseIndex + 1 + enabled.length) % enabled.length;
|
|
7630
|
+
focusMenuItem(next);
|
|
7614
7631
|
} else if (e.key === "ArrowUp") {
|
|
7615
7632
|
e.preventDefault();
|
|
7616
|
-
const prev = (
|
|
7617
|
-
|
|
7618
|
-
enabled[prev]?.focus();
|
|
7633
|
+
const prev = (baseIndex - 1 + enabled.length) % enabled.length;
|
|
7634
|
+
focusMenuItem(prev);
|
|
7619
7635
|
} else if (e.key === "Home") {
|
|
7620
7636
|
e.preventDefault();
|
|
7621
|
-
|
|
7622
|
-
enabled[0]?.focus();
|
|
7637
|
+
focusMenuItem(0);
|
|
7623
7638
|
} else if (e.key === "End") {
|
|
7624
7639
|
e.preventDefault();
|
|
7625
|
-
|
|
7626
|
-
|
|
7640
|
+
focusMenuItem(enabled.length - 1);
|
|
7641
|
+
} else if (e.key === "Escape" && (isInMenu || isOnTrigger)) {
|
|
7642
|
+
e.preventDefault();
|
|
7643
|
+
closeMenu();
|
|
7627
7644
|
}
|
|
7628
7645
|
};
|
|
7629
|
-
document.addEventListener("keydown", handleKeyNav);
|
|
7646
|
+
document.addEventListener("keydown", handleKeyNav, true);
|
|
7630
7647
|
return () => {
|
|
7631
|
-
document.removeEventListener("keydown", handleKeyNav);
|
|
7648
|
+
document.removeEventListener("keydown", handleKeyNav, true);
|
|
7632
7649
|
};
|
|
7633
|
-
}, [open, activeIndex,
|
|
7634
|
-
const closeMenu = React25.useCallback(() => {
|
|
7635
|
-
setOpen(false);
|
|
7636
|
-
parentMenu?.closeMenu();
|
|
7637
|
-
}, [parentMenu, setOpen]);
|
|
7650
|
+
}, [open, activeIndex, closeMenu, focusMenuItem, getEnabledMenuItems]);
|
|
7638
7651
|
const menuContext = React25.useMemo(
|
|
7639
7652
|
() => ({
|
|
7640
7653
|
closeMenu,
|
|
@@ -7659,6 +7672,7 @@ var DropdownMenu = ({
|
|
|
7659
7672
|
onClick: () => handleItemClick(item.onClick),
|
|
7660
7673
|
disabled: item.disabled,
|
|
7661
7674
|
role: "menuitem",
|
|
7675
|
+
"data-dropdown-menu-item": "",
|
|
7662
7676
|
tabIndex: -1,
|
|
7663
7677
|
style: {
|
|
7664
7678
|
animationDelay: open ? `${Math.min(index * 20, 200)}ms` : "0ms"
|
|
@@ -7694,13 +7708,13 @@ var DropdownMenu = ({
|
|
|
7694
7708
|
if (e.key === "ArrowDown") {
|
|
7695
7709
|
e.preventDefault();
|
|
7696
7710
|
setOpen(true);
|
|
7697
|
-
requestAnimationFrame(() =>
|
|
7711
|
+
requestAnimationFrame(() => focusMenuItem(0));
|
|
7698
7712
|
} else if (e.key === "ArrowUp") {
|
|
7699
7713
|
e.preventDefault();
|
|
7700
7714
|
setOpen(true);
|
|
7701
7715
|
requestAnimationFrame(() => {
|
|
7702
|
-
const enabled =
|
|
7703
|
-
enabled
|
|
7716
|
+
const enabled = getEnabledMenuItems();
|
|
7717
|
+
focusMenuItem(enabled.length - 1);
|
|
7704
7718
|
});
|
|
7705
7719
|
} else if (e.key === "Escape") {
|
|
7706
7720
|
e.preventDefault();
|
|
@@ -7751,6 +7765,8 @@ var DropdownMenuItem = ({
|
|
|
7751
7765
|
},
|
|
7752
7766
|
disabled,
|
|
7753
7767
|
onMouseDown: (e) => e.preventDefault(),
|
|
7768
|
+
"data-dropdown-menu-item": "",
|
|
7769
|
+
tabIndex: -1,
|
|
7754
7770
|
className: cn(
|
|
7755
7771
|
"flex w-full items-center gap-2 px-3 py-2 text-sm rounded-lg transition-colors group cursor-pointer",
|
|
7756
7772
|
"hover:bg-accent hover:text-accent-foreground",
|
|
@@ -32123,9 +32139,14 @@ var CustomBubbleMenu = ({
|
|
|
32123
32139
|
}) => {
|
|
32124
32140
|
const SHOW_DELAY_MS = 180;
|
|
32125
32141
|
const BUBBLE_MENU_OFFSET = 16;
|
|
32142
|
+
const BUBBLE_MENU_ESTIMATED_HEIGHT = 44;
|
|
32126
32143
|
const [isVisible, setIsVisible] = useState48(false);
|
|
32127
32144
|
const [linkInputOpen, setLinkInputOpen] = useState48(false);
|
|
32128
|
-
const [position, setPosition] = useState48({
|
|
32145
|
+
const [position, setPosition] = useState48({
|
|
32146
|
+
top: 0,
|
|
32147
|
+
left: 0,
|
|
32148
|
+
placement: "top"
|
|
32149
|
+
});
|
|
32129
32150
|
const menuRef = useRef33(null);
|
|
32130
32151
|
const keepOpenRef = useRef33(false);
|
|
32131
32152
|
const showTimeoutRef = useRef33(null);
|
|
@@ -32182,12 +32203,18 @@ var CustomBubbleMenu = ({
|
|
|
32182
32203
|
return;
|
|
32183
32204
|
}
|
|
32184
32205
|
const viewportPadding = 8;
|
|
32206
|
+
const menuHeight = menuRef.current?.getBoundingClientRect().height || BUBBLE_MENU_ESTIMATED_HEIGHT;
|
|
32207
|
+
const editorTop = view.dom.getBoundingClientRect().top;
|
|
32208
|
+
const selectionTop = Math.min(start.top, end.top);
|
|
32209
|
+
const selectionBottom = Math.max(start.bottom, end.bottom);
|
|
32210
|
+
const hasRoomAboveEditor = selectionTop - BUBBLE_MENU_OFFSET - menuHeight >= editorTop + viewportPadding;
|
|
32211
|
+
const placement = hasRoomAboveEditor ? "top" : "bottom";
|
|
32185
32212
|
const left = Math.min(
|
|
32186
32213
|
window.innerWidth - viewportPadding,
|
|
32187
32214
|
Math.max(viewportPadding, (start.left + end.left) / 2)
|
|
32188
32215
|
);
|
|
32189
|
-
const top = Math.max(viewportPadding,
|
|
32190
|
-
setPosition({ top, left });
|
|
32216
|
+
const top = placement === "top" ? Math.max(viewportPadding, selectionTop - BUBBLE_MENU_OFFSET) : Math.min(window.innerHeight - viewportPadding, selectionBottom + BUBBLE_MENU_OFFSET);
|
|
32217
|
+
setPosition({ top, left, placement });
|
|
32191
32218
|
if (keepOpenRef.current) {
|
|
32192
32219
|
clearShowTimeout();
|
|
32193
32220
|
setIsVisible(true);
|
|
@@ -32232,7 +32259,7 @@ var CustomBubbleMenu = ({
|
|
|
32232
32259
|
style: {
|
|
32233
32260
|
top: `${position.top}px`,
|
|
32234
32261
|
left: `${position.left}px`,
|
|
32235
|
-
transform: "translate(-50%, -100%)"
|
|
32262
|
+
transform: position.placement === "top" ? "translate(-50%, -100%)" : "translate(-50%, 0)"
|
|
32236
32263
|
},
|
|
32237
32264
|
onMouseDown: (e) => {
|
|
32238
32265
|
const target = e.target;
|