@tiptap/react 2.0.0-beta.7 → 2.0.0-beta.70
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +1 -1
- package/README.md +2 -2
- package/dist/packages/react/src/BubbleMenu.d.ts +3 -1
- package/dist/packages/react/src/EditorContent.d.ts +2 -2
- package/dist/packages/react/src/FloatingMenu.d.ts +8 -0
- package/dist/packages/react/src/NodeViewContent.d.ts +2 -2
- package/dist/packages/react/src/NodeViewWrapper.d.ts +2 -2
- package/dist/packages/react/src/ReactNodeViewRenderer.d.ts +9 -5
- package/dist/packages/react/src/ReactRenderer.d.ts +10 -6
- package/dist/packages/react/src/index.d.ts +1 -0
- package/dist/packages/react/src/useEditor.d.ts +2 -1
- package/dist/packages/react/src/useReactNodeView.d.ts +1 -1
- package/dist/tiptap-react.cjs.js +104 -40
- package/dist/tiptap-react.cjs.js.map +1 -1
- package/dist/tiptap-react.esm.js +105 -42
- package/dist/tiptap-react.esm.js.map +1 -1
- package/dist/tiptap-react.umd.js +107 -44
- package/dist/tiptap-react.umd.js.map +1 -1
- package/package.json +17 -9
- package/src/BubbleMenu.tsx +15 -6
- package/src/EditorContent.tsx +8 -7
- package/src/FloatingMenu.tsx +39 -0
- package/src/NodeViewContent.tsx +16 -9
- package/src/NodeViewWrapper.tsx +11 -9
- package/src/ReactNodeViewRenderer.tsx +70 -23
- package/src/ReactRenderer.tsx +19 -8
- package/src/index.ts +1 -0
- package/src/useEditor.ts +3 -3
- package/src/useReactNodeView.ts +1 -2
- package/CHANGELOG.md +0 -64
- package/dist/tiptap-react.bundle.umd.min.js +0 -54
- package/dist/tiptap-react.bundle.umd.min.js.map +0 -1
package/src/NodeViewWrapper.tsx
CHANGED
|
@@ -2,22 +2,24 @@ import React from 'react'
|
|
|
2
2
|
import { useReactNodeView } from './useReactNodeView'
|
|
3
3
|
|
|
4
4
|
export interface NodeViewWrapperProps {
|
|
5
|
-
|
|
6
|
-
as
|
|
5
|
+
[key: string]: any,
|
|
6
|
+
as?: React.ElementType,
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
-
export const NodeViewWrapper: React.FC<NodeViewWrapperProps> = props => {
|
|
9
|
+
export const NodeViewWrapper: React.FC<NodeViewWrapperProps> = React.forwardRef((props, ref) => {
|
|
10
10
|
const { onDragStart } = useReactNodeView()
|
|
11
11
|
const Tag = props.as || 'div'
|
|
12
12
|
|
|
13
13
|
return (
|
|
14
14
|
<Tag
|
|
15
|
-
|
|
15
|
+
{...props}
|
|
16
|
+
ref={ref}
|
|
16
17
|
data-node-view-wrapper=""
|
|
17
18
|
onDragStart={onDragStart}
|
|
18
|
-
style={{
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
style={{
|
|
20
|
+
...props.style,
|
|
21
|
+
whiteSpace: 'normal',
|
|
22
|
+
}}
|
|
23
|
+
/>
|
|
22
24
|
)
|
|
23
|
-
}
|
|
25
|
+
})
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import React
|
|
1
|
+
import React from 'react'
|
|
2
2
|
import {
|
|
3
3
|
NodeView,
|
|
4
4
|
NodeViewProps,
|
|
5
5
|
NodeViewRenderer,
|
|
6
6
|
NodeViewRendererProps,
|
|
7
|
+
NodeViewRendererOptions,
|
|
7
8
|
} from '@tiptap/core'
|
|
8
9
|
import { Decoration, NodeView as ProseMirrorNodeView } from 'prosemirror-view'
|
|
9
10
|
import { Node as ProseMirrorNode } from 'prosemirror-model'
|
|
@@ -11,15 +12,22 @@ import { Editor } from './Editor'
|
|
|
11
12
|
import { ReactRenderer } from './ReactRenderer'
|
|
12
13
|
import { ReactNodeViewContext } from './useReactNodeView'
|
|
13
14
|
|
|
14
|
-
interface ReactNodeViewRendererOptions {
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
export interface ReactNodeViewRendererOptions extends NodeViewRendererOptions {
|
|
16
|
+
update: ((props: {
|
|
17
|
+
oldNode: ProseMirrorNode,
|
|
18
|
+
oldDecorations: Decoration[],
|
|
19
|
+
newNode: ProseMirrorNode,
|
|
20
|
+
newDecorations: Decoration[],
|
|
21
|
+
updateProps: () => void,
|
|
22
|
+
}) => boolean) | null,
|
|
17
23
|
}
|
|
18
24
|
|
|
19
|
-
class ReactNodeView extends NodeView<React.FunctionComponent, Editor> {
|
|
25
|
+
class ReactNodeView extends NodeView<React.FunctionComponent, Editor, ReactNodeViewRendererOptions> {
|
|
20
26
|
|
|
21
27
|
renderer!: ReactRenderer
|
|
22
28
|
|
|
29
|
+
contentDOMElement!: HTMLElement | null
|
|
30
|
+
|
|
23
31
|
mount() {
|
|
24
32
|
const props: NodeViewProps = {
|
|
25
33
|
editor: this.editor,
|
|
@@ -29,6 +37,7 @@ class ReactNodeView extends NodeView<React.FunctionComponent, Editor> {
|
|
|
29
37
|
extension: this.extension,
|
|
30
38
|
getPos: () => this.getPos(),
|
|
31
39
|
updateAttributes: (attributes = {}) => this.updateAttributes(attributes),
|
|
40
|
+
deleteNode: () => this.deleteNode(),
|
|
32
41
|
}
|
|
33
42
|
|
|
34
43
|
if (!(this.component as any).displayName) {
|
|
@@ -36,26 +45,16 @@ class ReactNodeView extends NodeView<React.FunctionComponent, Editor> {
|
|
|
36
45
|
return string.charAt(0).toUpperCase() + string.substring(1)
|
|
37
46
|
}
|
|
38
47
|
|
|
39
|
-
|
|
40
|
-
this.component.displayName = capitalizeFirstChar(this.extension.config.name)
|
|
48
|
+
this.component.displayName = capitalizeFirstChar(this.extension.name)
|
|
41
49
|
}
|
|
42
50
|
|
|
43
51
|
const ReactNodeViewProvider: React.FunctionComponent = componentProps => {
|
|
44
|
-
const [isEditable, setIsEditable] = useState(this.editor.isEditable)
|
|
45
52
|
const onDragStart = this.onDragStart.bind(this)
|
|
46
|
-
const
|
|
53
|
+
const maybeMoveContentDOM = this.maybeMoveContentDOM.bind(this)
|
|
47
54
|
const Component = this.component
|
|
48
55
|
|
|
49
|
-
useEffect(() => {
|
|
50
|
-
this.editor.on('viewUpdate', onViewUpdate)
|
|
51
|
-
|
|
52
|
-
return () => {
|
|
53
|
-
this.editor.off('viewUpdate', onViewUpdate)
|
|
54
|
-
}
|
|
55
|
-
}, [])
|
|
56
|
-
|
|
57
56
|
return (
|
|
58
|
-
<ReactNodeViewContext.Provider value={{ onDragStart,
|
|
57
|
+
<ReactNodeViewContext.Provider value={{ onDragStart, maybeMoveContentDOM }}>
|
|
59
58
|
<Component {...componentProps} />
|
|
60
59
|
</ReactNodeViewContext.Provider>
|
|
61
60
|
)
|
|
@@ -63,15 +62,32 @@ class ReactNodeView extends NodeView<React.FunctionComponent, Editor> {
|
|
|
63
62
|
|
|
64
63
|
ReactNodeViewProvider.displayName = 'ReactNodeView'
|
|
65
64
|
|
|
65
|
+
this.contentDOMElement = this.node.isLeaf
|
|
66
|
+
? null
|
|
67
|
+
: document.createElement(this.node.isInline ? 'span' : 'div')
|
|
68
|
+
|
|
69
|
+
if (this.contentDOMElement) {
|
|
70
|
+
// For some reason the whiteSpace prop is not inherited properly in Chrome and Safari
|
|
71
|
+
// With this fix it seems to work fine
|
|
72
|
+
// See: https://github.com/ueberdosis/tiptap/issues/1197
|
|
73
|
+
this.contentDOMElement.style.whiteSpace = 'inherit'
|
|
74
|
+
}
|
|
75
|
+
|
|
66
76
|
this.renderer = new ReactRenderer(ReactNodeViewProvider, {
|
|
67
77
|
editor: this.editor,
|
|
68
78
|
props,
|
|
79
|
+
as: this.node.isInline
|
|
80
|
+
? 'span'
|
|
81
|
+
: 'div',
|
|
69
82
|
})
|
|
70
83
|
}
|
|
71
84
|
|
|
72
85
|
get dom() {
|
|
73
|
-
if (
|
|
74
|
-
|
|
86
|
+
if (
|
|
87
|
+
this.renderer.element.firstElementChild
|
|
88
|
+
&& !this.renderer.element.firstElementChild?.hasAttribute('data-node-view-wrapper')
|
|
89
|
+
) {
|
|
90
|
+
throw Error('Please use the NodeViewWrapper component for your node view.')
|
|
75
91
|
}
|
|
76
92
|
|
|
77
93
|
return this.renderer.element
|
|
@@ -82,14 +98,43 @@ class ReactNodeView extends NodeView<React.FunctionComponent, Editor> {
|
|
|
82
98
|
return null
|
|
83
99
|
}
|
|
84
100
|
|
|
101
|
+
this.maybeMoveContentDOM()
|
|
102
|
+
|
|
103
|
+
return this.contentDOMElement
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
maybeMoveContentDOM(): void {
|
|
85
107
|
const contentElement = this.dom.querySelector('[data-node-view-content]')
|
|
86
108
|
|
|
87
|
-
|
|
109
|
+
if (
|
|
110
|
+
this.contentDOMElement
|
|
111
|
+
&& contentElement
|
|
112
|
+
&& !contentElement.contains(this.contentDOMElement)
|
|
113
|
+
) {
|
|
114
|
+
contentElement.appendChild(this.contentDOMElement)
|
|
115
|
+
}
|
|
88
116
|
}
|
|
89
117
|
|
|
90
118
|
update(node: ProseMirrorNode, decorations: Decoration[]) {
|
|
119
|
+
const updateProps = (props?: Record<string, any>) => {
|
|
120
|
+
this.renderer.updateProps(props)
|
|
121
|
+
this.maybeMoveContentDOM()
|
|
122
|
+
}
|
|
123
|
+
|
|
91
124
|
if (typeof this.options.update === 'function') {
|
|
92
|
-
|
|
125
|
+
const oldNode = this.node
|
|
126
|
+
const oldDecorations = this.decorations
|
|
127
|
+
|
|
128
|
+
this.node = node
|
|
129
|
+
this.decorations = decorations
|
|
130
|
+
|
|
131
|
+
return this.options.update({
|
|
132
|
+
oldNode,
|
|
133
|
+
oldDecorations,
|
|
134
|
+
newNode: node,
|
|
135
|
+
newDecorations: decorations,
|
|
136
|
+
updateProps: () => updateProps({ node, decorations }),
|
|
137
|
+
})
|
|
93
138
|
}
|
|
94
139
|
|
|
95
140
|
if (node.type !== this.node.type) {
|
|
@@ -102,7 +147,8 @@ class ReactNodeView extends NodeView<React.FunctionComponent, Editor> {
|
|
|
102
147
|
|
|
103
148
|
this.node = node
|
|
104
149
|
this.decorations = decorations
|
|
105
|
-
|
|
150
|
+
|
|
151
|
+
updateProps({ node, decorations })
|
|
106
152
|
|
|
107
153
|
return true
|
|
108
154
|
}
|
|
@@ -121,6 +167,7 @@ class ReactNodeView extends NodeView<React.FunctionComponent, Editor> {
|
|
|
121
167
|
|
|
122
168
|
destroy() {
|
|
123
169
|
this.renderer.destroy()
|
|
170
|
+
this.contentDOMElement = null
|
|
124
171
|
}
|
|
125
172
|
}
|
|
126
173
|
|
package/src/ReactRenderer.tsx
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
|
-
import { AnyObject } from '@tiptap/core'
|
|
3
2
|
import { Editor } from './Editor'
|
|
4
3
|
|
|
5
4
|
function isClassComponent(Component: any) {
|
|
@@ -10,12 +9,24 @@ function isClassComponent(Component: any) {
|
|
|
10
9
|
)
|
|
11
10
|
}
|
|
12
11
|
|
|
12
|
+
function isForwardRefComponent(Component: any) {
|
|
13
|
+
return !!(
|
|
14
|
+
typeof Component === 'object'
|
|
15
|
+
&& Component.$$typeof?.toString() === 'Symbol(react.forward_ref)'
|
|
16
|
+
)
|
|
17
|
+
}
|
|
18
|
+
|
|
13
19
|
export interface ReactRendererOptions {
|
|
14
|
-
as?: string,
|
|
15
20
|
editor: Editor,
|
|
16
|
-
props?:
|
|
21
|
+
props?: Record<string, any>,
|
|
22
|
+
as?: string,
|
|
17
23
|
}
|
|
18
24
|
|
|
25
|
+
type ComponentType =
|
|
26
|
+
| React.ComponentClass
|
|
27
|
+
| React.FunctionComponent
|
|
28
|
+
| React.ForwardRefExoticComponent<{ items: any[], command: any } & React.RefAttributes<unknown>>
|
|
29
|
+
|
|
19
30
|
export class ReactRenderer {
|
|
20
31
|
id: string
|
|
21
32
|
|
|
@@ -25,18 +36,18 @@ export class ReactRenderer {
|
|
|
25
36
|
|
|
26
37
|
element: Element
|
|
27
38
|
|
|
28
|
-
props:
|
|
39
|
+
props: Record<string, any>
|
|
29
40
|
|
|
30
41
|
reactElement: React.ReactNode
|
|
31
42
|
|
|
32
43
|
ref: React.Component | null = null
|
|
33
44
|
|
|
34
|
-
constructor(component:
|
|
45
|
+
constructor(component: ComponentType, { editor, props = {}, as = 'div' }: ReactRendererOptions) {
|
|
35
46
|
this.id = Math.floor(Math.random() * 0xFFFFFFFF).toString()
|
|
36
47
|
this.component = component
|
|
37
48
|
this.editor = editor
|
|
38
49
|
this.props = props
|
|
39
|
-
this.element = document.createElement(
|
|
50
|
+
this.element = document.createElement(as)
|
|
40
51
|
this.element.classList.add('react-renderer')
|
|
41
52
|
this.render()
|
|
42
53
|
}
|
|
@@ -45,7 +56,7 @@ export class ReactRenderer {
|
|
|
45
56
|
const Component = this.component
|
|
46
57
|
const props = this.props
|
|
47
58
|
|
|
48
|
-
if (isClassComponent(Component)) {
|
|
59
|
+
if (isClassComponent(Component) || isForwardRefComponent(Component)) {
|
|
49
60
|
props.ref = (ref: React.Component) => {
|
|
50
61
|
this.ref = ref
|
|
51
62
|
}
|
|
@@ -63,7 +74,7 @@ export class ReactRenderer {
|
|
|
63
74
|
}
|
|
64
75
|
}
|
|
65
76
|
|
|
66
|
-
updateProps(props:
|
|
77
|
+
updateProps(props: Record<string, any> = {}): void {
|
|
67
78
|
this.props = {
|
|
68
79
|
...this.props,
|
|
69
80
|
...props,
|
package/src/index.ts
CHANGED
package/src/useEditor.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useState, useEffect } from 'react'
|
|
1
|
+
import { useState, useEffect, DependencyList } from 'react'
|
|
2
2
|
import { EditorOptions } from '@tiptap/core'
|
|
3
3
|
import { Editor } from './Editor'
|
|
4
4
|
|
|
@@ -8,7 +8,7 @@ function useForceUpdate() {
|
|
|
8
8
|
return () => setValue(value => value + 1)
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
export const useEditor = (options: Partial<EditorOptions> = {}) => {
|
|
11
|
+
export const useEditor = (options: Partial<EditorOptions> = {}, deps: DependencyList = []) => {
|
|
12
12
|
const [editor, setEditor] = useState<Editor | null>(null)
|
|
13
13
|
const forceUpdate = useForceUpdate()
|
|
14
14
|
|
|
@@ -22,7 +22,7 @@ export const useEditor = (options: Partial<EditorOptions> = {}) => {
|
|
|
22
22
|
return () => {
|
|
23
23
|
instance.destroy()
|
|
24
24
|
}
|
|
25
|
-
},
|
|
25
|
+
}, deps)
|
|
26
26
|
|
|
27
27
|
return editor
|
|
28
28
|
}
|
package/src/useReactNodeView.ts
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import { createContext, useContext } from 'react'
|
|
2
2
|
|
|
3
3
|
export interface ReactNodeViewContextProps {
|
|
4
|
-
isEditable: boolean,
|
|
5
4
|
onDragStart: (event: DragEvent) => void,
|
|
5
|
+
maybeMoveContentDOM: () => void,
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
export const ReactNodeViewContext = createContext<Partial<ReactNodeViewContextProps>>({
|
|
9
|
-
isEditable: undefined,
|
|
10
9
|
onDragStart: undefined,
|
|
11
10
|
})
|
|
12
11
|
|
package/CHANGELOG.md
DELETED
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
# Change Log
|
|
2
|
-
|
|
3
|
-
All notable changes to this project will be documented in this file.
|
|
4
|
-
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
|
-
|
|
6
|
-
# [2.0.0-beta.7](https://github.com/ueberdosis/tiptap-next/compare/@tiptap/react@2.0.0-beta.6...@tiptap/react@2.0.0-beta.7) (2021-03-31)
|
|
7
|
-
|
|
8
|
-
**Note:** Version bump only for package @tiptap/react
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
# [2.0.0-beta.6](https://github.com/ueberdosis/tiptap-next/compare/@tiptap/react@2.0.0-beta.5...@tiptap/react@2.0.0-beta.6) (2021-03-28)
|
|
15
|
-
|
|
16
|
-
**Note:** Version bump only for package @tiptap/react
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
# [2.0.0-beta.5](https://github.com/ueberdosis/tiptap-next/compare/@tiptap/react@2.0.0-beta.4...@tiptap/react@2.0.0-beta.5) (2021-03-24)
|
|
23
|
-
|
|
24
|
-
**Note:** Version bump only for package @tiptap/react
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
# [2.0.0-beta.4](https://github.com/ueberdosis/tiptap-next/compare/@tiptap/react@2.0.0-beta.3...@tiptap/react@2.0.0-beta.4) (2021-03-18)
|
|
31
|
-
|
|
32
|
-
**Note:** Version bump only for package @tiptap/react
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
# [2.0.0-beta.3](https://github.com/ueberdosis/tiptap-next/compare/@tiptap/react@2.0.0-beta.2...@tiptap/react@2.0.0-beta.3) (2021-03-16)
|
|
39
|
-
|
|
40
|
-
**Note:** Version bump only for package @tiptap/react
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
# [2.0.0-beta.2](https://github.com/ueberdosis/tiptap-next/compare/@tiptap/react@2.0.0-beta.1...@tiptap/react@2.0.0-beta.2) (2021-03-09)
|
|
47
|
-
|
|
48
|
-
**Note:** Version bump only for package @tiptap/react
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
# [2.0.0-beta.1](https://github.com/ueberdosis/tiptap-next/compare/@tiptap/react@2.0.0-alpha.2...@tiptap/react@2.0.0-beta.1) (2021-03-05)
|
|
55
|
-
|
|
56
|
-
**Note:** Version bump only for package @tiptap/react
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
# 2.0.0-alpha.2 (2021-02-26)
|
|
63
|
-
|
|
64
|
-
**Note:** Version bump only for package @tiptap/react
|