1
1
import * as React from 'react' ;
2
- import { Dropdown , DropdownItem } from '@patternfly/react-core' ;
2
+ import { Menu , DropdownItem } from '@patternfly/react-core' ;
3
3
import AngleRightIcon from '@patternfly/react-icons/dist/esm/icons/angle-right-icon' ;
4
4
import { css } from '@patternfly/react-styles' ;
5
5
import topologyStyles from '../../css/topology-components' ;
@@ -11,6 +11,14 @@ interface ContextSubMenuItemProps {
11
11
children : React . ReactNode [ ] ;
12
12
}
13
13
14
+ /**
15
+ * Check if an event target is also a [Node](https://developer.mozilla.org/en-US/docs/Web/API/Node).
16
+ * Needed to stop runtime errors where the target does not implement Node.
17
+ */
18
+ const implementsDOMNode = ( node : any ) : boolean => {
19
+ return node && typeof node === 'object' && node . nodeType && node . nodeName ;
20
+ } ;
21
+
14
22
const ContextSubMenuItem : React . FunctionComponent < ContextSubMenuItemProps > = ( { label, children, ...other } ) => {
15
23
const nodeRef = React . useRef < HTMLButtonElement > ( null ) ;
16
24
const subMenuRef = React . useRef < HTMLDivElement > ( null ) ;
@@ -29,7 +37,10 @@ const ContextSubMenuItem: React.FunctionComponent<ContextSubMenuItemProps> = ({
29
37
onMouseEnter = { ( ) => setOpen ( true ) }
30
38
onMouseLeave = { ( e ) => {
31
39
// if the mouse leaves this item, close the sub menu only if the mouse did not enter the sub menu itself
32
- if ( ! subMenuRef . current || ! subMenuRef . current . contains ( e . relatedTarget as Node ) ) {
40
+ if (
41
+ ! subMenuRef . current ||
42
+ ( implementsDOMNode ( e . relatedTarget ) && ! subMenuRef . current . contains ( e . relatedTarget as Node ) )
43
+ ) {
33
44
setOpen ( false ) ;
34
45
}
35
46
} }
@@ -51,22 +62,21 @@ const ContextSubMenuItem: React.FunctionComponent<ContextSubMenuItemProps> = ({
51
62
closeOnOutsideClick
52
63
onRequestClose = { ( e ) => {
53
64
// only close the sub menu if clicking anywhere outside the menu item that owns the sub menu
54
- if ( ! e || ! nodeRef . current || ! nodeRef . current . contains ( e . target as Node ) ) {
65
+ if ( ! e || ! nodeRef . current || ( implementsDOMNode ( e . target ) && ! nodeRef . current . contains ( e . target as Node ) ) ) {
55
66
setOpen ( false ) ;
56
67
}
57
68
} }
58
69
reference = { referenceCb }
59
- // use the parent node to capture the li
60
- container = { nodeRef . current ? nodeRef . current . parentElement : nodeRef . current }
70
+ container = { nodeRef . current ?. closest ( '.pf-v6-c-menu__content' ) }
61
71
returnFocus
62
72
>
63
- < div
64
- ref = { subMenuRef }
65
- role = "presentation"
66
- className = "pf-v6-c-dropdown pf-m-expanded"
73
+ < Menu
67
74
onMouseLeave = { ( e ) => {
68
75
// only close the sub menu if the mouse does not enter the item
69
- if ( ! nodeRef . current || ! nodeRef . current . contains ( e . relatedTarget as Node ) ) {
76
+ if (
77
+ ! nodeRef . current ||
78
+ ( implementsDOMNode ( e . relatedTarget ) && ! nodeRef . current . contains ( e . relatedTarget as Node ) )
79
+ ) {
70
80
setOpen ( false ) ;
71
81
}
72
82
} }
@@ -77,11 +87,12 @@ const ContextSubMenuItem: React.FunctionComponent<ContextSubMenuItemProps> = ({
77
87
e . stopPropagation ( ) ;
78
88
}
79
89
} }
90
+ ref = { subMenuRef }
91
+ role = "presentation"
92
+ isNavFlyout
80
93
>
81
- < Dropdown toggle = { ( ) => < > </ > } className = { css ( topologyStyles . topologyContextMenuCDropdownMenu ) } >
82
- { children }
83
- </ Dropdown >
84
- </ div >
94
+ { children }
95
+ </ Menu >
85
96
</ Popper >
86
97
</ >
87
98
) ;
0 commit comments