From ecdcd7e034e876648e1cfd7a1dd27819f5cc8559 Mon Sep 17 00:00:00 2001 From: nouar salah eddine Date: Sun, 31 Dec 2023 13:03:56 +0100 Subject: [PATCH] Fix styles and save in popout window --- package.json | 13 +- src/view/FloatingWindow.tsx | 121 ++++-- src/view/styles.js | 800 ++++++++++++++++++++++++++++++++++++ 3 files changed, 905 insertions(+), 29 deletions(-) create mode 100644 src/view/styles.js diff --git a/package.json b/package.json index 9e24cc1b..1695255b 100755 --- a/package.json +++ b/package.json @@ -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", @@ -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", @@ -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", @@ -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" + } } diff --git a/src/view/FloatingWindow.tsx b/src/view/FloatingWindow.tsx index 646fd23d..2b808c7b 100644 --- a/src/view/FloatingWindow.tsx +++ b/src/view/FloatingWindow.tsx @@ -25,7 +25,27 @@ export const FloatingWindow = (props: React.PropsWithChildren(null); const timerId = React.useRef(null); const [content, setContent] = React.useState(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); @@ -35,39 +55,56 @@ export const FloatingWindow = (props: React.PropsWithChildren { - 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; @@ -95,13 +132,47 @@ export const FloatingWindow = (props: React.PropsWithChildren { 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 { @@ -137,4 +208,4 @@ function copyStyles(doc: Document, styleSheets: IStyleSheet[]): Promise .css-sy9hzh:not(:last-of-type) { margin-inline-end: -1px; }" + ] + }, + { + "href": null, + "type": "text/css", + "rules": [ + ".chakra-button__group[data-attached][data-orientation=\"vertical\"] > .css-sy9hzh:not(:last-of-type) { margin-bottom: -1px; }" + ] + }, + { + "href": null, + "type": "text/css", + "rules": [ + ".css-sy9hzh:active, .css-sy9hzh[data-active] { background: var(--chakra-colors-gray-200); }" + ] + }, + { + "href": null, + "type": "text/css", + "rules": [ + ".css-jut409 { display: inline-flex; appearance: none; -webkit-box-align: center; align-items: center; -webkit-box-pack: center; justify-content: center; user-select: none; position: relative; white-space: nowrap; vertical-align: middle; outline: transparent solid 2px; outline-offset: 2px; line-height: 1.2; border-radius: var(--chakra-radii-md); font-weight: var(--chakra-fontWeights-semibold); transition-property: var(--chakra-transition-property-common); transition-duration: var(--chakra-transition-duration-normal); height: var(--chakra-sizes-10); min-width: var(--chakra-sizes-10); font-size: var(--chakra-fontSizes-md); padding-inline-start: var(--chakra-space-4); padding-inline-end: var(--chakra-space-4); background: var(--chakra-colors-blue-500); color: var(--chakra-colors-white); }" + ] + }, + { + "href": null, + "type": "text/css", + "rules": [ + ".css-jut409:focus-visible, .css-jut409[data-focus-visible] { box-shadow: var(--chakra-shadows-outline); }" + ] + }, + { + "href": null, + "type": "text/css", + "rules": [ + ".css-jut409:disabled, .css-jut409[disabled], .css-jut409[aria-disabled=\"true\"], .css-jut409[data-disabled] { opacity: 0.4; cursor: not-allowed; box-shadow: var(--chakra-shadows-none); }" + ] + }, + { + "href": null, + "type": "text/css", + "rules": [ + ".css-jut409:hover, .css-jut409[data-hover] { background: var(--chakra-colors-blue-600); }" + ] + }, + { + "href": null, + "type": "text/css", + "rules": [ + ".css-jut409:hover:disabled, .css-jut409[data-hover]:disabled, .css-jut409:hover[disabled], .css-jut409[data-hover][disabled], .css-jut409:hover[aria-disabled=\"true\"], .css-jut409[data-hover][aria-disabled=\"true\"], .css-jut409:hover[data-disabled], .css-jut409[data-hover][data-disabled] { background: var(--chakra-colors-blue-500); }" + ] + }, + { + "href": null, + "type": "text/css", + "rules": [ + ".css-jut409:active, .css-jut409[data-active] { background: var(--chakra-colors-blue-700); }" + ] + } +] \ No newline at end of file