Refactor React demo
This commit is contained in:
30
docs/src/demos/React/components/Editor.js
Normal file
30
docs/src/demos/React/components/Editor.js
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
import React, { useState, useRef, useEffect, createContext, useContext } from 'react'
|
||||||
|
import { Editor as Tiptap } from '@tiptap/core'
|
||||||
|
|
||||||
|
export const EditorContext = createContext({})
|
||||||
|
|
||||||
|
export const useEditor = () => useContext(EditorContext)
|
||||||
|
|
||||||
|
export const Editor = ({ value, onChange, children, ...props }) => {
|
||||||
|
const [editor, setEditor] = useState(null)
|
||||||
|
const editorRef = useRef(null)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const e = new Tiptap({
|
||||||
|
element: editorRef.current,
|
||||||
|
content: value,
|
||||||
|
...props,
|
||||||
|
}).on('transaction', () => {
|
||||||
|
onChange(e.json())
|
||||||
|
})
|
||||||
|
|
||||||
|
setEditor(e)
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<EditorContext.Provider value={editor}>
|
||||||
|
{editorRef.current && children}
|
||||||
|
<div ref={editorRef} />
|
||||||
|
</EditorContext.Provider>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -1,40 +1,69 @@
|
|||||||
import React, { Component } from 'react'
|
import React, { useState } from 'react'
|
||||||
import { Editor } from '@tiptap/core'
|
import { useEditor, Editor } from './components/Editor'
|
||||||
import extensions from '@tiptap/starter-kit'
|
import extensions from '@tiptap/starter-kit'
|
||||||
|
|
||||||
export default class extends Component {
|
// Menu bar example component
|
||||||
constructor() {
|
// useEditor only works for child components of <Editor />
|
||||||
super()
|
const MenuBar = () => {
|
||||||
this.editorNode = React.createRef()
|
const editor = useEditor()
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount() {
|
return (
|
||||||
this.editor = new Editor({
|
<>
|
||||||
element: this.editorNode.current,
|
<button onClick={() => editor.focus().removeMarks()}>
|
||||||
content: '<p>rendered in <strong>react</strong>!</p>',
|
Clear formatting
|
||||||
extensions: extensions(),
|
</button>
|
||||||
})
|
<button
|
||||||
this.forceUpdate()
|
className={`${editor.isActive('bold') ? 'is-active' : ''}`}
|
||||||
}
|
onClick={() => editor.focus().bold()}
|
||||||
|
>
|
||||||
render() {
|
Bold
|
||||||
return (
|
</button>
|
||||||
<div>
|
</>
|
||||||
{this.editor &&
|
)
|
||||||
<div>
|
}
|
||||||
<button onClick={() => this.editor.focus().removeMarks()}>
|
|
||||||
clear formatting
|
export default () => {
|
||||||
</button>
|
const [value, setValue] = useState({
|
||||||
<button
|
'type': 'document',
|
||||||
onClick={() => this.editor.focus().bold()}
|
'content': [
|
||||||
className={`${this.editor.isActive('bold') ? 'is-active' : ''}`}
|
{
|
||||||
>
|
'type': 'paragraph',
|
||||||
bold
|
'content': [
|
||||||
</button>
|
{
|
||||||
</div>
|
'type': 'text',
|
||||||
}
|
'text': 'rendered in '
|
||||||
<div ref={this.editorNode} />
|
},
|
||||||
</div>
|
{
|
||||||
)
|
'type': 'text',
|
||||||
}
|
'marks': [
|
||||||
|
{
|
||||||
|
'type': 'bold'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'text': 'react'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'type': 'text',
|
||||||
|
'text': '!'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<p>
|
||||||
|
<button onClick={() => alert(JSON.stringify(value))}>Alert state</button>
|
||||||
|
</p>
|
||||||
|
<hr style={{ margin: '0.85rem 0'}} />
|
||||||
|
<Editor
|
||||||
|
value={value}
|
||||||
|
onChange={setValue}
|
||||||
|
extensions={extensions()}
|
||||||
|
>
|
||||||
|
<MenuBar />
|
||||||
|
</Editor>
|
||||||
|
</>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user