mirror of
https://github.com/AmruthPillai/Reactive-Resume.git
synced 2025-11-22 12:41:31 +10:00
feat(templates): replace library with microfrontend app for templates
This commit is contained in:
45
apps/artboard/src/pages/artboard.tsx
Normal file
45
apps/artboard/src/pages/artboard.tsx
Normal file
@ -0,0 +1,45 @@
|
||||
import { useEffect, useMemo } from "react";
|
||||
import { Outlet } from "react-router-dom";
|
||||
import webfontloader from "webfontloader";
|
||||
|
||||
import { useArtboardStore } from "../store/artboard";
|
||||
|
||||
export const ArtboardPage = () => {
|
||||
const metadata = useArtboardStore((state) => state.resume.metadata);
|
||||
|
||||
const fontString = useMemo(() => {
|
||||
const family = metadata.typography.font.family;
|
||||
const variants = metadata.typography.font.variants.join(",");
|
||||
const subset = metadata.typography.font.subset;
|
||||
|
||||
return `${family}:${variants}:${subset}`;
|
||||
}, [metadata.typography.font]);
|
||||
|
||||
useEffect(() => {
|
||||
webfontloader.load({
|
||||
google: { families: [fontString] },
|
||||
active: () => {
|
||||
const height = window.document.body.offsetHeight;
|
||||
const message = { type: "PAGE_LOADED", payload: { height } };
|
||||
window.postMessage(message, "*");
|
||||
},
|
||||
});
|
||||
}, [fontString]);
|
||||
|
||||
// Font Size & Line Height
|
||||
useEffect(() => {
|
||||
document.documentElement.style.setProperty("font-size", `${metadata.typography.font.size}px`);
|
||||
document.documentElement.style.setProperty("line-height", `${metadata.typography.lineHeight}`);
|
||||
}, [metadata]);
|
||||
|
||||
// Underline Links
|
||||
useEffect(() => {
|
||||
if (metadata.typography.underlineLinks) {
|
||||
document.querySelector("#root")!.classList.add("underline-links");
|
||||
} else {
|
||||
document.querySelector("#root")!.classList.remove("underline-links");
|
||||
}
|
||||
}, [metadata]);
|
||||
|
||||
return <Outlet />;
|
||||
};
|
||||
63
apps/artboard/src/pages/builder.tsx
Normal file
63
apps/artboard/src/pages/builder.tsx
Normal file
@ -0,0 +1,63 @@
|
||||
import { SectionKey } from "@reactive-resume/schema";
|
||||
import { pageSizeMap } from "@reactive-resume/utils";
|
||||
import { useEffect, useRef } from "react";
|
||||
import { ReactZoomPanPinchRef, TransformComponent, TransformWrapper } from "react-zoom-pan-pinch";
|
||||
|
||||
import { MM_TO_PX, Page } from "../components/page";
|
||||
import { useArtboardStore } from "../store/artboard";
|
||||
import { Rhyhorn } from "../templates/rhyhorn";
|
||||
|
||||
export const BuilderLayout = () => {
|
||||
const transformRef = useRef<ReactZoomPanPinchRef>(null);
|
||||
const format = useArtboardStore((state) => state.resume.metadata.page.format);
|
||||
const layout = useArtboardStore((state) => state.resume.metadata.layout);
|
||||
const template = useArtboardStore((state) => state.resume.metadata.template);
|
||||
|
||||
useEffect(() => {
|
||||
const handleMessage = (event: MessageEvent) => {
|
||||
if (event.origin !== window.location.origin) return;
|
||||
|
||||
if (event.data.type === "ZOOM_IN") transformRef.current?.zoomIn(0.2);
|
||||
if (event.data.type === "ZOOM_OUT") transformRef.current?.zoomOut(0.2);
|
||||
if (event.data.type === "CENTER_VIEW") transformRef.current?.centerView();
|
||||
if (event.data.type === "RESET_VIEW") {
|
||||
transformRef.current?.resetTransform(0);
|
||||
setTimeout(() => transformRef.current?.centerView(0.8, 0), 10);
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener("message", handleMessage);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener("message", handleMessage);
|
||||
};
|
||||
}, [transformRef]);
|
||||
|
||||
return (
|
||||
<TransformWrapper
|
||||
centerOnInit
|
||||
maxScale={2}
|
||||
minScale={0.4}
|
||||
initialScale={0.8}
|
||||
ref={transformRef}
|
||||
limitToBounds={false}
|
||||
>
|
||||
<TransformComponent
|
||||
wrapperClass="!w-screen !h-screen"
|
||||
contentClass="grid items-start justify-center space-x-12 pointer-events-none"
|
||||
contentStyle={{
|
||||
width: `${layout.length * (pageSizeMap[format].width * MM_TO_PX + 42)}px`,
|
||||
gridTemplateColumns: `repeat(${layout.length}, 1fr)`,
|
||||
}}
|
||||
>
|
||||
{layout.map((columns, pageIndex) => (
|
||||
<Page key={pageIndex} mode="builder" pageNumber={pageIndex + 1}>
|
||||
{template === "rhyhorn" && (
|
||||
<Rhyhorn isFirstPage={pageIndex === 0} columns={columns as SectionKey[][]} />
|
||||
)}
|
||||
</Page>
|
||||
))}
|
||||
</TransformComponent>
|
||||
</TransformWrapper>
|
||||
);
|
||||
};
|
||||
22
apps/artboard/src/pages/preview.tsx
Normal file
22
apps/artboard/src/pages/preview.tsx
Normal file
@ -0,0 +1,22 @@
|
||||
import { SectionKey } from "@reactive-resume/schema";
|
||||
|
||||
import { Page } from "../components/page";
|
||||
import { useArtboardStore } from "../store/artboard";
|
||||
import { Rhyhorn } from "../templates/rhyhorn";
|
||||
|
||||
export const PreviewLayout = () => {
|
||||
const layout = useArtboardStore((state) => state.resume.metadata.layout);
|
||||
const template = useArtboardStore((state) => state.resume.metadata.template);
|
||||
|
||||
return (
|
||||
<>
|
||||
{layout.map((columns, pageIndex) => (
|
||||
<Page key={pageIndex} mode="preview" pageNumber={pageIndex + 1}>
|
||||
{template === "rhyhorn" && (
|
||||
<Rhyhorn isFirstPage={pageIndex === 0} columns={columns as SectionKey[][]} />
|
||||
)}
|
||||
</Page>
|
||||
))}
|
||||
</>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user