Merge branch 'main' of github.com:ueberdosis/tiptap-next into main

This commit is contained in:
Hans Pagel
2021-03-09 11:18:05 +01:00
43 changed files with 688 additions and 315 deletions

View File

@@ -5,5 +5,6 @@ module.exports = {
],
plugins: [
'@babel/plugin-proposal-optional-chaining',
'@babel/plugin-proposal-class-properties',
],
}

View File

@@ -57,6 +57,7 @@ module.exports = function (api) {
api.chainWebpack(config => {
config.resolve.extensions
.add('.ts')
.add('.tsx')
.add('.jsx')
config.module

View File

@@ -35,7 +35,9 @@
"yjs": "^13.5.1"
},
"devDependencies": {
"@babel/plugin-proposal-class-properties": "^7.13.0",
"@babel/plugin-proposal-optional-chaining": "^7.13.0",
"@babel/plugin-syntax-class-properties": "^7.12.13",
"@babel/preset-env": "^7.13.5",
"@babel/preset-react": "^7.12.13",
"html-loader": "^1.3.2",

View File

@@ -1,35 +1,36 @@
import React, { useState } from 'react'
import React from 'react'
import { useEditor, EditorContent } from '@tiptap/react'
import { defaultExtensions } from '@tiptap/starter-kit'
import { useEditor, Editor } from '@tiptap/react'
import './styles.scss'
// useEditor only works for child components of <Editor />
const MenuBar = () => {
const editor = useEditor()
const MenuBar = ({ editor }) => {
if (!editor) {
return null
}
return (
<>
<button
onClick={() => editor.chain().focus().toggleBold().run()}
className={`${editor.isActive('bold') ? 'is-active' : ''}`}
className={editor.isActive('bold') ? 'is-active' : ''}
>
bold
</button>
<button
onClick={() => editor.chain().focus().toggleItalic().run()}
className={`${editor.isActive('italic') ? 'active' : ''}`}
className={editor.isActive('italic') ? 'is-active' : ''}
>
italic
</button>
<button
onClick={() => editor.chain().focus().toggleStrike().run()}
className={`${editor.isActive('strike') ? 'active' : ''}`}
className={editor.isActive('strike') ? 'is-active' : ''}
>
strike
</button>
<button
onClick={() => editor.chain().focus().toggleCode().run()}
className={`${editor.isActive('code') ? 'active' : ''}`}
className={editor.isActive('code') ? 'is-active' : ''}
>
code
</button>
@@ -41,67 +42,67 @@ const MenuBar = () => {
</button>
<button
onClick={() => editor.chain().focus().setParagraph().run()}
className={`${editor.isActive('paragraph') ? 'active' : ''}`}
className={editor.isActive('paragraph') ? 'is-active' : ''}
>
paragraph
</button>
<button
onClick={() => editor.chain().focus().toggleHeading({ level: 1 }).run()}
className={`${editor.isActive('heading', { level: 1 }) ? 'active' : ''}`}
className={editor.isActive('heading', { level: 1 }) ? 'is-active' : ''}
>
h1
</button>
<button
onClick={() => editor.chain().focus().toggleHeading({ level: 2 }).run()}
className={`${editor.isActive('heading', { level: 2 }) ? 'active' : ''}`}
className={editor.isActive('heading', { level: 2 }) ? 'is-active' : ''}
>
h2
</button>
<button
onClick={() => editor.chain().focus().toggleHeading({ level: 3 }).run()}
className={`${editor.isActive('heading', { level: 3 }) ? 'active' : ''}`}
className={editor.isActive('heading', { level: 3 }) ? 'is-active' : ''}
>
h3
</button>
<button
onClick={() => editor.chain().focus().toggleHeading({ level: 4 }).run()}
className={`${editor.isActive('heading', { level: 4 }) ? 'active' : ''}`}
className={editor.isActive('heading', { level: 4 }) ? 'is-active' : ''}
>
h4
</button>
<button
onClick={() => editor.chain().focus().toggleHeading({ level: 5 }).run()}
className={`${editor.isActive('heading', { level: 5 }) ? 'active' : ''}`}
className={editor.isActive('heading', { level: 5 }) ? 'is-active' : ''}
>
h5
</button>
<button
onClick={() => editor.chain().focus().toggleHeading({ level: 6 }).run()}
className={`${editor.isActive('heading', { level: 6 }) ? 'active' : ''}`}
className={editor.isActive('heading', { level: 6 }) ? 'is-active' : ''}
>
h6
</button>
<button
onClick={() => editor.chain().focus().toggleBulletList().run()}
className={`${editor.isActive('bulletList') ? 'active' : ''}`}
className={editor.isActive('bulletList') ? 'is-active' : ''}
>
bullet list
</button>
<button
onClick={() => editor.chain().focus().toggleOrderedList().run()}
className={`${editor.isActive('orderedList') ? 'active' : ''}`}
className={editor.isActive('orderedList') ? 'is-active' : ''}
>
ordered list
</button>
<button
onClick={() => editor.chain().focus().toggleCodeBlock().run()}
className={`${editor.isActive('codeBlock') ? 'active' : ''}`}
className={editor.isActive('codeBlock') ? 'is-active' : ''}
>
code block
</button>
<button
onClick={() => editor.chain().focus().toggleBlockquote().run()}
className={`${editor.isActive('blockquote') ? 'active' : ''}`}
className={editor.isActive('blockquote') ? 'is-active' : ''}
>
blockquote
</button>
@@ -122,46 +123,46 @@ const MenuBar = () => {
}
export default () => {
const [value, setValue] = useState(`
<h2>
Hi there,
</h2>
<p>
this is a basic <em>basic</em> example of <strong>tiptap</strong>. Sure, there are all kind of basic text styles youd probably expect from a text editor. But wait until you see the lists:
</p>
<ul>
<li>
Thats a bullet list with one …
</li>
<li>
… or two list items.
</li>
</ul>
<p>
Isnt that great? And all of that is editable. But wait, theres more. Lets try a code block:
</p>
<pre><code class="language-css">body {
const editor = useEditor({
extensions: [
...defaultExtensions(),
],
content: `
<h2>
Hi there,
</h2>
<p>
this is a basic <em>basic</em> example of <strong>tiptap</strong>. Sure, there are all kind of basic text styles youd probably expect from a text editor. But wait until you see the lists:
</p>
<ul>
<li>
Thats a bullet list with one …
</li>
<li>
or two list items.
</li>
</ul>
<p>
Isnt that great? And all of that is editable. But wait, theres more. Lets try a code block:
</p>
<pre><code class="language-css">body {
display: none;
}</code></pre>
<p>
I know, I know, this is impressive. Its only the tip of the iceberg though. Give it a try and click a little bit around. Dont forget to check the other examples too.
</p>
<blockquote>
Wow, thats amazing. Good work, boy! 👏
<br />
— Mom
</blockquote>
`)
<p>
I know, I know, this is impressive. Its only the tip of the iceberg though. Give it a try and click a little bit around. Dont forget to check the other examples too.
</p>
<blockquote>
Wow, thats amazing. Good work, boy! 👏
<br />
— Mom
</blockquote>
`,
})
return (
<>
<Editor
value={value}
onChange={setValue}
extensions={defaultExtensions()}
>
<MenuBar />
</Editor>
</>
<div>
<MenuBar editor={editor} />
<EditorContent editor={editor} />
</div>
)
}

View File

@@ -1,34 +0,0 @@
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.getJSON())
})
setEditor(e)
}, [])
return (
<EditorContext.Provider value={editor}>
{editorRef.current && children}
<div ref={editorRef} />
</EditorContext.Provider>
)
}

