Skip to content

Commit

Permalink
extract hooks
Browse files Browse the repository at this point in the history
  • Loading branch information
alextaing committed Oct 17, 2023
1 parent 6f557e9 commit e9f63ed
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 94 deletions.
96 changes: 2 additions & 94 deletions packages/studio-ui/src/components/IFramePortal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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<{
Expand Down Expand Up @@ -41,93 +39,3 @@ export default function IFramePortal(
</div>
);
}

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<HTMLDivElement>
) => {
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;
};
63 changes: 63 additions & 0 deletions packages/studio-ui/src/hooks/useInjectUserStyles.tsx
Original file line number Diff line number Diff line change
@@ -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);
}
}
34 changes: 34 additions & 0 deletions packages/studio-ui/src/hooks/useViewportOption.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { RefObject, useEffect, useState } from "react";
import { Viewport } from "../components/Viewport/defaults";

export default function useViewportOption (
viewport: Viewport,
previewRef: RefObject<HTMLDivElement>
) {
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;
};

0 comments on commit e9f63ed

Please sign in to comment.