@itwin/core-react
Version:
A react component library of iTwin.js UI general purpose components
99 lines • 4.36 kB
JavaScript
/*---------------------------------------------------------------------------------------------
* 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(undefined);
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