-
Notifications
You must be signed in to change notification settings - Fork 51
/
App.tsx
119 lines (104 loc) · 3 KB
/
App.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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
// eslint-disable-next-line simple-import-sort/imports
import {
plugins,
schema,
toolbar,
} from '@aeaton/react-prosemirror-config-default'
import {
ChangeHandler,
Editor,
EditorProvider,
Floater,
HtmlEditor,
Toolbar,
useDebounce,
} from '@aeaton/react-prosemirror'
import {
createHTMLTransformer,
createJSONTransformer,
createNullTransformer,
} from '@aeaton/prosemirror-transformers'
import { Node as ProsemirrorNode } from 'prosemirror-model'
import React, { useMemo, useState } from 'react'
import './styles/demo.css'
import './styles/prosemirror.css'
const htmlTransformer = createHTMLTransformer(schema)
const jsonTransformer = createJSONTransformer(schema)
const nullTransformer = createNullTransformer()
const initialValue = `<p></p>`
const initialDoc = htmlTransformer.parse(initialValue)
const floatingTools = toolbar.slice(0, 2)
const fixedTools = toolbar.slice(2)
// TODO: nodeviews, perhaps displaying a node type switcher alongside each node?
export const App: React.FC = () => {
const [doc, setDoc] = useState<ProsemirrorNode>(initialDoc)
const [html, setHTML] = useState<string>(initialValue)
return (
<div>
<div className="prosemirror-demo">
<div className="prosemirror-demo-editor">
<HtmlEditor
schema={schema}
plugins={plugins}
value={initialValue}
handleChange={setHTML}
debounce={1000}
>
<Toolbar toolbar={toolbar} />
<Editor autoFocus />
</HtmlEditor>
</div>
<div className="prosemirror-demo-output">
<pre>{html}</pre>
</div>
</div>
<div className="prosemirror-demo">
<div className="prosemirror-demo-editor">
<EditorProvider plugins={plugins} doc={initialDoc}>
<ChangeHandler
handleChange={setDoc}
transformer={nullTransformer}
/>
<Toolbar toolbar={fixedTools} />
<Floater>
<Toolbar toolbar={floatingTools} />
</Floater>
<Editor autoFocus />
</EditorProvider>
</div>
{doc !== undefined && (
<div className="prosemirror-demo-output">
<JSONOutput doc={doc} />
<HTMLOutput doc={doc} />
</div>
)}
</div>
</div>
)
}
const JSONOutput: React.FC<{ doc: ProsemirrorNode }> = ({ doc }) => {
const debouncedDoc = useDebounce(doc, 1000)
const json = useMemo(() => jsonTransformer.serialize(debouncedDoc), [
debouncedDoc,
])
return (
<div className="output">
<pre>{json}</pre>
</div>
)
}
const HTMLOutput: React.FC<{ doc: ProsemirrorNode }> = ({ doc }) => {
const [html, setHTML] = useState('')
// serialize when the button is clicked
const handleClick = () => {
setHTML(htmlTransformer.serialize(doc))
}
return (
<div className="output">
<button type="button" onClick={handleClick}>
Show HTML
</button>
<pre>{html}</pre>
</div>
)
}