Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "flexlayout-react",
"version": "0.7.15",
"name": "flexlayout-react-omran",
"version": "0.7.17",
"description": "A multi-tab docking layout manager",
"main": "lib/index.js",
"types": "./declarations/index.d.ts",
Expand All @@ -25,7 +25,7 @@
],
"scripts": {
"start": "webpack serve",
"build": "npm run css && npm run test && npm run doc && npm run build:demo && npm run build:commonjs && npm run build:umd && npm run build:umd:min",
"build": " npm run build:demo && npm run build:commonjs && npm run build:umd && npm run build:umd:min",
"build:commonjs": "tsc -p tsconfig2.json",
"build:umd": "webpack --mode=development --config webpack_build.config.js",
"build:umd:min": "webpack --mode=production --config webpack_build_min.config.js",
Expand All @@ -48,6 +48,7 @@
"extends": "react-app"
},
"devDependencies": {
"@chakra-ui/react": "^2.8.2",
"@cypress/react": "^7.0.3",
"@cypress/webpack-dev-server": "^3.4.1",
"@types/node": "^18.15.13",
Expand All @@ -72,5 +73,9 @@
"webpack-cli": "^5.0.1",
"webpack-dev-server": "^4.8.1"
},
"dependencies": {}
"dependencies": {
"@emotion/react": "^11.11.3",
"@emotion/styled": "^11.11.0",
"framer-motion": "^10.16.16"
}
}
121 changes: 96 additions & 25 deletions src/view/FloatingWindow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,27 @@ export const FloatingWindow = (props: React.PropsWithChildren<IFloatingWindowPro
const popoutWindow = React.useRef<Window | null>(null);
const timerId = React.useRef<any>(null);
const [content, setContent] = React.useState<HTMLElement | undefined>(undefined);
const styles = Array.from(window.document.styleSheets).reduce((result, styleSheet) => {
let rules: CSSRuleList | undefined = 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;
}
}, [] as IStyleSheet[]);
React.useLayoutEffect(() => {
if (timerId.current) {
clearTimeout(timerId.current);
Expand All @@ -35,39 +55,56 @@ export const FloatingWindow = (props: React.PropsWithChildren<IFloatingWindowPro
// 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: CSSRuleList | undefined = undefined;
try {
rules = styleSheet.cssRules;
} catch (e) {
// styleSheet.cssRules can throw security exception
}

// let test = false;

try {
return [
...result,
{
href: styleSheet.href,
type: styleSheet.type,
rules: rules ? Array.from(rules).map(rule => rule.cssText) : null,
}
];
} catch (e) {
return result;
}
}, [] as IStyleSheet[]);
popoutWindow.current = window.open(url, id, `left=${r.x},top=${r.y},width=${r.width},height=${r.height}`);
let left, top, width, height;
let X, Y, W, H;

const storedPosition = localStorage.getItem(`popoutWindowPosition_${id}`);
const storedPositionObj = storedPosition ? JSON.parse(storedPosition) : null;

if (storedPositionObj) {
X = storedPositionObj.x;
Y = storedPositionObj.y;
W = storedPositionObj.width;
H = storedPositionObj.height;
} else {
X = r.x;
Y = r.y;
W = r.width;
H = r.height;
}

popoutWindow.current = window.open(url, id, `left=${X},top=${Y},width=${W},height=${H}`);

// if(test){
// popoutWindow.current = window.open(url, id, `left=${r.x},top=${r.y},width=${r.width},height=${r.height}`);
// } else {
// popoutWindow.current = window.open(url, id, `left=${X},top=${Y},width=${W},height=${H}`);
// }


if (popoutWindow.current !== null) {
onSetWindow(id, popoutWindow.current);

// listen for parent unloading to remove all popouts
window.addEventListener("beforeunload", () => {
if (popoutWindow.current) {
// test = true;
left = popoutWindow.current.screenX;
top = popoutWindow.current.screenY;
width = popoutWindow.current.innerWidth;
height = popoutWindow.current.innerHeight;

// Store the window position in localStorage
localStorage.setItem(`popoutWindowPosition_${id}`, JSON.stringify({ x: left, y: top, width, height }));

popoutWindow.current.close();
popoutWindow.current = null;
}
});


popoutWindow.current.addEventListener("load", () => {
if (isMounted) {
const popoutDocument = popoutWindow.current!.document;
Expand Down Expand Up @@ -95,13 +132,47 @@ export const FloatingWindow = (props: React.PropsWithChildren<IFloatingWindowPro
// delay so refresh will close window
timerId.current = setTimeout(() => {
if (popoutWindow.current) {
popoutWindow.current.close();
popoutWindow.current = null;
// popoutWindow.current.close();
// popoutWindow.current = null;
}
}, 0);
};
}, []);
React.useEffect(() => {
copyStyles(popoutWindow.current!.document, styles).then(() => {
});
const handleMutations = (mutationsList: any) => {
for (const mutation of mutationsList) {
if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
// Copy the new styles to the floating window
copyStyles(popoutWindow.current!.document, [{
href: null,
type: 'text/css',
rules: [mutation.addedNodes[0].textContent], // Assuming the added node is a style element
}]);
}
}
};

const observer = new MutationObserver(handleMutations);
const observerConfig = {
childList: true,
subtree: true,
};

observer.observe(document.head, observerConfig);

return () => {
observer.disconnect(); // Disconnect the observer when the component unmounts

if (popoutWindow.current) {
popoutWindow.current.removeEventListener("beforeunload", () => {
onCloseWindow(id);
});
}
};
// eslint-disable-next-line react-hooks/exhaustive-deps
} ,[]);
if (content !== undefined) {
return createPortal(children, content!);
} else {
Expand Down Expand Up @@ -137,4 +208,4 @@ function copyStyles(doc: Document, styleSheets: IStyleSheet[]): Promise<boolean[
}
}
return Promise.all(promises);
}
}
Loading