@@ -11,8 +11,9 @@ import {DataContext, RegistryContext} from './Contexts';
1111import styles from './ContextMenu.css' ;
1212
1313function respositionToFit ( element , pageX , pageY ) {
14+ const ownerWindow = element . ownerDocument . defaultView ;
1415 if ( element !== null ) {
15- if ( pageY + element . offsetHeight >= window . innerHeight ) {
16+ if ( pageY + element . offsetHeight >= ownerWindow . innerHeight ) {
1617 if ( pageY - element . offsetHeight > 0 ) {
1718 element . style . top = `${ pageY - element . offsetHeight } px` ;
1819 } else {
@@ -22,7 +23,7 @@ function respositionToFit(element, pageX, pageY) {
2223 element . style . top = `${ pageY } px` ;
2324 }
2425
25- if ( pageX + element . offsetWidth >= window . innerWidth ) {
26+ if ( pageX + element . offsetWidth >= ownerWindow . innerWidth ) {
2627 if ( pageX - element . offsetWidth > 0 ) {
2728 element . style . left = `${ pageX - element . offsetWidth } px` ;
2829 } else {
@@ -51,14 +52,16 @@ export default function ContextMenu({children, id}: Props) {
5152
5253 const [ state , setState ] = useState ( HIDDEN_STATE ) ;
5354
55+ const bodyAccessorRef = useRef ( null ) ;
5456 const containerRef = useRef ( null ) ;
5557 const menuRef = useRef ( null ) ;
5658
5759 useEffect ( ( ) => {
58- containerRef . current = document . createElement ( 'div' ) ;
59- document . body . appendChild ( containerRef . current ) ;
60+ const ownerDocument = bodyAccessorRef . current . ownerDocument ;
61+ containerRef . current = ownerDocument . createElement ( 'div' ) ;
62+ ownerDocument . body . appendChild ( containerRef . current ) ;
6063 return ( ) => {
61- document . body . removeChild ( containerRef . current ) ;
64+ ownerDocument . body . removeChild ( containerRef . current ) ;
6265 } ;
6366 } , [ ] ) ;
6467
@@ -81,33 +84,39 @@ export default function ContextMenu({children, id}: Props) {
8184
8285 const menu = menuRef . current ;
8386
84- const hide = event => {
87+ const hideUnlessContains = event => {
8588 if ( ! menu . contains ( event . target ) ) {
8689 setState ( HIDDEN_STATE ) ;
8790 }
8891 } ;
8992
90- document . addEventListener ( 'mousedown' , hide ) ;
91- document . addEventListener ( 'touchstart' , hide ) ;
92- document . addEventListener ( 'keydown' , hide ) ;
93+ const hide = event => {
94+ setState ( HIDDEN_STATE ) ;
95+ } ;
96+
97+ const ownerDocument = containerRef . current . ownerDocument ;
98+ ownerDocument . addEventListener ( 'mousedown' , hideUnlessContains ) ;
99+ ownerDocument . addEventListener ( 'touchstart' , hideUnlessContains ) ;
100+ ownerDocument . addEventListener ( 'keydown' , hideUnlessContains ) ;
93101
94- window . addEventListener ( 'resize' , hide ) ;
102+ const ownerWindow = ownerDocument . defaultView ;
103+ ownerWindow . addEventListener ( 'resize' , hide ) ;
95104
96105 respositionToFit ( menu , state . pageX , state . pageY ) ;
97106
98107 return ( ) => {
99- document . removeEventListener ( 'mousedown' , hide ) ;
100- document . removeEventListener ( 'touchstart' , hide ) ;
101- document . removeEventListener ( 'keydown' , hide ) ;
108+ ownerDocument . removeEventListener ( 'mousedown' , hideUnlessContains ) ;
109+ ownerDocument . removeEventListener ( 'touchstart' , hideUnlessContains ) ;
110+ ownerDocument . removeEventListener ( 'keydown' , hideUnlessContains ) ;
102111
103- window . removeEventListener ( 'resize' , hide ) ;
112+ ownerWindow . removeEventListener ( 'resize' , hide ) ;
104113 } ;
105114 } ,
106115 [ state ] ,
107116 ) ;
108117
109118 if ( ! state . isVisible ) {
110- return null ;
119+ return < div ref = { bodyAccessorRef } /> ;
111120 } else {
112121 return createPortal (
113122 < div ref = { menuRef } className = { styles . ContextMenu } >
0 commit comments