From af993111bebcd0cfb19ce23ce48c1122e001527f Mon Sep 17 00:00:00 2001 From: softmarshmallow Date: Thu, 3 Mar 2022 19:05:44 +0900 Subject: [PATCH 1/3] wip full screen preview --- .../default-editor-workspace-layout.tsx | 12 +- editor/scaffolds/editor/editor.tsx | 16 +- .../scaffolds/preview-full-screen/README.md | 1 + .../scaffolds/preview-full-screen/index.tsx | 262 ++++++++++++++++++ 4 files changed, 283 insertions(+), 8 deletions(-) create mode 100644 editor/scaffolds/preview-full-screen/README.md create mode 100644 editor/scaffolds/preview-full-screen/index.tsx diff --git a/editor/layouts/default-editor-workspace-layout.tsx b/editor/layouts/default-editor-workspace-layout.tsx index f91c317d..ac00b846 100644 --- a/editor/layouts/default-editor-workspace-layout.tsx +++ b/editor/layouts/default-editor-workspace-layout.tsx @@ -7,10 +7,14 @@ export function DefaultEditorWorkspaceLayout(props: { rightbar?: JSX.Element; appbar?: JSX.Element; children: JSX.Element | Array; + display?: "none" | "initial"; // set to none when to hide. backgroundColor?: string; }) { return ( - + {props.appbar && {props.appbar}} @@ -27,7 +31,11 @@ export function DefaultEditorWorkspaceLayout(props: { ); } -const WorkspaceRoot = styled.div<{ backgroundColor: string }>` +const WorkspaceRoot = styled.div<{ + display?: "none" | "initial"; + backgroundColor: string; +}>` + ${(props) => props.display && `display: ${props.display};`} width: 100vw; height: 100vh; background-color: ${(p) => p.backgroundColor ?? "transparent"}; diff --git a/editor/scaffolds/editor/editor.tsx b/editor/scaffolds/editor/editor.tsx index ed6de5ee..a9bc1bf3 100644 --- a/editor/scaffolds/editor/editor.tsx +++ b/editor/scaffolds/editor/editor.tsx @@ -4,18 +4,13 @@ import { WorkspaceContentPanel, WorkspaceContentPanelGridLayout, } from "layouts/panel"; -import { WorkspaceBottomPanelDockLayout } from "layouts/panel/workspace-bottom-panel-dock-layout"; +import { FullScreenPreview } from "scaffolds/preview-full-screen"; import { EditorSidebar } from "components/editor"; import { useEditorState, useWorkspaceState } from "core/states"; - import { Canvas } from "scaffolds/canvas"; import { CodeSegment } from "scaffolds/code"; -import { Inspector } from "scaffolds/inspector"; - import { EditorSkeleton } from "./skeleton"; import { colors } from "theme"; -import { Debugger } from "@code-editor/debugger"; - import { RemoteImageRepositories } from "@design-sdk/figma-remote/lib/asset-repository/image-repository"; import { ImageRepository, @@ -71,14 +66,23 @@ export function Editor({ // this key is used for force re-rendering canvas after the whole file is fetched. const _refreshkey = loading || !_initially_loaded ? "1" : "0"; + // TODO: migrate this to wsstate or editor state, - only for development. + const [mode, setMode] = useState<"edit" | "fullscreen-preview">("edit"); + + const FullscreenPreviewMode = () => { + return ; + }; + return ( <> {(loading || !_initially_loaded) && ( )} + {mode == "fullscreen-preview" && } } + display={mode == "fullscreen-preview" ? "none" : undefined} // rightbar={} > diff --git a/editor/scaffolds/preview-full-screen/README.md b/editor/scaffolds/preview-full-screen/README.md new file mode 100644 index 00000000..eb603ee0 --- /dev/null +++ b/editor/scaffolds/preview-full-screen/README.md @@ -0,0 +1 @@ +# Full screen previewer diff --git a/editor/scaffolds/preview-full-screen/index.tsx b/editor/scaffolds/preview-full-screen/index.tsx new file mode 100644 index 00000000..bb3747a2 --- /dev/null +++ b/editor/scaffolds/preview-full-screen/index.tsx @@ -0,0 +1,262 @@ +import React, { useEffect, useState } from "react"; +import { useEditorState } from "core/states"; +import styled from "@emotion/styled"; +import { vanilla_presets } from "@grida/builder-config-preset"; +import { designToCode, Result } from "@designto/code"; +import { config } from "@designto/config"; +import { + ImageRepository, + MainImageRepository, +} from "@design-sdk/core/assets-repository"; +import { RemoteImageRepositories } from "@design-sdk/figma-remote/lib/asset-repository/image-repository"; +import { VanillaRunner } from "components/app-runner/vanilla-app-runner"; +import { useTargetContainer, useWindowSize } from "hooks"; +import Close from "@material-ui/icons/Close"; +import ClientOnly from "components/client-only"; + +export function FullScreenPreview() { + const [state] = useEditorState(); + const [preview, setPreview] = useState(); + const windowsize = useWindowSize(); + const target = useTargetContainer(); + + const on_preview_result = (result: Result) => { + setPreview(result); + }; + + useEffect(() => { + const __target = target?.target; // root.entry; + if (__target) { + if (!MainImageRepository.isReady) { + // this is not the smartest way, but the image repo has a design flaw. + // this happens when the target node is setted on the query param on first load, when the image repo is not set by the higher editor container. + MainImageRepository.instance = new RemoteImageRepositories( + state.design.key, + { + // setting this won't load any image btw. (just to prevent errors) + authentication: { accessToken: "" }, + } + ); + MainImageRepository.instance.register( + new ImageRepository( + "fill-later-assets", + "grida://assets-reservation/images/" + ) + ); + } + + const _input = { + id: __target.id, + name: __target.name, + entry: __target, + }; + const build_config = { + ...config.default_build_configuration, + disable_components: true, + }; + + // ----- for preview ----- + designToCode({ + input: _input, + build_config: build_config, + framework: vanilla_presets.vanilla_default, + asset_config: { + skip_asset_replacement: false, + asset_repository: MainImageRepository.instance, + custom_asset_replacement: { + type: "static", + resource: + "https://bridged-service-static.s3.us-west-1.amazonaws.com/placeholder-images/image-placeholder-bw-tile-100.png", + }, + }, + }) + .then(on_preview_result) + .catch(console.error); + + if (!MainImageRepository.instance.empty) { + designToCode({ + input: target.root, + build_config: build_config, + framework: vanilla_presets.vanilla_default, + asset_config: { asset_repository: MainImageRepository.instance }, + }) + .then(on_preview_result) + .catch(console.error); + } else { + console.error("MainImageRepository is empty"); + } + } + }, [target?.target?.id]); + + // + return ( + + + + + + + + { + // TODO: end preview mode + }} + /> + + + + {preview && ( + + )} + + + ); +} + +const StaticSizeInput = ({ + value, + suffix, +}: { + value: number; + suffix: string; +}) => { + return ( + + {value} + {suffix} + + ); +}; + +const CloseButton = ({ onClick }: { onClick: () => void }) => { + return ( + + + + + + ); +}; + +const RootWrapperFullScreenRunnerViewLayout = styled.div` + display: flex; + justify-content: flex-start; + flex-direction: column; + align-items: center; + flex: none; + min-height: 100vh; + box-sizing: border-box; +`; + +const FullscreenPreviewAppbar = styled.div` + height: 50px; + overflow: hidden; + background-color: rgba(17, 17, 17, 1); + position: relative; + align-self: stretch; +`; + +const AppbarControlSizeInputs = styled.div` + display: flex; + justify-content: space-between; + flex-direction: row; + align-items: flex-start; + flex: none; + width: 170px; + box-sizing: border-box; + position: absolute; + left: calc((calc((50% + 0px)) - 85px)); + top: calc((calc((50% + 0px)) - 12px)); +`; + +const WidthInput = styled.div` + width: 68px; + height: 24px; + position: relative; +`; + +const Value = styled.span` + color: rgba(255, 255, 255, 1); + text-overflow: ellipsis; + font-size: 11px; + font-family: Inter, sans-serif; + font-weight: 500; + text-align: left; + position: absolute; + left: 8px; + top: 5px; +`; + +const ValueSuffixText = styled.span` + color: rgba(182, 182, 182, 1); + text-overflow: ellipsis; + font-size: 11px; + font-family: Inter, sans-serif; + font-weight: 500; + text-align: left; + position: absolute; + left: 54px; + top: 6px; +`; + +const AppbarActionsSegment = styled.div` + display: flex; + justify-content: flex-start; + flex-direction: row; + align-items: flex-start; + flex: none; + gap: 21px; + box-sizing: border-box; + position: absolute; + top: calc((calc((50% + 0px)) - 13px)); + right: 24px; +`; + +const CloseButtonBase = styled.div` + display: flex; + justify-content: center; + flex-direction: row; + align-items: center; + flex: none; + gap: 10px; + box-shadow: 0px 4px 12px 0px rgba(0, 0, 0, 0.1); + border-radius: 4px; + width: 34px; + height: 26px; + background-color: rgba(43, 43, 43, 1); + box-sizing: border-box; +`; + +const IconsMdiClose = styled.img` + width: 20px; + height: 20px; + object-fit: cover; +`; + +const Body = styled.div` + display: flex; + justify-content: center; + flex-direction: column; + align-items: center; + flex: 1; + height: 100%; + align-self: stretch; + box-sizing: border-box; +`; From 15a371dd8d04540424142e2de89078d58220c4e7 Mon Sep 17 00:00:00 2001 From: softmarshmallow Date: Thu, 3 Mar 2022 23:33:13 +0900 Subject: [PATCH 2/3] add fullscreen preview mode on isolated canvas --- editor/components/canvas/isolated-canvas.tsx | 13 +++- editor/scaffolds/canvas/isolate-mode.tsx | 66 ++++++++++++------- editor/scaffolds/editor/editor.tsx | 13 +--- .../scaffolds/preview-full-screen/index.tsx | 8 +-- 4 files changed, 58 insertions(+), 42 deletions(-) diff --git a/editor/components/canvas/isolated-canvas.tsx b/editor/components/canvas/isolated-canvas.tsx index 9cf03779..4e4a5b64 100644 --- a/editor/components/canvas/isolated-canvas.tsx +++ b/editor/components/canvas/isolated-canvas.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useLayoutEffect, useRef, useState } from "react"; +import React, { useEffect, useRef, useState } from "react"; import styled from "@emotion/styled"; import { useGesture } from "@use-gesture/react"; import useMeasure from "react-use-measure"; @@ -61,10 +61,12 @@ export function IsolatedCanvas({ children, defaultSize, onExit, + onFullscreen, }: { defaultSize: { width: number; height: number }; children?: React.ReactNode; onExit?: () => void; + onFullscreen?: () => void; }) { const _margin = 20; const [canvasSizingRef, canvasBounds] = useMeasure(); @@ -136,7 +138,12 @@ export function IsolatedCanvas({ scale={scale} onChange={setScale} /> - {onExit && End Isolation} + {onFullscreen && ( + Full Screen + )} + {onExit && ( + End Isolation + )} {/* */} void }) { const [state] = useEditorState(); const [preview, setPreview] = useState(); + const [fullscreen, setFullscreen] = useState(false); const { target, root } = useTargetContainer(); @@ -69,30 +72,49 @@ export function IsolateModeCanvas({ onClose }: { onClose: () => void }) { }, [target?.id]); return ( - - {preview ? ( - + { + setFullscreen(false); + }} + open={fullscreen} + > + { + setFullscreen(false); }} - source={preview.scaffold.raw} - width="100%" - height="100%" - componentName={preview.name} /> - ) : ( - - )} - + ; + + { + setFullscreen(true); + }} + defaultSize={{ + width: target?.width ?? 375, + height: target?.height ?? 812, + }} + > + {preview ? ( + + ) : ( + + )} + + ); } diff --git a/editor/scaffolds/editor/editor.tsx b/editor/scaffolds/editor/editor.tsx index a9bc1bf3..75c5e980 100644 --- a/editor/scaffolds/editor/editor.tsx +++ b/editor/scaffolds/editor/editor.tsx @@ -1,10 +1,9 @@ -import React, { useEffect, useRef, useState } from "react"; +import React, { useEffect } from "react"; import { DefaultEditorWorkspaceLayout } from "layouts/default-editor-workspace-layout"; import { WorkspaceContentPanel, WorkspaceContentPanelGridLayout, } from "layouts/panel"; -import { FullScreenPreview } from "scaffolds/preview-full-screen"; import { EditorSidebar } from "components/editor"; import { useEditorState, useWorkspaceState } from "core/states"; import { Canvas } from "scaffolds/canvas"; @@ -66,23 +65,15 @@ export function Editor({ // this key is used for force re-rendering canvas after the whole file is fetched. const _refreshkey = loading || !_initially_loaded ? "1" : "0"; - // TODO: migrate this to wsstate or editor state, - only for development. - const [mode, setMode] = useState<"edit" | "fullscreen-preview">("edit"); - - const FullscreenPreviewMode = () => { - return ; - }; - return ( <> {(loading || !_initially_loaded) && ( )} - {mode == "fullscreen-preview" && } + } - display={mode == "fullscreen-preview" ? "none" : undefined} // rightbar={} > diff --git a/editor/scaffolds/preview-full-screen/index.tsx b/editor/scaffolds/preview-full-screen/index.tsx index bb3747a2..a1728b60 100644 --- a/editor/scaffolds/preview-full-screen/index.tsx +++ b/editor/scaffolds/preview-full-screen/index.tsx @@ -14,7 +14,7 @@ import { useTargetContainer, useWindowSize } from "hooks"; import Close from "@material-ui/icons/Close"; import ClientOnly from "components/client-only"; -export function FullScreenPreview() { +export function FullScreenPreview({ onClose }: { onClose: () => void }) { const [state] = useEditorState(); const [preview, setPreview] = useState(); const windowsize = useWindowSize(); @@ -97,11 +97,7 @@ export function FullScreenPreview() { - { - // TODO: end preview mode - }} - /> + From 43f94f845437306d1fa0763534187381eb032bb9 Mon Sep 17 00:00:00 2001 From: softmarshmallow Date: Thu, 3 Mar 2022 23:50:08 +0900 Subject: [PATCH 3/3] fix fullscreen styling --- editor/scaffolds/canvas/isolate-mode.tsx | 2 +- editor/scaffolds/preview-full-screen/index.tsx | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/editor/scaffolds/canvas/isolate-mode.tsx b/editor/scaffolds/canvas/isolate-mode.tsx index 277b189a..f6ee6a75 100644 --- a/editor/scaffolds/canvas/isolate-mode.tsx +++ b/editor/scaffolds/canvas/isolate-mode.tsx @@ -85,8 +85,8 @@ export function IsolateModeCanvas({ onClose }: { onClose: () => void }) { setFullscreen(false); }} /> - ; +