@@ -29,7 +29,10 @@ import {
29
29
type OpenChangeReason ,
30
30
translateOpenChangeReason ,
31
31
} from '../../utils/translateOpenChangeReason' ;
32
- import { useContextMenuRootContext } from '../../context-menu/root/ContextMenuRootContext' ;
32
+ import {
33
+ ContextMenuRootContext ,
34
+ useContextMenuRootContext ,
35
+ } from '../../context-menu/root/ContextMenuRootContext' ;
33
36
import { ownerDocument } from '../../utils/owner' ;
34
37
35
38
const EMPTY_ARRAY : never [ ] = [ ] ;
@@ -49,9 +52,6 @@ export function useMenuRoot(parameters: useMenuRoot.Parameters): useMenuRoot.Ret
49
52
modal : modalParam ,
50
53
} = parameters ;
51
54
52
- const contextMenuContext = useContextMenuRootContext ( ) ;
53
- const hasContextMenuParent = Boolean ( contextMenuContext ) && ! nested ;
54
-
55
55
const [ triggerElement , setTriggerElement ] = React . useState < HTMLElement | null > ( null ) ;
56
56
const [ positionerElement , setPositionerElementUnwrapped ] = React . useState < HTMLElement | null > (
57
57
null ,
@@ -72,6 +72,7 @@ export function useMenuRoot(parameters: useMenuRoot.Parameters): useMenuRoot.Ret
72
72
{
73
73
const parentContext = useMenuRootContext ( true ) ;
74
74
const menubarContext = useMenubarContext ( true ) ;
75
+ const contextMenuContext = useContextMenuRootContext ( true ) ;
75
76
76
77
if ( parentContext ) {
77
78
parent = {
@@ -83,6 +84,11 @@ export function useMenuRoot(parameters: useMenuRoot.Parameters): useMenuRoot.Ret
83
84
type : 'menubar' ,
84
85
context : menubarContext ,
85
86
} ;
87
+ } else if ( contextMenuContext ) {
88
+ parent = {
89
+ type : 'context-menu' ,
90
+ context : contextMenuContext ,
91
+ } ;
86
92
} else {
87
93
parent = {
88
94
type : undefined ,
@@ -105,7 +111,7 @@ export function useMenuRoot(parameters: useMenuRoot.Parameters): useMenuRoot.Ret
105
111
( parent . type === 'menu' || ( parent . type === 'menubar' && parent . context . hasSubmenuOpen ) ) ;
106
112
107
113
React . useImperativeHandle < HTMLElement | null , HTMLElement | null > (
108
- contextMenuContext ?. positionerRef ,
114
+ parent . type === 'context-menu' ? parent . context ?. positionerRef : null ,
109
115
( ) => positionerElement ,
110
116
[ positionerElement ] ,
111
117
) ;
@@ -122,7 +128,7 @@ export function useMenuRoot(parameters: useMenuRoot.Parameters): useMenuRoot.Ret
122
128
setPositionerElementUnwrapped ( value ) ;
123
129
} , [ ] ) ;
124
130
125
- const allowMouseUpTriggerRef = React . useRef ( hasContextMenuParent ) ;
131
+ const allowMouseUpTriggerRef = React . useRef ( parent . type === 'context-menu' ) ;
126
132
127
133
const { mounted, setMounted, transitionStatus } = useTransitionStatus ( open ) ;
128
134
@@ -154,18 +160,6 @@ export function useMenuRoot(parameters: useMenuRoot.Parameters): useMenuRoot.Ret
154
160
} ,
155
161
} ) ;
156
162
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
-
169
163
const ignoreClickRef = React . useRef ( false ) ;
170
164
const allowTouchToCloseRef = React . useRef ( true ) ;
171
165
const allowTouchToCloseTimeout = useTimeout ( ) ;
@@ -260,6 +254,22 @@ export function useMenuRoot(parameters: useMenuRoot.Parameters): useMenuRoot.Ret
260
254
} ,
261
255
) ;
262
256
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
+
263
273
const floatingRootContext = useFloatingRootContext ( {
264
274
elements : {
265
275
reference : triggerElement ,
@@ -276,7 +286,7 @@ export function useMenuRoot(parameters: useMenuRoot.Parameters): useMenuRoot.Ret
276
286
hoverEnabled &&
277
287
openOnHover &&
278
288
! disabled &&
279
- ! hasContextMenuParent &&
289
+ parent . type !== 'context-menu' &&
280
290
( parent . type !== 'menubar' || ( parent . context . hasSubmenuOpen && ! open ) ) ,
281
291
handleClose : safePolygon ( { blockPointerEvents : true } ) ,
282
292
mouseOnly : true ,
@@ -290,23 +300,19 @@ export function useMenuRoot(parameters: useMenuRoot.Parameters): useMenuRoot.Ret
290
300
} ) ;
291
301
292
302
const click = useClick ( floatingRootContext , {
293
- enabled : ! disabled && ! hasContextMenuParent ,
303
+ enabled : ! disabled && parent . type !== 'context-menu' ,
294
304
event : open ? 'click' : 'mousedown' ,
295
305
toggle : ! openOnHover || parent . type !== 'menu' ,
296
306
ignoreMouse : openOnHover && parent . type === 'menu' ,
297
307
stickIfOpen : parent . type === undefined ? stickIfOpen : false ,
298
308
} ) ;
299
309
300
310
const dismiss = useDismiss ( floatingRootContext , {
311
+ enabled : ! disabled ,
301
312
bubbles : closeParentOnEsc && parent . type === 'menu' ,
302
313
// For context menus, this avoids an issue on long press where the menu closes right
303
314
// 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' ,
310
316
} ) ;
311
317
312
318
const role = useRole ( floatingRootContext , {
@@ -329,7 +335,7 @@ export function useMenuRoot(parameters: useMenuRoot.Parameters): useMenuRoot.Ret
329
335
rtl : direction === 'rtl' ,
330
336
disabledIndices : EMPTY_ARRAY ,
331
337
onNavigate : setActiveIndex ,
332
- openOnArrowKeyDown : ! hasContextMenuParent ,
338
+ openOnArrowKeyDown : parent . type !== 'context-menu' ,
333
339
} ) ;
334
340
335
341
const typingRef = React . useRef ( false ) ;
@@ -389,14 +395,14 @@ export function useMenuRoot(parameters: useMenuRoot.Parameters): useMenuRoot.Ret
389
395
390
396
const itemProps = React . useMemo ( ( ) => getItemProps ( ) , [ getItemProps ] ) ;
391
397
392
- const allowMouseUpTriggerRef = React . useRef ( false ) ;
393
-
394
398
return React . useMemo (
395
399
( ) => ( {
396
400
activeIndex,
397
401
setActiveIndex,
398
402
allowMouseUpTriggerRef :
399
- parent . type !== undefined ? parent . context . allowMouseUpTriggerRef : allowMouseUpTriggerRef ,
403
+ parent . type && parent . type !== 'context-menu'
404
+ ? parent . context . allowMouseUpTriggerRef
405
+ : allowMouseUpTriggerRef ,
400
406
floatingRootContext,
401
407
itemProps,
402
408
popupProps,
@@ -554,6 +560,10 @@ export namespace useMenuRoot {
554
560
type : 'menubar' ;
555
561
context : MenubarContext ;
556
562
}
563
+ | {
564
+ type : 'context-menu' ;
565
+ context : ContextMenuRootContext ;
566
+ }
557
567
| {
558
568
type : undefined ;
559
569
} ;
0 commit comments