diff --git a/packages/react-devtools-shared/src/devtools/ContextMenu/ContextMenu.js b/packages/react-devtools-shared/src/devtools/ContextMenu/ContextMenu.js index f71f158abce5b..b7afff4e32e36 100644 --- a/packages/react-devtools-shared/src/devtools/ContextMenu/ContextMenu.js +++ b/packages/react-devtools-shared/src/devtools/ContextMenu/ContextMenu.js @@ -11,8 +11,9 @@ import {DataContext, RegistryContext} from './Contexts'; import styles from './ContextMenu.css'; function respositionToFit(element, pageX, pageY) { + const ownerWindow = element.ownerDocument.defaultView; if (element !== null) { - if (pageY + element.offsetHeight >= window.innerHeight) { + if (pageY + element.offsetHeight >= ownerWindow.innerHeight) { if (pageY - element.offsetHeight > 0) { element.style.top = `${pageY - element.offsetHeight}px`; } else { @@ -22,7 +23,7 @@ function respositionToFit(element, pageX, pageY) { element.style.top = `${pageY}px`; } - if (pageX + element.offsetWidth >= window.innerWidth) { + if (pageX + element.offsetWidth >= ownerWindow.innerWidth) { if (pageX - element.offsetWidth > 0) { element.style.left = `${pageX - element.offsetWidth}px`; } else { @@ -51,14 +52,16 @@ export default function ContextMenu({children, id}: Props) { const [state, setState] = useState(HIDDEN_STATE); + const bodyAccessorRef = useRef(null); const containerRef = useRef(null); const menuRef = useRef(null); useEffect(() => { - containerRef.current = document.createElement('div'); - document.body.appendChild(containerRef.current); + const ownerDocument = bodyAccessorRef.current.ownerDocument; + containerRef.current = ownerDocument.createElement('div'); + ownerDocument.body.appendChild(containerRef.current); return () => { - document.body.removeChild(containerRef.current); + ownerDocument.body.removeChild(containerRef.current); }; }, []); @@ -81,33 +84,39 @@ export default function ContextMenu({children, id}: Props) { const menu = menuRef.current; - const hide = event => { + const hideUnlessContains = event => { if (!menu.contains(event.target)) { setState(HIDDEN_STATE); } }; - document.addEventListener('mousedown', hide); - document.addEventListener('touchstart', hide); - document.addEventListener('keydown', hide); + const hide = event => { + setState(HIDDEN_STATE); + }; + + const ownerDocument = containerRef.current.ownerDocument; + ownerDocument.addEventListener('mousedown', hideUnlessContains); + ownerDocument.addEventListener('touchstart', hideUnlessContains); + ownerDocument.addEventListener('keydown', hideUnlessContains); - window.addEventListener('resize', hide); + const ownerWindow = ownerDocument.defaultView; + ownerWindow.addEventListener('resize', hide); respositionToFit(menu, state.pageX, state.pageY); return () => { - document.removeEventListener('mousedown', hide); - document.removeEventListener('touchstart', hide); - document.removeEventListener('keydown', hide); + ownerDocument.removeEventListener('mousedown', hideUnlessContains); + ownerDocument.removeEventListener('touchstart', hideUnlessContains); + ownerDocument.removeEventListener('keydown', hideUnlessContains); - window.removeEventListener('resize', hide); + ownerWindow.removeEventListener('resize', hide); }; }, [state], ); if (!state.isVisible) { - return null; + return
; } else { return createPortal(
diff --git a/packages/react-devtools-shared/src/devtools/ContextMenu/useContextMenu.js b/packages/react-devtools-shared/src/devtools/ContextMenu/useContextMenu.js index 380c4469bac66..54cdcdb0a2d75 100644 --- a/packages/react-devtools-shared/src/devtools/ContextMenu/useContextMenu.js +++ b/packages/react-devtools-shared/src/devtools/ContextMenu/useContextMenu.js @@ -12,9 +12,9 @@ export default function useContextMenu({data, id, ref}) { event.stopPropagation(); const pageX = - event.clientX || (event.touches && event.touches[0].pageX); + event.pageX || (event.touches && event.touches[0].pageX); const pageY = - event.clientY || (event.touches && event.touches[0].pageY); + event.pageY || (event.touches && event.touches[0].pageY); showMenu({data, id, pageX, pageY}); };