Skip to content

Commit af0da31

Browse files
committed
Handle parent.type
1 parent 7709c23 commit af0da31

File tree

1 file changed

+40
-30
lines changed

1 file changed

+40
-30
lines changed

packages/react/src/menu/root/useMenuRoot.ts

+40-30
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,10 @@ import {
2929
type OpenChangeReason,
3030
translateOpenChangeReason,
3131
} from '../../utils/translateOpenChangeReason';
32-
import { useContextMenuRootContext } from '../../context-menu/root/ContextMenuRootContext';
32+
import {
33+
ContextMenuRootContext,
34+
useContextMenuRootContext,
35+
} from '../../context-menu/root/ContextMenuRootContext';
3336
import { ownerDocument } from '../../utils/owner';
3437

3538
const EMPTY_ARRAY: never[] = [];
@@ -49,9 +52,6 @@ export function useMenuRoot(parameters: useMenuRoot.Parameters): useMenuRoot.Ret
4952
modal: modalParam,
5053
} = parameters;
5154

52-
const contextMenuContext = useContextMenuRootContext();
53-
const hasContextMenuParent = Boolean(contextMenuContext) && !nested;
54-
5555
const [triggerElement, setTriggerElement] = React.useState<HTMLElement | null>(null);
5656
const [positionerElement, setPositionerElementUnwrapped] = React.useState<HTMLElement | null>(
5757
null,
@@ -72,6 +72,7 @@ export function useMenuRoot(parameters: useMenuRoot.Parameters): useMenuRoot.Ret
7272
{
7373
const parentContext = useMenuRootContext(true);
7474
const menubarContext = useMenubarContext(true);
75+
const contextMenuContext = useContextMenuRootContext(true);
7576

7677
if (parentContext) {
7778
parent = {
@@ -83,6 +84,11 @@ export function useMenuRoot(parameters: useMenuRoot.Parameters): useMenuRoot.Ret
8384
type: 'menubar',
8485
context: menubarContext,
8586
};
87+
} else if (contextMenuContext) {
88+
parent = {
89+
type: 'context-menu',
90+
context: contextMenuContext,
91+
};
8692
} else {
8793
parent = {
8894
type: undefined,
@@ -105,7 +111,7 @@ export function useMenuRoot(parameters: useMenuRoot.Parameters): useMenuRoot.Ret
105111
(parent.type === 'menu' || (parent.type === 'menubar' && parent.context.hasSubmenuOpen));
106112

107113
React.useImperativeHandle<HTMLElement | null, HTMLElement | null>(
108-
contextMenuContext?.positionerRef,
114+
parent.type === 'context-menu' ? parent.context?.positionerRef : null,
109115
() => positionerElement,
110116
[positionerElement],
111117
);
@@ -122,7 +128,7 @@ export function useMenuRoot(parameters: useMenuRoot.Parameters): useMenuRoot.Ret
122128
setPositionerElementUnwrapped(value);
123129
}, []);
124130

125-
const allowMouseUpTriggerRef = React.useRef(hasContextMenuParent);
131+
const allowMouseUpTriggerRef = React.useRef(parent.type === 'context-menu');
126132

127133
const { mounted, setMounted, transitionStatus } = useTransitionStatus(open);
128134

@@ -154,18 +160,6 @@ export function useMenuRoot(parameters: useMenuRoot.Parameters): useMenuRoot.Ret
154160
},
155161
});
156162

157-
React.useImperativeHandle(parameters.actionsRef, () => ({ unmount: handleUnmount }), [
158-
handleUnmount,
159-
]);
160-
161-
React.useImperativeHandle(contextMenuContext?.actionsRef, () => ({ setOpen }), [setOpen]);
162-
163-
React.useEffect(() => {
164-
if (!open) {
165-
stickIfOpenTimeout.clear();
166-
}
167-
}, [stickIfOpenTimeout, open]);
168-
169163
const ignoreClickRef = React.useRef(false);
170164
const allowTouchToCloseRef = React.useRef(true);
171165
const allowTouchToCloseTimeout = useTimeout();
@@ -260,6 +254,22 @@ export function useMenuRoot(parameters: useMenuRoot.Parameters): useMenuRoot.Ret
260254
},
261255
);
262256

