refactoring
This commit is contained in:
@@ -11,7 +11,9 @@ module.exports = {
|
|||||||
{
|
{
|
||||||
files: [
|
files: [
|
||||||
'./**/*.ts',
|
'./**/*.ts',
|
||||||
|
'./**/*.tsx',
|
||||||
'./**/*.js',
|
'./**/*.js',
|
||||||
|
'./**/*.jsx',
|
||||||
'./**/*.vue',
|
'./**/*.vue',
|
||||||
],
|
],
|
||||||
plugins: [
|
plugins: [
|
||||||
@@ -27,6 +29,7 @@ module.exports = {
|
|||||||
window: false,
|
window: false,
|
||||||
},
|
},
|
||||||
extends: [
|
extends: [
|
||||||
|
'plugin:@typescript-eslint/eslint-recommended',
|
||||||
'plugin:@typescript-eslint/recommended',
|
'plugin:@typescript-eslint/recommended',
|
||||||
'plugin:vue/strongly-recommended',
|
'plugin:vue/strongly-recommended',
|
||||||
'airbnb-base',
|
'airbnb-base',
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ export class MentionList extends React.Component {
|
|||||||
componentDidUpdate(oldProps) {
|
componentDidUpdate(oldProps) {
|
||||||
if (this.props.items !== oldProps.items) {
|
if (this.props.items !== oldProps.items) {
|
||||||
this.setState({
|
this.setState({
|
||||||
selectedIndex: 0
|
selectedIndex: 0,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -39,13 +39,13 @@ export class MentionList extends React.Component {
|
|||||||
|
|
||||||
upHandler() {
|
upHandler() {
|
||||||
this.setState({
|
this.setState({
|
||||||
selectedIndex: ((this.state.selectedIndex + this.props.items.length) - 1) % this.props.items.length
|
selectedIndex: ((this.state.selectedIndex + this.props.items.length) - 1) % this.props.items.length,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
downHandler() {
|
downHandler() {
|
||||||
this.setState({
|
this.setState({
|
||||||
selectedIndex: (this.state.selectedIndex + 1) % this.props.items.length
|
selectedIndex: (this.state.selectedIndex + 1) % this.props.items.length,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -66,9 +66,9 @@ export default () => {
|
|||||||
reactRenderer.destroy()
|
reactRenderer.destroy()
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
})
|
}),
|
||||||
],
|
],
|
||||||
content: `
|
content: `
|
||||||
<p>
|
<p>
|
||||||
@@ -84,8 +84,8 @@ export default () => {
|
|||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<EditorContent editor={editor} />
|
<EditorContent editor={editor} />
|
||||||
{editor &&
|
{editor
|
||||||
<div className={`character-count ${editor.getCharacterCount() === limit ? 'character-count--warning' : ''}`}>
|
&& <div className={`character-count ${editor.getCharacterCount() === limit ? 'character-count--warning' : ''}`}>
|
||||||
<svg
|
<svg
|
||||||
height="20"
|
height="20"
|
||||||
width="20"
|
width="20"
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
|
/* eslint-disable */
|
||||||
import React, { useState } from 'react'
|
import React, { useState } from 'react'
|
||||||
import tippy from 'tippy.js'
|
import tippy from 'tippy.js'
|
||||||
import { useEditor, EditorContent, ReactRenderer, ReactNodeViewRenderer, NodeViewWrapper, NodeViewContent } from '@tiptap/react'
|
import {
|
||||||
|
useEditor, EditorContent, ReactRenderer, ReactNodeViewRenderer, NodeViewWrapper, NodeViewContent,
|
||||||
|
} from '@tiptap/react'
|
||||||
import { defaultExtensions } from '@tiptap/starter-kit'
|
import { defaultExtensions } from '@tiptap/starter-kit'
|
||||||
import Heading from '@tiptap/extension-heading'
|
import Heading from '@tiptap/extension-heading'
|
||||||
import Paragraph from '@tiptap/extension-paragraph'
|
import Paragraph from '@tiptap/extension-paragraph'
|
||||||
@@ -127,13 +130,13 @@ const MenuBar = ({ editor }) => {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const MentionList = (props) => {
|
const MentionList = props => {
|
||||||
console.log({props})
|
console.log({ props })
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
mentions
|
mentions
|
||||||
{props.items.map((item) => (
|
{props.items.map(item => (
|
||||||
<div>
|
<div>
|
||||||
{item}
|
{item}
|
||||||
</div>
|
</div>
|
||||||
@@ -174,7 +177,7 @@ export default () => {
|
|||||||
Heading.extend({
|
Heading.extend({
|
||||||
draggable: true,
|
draggable: true,
|
||||||
addNodeView() {
|
addNodeView() {
|
||||||
return ReactNodeViewRenderer((props) => {
|
return ReactNodeViewRenderer(props => {
|
||||||
return (
|
return (
|
||||||
<NodeViewWrapper>
|
<NodeViewWrapper>
|
||||||
<div className="heading">
|
<div className="heading">
|
||||||
@@ -193,7 +196,7 @@ export default () => {
|
|||||||
</NodeViewWrapper>
|
</NodeViewWrapper>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
},
|
||||||
}),
|
}),
|
||||||
Mention.configure({
|
Mention.configure({
|
||||||
suggestion: {
|
suggestion: {
|
||||||
@@ -238,45 +241,45 @@ export default () => {
|
|||||||
reactRenderer.destroy()
|
reactRenderer.destroy()
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
})
|
}),
|
||||||
],
|
],
|
||||||
content: `
|
content: `
|
||||||
<h1>heading</h1>
|
<h1>heading</h1>
|
||||||
<h2>heading</h2>
|
<h2>heading</h2>
|
||||||
<p>paragraph</p>
|
<p>paragraph</p>
|
||||||
`,
|
`,
|
||||||
// content: `
|
// content: `
|
||||||
// <h2>
|
// <h2>
|
||||||
// Hi there,
|
// Hi there,
|
||||||
// </h2>
|
// </h2>
|
||||||
// <p>
|
// <p>
|
||||||
// this is a basic <em>basic</em> example of <strong>tiptap</strong>. Sure, there are all kind of basic text styles you’d probably expect from a text editor. But wait until you see the lists:
|
// this is a basic <em>basic</em> example of <strong>tiptap</strong>. Sure, there are all kind of basic text styles you’d probably expect from a text editor. But wait until you see the lists:
|
||||||
// </p>
|
// </p>
|
||||||
// <ul>
|
// <ul>
|
||||||
// <li>
|
// <li>
|
||||||
// That’s a bullet list with one …
|
// That’s a bullet list with one …
|
||||||
// </li>
|
// </li>
|
||||||
// <li>
|
// <li>
|
||||||
// … or two list items.
|
// … or two list items.
|
||||||
// </li>
|
// </li>
|
||||||
// </ul>
|
// </ul>
|
||||||
// <p>
|
// <p>
|
||||||
// Isn’t that great? And all of that is editable. But wait, there’s more. Let’s try a code block:
|
// Isn’t that great? And all of that is editable. But wait, there’s more. Let’s try a code block:
|
||||||
// </p>
|
// </p>
|
||||||
// <pre><code class="language-css">body {
|
// <pre><code class="language-css">body {
|
||||||
// display: none;
|
// display: none;
|
||||||
// }</code></pre>
|
// }</code></pre>
|
||||||
// <p>
|
// <p>
|
||||||
// I know, I know, this is impressive. It’s only the tip of the iceberg though. Give it a try and click a little bit around. Don’t forget to check the other examples too.
|
// I know, I know, this is impressive. It’s only the tip of the iceberg though. Give it a try and click a little bit around. Don’t forget to check the other examples too.
|
||||||
// </p>
|
// </p>
|
||||||
// <blockquote>
|
// <blockquote>
|
||||||
// Wow, that’s amazing. Good work, boy! 👏
|
// Wow, that’s amazing. Good work, boy! 👏
|
||||||
// <br />
|
// <br />
|
||||||
// — Mom
|
// — Mom
|
||||||
// </blockquote>
|
// </blockquote>
|
||||||
// `,
|
// `,
|
||||||
})
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -112,6 +112,16 @@ export type ValuesOf<T> = T[keyof T];
|
|||||||
|
|
||||||
export type KeysWithTypeOf<T, Type> = ({[P in keyof T]: T[P] extends Type ? P : never })[keyof T]
|
export type KeysWithTypeOf<T, Type> = ({[P in keyof T]: T[P] extends Type ? P : never })[keyof T]
|
||||||
|
|
||||||
|
export type NodeViewProps = {
|
||||||
|
editor: Editor,
|
||||||
|
node: ProseMirrorNode,
|
||||||
|
decorations: Decoration[],
|
||||||
|
selected: boolean,
|
||||||
|
extension: Node,
|
||||||
|
getPos: () => number,
|
||||||
|
updateAttributes: (attributes: AnyObject) => void,
|
||||||
|
}
|
||||||
|
|
||||||
export type NodeViewRendererProps = {
|
export type NodeViewRendererProps = {
|
||||||
editor: Editor,
|
editor: Editor,
|
||||||
node: ProseMirrorNode,
|
node: ProseMirrorNode,
|
||||||
|
|||||||
@@ -1,5 +1,10 @@
|
|||||||
import React, { useState, useEffect } from 'react'
|
import React, { useState, useEffect } from 'react'
|
||||||
import { NodeView, NodeViewRenderer, NodeViewRendererProps } from '@tiptap/core'
|
import {
|
||||||
|
NodeView,
|
||||||
|
NodeViewProps,
|
||||||
|
NodeViewRenderer,
|
||||||
|
NodeViewRendererProps,
|
||||||
|
} from '@tiptap/core'
|
||||||
import { Decoration, NodeView as ProseMirrorNodeView } from 'prosemirror-view'
|
import { Decoration, NodeView as ProseMirrorNodeView } from 'prosemirror-view'
|
||||||
import { Node as ProseMirrorNode } from 'prosemirror-model'
|
import { Node as ProseMirrorNode } from 'prosemirror-model'
|
||||||
import { Editor } from './Editor'
|
import { Editor } from './Editor'
|
||||||
@@ -16,7 +21,7 @@ class ReactNodeView extends NodeView<React.FunctionComponent, Editor> {
|
|||||||
renderer!: ReactRenderer
|
renderer!: ReactRenderer
|
||||||
|
|
||||||
mount() {
|
mount() {
|
||||||
const props = {
|
const props: NodeViewProps = {
|
||||||
editor: this.editor,
|
editor: this.editor,
|
||||||
node: this.node,
|
node: this.node,
|
||||||
decorations: this.decorations,
|
decorations: this.decorations,
|
||||||
@@ -35,10 +40,11 @@ class ReactNodeView extends NodeView<React.FunctionComponent, Editor> {
|
|||||||
this.component.displayName = capitalizeFirstChar(this.extension.config.name)
|
this.component.displayName = capitalizeFirstChar(this.extension.config.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
const ReactNodeView: React.FunctionComponent = (props) => {
|
const ReactNodeViewProvider: React.FunctionComponent = componentProps => {
|
||||||
const [isEditable, setIsEditable] = useState(this.editor.isEditable)
|
const [isEditable, setIsEditable] = useState(this.editor.isEditable)
|
||||||
const onDragStart = this.onDragStart.bind(this)
|
const onDragStart = this.onDragStart.bind(this)
|
||||||
const onViewUpdate = () => setIsEditable(this.editor.isEditable)
|
const onViewUpdate = () => setIsEditable(this.editor.isEditable)
|
||||||
|
const Component = this.component
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
this.editor.on('viewUpdate', onViewUpdate)
|
this.editor.on('viewUpdate', onViewUpdate)
|
||||||
@@ -50,12 +56,14 @@ class ReactNodeView extends NodeView<React.FunctionComponent, Editor> {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<ReactNodeViewContext.Provider value={{ onDragStart, isEditable }}>
|
<ReactNodeViewContext.Provider value={{ onDragStart, isEditable }}>
|
||||||
<this.component {...props} />
|
<Component {...componentProps} />
|
||||||
</ReactNodeViewContext.Provider>
|
</ReactNodeViewContext.Provider>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
this.renderer = new ReactRenderer(ReactNodeView, {
|
ReactNodeViewProvider.displayName = 'ReactNodeView'
|
||||||
|
|
||||||
|
this.renderer = new ReactRenderer(ReactNodeViewProvider, {
|
||||||
editor: this.editor,
|
editor: this.editor,
|
||||||
props,
|
props,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -46,7 +46,9 @@ export class ReactRenderer {
|
|||||||
const props = this.props
|
const props = this.props
|
||||||
|
|
||||||
if (isClassComponent(Component)) {
|
if (isClassComponent(Component)) {
|
||||||
props.ref = (ref: React.Component) => this.ref = ref
|
props.ref = (ref: React.Component) => {
|
||||||
|
this.ref = ref
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.reactElement = <Component {...props } />
|
this.reactElement = <Component {...props } />
|
||||||
|
|||||||
@@ -1,4 +1,9 @@
|
|||||||
import { NodeView, NodeViewRenderer, NodeViewRendererProps } from '@tiptap/core'
|
import {
|
||||||
|
NodeView,
|
||||||
|
NodeViewProps,
|
||||||
|
NodeViewRenderer,
|
||||||
|
NodeViewRendererProps,
|
||||||
|
} from '@tiptap/core'
|
||||||
import { Decoration, NodeView as ProseMirrorNodeView } from 'prosemirror-view'
|
import { Decoration, NodeView as ProseMirrorNodeView } from 'prosemirror-view'
|
||||||
import { Node as ProseMirrorNode } from 'prosemirror-model'
|
import { Node as ProseMirrorNode } from 'prosemirror-model'
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
@@ -16,7 +21,7 @@ class VueNodeView extends NodeView<(Vue | VueConstructor), Editor> {
|
|||||||
renderer!: VueRenderer
|
renderer!: VueRenderer
|
||||||
|
|
||||||
mount() {
|
mount() {
|
||||||
const props = {
|
const props: NodeViewProps = {
|
||||||
editor: this.editor,
|
editor: this.editor,
|
||||||
node: this.node,
|
node: this.node,
|
||||||
decorations: this.decorations,
|
decorations: this.decorations,
|
||||||
|
|||||||
@@ -1,4 +1,9 @@
|
|||||||
import { NodeView, NodeViewRenderer, NodeViewRendererProps } from '@tiptap/core'
|
import {
|
||||||
|
NodeView,
|
||||||
|
NodeViewProps,
|
||||||
|
NodeViewRenderer,
|
||||||
|
NodeViewRendererProps,
|
||||||
|
} from '@tiptap/core'
|
||||||
import {
|
import {
|
||||||
ref,
|
ref,
|
||||||
provide,
|
provide,
|
||||||
@@ -20,7 +25,7 @@ class VueNodeView extends NodeView<Component, Editor> {
|
|||||||
renderer!: VueRenderer
|
renderer!: VueRenderer
|
||||||
|
|
||||||
mount() {
|
mount() {
|
||||||
const props = {
|
const props: NodeViewProps = {
|
||||||
editor: this.editor,
|
editor: this.editor,
|
||||||
node: this.node,
|
node: this.node,
|
||||||
decorations: this.decorations,
|
decorations: this.decorations,
|
||||||
|
|||||||
Reference in New Issue
Block a user