Skip to content

Commit 41249e4

Browse files
committed
render react
1 parent 87673cb commit 41249e4

File tree

5 files changed

+66
-147
lines changed

5 files changed

+66
-147
lines changed

src/ConsolePanel.res

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,7 @@ type logLevel = [
55
]
66

77
@react.component
8-
let make = (~compilerState, ~runOutput) => {
9-
let (logs, setLogs) = React.useState(_ => [])
10-
8+
let make = (~logs, ~setLogs) => {
119
React.useEffect(() => {
1210
let cb = e => {
1311
let data = e["data"]
@@ -22,20 +20,6 @@ let make = (~compilerState, ~runOutput) => {
2220
Some(() => Webapi.Window.removeEventListener("message", cb))
2321
}, [])
2422

25-
React.useEffect(() => {
26-
if runOutput {
27-
switch compilerState {
28-
| CompilerManagerHook.Ready({result: Comp(Success({js_code}))}) =>
29-
setLogs(_ => [])
30-
let ast = AcornParse.parse(js_code)
31-
let transpiled = AcornParse.removeImportsAndExports(ast)
32-
EvalIFrame.sendOutput(transpiled)
33-
| _ => ()
34-
}
35-
}
36-
None
37-
}, (compilerState, runOutput))
38-
3923
<div>
4024
{switch logs {
4125
| [] => React.null
@@ -58,6 +42,5 @@ let make = (~compilerState, ~runOutput) => {
5842

5943
<div className="whitespace-pre-wrap p-4 block"> content </div>
6044
}}
61-
<EvalIFrame />
6245
</div>
6346
}

src/Playground.res

Lines changed: 26 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ open CompilerManagerHook
2222
module Api = RescriptCompilerApi
2323

2424
type layout = Column | Row
25-
type tab = JavaScript | Problems | Settings | Console
25+
type tab = JavaScript | RenderOutput | Console | Problems | Settings
2626
let breakingPoint = 1024
2727

2828
module DropdownSelect = {
@@ -1212,67 +1212,6 @@ let locMsgToCmError = (~kind: CodeMirror.Error.kind, locMsg: Api.LocMsg.t): Code
12121212
}
12131213
}
12141214

1215-
// module RenderOutput = {
1216-
// @react.component
1217-
// let make = (~compilerState: CompilerManagerHook.state) => {
1218-
// React.useEffect(() => {
1219-
// let code = switch compilerState {
1220-
// | Ready(ready) =>
1221-
// switch ready.result {
1222-
// | Comp(Success(_)) => ControlPanel.codeFromResult(ready.result)->Some
1223-
// | _ => None
1224-
// }
1225-
// | _ => None
1226-
// }
1227-
1228-
// let _valid = switch code {
1229-
// | Some(code) =>
1230-
// switch RenderOutputManager.renderOutput(code) {
1231-
// | Ok(_) => true
1232-
// | Error(_) => false
1233-
// }
1234-
// | None => false
1235-
// }
1236-
// None
1237-
// }, [compilerState])
1238-
1239-
// <div className={""}>
1240-
// <iframe
1241-
// width="100%"
1242-
// id="iframe-eval"
1243-
// className="relative w-full text-gray-20"
1244-
// srcDoc=RenderOutputManager.Frame.srcdoc
1245-
// />
1246-
// </div>
1247-
1248-
// // switch code {
1249-
// // | Some(code) =>
1250-
// // switch RenderOutputManager.renderOutput(code) {
1251-
// // | Ok() =>
1252-
// // <iframe
1253-
// // width="100%"
1254-
// // id="iframe-eval"
1255-
// // className="relative w-full text-gray-20"
1256-
// // srcDoc=RenderOutputManager.Frame.srcdoc
1257-
// // />
1258-
// // | Error() =>
1259-
// // let code = `module App = {
1260-
// // @react.component
1261-
// // let make = () => {
1262-
// // <ModuleName />
1263-
// // }
1264-
// // }`
1265-
// // <div className={"whitespace-pre-wrap p-4 block"}>
1266-
// // <p className={"mb-2"}> {React.string("To render element create a module App")} </p>
1267-
// // <pre> {HighlightJs.renderHLJS(~code, ~darkmode=true, ~lang="rescript", ())} </pre>
1268-
// // </div>
1269-
// // }
1270-
1271-
// // | _ => React.null
1272-
// // }
1273-
// }
1274-
// }
1275-
12761215
module OutputPanel = {
12771216
@react.component
12781217
let make = (
@@ -1389,8 +1328,11 @@ module OutputPanel = {
13891328

13901329
prevSelected.current = selected
13911330

1331+
let (logs, setLogs) = React.useState(_ => [])
1332+
13921333
let tabs = [
1393-
(Console, <ConsolePanel compilerState runOutput />),
1334+
(RenderOutput, <RenderPanel runOutput compilerState clearLogs={() => setLogs(_ => [])} />),
1335+
(Console, <ConsolePanel logs setLogs />),
13941336
(JavaScript, output),
13951337
(Problems, errorPane),
13961338
(Settings, settingsPane),
@@ -1416,68 +1358,51 @@ and the different jsx modes (classic and automatic).
14161358
module InitialContent = {
14171359
let original = `module Button = {
14181360
@react.component
1419-
let make = (~count) => {
1361+
let make = () => {
1362+
let (count, setCount) = React.useState(_ => 0)
14201363
let times = switch count {
14211364
| 1 => "once"
14221365
| 2 => "twice"
14231366
| n => n->Belt.Int.toString ++ " times"
14241367
}
14251368
let text = \`Click me $\{times\}\`
14261369
1427-
<button> {text->React.string} </button>
1370+
<button onClick={_ => setCount(c => c + 1)}> {msg->React.string} </button>
1371+
}
1372+
}
1373+
1374+
module App = {
1375+
@react.component
1376+
let make = () => {
1377+
<Button />
14281378
}
14291379
}
14301380
`
14311381

1432-
let since_10_1 = `@@jsxConfig({ version: 4, mode: "automatic" })
1382+
let since_10_1 = `@@jsxConfig({version: 4, mode: "classic"})
14331383
1434-
module CounterMessage = {
1384+
module Button = {
14351385
@react.component
1436-
let make = (~count, ~username=?) => {
1386+
let make = () => {
1387+
let (count, setCount) = React.useState(_ => 0)
14371388
let times = switch count {
14381389
| 1 => "once"
14391390
| 2 => "twice"
1440-
| n => Belt.Int.toString(n) ++ " times"
1441-
}
1442-
1443-
let name = switch username {
1444-
| Some("") => "Anonymous"
1445-
| Some(name) => name
1446-
| None => "Anonymous"
1391+
| n => n->Int.toString ++ " times"
14471392
}
1393+
let msg = \`Click me $\{times\}\`
14481394
1449-
<div> {React.string(\`Hello \$\{name\}, you clicked me \` ++ times)} </div>
1395+
<button onClick={_ => setCount(c => c + 1)}> {msg->React.string} </button>
14501396
}
14511397
}
14521398
14531399
module App = {
14541400
@react.component
14551401
let make = () => {
1456-
let (count, setCount) = React.useState(() => 0)
1457-
let (username, setUsername) = React.useState(() => "Anonymous")
1458-
1459-
<div>
1460-
{React.string("Username: ")}
1461-
<input
1462-
type_="text"
1463-
value={username}
1464-
onChange={evt => {
1465-
evt->ReactEvent.Form.preventDefault
1466-
let username = (evt->ReactEvent.Form.target)["value"]
1467-
setUsername(_prev => username)
1468-
}}
1469-
/>
1470-
<button
1471-
onClick={_evt => {
1472-
setCount(prev => prev + 1)
1473-
}}>
1474-
{React.string("Click me")}
1475-
</button>
1476-
<button onClick={_evt => setCount(_ => 0)}> {React.string("Reset")} </button>
1477-
<CounterMessage count username />
1478-
</div>
1402+
<Button />
14791403
}
14801404
}
1405+
14811406
`
14821407
}
14831408

@@ -1772,11 +1697,11 @@ let make = (~versions: array<string>) => {
17721697
"flex-1 items-center p-4 border-t-4 border-transparent " ++ activeClass
17731698
}
17741699

1775-
let tabs = [JavaScript, Console, Problems, Settings]
1700+
let tabs = [JavaScript, RenderOutput, Console, Problems, Settings]
17761701

17771702
let headers = Belt.Array.mapWithIndex(tabs, (i, tab) => {
17781703
let title = switch tab {
1779-
// | RenderOutput => "Render Output"
1704+
| RenderOutput => "Render Output"
17801705
| Console => "Console"
17811706
| JavaScript => "JavaScript"
17821707
| Problems => "Problems"

src/RenderPanel.res

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
let wrapReactApp = code =>
2+
`(function () {
3+
${code}
4+
if (!window.reactRoot){
5+
const container = document.getElementById("root");
6+
const root = ReactDOM.createRoot(container);
7+
window.reactRoot = root;
8+
}
9+
const appContainer$$ = () => App.make();
10+
window.reactRoot.render(appContainer$$());
11+
})();`
12+
13+
@react.component
14+
let make = (~compilerState: CompilerManagerHook.state, ~clearLogs, ~runOutput) => {
15+
React.useEffect(() => {
16+
if runOutput {
17+
switch compilerState {
18+
| CompilerManagerHook.Ready({result: Comp(Success({js_code}))}) =>
19+
clearLogs()
20+
let ast = AcornParse.parse(js_code)
21+
let transpiled = AcornParse.removeImportsAndExports(ast)
22+
switch AcornParse.hasEntryPoint(ast) {
23+
| true => transpiled->wrapReactApp->EvalIFrame.sendOutput
24+
| false => EvalIFrame.sendOutput(transpiled)
25+
}
26+
| _ => ()
27+
}
28+
}
29+
None
30+
}, (compilerState, runOutput))
31+
32+
<EvalIFrame />
33+
}

src/common/EvalIFrame.res

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ let css = `body {
44
color-scheme: light dark;
55
}`
66

7+
let reactVersion = "18.2.0"
8+
79
let srcDoc = `
810
<html>
911
<head>
@@ -41,18 +43,15 @@ let srcDoc = `
4143
let sendOutput = code => {
4244
open Webapi
4345

44-
let frame =
45-
Document.document
46-
->Element.getElementById("iframe-eval")
47-
->Js.Nullable.toOption
46+
let frame = Document.document->Element.getElementById("iframe-eval")
4847

4948
switch frame {
50-
| Some(element) =>
49+
| Value(element) =>
5150
switch element->Element.contentWindow {
5251
| Some(win) => win->Element.postMessage(code, ~targetOrigin="*")
53-
| None => ()
52+
| None => RescriptCore.Console.error("contentWindow not found")
5453
}
55-
| None => ()
54+
| Null | Undefined => RescriptCore.Console.error("iframe not found")
5655
}
5756
}
5857

src/common/RenderOutputManager.res

Lines changed: 0 additions & 21 deletions
This file was deleted.

0 commit comments

Comments
 (0)