Skip to content

Commit af99311

Browse files
wip full screen preview
1 parent 1f7f64f commit af99311

4 files changed

Lines changed: 283 additions & 8 deletions

File tree

editor/layouts/default-editor-workspace-layout.tsx

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,14 @@ export function DefaultEditorWorkspaceLayout(props: {
77
rightbar?: JSX.Element;
88
appbar?: JSX.Element;
99
children: JSX.Element | Array<JSX.Element>;
10+
display?: "none" | "initial"; // set to none when to hide.
1011
backgroundColor?: string;
1112
}) {
1213
return (
13-
<WorkspaceRoot backgroundColor={props.backgroundColor}>
14+
<WorkspaceRoot
15+
display={props.display}
16+
backgroundColor={props.backgroundColor}
17+
>
1418
<AppBarMenuAndBelowContentWrap>
1519
{props.appbar && <AppBarWrap>{props.appbar}</AppBarWrap>}
1620
<NonMenuContentZoneWrap>
@@ -27,7 +31,11 @@ export function DefaultEditorWorkspaceLayout(props: {
2731
);
2832
}
2933

30-
const WorkspaceRoot = styled.div<{ backgroundColor: string }>`
34+
const WorkspaceRoot = styled.div<{
35+
display?: "none" | "initial";
36+
backgroundColor: string;
37+
}>`
38+
${(props) => props.display && `display: ${props.display};`}
3139
width: 100vw;
3240
height: 100vh;
3341
background-color: ${(p) => p.backgroundColor ?? "transparent"};

editor/scaffolds/editor/editor.tsx

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,13 @@ import {
44
WorkspaceContentPanel,
55
WorkspaceContentPanelGridLayout,
66
} from "layouts/panel";
7-
import { WorkspaceBottomPanelDockLayout } from "layouts/panel/workspace-bottom-panel-dock-layout";
7+
import { FullScreenPreview } from "scaffolds/preview-full-screen";
88
import { EditorSidebar } from "components/editor";
99
import { useEditorState, useWorkspaceState } from "core/states";
10-
1110
import { Canvas } from "scaffolds/canvas";
1211
import { CodeSegment } from "scaffolds/code";
13-
import { Inspector } from "scaffolds/inspector";
14-
1512
import { EditorSkeleton } from "./skeleton";
1613
import { colors } from "theme";
17-
import { Debugger } from "@code-editor/debugger";
18-
1914
import { RemoteImageRepositories } from "@design-sdk/figma-remote/lib/asset-repository/image-repository";
2015
import {
2116
ImageRepository,
@@ -71,14 +66,23 @@ export function Editor({
7166
// this key is used for force re-rendering canvas after the whole file is fetched.
7267
const _refreshkey = loading || !_initially_loaded ? "1" : "0";
7368

69+
// TODO: migrate this to wsstate or editor state, - only for development.
70+
const [mode, setMode] = useState<"edit" | "fullscreen-preview">("edit");
71+
72+
const FullscreenPreviewMode = () => {
73+
return <FullScreenPreview />;
74+
};
75+
7476
return (
7577
<>
7678
{(loading || !_initially_loaded) && (
7779
<EditorSkeleton percent={_initial_load_progress * 100} />
7880
)}
81+
{mode == "fullscreen-preview" && <FullscreenPreviewMode />}
7982
<DefaultEditorWorkspaceLayout
8083
backgroundColor={colors.color_editor_bg_on_dark}
8184
leftbar={<EditorSidebar />}
85+
display={mode == "fullscreen-preview" ? "none" : undefined}
8286
// rightbar={<Inspector />}
8387
>
8488
<WorkspaceContentPanelGridLayout>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# Full screen previewer
Lines changed: 262 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,262 @@
1+
import React, { useEffect, useState } from "react";
2+
import { useEditorState } from "core/states";
3+
import styled from "@emotion/styled";
4+
import { vanilla_presets } from "@grida/builder-config-preset";
5+
import { designToCode, Result } from "@designto/code";
6+
import { config } from "@designto/config";
7+
import {
8+
ImageRepository,
9+
MainImageRepository,
10+
} from "@design-sdk/core/assets-repository";
11+
import { RemoteImageRepositories } from "@design-sdk/figma-remote/lib/asset-repository/image-repository";
12+
import { VanillaRunner } from "components/app-runner/vanilla-app-runner";
13+
import { useTargetContainer, useWindowSize } from "hooks";
14+
import Close from "@material-ui/icons/Close";
15+
import ClientOnly from "components/client-only";
16+
17+
export function FullScreenPreview() {
18+
const [state] = useEditorState();
19+
const [preview, setPreview] = useState<Result>();
20+
const windowsize = useWindowSize();
21+
const target = useTargetContainer();
22+
23+
const on_preview_result = (result: Result) => {
24+
setPreview(result);
25+
};
26+
27+
useEffect(() => {
28+
const __target = target?.target; // root.entry;
29+
if (__target) {
30+
if (!MainImageRepository.isReady) {
31+
// this is not the smartest way, but the image repo has a design flaw.
32+
// 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.
33+
MainImageRepository.instance = new RemoteImageRepositories(
34+
state.design.key,
35+
{
36+
// setting this won't load any image btw. (just to prevent errors)
37+
authentication: { accessToken: "" },
38+
}
39+
);
40+
MainImageRepository.instance.register(
41+
new ImageRepository(
42+
"fill-later-assets",
43+
"grida://assets-reservation/images/"
44+
)
45+
);
46+
}
47+
48+
const _input = {
49+
id: __target.id,
50+
name: __target.name,
51+
entry: __target,
52+
};
53+
const build_config = {
54+
...config.default_build_configuration,
55+
disable_components: true,
56+
};
57+
58+
// ----- for preview -----
59+
designToCode({
60+
input: _input,
61+
build_config: build_config,
62+
framework: vanilla_presets.vanilla_default,
63+
asset_config: {
64+
skip_asset_replacement: false,
65+
asset_repository: MainImageRepository.instance,
66+
custom_asset_replacement: {
67+
type: "static",
68+
resource:
69+
"https://bridged-service-static.s3.us-west-1.amazonaws.com/placeholder-images/image-placeholder-bw-tile-100.png",
70+
},
71+
},
72+
})
73+
.then(on_preview_result)
74+
.catch(console.error);
75+
76+
if (!MainImageRepository.instance.empty) {
77+
designToCode({
78+
input: target.root,
79+
build_config: build_config,
80+
framework: vanilla_presets.vanilla_default,
81+
asset_config: { asset_repository: MainImageRepository.instance },
82+
})
83+
.then(on_preview_result)
84+
.catch(console.error);
85+
} else {
86+
console.error("MainImageRepository is empty");
87+
}
88+
}
89+
}, [target?.target?.id]);
90+
91+
//
92+
return (
93+
<RootWrapperFullScreenRunnerViewLayout>
94+
<FullscreenPreviewAppbar>
95+
<AppbarControlSizeInputs>
96+
<StaticSizeInput value={windowsize.width ?? 0} suffix={"W"} />
97+
<StaticSizeInput value={windowsize.height ?? 0} suffix={"H"} />
98+
</AppbarControlSizeInputs>
99+
<AppbarActionsSegment>
100+
<CloseButton
101+
onClick={() => {
102+
// TODO: end preview mode
103+
}}
104+
/>
105+
</AppbarActionsSegment>
106+
</FullscreenPreviewAppbar>
107+
<Body>
108+
{preview && (
109+
<VanillaRunner
110+
key={preview.scaffold.raw}
111+
style={{
112+
alignSelf: "stretch",
113+
borderRadius: 0,
114+
// TODO: do not specify static bg color
115+
background: "white",
116+
flexGrow: 1,
117+
border: "none",
118+
margin: 0,
119+
padding: 0,
120+
}}
121+
enableInspector={false}
122+
source={preview.scaffold.raw}
123+
width="100%"
124+
height="100%"
125+
componentName={preview.name}
126+
/>
127+
)}
128+
</Body>
129+
</RootWrapperFullScreenRunnerViewLayout>
130+
);
131+
}
132+
133+
const StaticSizeInput = ({
134+
value,
135+
suffix,
136+
}: {
137+
value: number;
138+
suffix: string;
139+
}) => {
140+
return (
141+
<WidthInput>
142+
<Value>{value}</Value>
143+
<ValueSuffixText>{suffix}</ValueSuffixText>
144+
</WidthInput>
145+
);
146+
};
147+
148+
const CloseButton = ({ onClick }: { onClick: () => void }) => {
149+
return (
150+
<CloseButtonBase onClick={onClick}>
151+
<ClientOnly>
152+
<Close style={{ color: "white" }} />
153+
</ClientOnly>
154+
</CloseButtonBase>
155+
);
156+
};
157+
158+
const RootWrapperFullScreenRunnerViewLayout = styled.div`
159+
display: flex;
160+
justify-content: flex-start;
161+
flex-direction: column;
162+
align-items: center;
163+
flex: none;
164+
min-height: 100vh;
165+
box-sizing: border-box;
166+
`;
167+
168+
const FullscreenPreviewAppbar = styled.div`
169+
height: 50px;
170+
overflow: hidden;
171+
background-color: rgba(17, 17, 17, 1);
172+
position: relative;
173+
align-self: stretch;
174+
`;
175+
176+
const AppbarControlSizeInputs = styled.div`
177+
display: flex;
178+
justify-content: space-between;
179+
flex-direction: row;
180+
align-items: flex-start;
181+
flex: none;
182+
width: 170px;
183+
box-sizing: border-box;
184+
position: absolute;
185+
left: calc((calc((50% + 0px)) - 85px));
186+
top: calc((calc((50% + 0px)) - 12px));
187+
`;
188+
189+
const WidthInput = styled.div`
190+
width: 68px;
191+
height: 24px;
192+
position: relative;
193+
`;
194+
195+
const Value = styled.span`
196+
color: rgba(255, 255, 255, 1);
197+
text-overflow: ellipsis;
198+
font-size: 11px;
199+
font-family: Inter, sans-serif;
200+
font-weight: 500;
201+
text-align: left;
202+
position: absolute;
203+
left: 8px;
204+
top: 5px;
205+
`;
206+
207+
const ValueSuffixText = styled.span`
208+
color: rgba(182, 182, 182, 1);
209+
text-overflow: ellipsis;
210+
font-size: 11px;
211+
font-family: Inter, sans-serif;
212+
font-weight: 500;
213+
text-align: left;
214+
position: absolute;
215+
left: 54px;
216+
top: 6px;
217+
`;
218+
219+
const AppbarActionsSegment = styled.div`
220+
display: flex;
221+
justify-content: flex-start;
222+
flex-direction: row;
223+
align-items: flex-start;
224+
flex: none;
225+
gap: 21px;
226+
box-sizing: border-box;
227+
position: absolute;
228+
top: calc((calc((50% + 0px)) - 13px));
229+
right: 24px;
230+
`;
231+
232+
const CloseButtonBase = styled.div`
233+
display: flex;
234+
justify-content: center;
235+
flex-direction: row;
236+
align-items: center;
237+
flex: none;
238+
gap: 10px;
239+
box-shadow: 0px 4px 12px 0px rgba(0, 0, 0, 0.1);
240+
border-radius: 4px;
241+
width: 34px;
242+
height: 26px;
243+
background-color: rgba(43, 43, 43, 1);
244+
box-sizing: border-box;
245+
`;
246+
247+
const IconsMdiClose = styled.img`
248+
width: 20px;
249+
height: 20px;
250+
object-fit: cover;
251+
`;
252+
253+
const Body = styled.div`
254+
display: flex;
255+
justify-content: center;
256+
flex-direction: column;
257+
align-items: center;
258+
flex: 1;
259+
height: 100%;
260+
align-self: stretch;
261+
box-sizing: border-box;
262+
`;

0 commit comments

Comments
 (0)