the next generation of the in-browser educational proof assistant
1open Component
2
3module TextArea = (Underlying: COMPONENT) => {
4 module Ports = Underlying.Ports
5 type props = {
6 content: result<Underlying.state, (string, string)>,
7 imports: Ports.t,
8 onChange: (result<Underlying.state, (string, string)>, ~exports: Ports.t=?) => unit,
9 }
10 type state = result<Underlying.state, (string, string)>
11
12 let serialise = state =>
13 switch state {
14 | Ok(s) => Underlying.serialise(s)
15 | Error((_err, str)) => str
16 }
17 let deserialise = (str: string, ~imports: Ports.t) => {
18 switch Underlying.deserialise(str, ~imports) {
19 | Ok((s, e)) => Ok(Ok(s), e)
20 | Error(e) => Ok(Error(e, str), Ports.empty)
21 }
22 }
23 let make = props => {
24 let (editing, setEditing) = React.useState(_ => false)
25 let (text, setText) = React.useState(_ => serialise(props.content))
26 let onTextChange = (ev: JsxEvent.Form.t) => {
27 let target = JsxEvent.Form.target(ev)
28 let value: string = target["value"]
29 setText(_ => value)
30 }
31 let done = _ => {
32 switch deserialise(text, ~imports=props.imports) {
33 | Ok((st, ex)) => props.onChange(st, ~exports=ex)
34 | Error(_e) => Console.log("Impossible happened")
35 }
36 setEditing(_ => false)
37 }
38 if editing {
39 <div>
40 <textarea className="editor-textArea" value={text} onChange={onTextChange} />
41 <div className="editor-controls">
42 <span
43 className="editor-button button-icon button-icon-blue typcn typcn-tick" onClick={done}
44 />
45 </div>
46 </div>
47 } else {
48 switch props.content {
49 | Ok(us) =>
50 <div>
51 <Underlying
52 content={us}
53 imports={props.imports}
54 /* onLoad={(~exports, ~string=?) =>
55 props.onLoad(~exports, ~string=string->Option.getOr(Underlying.serialise(us)))} */
56 onChange={(state, ~exports=?) => {
57 props.onChange(Ok(state), ~exports?)
58 }}
59 />
60 <div className="editor-controls">
61 <span
62 className="editor-button button-icon button-icon-blue typcn typcn-edit"
63 onClick={_ => {
64 setText(_ => serialise(props.content))
65 setEditing(_ => true)
66 }}
67 />
68 </div>
69 </div>
70 | Error((err, _str)) =>
71 <div>
72 <div className="error"> {React.string(err)} </div>
73 <div className="editor-controls">
74 <span
75 className="editor-button button-icon button-icon-blue typcn typcn-edit"
76 onClick={_ => {
77 setText(_ => serialise(props.content))
78 setEditing(_ => true)
79 }}
80 />
81 </div>
82 </div>
83 }
84 }
85 }
86}