Skip to content

Commit

Permalink
Merge branch 'main' into feature/css-in-iframe
Browse files Browse the repository at this point in the history
  • Loading branch information
alextaing committed Oct 26, 2023
2 parents 3cd5776 + f19478a commit 09f2b38
Show file tree
Hide file tree
Showing 18 changed files with 161 additions and 74 deletions.
6 changes: 6 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions packages/studio-plugin/src/orchestrators/ParsingOrchestrator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,18 @@ export default class ParsingOrchestrator {
`The pages directory does not exist, expected directory to be at "${this.paths.pages}".`
);
}

if (this.studioConfig.isPagesJSRepo) {
const excludeReservedPagesJSFiles = (filename: string) =>
!(filename.includes("_server") || filename.includes("_client"));

return createFilenameMapping(
this.paths.pages,
this.getOrCreatePageFile,
excludeReservedPagesJSFiles
);
}

return createFilenameMapping(this.paths.pages, this.getOrCreatePageFile);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@ import upath from "upath";

export default function createFilenameMapping<T>(
dirPath: string,
getMappedValue: (name: string) => T
getMappedValue: (name: string) => T,
fileFilter?: (filename: string) => boolean
): Record<string, T> {
const files = fs.readdirSync(dirPath, "utf-8").filter((filename) => {
const absPath = upath.join(dirPath, filename);
return fs.lstatSync(absPath).isFile();

const isFile = fs.lstatSync(absPath).isFile();
return fileFilter ? isFile && fileFilter(filename) : isFile;
});
return files.reduce((filepathMapping, filename) => {
const name = upath.basename(filename, ".tsx");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { PageContext } from "@yext/pages";
import { hydrateRoot } from "react-dom/client";

export { render };

const render = async (pageContext: PageContext<any>) => {
const { Page, pageProps } = pageContext;
const rootElement = document.getElementById("reactele");
if (rootElement) {
hydrateRoot(rootElement, <Page {...pageProps} />);
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import * as ReactDOMServer from "react-dom/server";
import { PageContext } from "@yext/pages";

export { render };

const render = async (pageContext: PageContext<any>) => {
const { Page, pageProps } = pageContext;
const viewHtml = ReactDOMServer.renderToString(<Page {...pageProps} />);
return `<!DOCTYPE html>
<html lang="<!--app-lang-->">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
</head>
<body>
<div id="reactele">${viewHtml}</div>
</body>
</html>`;
};
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ describe("aggregates data as expected", () => {
isPagesJS: true,
});
const studioData = orchestrator.getStudioData();
expect(studioData.pageNameToErrorPageState).toEqual({});
expect(studioData.pageNameToPageState).toEqual({
basicPage: {
...basicPageState,
Expand All @@ -138,7 +139,10 @@ it("throws an error when the page imports components from unexpected folders", (
__dirname,
"../__fixtures__/ParsingOrchestrator/src/pages"
);
createParsingOrchestrator({ paths: userPaths }).getStudioData();
createParsingOrchestrator({
paths: userPaths,
isPagesJS: true,
}).getStudioData();
expect(prettyPrintError).toHaveBeenCalledTimes(1);
expect(prettyPrintError).toHaveBeenCalledWith(
expect.stringMatching(/^Failed to parse PageState/),
Expand Down
2 changes: 1 addition & 1 deletion packages/studio-ui/.size-limit.cjs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
module.exports = [
{
path: "lib/**/*.js",
limit: "850 kB",
limit: "870 kB",
gzip: false,
},
];
3 changes: 2 additions & 1 deletion packages/studio-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,17 @@
"immer": "^9.0.21",
"lodash": "^4.17.21",
"path-browserify": "^1.0.1",
"platform": "^1.3.6",
"postcss": "^8.4.27",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-modal": "3.16.1",
"react-select": "^5.7.4",
"react-toastify": "^9.1.1",
"react-tooltip": "^5.18.0",
"true-myth": "^6.2.0",
"tailwind-merge": "^1.8.1",
"tailwindcss": "^3.3.3",
"true-myth": "^6.2.0",
"zundo": "2.0.0-beta.12",
"zustand": "^4.3.2"
},
Expand Down
14 changes: 4 additions & 10 deletions packages/studio-ui/src/components/IFramePortal.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { createPortal } from "react-dom";
import { Dispatch, PropsWithChildren, SetStateAction, useRef } from "react";
import { Dispatch, PropsWithChildren, SetStateAction } from "react";
import useStudioStore from "../store/useStudioStore";
import { twMerge } from "tailwind-merge";
import useInjectActiveStyles from "../hooks/useInjectActiveStyles";
import useViewportOption from "../hooks/useViewportOption";

export default function IFramePortal(
props: PropsWithChildren<{
Expand All @@ -12,18 +11,13 @@ export default function IFramePortal(
setIframeEl: Dispatch<SetStateAction<HTMLIFrameElement | null>>;
}>
) {
const previewRef = useRef<HTMLDivElement>(null);
const iframeDocument = props.iframeEl?.contentWindow?.document;
const [viewport] = useStudioStore((store) => [store.pagePreview.viewport]);
useInjectActiveStyles(iframeDocument);
const iframeCSS = twMerge(
"mr-auto ml-auto",
viewport.css,
useViewportOption(viewport, previewRef)
);
const viewportCss = useStudioStore((store) => store.pagePreview.viewport.css);
const iframeCSS = twMerge("mr-auto ml-auto", viewportCss);

return (
<div ref={previewRef} className="grow w-1/3 bg-white border-y-8">
<div className="grow w-1/3 bg-white border-y-8 overflow-x-scroll">
<iframe
id="iframe"
title={props.title}
Expand Down
20 changes: 19 additions & 1 deletion packages/studio-ui/src/components/UndoRedo.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import useTemporalStore from "../store/useTemporalStore";
import { ReactComponent as Undo } from "../icons/undo.svg";
import { useCallback } from "react";
import { useCallback, useEffect } from "react";
import classNames from "classnames";
import platform from "platform";

/**
* Buttons for undo and redo actions.
Expand All @@ -22,6 +23,23 @@ export default function UndoRedo(): JSX.Element {
redo();
}, [redo]);

const handleUndoKeydown = useCallback(
(event: KeyboardEvent) => {
const actionKey =
platform.os.family === "OS X" ? event.metaKey : event.ctrlKey;
if (actionKey && event.key === "z") {
event.preventDefault();
undo();
}
},
[undo]
);

useEffect(() => {
document.addEventListener("keydown", handleUndoKeydown);
return () => document.removeEventListener("keydown", handleUndoKeydown);
}, [handleUndoKeydown]);

const disableUndo = pastStates.length === 0;
const disableRedo = futureStates.length === 0;
const undoClasses = classNames("w-4", {
Expand Down
6 changes: 2 additions & 4 deletions packages/studio-ui/src/components/Viewport/ViewportButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,8 @@ export default function ViewportButton(): JSX.Element {
const [isOpen, setIsOpen] = useState(false);
const containerRef = useRef<HTMLDivElement>(null);
const handleClose = useCallback(() => setIsOpen(false), []);
useRootClose(containerRef, () => {
handleClose();
});
const handleClick = useCallback(() => setIsOpen(!isOpen), [isOpen]);
useRootClose(containerRef, handleClose);
const handleClick = useCallback(() => setIsOpen((isOpen) => !isOpen), []);

return (
<div ref={containerRef}>
Expand Down
14 changes: 6 additions & 8 deletions packages/studio-ui/src/components/Viewport/ViewportMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export default function ViewportMenu({
interface OptionProps {
viewport: Viewport;
isCurrentlySelected: boolean;
handleSelect: (viewport) => void;
handleSelect: (viewport: Viewport) => void;
}

function Option({ viewport, isCurrentlySelected, handleSelect }: OptionProps) {
Expand All @@ -56,19 +56,17 @@ function Option({ viewport, isCurrentlySelected, handleSelect }: OptionProps) {
[handleSelect, viewport]
);
const { name, styles } = viewport;
const className = classNames(
"flex items-center gap-x-2 px-6 py-2 cursor-pointer w-full text-left",
{
"bg-gray-300": isCurrentlySelected,
"hover:bg-gray-100": !isCurrentlySelected,
}
);
const className = classNames("flex items-center gap-x-2 px-6 py-2 w-full", {
"bg-gray-300": isCurrentlySelected,
"hover:bg-gray-100": !isCurrentlySelected,
});

return (
<button
className={className}
onClick={onClick}
aria-label={`Select ${name} Viewport`}
disabled={isCurrentlySelected}
>
<div className="flex flex-row gap-x-2 items-center">
{name}
Expand Down
14 changes: 7 additions & 7 deletions packages/studio-ui/src/components/Viewport/defaults.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export const VIEWPORTS: ViewportMap = {
width: 375,
},
type: "mobile",
css: "aspect-[375/667]",
css: "w-[375px] h-[667px]",
},
iphone14: {
name: "iPhone 14",
Expand All @@ -38,7 +38,7 @@ export const VIEWPORTS: ViewportMap = {
width: 390,
},
type: "mobile",
css: "aspect-[390/844]",
css: "w-[390px] h-[844px]",
},
galaxyzflip5folded: {
name: "Galaxy Z Flip5 Folded",
Expand All @@ -47,7 +47,7 @@ export const VIEWPORTS: ViewportMap = {
width: 720,
},
type: "mobile",
css: "aspect-[720/748]",
css: "w-[720px] h-[748px]",
},
galaxyzflip5unfolded: {
name: "Galaxy Z Flip5 Unfolded",
Expand All @@ -56,7 +56,7 @@ export const VIEWPORTS: ViewportMap = {
width: 720,
},
type: "mobile",
css: "aspect-[720/1760]",
css: "w-[720px] h-[1760px]",
},
pixel7: {
name: "Pixel 7",
Expand All @@ -65,7 +65,7 @@ export const VIEWPORTS: ViewportMap = {
width: 360,
},
type: "mobile",
css: "aspect-[360/800]",
css: "w-[360px] h-[800px]",
},
pixelfoldfolded: {
name: "Pixel Fold Folded",
Expand All @@ -74,7 +74,7 @@ export const VIEWPORTS: ViewportMap = {
width: 372,
},
type: "mobile",
css: "aspect-[372/720]",
css: "w-[372px] h-[720px]",
},
pixelfoldunfolded: {
name: "Pixel Fold Unfolded",
Expand All @@ -83,6 +83,6 @@ export const VIEWPORTS: ViewportMap = {
width: 600,
},
type: "mobile",
css: "aspect-[600/720]",
css: "w-[600px] h-[720px]",
},
};
34 changes: 0 additions & 34 deletions packages/studio-ui/src/hooks/useViewportOption.tsx

This file was deleted.

7 changes: 7 additions & 0 deletions packages/studio-ui/src/utils/PageDataValidator.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { PagesRecord } from "../store/models/slices/PageSlice";

export const PAGES_JS_RESERVED_PAGE_NAMES = ["_server", "_client"];

export interface ValidationResult {
valid: boolean;
errorMessages: string[];
Expand Down Expand Up @@ -76,6 +78,11 @@ export default class PageDataValidator {
if (pageName.length > 255) {
errorMessages.push("Page name must be 255 characters or less.");
}
if (this.isPagesJSRepo && PAGES_JS_RESERVED_PAGE_NAMES.includes(pageName)) {
errorMessages.push(
`Page name "${pageName}" is a reserved PagesJS filename.`
);
}
if (this.pages[pageName]) {
errorMessages.push(`Page name "${pageName}" is already used.`);
}
Expand Down
Loading

0 comments on commit 09f2b38

Please sign in to comment.