@@ -443,8 +443,7 @@ const MenuContentImpl = React.forwardRef<MenuContentImplElement, MenuContentImpl
443
443
} else {
444
444
// In shadow DOM, force close other submenus when entering any menu item
445
445
const target = event . target as Element ;
446
- const isInShadowDOM = target && target . getRootNode ( ) !== document && 'host' in target . getRootNode ( ) ;
447
- if ( isInShadowDOM ) {
446
+ if ( isInShadowDOM ( target ) ) {
448
447
const menuItem = event . currentTarget as HTMLElement ;
449
448
450
449
// Clear grace intent
@@ -755,7 +754,6 @@ const MenuItemImpl = React.forwardRef<MenuItemImplElement, MenuItemImplProps>(
755
754
if ( ! event . defaultPrevented ) {
756
755
const item = event . currentTarget ;
757
756
item . focus ( { preventScroll : true } ) ;
758
-
759
757
}
760
758
}
761
759
} )
@@ -1154,49 +1152,35 @@ const MenuSubTrigger = React.forwardRef<MenuSubTriggerElement, MenuSubTriggerPro
1154
1152
const contentNearEdge = contentRect [ rightSide ? 'left' : 'right' ] ;
1155
1153
const contentFarEdge = contentRect [ rightSide ? 'right' : 'left' ] ;
1156
1154
1157
- // In shadow DOM, we may need to adjust coordinates to ensure
1158
- // both the mouse position and rectangle are in the same coordinate system
1159
- let adjustedClientX = event . clientX ;
1160
- let adjustedClientY = event . clientY ;
1161
- const adjustedContentRect = contentRect ;
1162
-
1155
+ // Check if we're in shadow DOM for adjusted behavior
1163
1156
const eventTarget = event . target as Element ;
1164
- const isInShadowDOM = eventTarget && eventTarget . getRootNode ( ) !== document && 'host' in eventTarget . getRootNode ( ) ;
1165
-
1166
- if ( isInShadowDOM && context . content ) {
1167
- // Use native event coordinates for more reliable positioning in shadow DOM
1168
- const nativeEvent = event . nativeEvent ;
1169
- if ( nativeEvent ) {
1170
- adjustedClientX = nativeEvent . clientX ;
1171
- adjustedClientY = nativeEvent . clientY ;
1172
- }
1173
- }
1157
+ const shadowDOM = isInShadowDOM ( eventTarget ) ;
1174
1158
1175
1159
contentContext . onPointerGraceIntentChange ( {
1176
1160
area : [
1177
1161
// Apply a bleed on clientX to ensure that our exit point is
1178
1162
// consistently within polygon bounds
1179
- { x : adjustedClientX + bleed , y : adjustedClientY } ,
1180
- { x : contentNearEdge , y : adjustedContentRect . top } ,
1181
- { x : contentFarEdge , y : adjustedContentRect . top } ,
1182
- { x : contentFarEdge , y : adjustedContentRect . bottom } ,
1183
- { x : contentNearEdge , y : adjustedContentRect . bottom } ,
1163
+ { x : event . clientX + bleed , y : event . clientY } ,
1164
+ { x : contentNearEdge , y : contentRect . top } ,
1165
+ { x : contentFarEdge , y : contentRect . top } ,
1166
+ { x : contentFarEdge , y : contentRect . bottom } ,
1167
+ { x : contentNearEdge , y : contentRect . bottom } ,
1184
1168
] ,
1185
1169
side,
1186
1170
} ) ;
1187
1171
1188
1172
window . clearTimeout ( pointerGraceTimerRef . current ) ;
1189
1173
1190
1174
// Use longer grace period in shadow DOM since coordinate detection may be less reliable
1191
- const gracePeriod = isInShadowDOM ? 800 : 300 ;
1175
+ const gracePeriod = shadowDOM ? 800 : 300 ;
1192
1176
1193
1177
pointerGraceTimerRef . current = window . setTimeout (
1194
1178
( ) => {
1195
1179
contentContext . onPointerGraceIntentChange ( null ) ;
1196
1180
1197
1181
// In shadow DOM, don't automatically close submenu on grace timer expiry
1198
1182
// Only close via explicit menu item selection logic
1199
- if ( ! isInShadowDOM && context . open ) {
1183
+ if ( ! shadowDOM && context . open ) {
1200
1184
// Normal behavior for non-shadow DOM
1201
1185
context . onOpenChange ( false ) ;
1202
1186
}
@@ -1404,17 +1388,14 @@ function isPointInPolygon(point: Point, polygon: Polygon) {
1404
1388
1405
1389
function isPointerInGraceArea ( event : React . PointerEvent , area ?: Polygon ) {
1406
1390
if ( ! area ) return false ;
1407
-
1408
- // Use the most reliable coordinates available
1409
- const nativeEvent = event . nativeEvent ;
1410
- const cursorPos = {
1411
- x : nativeEvent ? nativeEvent . clientX : event . clientX ,
1412
- y : nativeEvent ? nativeEvent . clientY : event . clientY
1413
- } ;
1414
-
1391
+ const cursorPos = { x : event . clientX , y : event . clientY } ;
1415
1392
return isPointInPolygon ( cursorPos , area ) ;
1416
1393
}
1417
1394
1395
+ function isInShadowDOM ( element : Element ) : boolean {
1396
+ return element && element . getRootNode ( ) !== document && 'host' in element . getRootNode ( ) ;
1397
+ }
1398
+
1418
1399
function whenMouse < E > ( handler : React . PointerEventHandler < E > ) : React . PointerEventHandler < E > {
1419
1400
return ( event ) => ( event . pointerType === 'mouse' ? handler ( event ) : undefined ) ;
1420
1401
}
0 commit comments