flexlayout-react-v7-react-19
Version:
A multi-tab docking layout manager
123 lines • 4.84 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.FloatingWindow = void 0;
const React = require("react");
const react_dom_1 = require("react-dom");
const Rect_1 = require("../Rect");
const Types_1 = require("../Types");
/** @internal */
const FloatingWindow = (props) => {
const { title, id, url, rect, onCloseWindow, onSetWindow, children } = props;
const popoutWindow = React.useRef(null);
const timerId = React.useRef(null);
const [content, setContent] = React.useState(undefined);
React.useLayoutEffect(() => {
if (timerId.current) {
clearTimeout(timerId.current);
}
let isMounted = true;
const r = rect || new Rect_1.Rect(0, 0, 100, 100);
// Make a local copy of the styles from the current window which will be passed into
// the floating window. window.document.styleSheets is mutable and we can't guarantee
// the styles will exist when 'popoutWindow.load' is called below.
const styles = Array.from(window.document.styleSheets).reduce((result, styleSheet) => {
let rules = undefined;
try {
rules = styleSheet.cssRules;
}
catch (e) {
// styleSheet.cssRules can throw security exception
}
try {
return [
...result,
{
href: styleSheet.href,
type: styleSheet.type,
rules: rules ? Array.from(rules).map(rule => rule.cssText) : null,
}
];
}
catch (e) {
return result;
}
}, []);
popoutWindow.current = window.open(url, id, `left=${r.x},top=${r.y},width=${r.width},height=${r.height}`);
if (popoutWindow.current !== null) {
onSetWindow(id, popoutWindow.current);
// listen for parent unloading to remove all popouts
window.addEventListener("beforeunload", () => {
if (popoutWindow.current) {
popoutWindow.current.close();
popoutWindow.current = null;
}
});
popoutWindow.current.addEventListener("load", () => {
if (isMounted) {
const popoutDocument = popoutWindow.current.document;
popoutDocument.title = title;
const popoutContent = popoutDocument.createElement("div");
popoutContent.className = Types_1.CLASSES.FLEXLAYOUT__FLOATING_WINDOW_CONTENT;
popoutDocument.body.appendChild(popoutContent);
copyStyles(popoutDocument, styles).then(() => {
setContent(popoutContent);
});
// listen for popout unloading (needs to be after load for safari)
popoutWindow.current.addEventListener("beforeunload", () => {
onCloseWindow(id);
});
}
});
}
else {
console.warn(`Unable to open window ${url}`);
onCloseWindow(id);
}
return () => {
isMounted = false;
// delay so refresh will close window
timerId.current = setTimeout(() => {
if (popoutWindow.current) {
popoutWindow.current.close();
popoutWindow.current = null;
}
}, 0);
};
}, []);
if (content !== undefined) {
return (0, react_dom_1.createPortal)(children, content);
}
else {
return null;
}
};
exports.FloatingWindow = FloatingWindow;
/** @internal */
function copyStyles(doc, styleSheets) {
const head = doc.head;
const promises = [];
for (const styleSheet of styleSheets) {
if (styleSheet.href) {
// prefer links since they will keep paths to images etc
const styleElement = doc.createElement("link");
styleElement.type = styleSheet.type;
styleElement.rel = "stylesheet";
styleElement.href = styleSheet.href;
head.appendChild(styleElement);
promises.push(new Promise((resolve) => {
styleElement.onload = () => resolve(true);
}));
}
else {
if (styleSheet.rules) {
const style = doc.createElement("style");
for (const rule of styleSheet.rules) {
style.appendChild(doc.createTextNode(rule));
}
head.appendChild(style);
}
}
}
return Promise.all(promises);
}
//# sourceMappingURL=FloatingWindow.js.map