UNPKG

@itwin/core-react

Version:

A react component library of iTwin.js UI general purpose components

99 lines 4.35 kB
/*--------------------------------------------------------------------------------------------- * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ /** @packageDocumentation * @module Utilities */ import * as React from "react"; import { useInterval } from "./useInterval.js"; /** Hook that will show a popup window * @public * @deprecated in 4.16.0. Without a replacement, use a custom solution instead. */ export function useCrossOriginPopup(visible, url, title, width, height, onClose) { const [checkPopupAliveDelay, setCheckPopupAliveDelay] = React.useState(); // ONLY re-render the popup when visibility changes, any other changes get deferred until next visibility change // hence the massive use of 'useRef' const popupWindow = React.useRef(); const savedUrl = React.useRef(url); const savedTitle = React.useRef(title); const savedWidth = React.useRef(width); const savedHeight = React.useRef(height); const savedOnClose = React.useRef(onClose); React.useEffect(() => { savedUrl.current = url; }, [url]); React.useEffect(() => { savedTitle.current = title; }, [title]); React.useEffect(() => { savedWidth.current = width; }, [width]); React.useEffect(() => { savedHeight.current = height; }, [height]); React.useEffect(() => { savedOnClose.current = onClose; }, [onClose]); // Cleanup method after a popup closure. Also calls the OnClose callback. const handleClosedPopup = React.useCallback(() => { savedOnClose.current(); setCheckPopupAliveDelay(undefined); popupWindow.current = undefined; }, []); const closePopup = React.useCallback(() => { if (popupWindow.current !== undefined) { popupWindow.current.close(); // Manually close the popup handleClosedPopup(); } }, [handleClosedPopup]); const checkPopupClosed = React.useCallback(() => { if (popupWindow.current?.closed) { // Popup has been closed by end-user, inform our host and cleanup handleClosedPopup(); } }, [handleClosedPopup]); // Close popup when parent window get closed React.useEffect(() => { window.onbeforeunload = (_event) => { closePopup(); }; return () => { window.onbeforeunload = null; }; }, [closePopup]); // Whenever the hook is unloaded, make sure the underlying popup get closed. // Note: An interval is used to check if popup was closed by user: because we access // a cross domain resource inside the popup, we don't have access to popup window events. // As a workaround, we periodically check if popup is still alive. // Reference: https://stackoverflow.com/questions/9388380/capture-the-close-event-of-popup-window-in-javascript/48240128#48240128 React.useEffect(() => { return () => { closePopup(); }; }, [closePopup]); // Timer that checks if popup was closed by end-user // eslint-disable-next-line @typescript-eslint/no-deprecated useInterval(checkPopupClosed, checkPopupAliveDelay); // ==> Main render effect // Monitors visibility changes and open/close the popup accordingly. React.useEffect(() => { // If visible and a popup window is not already open, open a new popup window if (visible && popupWindow.current === undefined) { const popup = window.open(savedUrl.current, savedTitle.current, `width=${savedWidth.current},height=${savedHeight.current}`); if (popup) { popup.focus(); popupWindow.current = popup; // Start and interval that will check if popup got closed by user setCheckPopupAliveDelay(1000); } } // If not visible but a previous popup window is still open, close it. if (!visible && popupWindow.current !== undefined) { popupWindow.current.close(); handleClosedPopup(); } }, [handleClosedPopup, visible]); } //# sourceMappingURL=useCrossOriginPopup.js.map