View File

@@ -1,69 +0,0 @@
import React, { useState } from 'react'
import { defaultExtensions } from '@tiptap/starter-kit'
import { useEditor, Editor } from '@tiptap/react'
// Menu bar example component
// useEditor only works for child components of <Editor />
const MenuBar = () => {
const editor = useEditor()
return (
<>
<button onClick={() => editor.chain().focus().unsetAllMarks().run()}>
Clear formatting
</button>
<button
className={`${editor.isActive('bold') ? 'is-active' : ''}`}
onClick={() => editor.chain().focus().toggleBold().run()}
>
Bold
</button>
</>
)
}
export default () => {
const [value, setValue] = useState({
type: 'doc',
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'rendered in ',
},
{
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={defaultExtensions()}
>
<MenuBar />
</Editor>
</>
)
}

View File

@@ -47,10 +47,14 @@ editor.on('update', () => {
// The content has changed.
}
editor.on('selection', () => {
editor.on('selectionUpdate', () => {
// The selection has changed.
}
editor.on('viewUpdate', () => {
// The view has changed.
}
editor.on('transaction', ({ transaction }) => {
// The editor state has changed.
}

View File

@@ -7,4 +7,4 @@ The following guide describes how to integrate tiptap with your [React](https://
TODO
<demo name="React" />
<demo name="Examples/Default/React" />