/
ReactEditor.tsx
60 lines (50 loc) · 1.82 KB
/
ReactEditor.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
import React, { useEffect, useState } from "react";
import ReactDOM from "react-dom";
import { ReactEditorProps } from "../../models/editor";
import { Code, TargetFramework } from "../../models/compiler";
import ErrorBoundary from "../error-boundary/ErrorBoundary";
import createBundler from "../../utilities/worker";
import "codemirror/mode/jsx/jsx";
import "codemirror/addon/edit/closebrackets";
import "codemirror/keymap/sublime";
import "codemirror/theme/shadowfox.css";
import CustomizableEditor from "./CustomizableEditor";
function ReactEditor({ viewer, codeEditorContext = "test", ...props }: ReactEditorProps) {
const [worker, setWorker] = useState<any>();
const renderViewer = (node: JSX.Element) => {
if (viewer) {
ReactDOM.render(<ErrorBoundary>{node}</ErrorBoundary>, viewer.current);
}
};
const runBundle = (bundle: string) => {
try {
const runner = new Function("render", "require", bundle);
renderViewer(runner(() => null));
} catch (err: any) {
renderViewer(<pre style={{ color: "red" }}>{err.message}</pre>);
}
};
const run = (code: Code) => {
if (worker) {
worker.onmessage = (event: any) => {
runBundle(event.data);
};
worker.onerror = (err: any) => {
renderViewer(<pre style={{ color: "red" }}>{err.message}</pre>);
};
worker.postMessage({ code, context: codeEditorContext, target: TargetFramework.REACT });
}
};
const loadDependencies = () => {
window["React"] = React;
};
useEffect(() => {
loadDependencies();
const bundler = createBundler();
setWorker(bundler);
return () => bundler.terminate();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
return <CustomizableEditor {...props} theme="shadowfox" keyMap="sublime" runCode={run} />;
}
export default ReactEditor;