@tiptap/vue-3 2.5.4 → 2.5.5
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/dist/index.cjs +55 -39
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +56 -40
- package/dist/index.js.map +1 -1
- package/dist/index.umd.js +55 -39
- package/dist/index.umd.js.map +1 -1
- package/dist/packages/core/src/Editor.d.ts +2 -4
- package/dist/packages/core/src/types.d.ts +5 -0
- package/dist/packages/vue-3/src/Editor.d.ts +2 -3
- package/dist/packages/vue-3/src/EditorContent.d.ts +2 -2
- package/dist/packages/vue-3/src/VueRenderer.d.ts +18 -4
- package/package.json +7 -7
- package/src/Editor.ts +5 -7
- package/src/EditorContent.ts +12 -26
- package/src/VueNodeViewRenderer.ts +8 -6
- package/src/VueRenderer.ts +51 -26
package/src/Editor.ts
CHANGED
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
import { Editor as CoreEditor, EditorOptions } from '@tiptap/core'
|
|
2
2
|
import { EditorState, Plugin, PluginKey } from '@tiptap/pm/state'
|
|
3
3
|
import {
|
|
4
|
+
AppContext,
|
|
4
5
|
ComponentInternalInstance,
|
|
5
6
|
ComponentPublicInstance,
|
|
6
7
|
customRef,
|
|
7
8
|
markRaw,
|
|
8
|
-
reactive,
|
|
9
9
|
Ref,
|
|
10
10
|
} from 'vue'
|
|
11
11
|
|
|
12
|
-
import { VueRenderer } from './VueRenderer.js'
|
|
13
|
-
|
|
14
12
|
function useDebouncedRef<T>(value: T) {
|
|
15
13
|
return customRef<T>((track, trigger) => {
|
|
16
14
|
return {
|
|
@@ -42,18 +40,18 @@ export class Editor extends CoreEditor {
|
|
|
42
40
|
|
|
43
41
|
private reactiveExtensionStorage: Ref<Record<string, any>>
|
|
44
42
|
|
|
45
|
-
public vueRenderers = reactive<Map<string, VueRenderer>>(new Map())
|
|
46
|
-
|
|
47
43
|
public contentComponent: ContentComponent | null = null
|
|
48
44
|
|
|
45
|
+
public appContext: AppContext | null = null
|
|
46
|
+
|
|
49
47
|
constructor(options: Partial<EditorOptions> = {}) {
|
|
50
48
|
super(options)
|
|
51
49
|
|
|
52
50
|
this.reactiveState = useDebouncedRef(this.view.state)
|
|
53
51
|
this.reactiveExtensionStorage = useDebouncedRef(this.extensionStorage)
|
|
54
52
|
|
|
55
|
-
this.on('
|
|
56
|
-
this.reactiveState.value =
|
|
53
|
+
this.on('beforeTransaction', ({ nextState }) => {
|
|
54
|
+
this.reactiveState.value = nextState
|
|
57
55
|
this.reactiveExtensionStorage.value = this.extensionStorage
|
|
58
56
|
})
|
|
59
57
|
|
package/src/EditorContent.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import {
|
|
2
|
-
DefineComponent,
|
|
3
2
|
defineComponent,
|
|
4
3
|
getCurrentInstance,
|
|
5
4
|
h,
|
|
@@ -8,7 +7,6 @@ import {
|
|
|
8
7
|
PropType,
|
|
9
8
|
Ref,
|
|
10
9
|
ref,
|
|
11
|
-
Teleport,
|
|
12
10
|
unref,
|
|
13
11
|
watchEffect,
|
|
14
12
|
} from 'vue'
|
|
@@ -45,6 +43,17 @@ export const EditorContent = defineComponent({
|
|
|
45
43
|
// @ts-ignore
|
|
46
44
|
editor.contentComponent = instance.ctx._
|
|
47
45
|
|
|
46
|
+
if (instance) {
|
|
47
|
+
editor.appContext = {
|
|
48
|
+
...instance.appContext,
|
|
49
|
+
provides: {
|
|
50
|
+
// @ts-ignore
|
|
51
|
+
...instance.provides,
|
|
52
|
+
...instance.appContext.provides,
|
|
53
|
+
},
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
48
57
|
editor.setOptions({
|
|
49
58
|
element,
|
|
50
59
|
})
|
|
@@ -69,6 +78,7 @@ export const EditorContent = defineComponent({
|
|
|
69
78
|
}
|
|
70
79
|
|
|
71
80
|
editor.contentComponent = null
|
|
81
|
+
editor.appContext = null
|
|
72
82
|
|
|
73
83
|
if (!editor.options.element.firstChild) {
|
|
74
84
|
return
|
|
@@ -87,35 +97,11 @@ export const EditorContent = defineComponent({
|
|
|
87
97
|
},
|
|
88
98
|
|
|
89
99
|
render() {
|
|
90
|
-
const vueRenderers: any[] = []
|
|
91
|
-
|
|
92
|
-
if (this.editor) {
|
|
93
|
-
this.editor.vueRenderers.forEach(vueRenderer => {
|
|
94
|
-
const node = h(
|
|
95
|
-
Teleport,
|
|
96
|
-
{
|
|
97
|
-
to: vueRenderer.teleportElement,
|
|
98
|
-
key: vueRenderer.id,
|
|
99
|
-
},
|
|
100
|
-
h(
|
|
101
|
-
vueRenderer.component as DefineComponent,
|
|
102
|
-
{
|
|
103
|
-
ref: vueRenderer.id,
|
|
104
|
-
...vueRenderer.props,
|
|
105
|
-
},
|
|
106
|
-
),
|
|
107
|
-
)
|
|
108
|
-
|
|
109
|
-
vueRenderers.push(node)
|
|
110
|
-
})
|
|
111
|
-
}
|
|
112
|
-
|
|
113
100
|
return h(
|
|
114
101
|
'div',
|
|
115
102
|
{
|
|
116
103
|
ref: (el: any) => { this.rootEl = el },
|
|
117
104
|
},
|
|
118
|
-
...vueRenderers,
|
|
119
105
|
)
|
|
120
106
|
},
|
|
121
107
|
})
|
|
@@ -124,7 +124,7 @@ class VueNodeView extends NodeView<Component, Editor, VueNodeViewRendererOptions
|
|
|
124
124
|
}
|
|
125
125
|
|
|
126
126
|
get dom() {
|
|
127
|
-
if (!this.renderer.element.hasAttribute('data-node-view-wrapper')) {
|
|
127
|
+
if (!this.renderer.element || !this.renderer.element.hasAttribute('data-node-view-wrapper')) {
|
|
128
128
|
throw Error('Please use the NodeViewWrapper component for your node view.')
|
|
129
129
|
}
|
|
130
130
|
|
|
@@ -136,9 +136,7 @@ class VueNodeView extends NodeView<Component, Editor, VueNodeViewRendererOptions
|
|
|
136
136
|
return null
|
|
137
137
|
}
|
|
138
138
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
return (contentElement || this.dom) as HTMLElement | null
|
|
139
|
+
return this.dom.querySelector('[data-node-view-content]') as HTMLElement | null
|
|
142
140
|
}
|
|
143
141
|
|
|
144
142
|
update(node: ProseMirrorNode, decorations: DecorationWithType[]) {
|
|
@@ -183,14 +181,18 @@ class VueNodeView extends NodeView<Component, Editor, VueNodeViewRendererOptions
|
|
|
183
181
|
this.renderer.updateProps({
|
|
184
182
|
selected: true,
|
|
185
183
|
})
|
|
186
|
-
this.renderer.element
|
|
184
|
+
if (this.renderer.element) {
|
|
185
|
+
this.renderer.element.classList.add('ProseMirror-selectednode')
|
|
186
|
+
}
|
|
187
187
|
}
|
|
188
188
|
|
|
189
189
|
deselectNode() {
|
|
190
190
|
this.renderer.updateProps({
|
|
191
191
|
selected: false,
|
|
192
192
|
})
|
|
193
|
-
this.renderer.element
|
|
193
|
+
if (this.renderer.element) {
|
|
194
|
+
this.renderer.element.classList.remove('ProseMirror-selectednode')
|
|
195
|
+
}
|
|
194
196
|
}
|
|
195
197
|
|
|
196
198
|
getDecorationClasses() {
|
package/src/VueRenderer.ts
CHANGED
|
@@ -1,62 +1,87 @@
|
|
|
1
1
|
import { Editor } from '@tiptap/core'
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
Component, DefineComponent, h, markRaw, reactive, render,
|
|
4
|
+
} from 'vue'
|
|
3
5
|
|
|
4
6
|
import { Editor as ExtendedEditor } from './Editor.js'
|
|
5
7
|
|
|
6
8
|
export interface VueRendererOptions {
|
|
7
|
-
editor: Editor
|
|
8
|
-
props?: Record<string, any
|
|
9
|
+
editor: Editor;
|
|
10
|
+
props?: Record<string, any>;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
type ExtendedVNode = ReturnType<typeof h> | null;
|
|
14
|
+
|
|
15
|
+
interface RenderedComponent {
|
|
16
|
+
vNode: ExtendedVNode;
|
|
17
|
+
destroy: () => void;
|
|
18
|
+
el: Element | null;
|
|
9
19
|
}
|
|
10
20
|
|
|
11
21
|
/**
|
|
12
22
|
* This class is used to render Vue components inside the editor.
|
|
13
23
|
*/
|
|
14
24
|
export class VueRenderer {
|
|
15
|
-
|
|
25
|
+
renderedComponent!: RenderedComponent
|
|
16
26
|
|
|
17
27
|
editor: ExtendedEditor
|
|
18
28
|
|
|
19
29
|
component: Component
|
|
20
30
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
element: Element
|
|
31
|
+
el: Element | null
|
|
24
32
|
|
|
25
33
|
props: Record<string, any>
|
|
26
34
|
|
|
27
35
|
constructor(component: Component, { props = {}, editor }: VueRendererOptions) {
|
|
28
|
-
this.id = Math.floor(Math.random() * 0xFFFFFFFF).toString()
|
|
29
36
|
this.editor = editor as ExtendedEditor
|
|
30
37
|
this.component = markRaw(component)
|
|
31
|
-
this.
|
|
32
|
-
this.element = this.teleportElement
|
|
38
|
+
this.el = document.createElement('div')
|
|
33
39
|
this.props = reactive(props)
|
|
34
|
-
this.
|
|
35
|
-
|
|
36
|
-
if (this.editor.contentComponent) {
|
|
37
|
-
this.editor.contentComponent.update()
|
|
40
|
+
this.renderedComponent = this.renderComponent()
|
|
41
|
+
}
|
|
38
42
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
43
|
+
get element(): Element | null {
|
|
44
|
+
return this.renderedComponent.el
|
|
45
|
+
}
|
|
42
46
|
|
|
43
|
-
|
|
47
|
+
get ref(): any {
|
|
48
|
+
// Composition API
|
|
49
|
+
if (this.renderedComponent.vNode?.component?.exposed) {
|
|
50
|
+
return this.renderedComponent.vNode.component.exposed
|
|
44
51
|
}
|
|
52
|
+
// Option API
|
|
53
|
+
return this.renderedComponent.vNode?.component?.proxy
|
|
45
54
|
}
|
|
46
55
|
|
|
47
|
-
|
|
48
|
-
|
|
56
|
+
renderComponent() {
|
|
57
|
+
let vNode: ExtendedVNode = h(this.component as DefineComponent, this.props)
|
|
58
|
+
|
|
59
|
+
if (this.editor.appContext) {
|
|
60
|
+
vNode.appContext = this.editor.appContext
|
|
61
|
+
}
|
|
62
|
+
if (typeof document !== 'undefined' && this.el) {
|
|
63
|
+
render(vNode, this.el)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const destroy = () => {
|
|
67
|
+
if (this.el) {
|
|
68
|
+
render(null, this.el)
|
|
69
|
+
}
|
|
70
|
+
this.el = null
|
|
71
|
+
vNode = null
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return { vNode, destroy, el: this.el ? this.el.firstElementChild : null }
|
|
49
75
|
}
|
|
50
76
|
|
|
51
77
|
updateProps(props: Record<string, any> = {}): void {
|
|
52
|
-
Object
|
|
53
|
-
.
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
})
|
|
78
|
+
Object.entries(props).forEach(([key, value]) => {
|
|
79
|
+
this.props[key] = value
|
|
80
|
+
})
|
|
81
|
+
this.renderComponent()
|
|
57
82
|
}
|
|
58
83
|
|
|
59
84
|
destroy(): void {
|
|
60
|
-
this.
|
|
85
|
+
this.renderedComponent.destroy()
|
|
61
86
|
}
|
|
62
87
|
}
|