Skip to content

Commit 1cf1013

Browse files
authored
Edit embeds (codesandbox#15)
* Edit embeds * Tweaks * Remove lint from test step
1 parent 039b3ff commit 1cf1013

File tree

5 files changed

+85
-21
lines changed

5 files changed

+85
-21
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@
121121
"scripts": {
122122
"start": "node scripts/start.js",
123123
"build": "NODE_ENV=production node scripts/build.js && gulp",
124-
"test": "jest --env=jsdom && npm run lint",
124+
"test": "jest --env=jsdom",
125125
"test:watch": "jest --watch --env=jsdom",
126126
"lint:app": "eslint src/app && npm run typecheck",
127127
"typecheck": "flow check",

src/app/components/sandbox/Preview/index.js

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,7 @@ type Props = {
3939
fetchBundle: (id: string) => Object,
4040
setProjectView: (id: string, isInProjectView: boolean) => any,
4141
module: Module,
42-
addError: (
43-
sandboxId: string,
44-
error: ?{ message: string, line: number },
45-
) => any,
42+
addError: (sandboxId: string, error: ModuleError) => any,
4643
clearErrors: (sandboxId: string) => any,
4744
sandboxActions: typeof sandboxActionCreators,
4845
noDelay: ?boolean,
@@ -170,7 +167,7 @@ export default class Preview extends React.PureComponent {
170167
this.setState({
171168
frameInitialized: true,
172169
});
173-
this.executeCode();
170+
this.executeCodeImmediately();
174171
} else {
175172
const { type } = e.data;
176173
if (type === 'error') {
@@ -217,6 +214,7 @@ export default class Preview extends React.PureComponent {
217214
}
218215
return;
219216
}
217+
// Do it here so we can see the dependency fetching screen if needed
220218
this.clearErrors();
221219
const renderedModule = this.getRenderedModule();
222220
this.sendMessage({

src/embed/App.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ const Container = styled.div`
2020
height: 100%;
2121
width: 100%;
2222
color: white;
23-
overflow-y: hidden;
2423
`;
2524

2625
const Fullscreen = styled.div`
@@ -45,7 +44,7 @@ const Moving = styled.div`
4544

4645
type State = {
4746
notFound: boolean,
48-
sandbox: Sandbox,
47+
sandbox: ?Sandbox,
4948
showEditor: boolean,
5049
showPreview: boolean,
5150
isInProjectView: boolean,

src/embed/components/Content.js

Lines changed: 79 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import Preview from 'app/components/sandbox/Preview';
66
import CodeEditor from 'app/components/sandbox/CodeEditor';
77
import { getModulePath } from 'app/store/entities/sandboxes/modules/selectors';
88

9-
import type { Sandbox, Module } from 'common/types';
9+
import type { Sandbox, Module, ModuleError } from 'common/types';
1010
import fetchBundle from 'app/store/entities/sandboxes/bundler';
1111

1212
const Container = styled.div`
@@ -26,7 +26,7 @@ const Split = styled.div`
2626

2727
type Props = {
2828
sandbox: Sandbox,
29-
currentModule: string,
29+
currentModule: ?string,
3030
showEditor: boolean,
3131
showPreview: boolean,
3232
isInProjectView: boolean,
@@ -37,11 +37,18 @@ type Props = {
3737
type State = {
3838
bundle: Object,
3939
isInProjectView: boolean,
40+
codes: { [id: string]: string },
41+
errors: Array<ModuleError>,
4042
};
4143

42-
export default class Content extends React.Component {
44+
export default class Content extends React.PureComponent {
4345
state: State = {
44-
bundle: { processing: true },
46+
bundle: {
47+
processing: true,
48+
},
49+
inInProjectView: false,
50+
codes: {},
51+
errors: [],
4552
};
4653

4754
componentDidMount() {
@@ -86,6 +93,63 @@ export default class Content extends React.Component {
8693
}
8794
};
8895

96+
setCode = (moduleId: string, code: string) => {
97+
this.setState({
98+
...this.state,
99+
codes: {
100+
...this.state.codes,
101+
[moduleId]: code,
102+
},
103+
});
104+
};
105+
106+
addError = (moduleId: string, error: ModuleError) => {
107+
if (!this.state.errors.find(e => e.moduleId === error.moduleId)) {
108+
this.setState({
109+
errors: [...this.state.errors, error],
110+
});
111+
}
112+
};
113+
114+
clearErrors = () => {
115+
if (this.state.errors.length > 0) {
116+
this.setState({
117+
errors: [],
118+
});
119+
}
120+
};
121+
122+
lastCodes = {};
123+
lastAlteredModules = [];
124+
/**
125+
* This is a bit of a hack, we utilize custom memoization so we don't return
126+
* a new array of new modules on each render, because map creates a new array
127+
*/
128+
getAlteredModules = () => {
129+
const { sandbox } = this.props;
130+
const { codes } = this.state;
131+
const codeChanged = this.lastCodes !== codes;
132+
133+
if (!codeChanged) {
134+
return this.lastAlteredModules;
135+
}
136+
137+
this.lastCodes = codes;
138+
139+
// $FlowIssue
140+
const alteredModules = sandbox.modules.map((m: Module) => ({
141+
...m,
142+
code: codes[m.id] || m.code,
143+
}));
144+
145+
this.lastAlteredModules = alteredModules;
146+
return alteredModules;
147+
};
148+
149+
preferences = {
150+
livePreviewEnabled: true,
151+
};
152+
89153
props: Props;
90154
state: State;
91155
render() {
@@ -98,7 +162,10 @@ export default class Content extends React.Component {
98162
hideNavigation,
99163
} = this.props;
100164

101-
const preferences = { livePreviewEnabled: true };
165+
const { errors } = this.state;
166+
167+
const alteredModules = this.getAlteredModules();
168+
102169
// $FlowIssue
103170
const mainModule: Module =
104171
sandbox.modules.find((m: Module) => m.shortid === currentModule) ||
@@ -121,8 +188,8 @@ export default class Content extends React.Component {
121188
sandbox.directories,
122189
mainModule.id,
123190
)}
124-
preferences={preferences}
125-
onlyViewMode
191+
changeCode={this.setCode}
192+
preferences={this.preferences}
126193
/>
127194
</Split>}
128195

@@ -131,19 +198,19 @@ export default class Content extends React.Component {
131198
<Preview
132199
sandboxId={sandbox.id}
133200
isInProjectView={isInProjectView}
134-
modules={sandbox.modules}
201+
modules={alteredModules}
135202
directories={sandbox.directories}
136203
bundle={this.state.bundle}
137204
externalResources={sandbox.externalResources}
138205
module={mainModule}
139206
fetchBundle={this.fetchBundle}
140-
addError={() => {}}
141-
clearErrors={() => {}}
142-
preferences={preferences}
207+
addError={this.addError}
208+
clearErrors={this.clearErrors}
209+
preferences={this.preferences}
143210
setProjectView={this.props.setProjectView}
144211
hideNavigation={hideNavigation}
145-
noDelay
146212
setFrameHeight={this.handleResize}
213+
errors={errors}
147214
/>
148215
</Split>}
149216
</Container>

src/embed/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
<!-- End Google Tag Manager -->
3838
</head>
3939

40-
<body style="margin: 0; padding: 0; background-color: #1C2022">
40+
<body style="margin: 0; padding: 0; background-color: #1C2022; overflow: hidden;">
4141
<!-- Google Tag Manager (noscript) -->
4242
<noscript>
4343
<iframe src="https://www.googletagmanager.com/ns.html?id=GTM-T3L6RFK" height="0" width="0" style="display:none;visibility:hidden"></iframe>

0 commit comments

Comments
 (0)