257+
React.useImperativeHandle(parameters.actionsRef, () => ({ unmount: handleUnmount }), [
258+
handleUnmount,
259+
]);
260+
261+
React.useImperativeHandle(
262+
parent.type === 'context-menu' ? parent.context?.actionsRef : null,
263+
() => ({ setOpen }),
264+
[setOpen],
265+
);
266+
267+
React.useEffect(() => {
268+
if (!open) {
269+
stickIfOpenTimeout.clear();
270+
}
271+
}, [stickIfOpenTimeout, open]);
272+
263273
const floatingRootContext = useFloatingRootContext({
264274
elements: {
265275
reference: triggerElement,
@@ -276,7 +286,7 @@ export function useMenuRoot(parameters: useMenuRoot.Parameters): useMenuRoot.Ret
276286
hoverEnabled &&
277287
openOnHover &&
278288
!disabled &&
279-
!hasContextMenuParent &&
289+
parent.type !== 'context-menu' &&
280290
(parent.type !== 'menubar' || (parent.context.hasSubmenuOpen && !open)),
281291
handleClose: safePolygon({ blockPointerEvents: true }),
282292
mouseOnly: true,
@@ -290,23 +300,19 @@ export function useMenuRoot(parameters: useMenuRoot.Parameters): useMenuRoot.Ret
290300
});
291301

292302
const click = useClick(floatingRootContext, {
293-
enabled: !disabled && !hasContextMenuParent,
303+
enabled: !disabled && parent.type !== 'context-menu',
294304
event: open ? 'click' : 'mousedown',
295305
toggle: !openOnHover || parent.type !== 'menu',
296306
ignoreMouse: openOnHover && parent.type === 'menu',
297307
stickIfOpen: parent.type === undefined ? stickIfOpen : false,
298308
});
299309

300310
const dismiss = useDismiss(floatingRootContext, {
311+
enabled: !disabled,
301312
bubbles: closeParentOnEsc && parent.type === 'menu',
302313
// For context menus, this avoids an issue on long press where the menu closes right
303314
// after opening.
304-
outsidePressEvent: hasContextMenuParent ? 'pointerdown' : 'mousedown',
305-
enabled: !disabled,
306-
event: open ? 'click' : 'mousedown',
307-
toggle: !openOnHover || parent.type !== 'menu',
308-
ignoreMouse: openOnHover && parent.type === 'menu',
309-
stickIfOpen: parent.type === undefined ? stickIfOpen : false,
315+
outsidePressEvent: parent.type === 'context-menu' ? 'pointerdown' : 'mousedown',
310316
});
311317

312318
const role = useRole(floatingRootContext, {
@@ -329,7 +335,7 @@ export function useMenuRoot(parameters: useMenuRoot.Parameters): useMenuRoot.Ret
329335
rtl: direction === 'rtl',
330336
disabledIndices: EMPTY_ARRAY,
331337
onNavigate: setActiveIndex,
332-
openOnArrowKeyDown: !hasContextMenuParent,
338+
openOnArrowKeyDown: parent.type !== 'context-menu',
333339
});
334340

335341
const typingRef = React.useRef(false);
@@ -389,14 +395,14 @@ export function useMenuRoot(parameters: useMenuRoot.Parameters): useMenuRoot.Ret
389395

390396
const itemProps = React.useMemo(() => getItemProps(), [getItemProps]);
391397

392-
const allowMouseUpTriggerRef = React.useRef(false);
393-
394398
return React.useMemo(
395399
() => ({
396400
activeIndex,
397401
setActiveIndex,
398402
allowMouseUpTriggerRef:
399-
parent.type !== undefined ? parent.context.allowMouseUpTriggerRef : allowMouseUpTriggerRef,
403+
parent.type && parent.type !== 'context-menu'
404+
? parent.context.allowMouseUpTriggerRef
405+
: allowMouseUpTriggerRef,
400406
floatingRootContext,
401407
itemProps,
402408
popupProps,
@@ -554,6 +560,10 @@ export namespace useMenuRoot {
554560
type: 'menubar';
555561
context: MenubarContext;
556562
}
563+
| {
564+
type: 'context-menu';
565+
context: ContextMenuRootContext;
566+
}
557567
| {
558568
type: undefined;
559569
};

0 commit comments

Comments
 (0)