From e9f63edb9b5ab93ba9c88f3a94a003e48289761e Mon Sep 17 00:00:00 2001 From: Alex Taing Date: Tue, 17 Oct 2023 11:54:12 -0400 Subject: [PATCH] extract hooks --- .../studio-ui/src/components/IFramePortal.tsx | 96 +------------------ .../src/hooks/useInjectUserStyles.tsx | 63 ++++++++++++ .../studio-ui/src/hooks/useViewportOption.tsx | 34 +++++++ 3 files changed, 99 insertions(+), 94 deletions(-) create mode 100644 packages/studio-ui/src/hooks/useInjectUserStyles.tsx create mode 100644 packages/studio-ui/src/hooks/useViewportOption.tsx diff --git a/packages/studio-ui/src/components/IFramePortal.tsx b/packages/studio-ui/src/components/IFramePortal.tsx index c8b60bf30..feadef983 100644 --- a/packages/studio-ui/src/components/IFramePortal.tsx +++ b/packages/studio-ui/src/components/IFramePortal.tsx @@ -2,15 +2,13 @@ import { createPortal } from "react-dom"; import { Dispatch, PropsWithChildren, - RefObject, SetStateAction, - useEffect, useRef, - useState, } from "react"; import useStudioStore from "../store/useStudioStore"; import { twMerge } from "tailwind-merge"; -import { Viewport } from "./Viewport/defaults"; +import useInjectUserStyles from "../hooks/useInjectUserStyles"; +import useViewportOption from "../hooks/useViewportOption"; export default function IFramePortal( props: PropsWithChildren<{ @@ -41,93 +39,3 @@ export default function IFramePortal( ); } - -function useInjectUserStyles(iframeDocument: Document | undefined) { - const [ - componentTree, - getComponentMetadata, - activePage, - UUIDToFileMetadata, - pageCss, - ] = useStudioStore((store) => [ - store.actions.getComponentTree(), - store.actions.getComponentMetadata, - store.pages.activePageName, - store.fileMetadatas.UUIDToFileMetadata, - store.pages.getActivePageState()?.cssImports, - ]); - useEffect(() => { - if (!iframeDocument) { - return; - } - componentTree?.forEach((component) => { - const cssImports = getComponentMetadata(component)?.cssImports; - cssImports?.forEach((cssFilepath) => { - injectStyleIntoIframe(iframeDocument, cssFilepath); - }); - }); - pageCss?.forEach((cssFilepath) => { - injectStyleIntoIframe(iframeDocument, cssFilepath); - }); - - return () => { - clearStylingFromIframe(iframeDocument); - }; - }, [ - componentTree, - getComponentMetadata, - iframeDocument, - pageCss, - activePage, - UUIDToFileMetadata, - ]); -} - -function clearStylingFromIframe(iframeDocument: Document) { - const styleElements = [...iframeDocument.head.getElementsByTagName("style")]; - styleElements.forEach((element) => { - element.remove(); - }); -} - -function injectStyleIntoIframe(iframeDocument: Document, filepath: string) { - const originalStyletag = document.querySelector( - `[studio-style-filepath='${filepath}']` - ); - if (originalStyletag) { - const iframeStyletag = originalStyletag.cloneNode(true); - iframeDocument.head.appendChild(iframeStyletag); - } -} - -const useViewportOption = ( - viewport: Viewport, - previewRef: RefObject -) => { - const [css, setCss] = useState( - (viewport.styles?.width ?? 0) * (previewRef.current?.clientHeight ?? 0) > - (viewport.styles?.height ?? 0) * (previewRef.current?.clientWidth ?? 0) - ? " w-full " - : " h-full " - ); - const handleResize = () => { - const tempCss = - (viewport.styles?.width ?? 0) * (previewRef.current?.clientHeight ?? 0) > - (viewport.styles?.height ?? 0) * (previewRef.current?.clientWidth ?? 0) - ? " w-full " - : " h-full "; - if (tempCss !== css) { - setCss(tempCss); - } - }; - - useEffect(() => { - const resizeObserver = new ResizeObserver(handleResize); - if (previewRef.current) { - resizeObserver.observe(previewRef.current); - } - return () => resizeObserver.disconnect(); - }); - - return css; -}; diff --git a/packages/studio-ui/src/hooks/useInjectUserStyles.tsx b/packages/studio-ui/src/hooks/useInjectUserStyles.tsx new file mode 100644 index 000000000..8ce0a47cb --- /dev/null +++ b/packages/studio-ui/src/hooks/useInjectUserStyles.tsx @@ -0,0 +1,63 @@ +import { useEffect } from "react"; +import useStudioStore from "../store/useStudioStore"; + +export default function useInjectUserStyles(iframeDocument: Document | undefined) { + const [ + componentTree, + getComponentMetadata, + activePage, + UUIDToFileMetadata, + pageCss, + ] = useStudioStore((store) => [ + store.actions.getComponentTree(), + store.actions.getComponentMetadata, + store.pages.activePageName, + store.fileMetadatas.UUIDToFileMetadata, + store.pages.getActivePageState()?.cssImports, + ]); + useEffect(() => { + if (!iframeDocument) { + return; + } + componentTree?.forEach((component) => { + const cssImports = getComponentMetadata(component)?.cssImports; + cssImports?.forEach((cssFilepath) => { + injectStyleIntoIframe(iframeDocument, cssFilepath); + }); + }); + pageCss?.forEach((cssFilepath) => { + injectStyleIntoIframe(iframeDocument, cssFilepath); + }); + + return () => { + clearStylingFromIframe(iframeDocument); + }; + }, [ + componentTree, + getComponentMetadata, + iframeDocument, + pageCss, + activePage, + UUIDToFileMetadata, + ]); +} + +function clearStylingFromIframe(iframeDocument: Document) { + const styleElements = [...iframeDocument.head.getElementsByTagName("style")]; + styleElements.forEach((element) => { + element.remove(); + }); +} + +function injectStyleIntoIframe( + iframeDocument: Document, + filepath: string +) { + const originalStyletag = document.querySelector( + `[studio-style-filepath='${filepath}']` + ); + if (originalStyletag) { + const iframeStyletag = originalStyletag.cloneNode(true); + iframeDocument.head.appendChild(iframeStyletag); + } +} \ No newline at end of file diff --git a/packages/studio-ui/src/hooks/useViewportOption.tsx b/packages/studio-ui/src/hooks/useViewportOption.tsx new file mode 100644 index 000000000..b024bfefb --- /dev/null +++ b/packages/studio-ui/src/hooks/useViewportOption.tsx @@ -0,0 +1,34 @@ +import { RefObject, useEffect, useState } from "react"; +import { Viewport } from "../components/Viewport/defaults"; + +export default function useViewportOption ( + viewport: Viewport, + previewRef: RefObject +) { + const [css, setCss] = useState( + (viewport.styles?.width ?? 0) * (previewRef.current?.clientHeight ?? 0) > + (viewport.styles?.height ?? 0) * (previewRef.current?.clientWidth ?? 0) + ? " w-full " + : " h-full " + ); + const handleResize = () => { + const tempCss = + (viewport.styles?.width ?? 0) * (previewRef.current?.clientHeight ?? 0) > + (viewport.styles?.height ?? 0) * (previewRef.current?.clientWidth ?? 0) + ? " w-full " + : " h-full "; + if (tempCss !== css) { + setCss(tempCss); + } + }; + + useEffect(() => { + const resizeObserver = new ResizeObserver(handleResize); + if (previewRef.current) { + resizeObserver.observe(previewRef.current); + } + return () => resizeObserver.disconnect(); + }); + + return css; +};