@tiptap/vue-3 2.11.6 → 3.0.0-beta.0
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 +21 -0
- package/README.md +5 -1
- package/dist/index.cjs +562 -528
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +219 -0
- package/dist/index.d.ts +218 -10
- package/dist/index.js +526 -516
- package/dist/index.js.map +1 -1
- package/dist/menus/index.cjs +587 -0
- package/dist/menus/index.cjs.map +1 -0
- package/dist/menus/index.d.cts +257 -0
- package/dist/menus/index.d.ts +257 -0
- package/dist/menus/index.js +579 -0
- package/dist/menus/index.js.map +1 -0
- package/package.json +27 -16
- package/src/Editor.ts +6 -11
- package/src/EditorContent.ts +10 -20
- package/src/VueMarkViewRenderer.ts +114 -0
- package/src/VueNodeViewRenderer.ts +19 -30
- package/src/VueRenderer.ts +10 -11
- package/src/index.ts +1 -2
- package/src/menus/BubbleMenu.ts +78 -0
- package/src/menus/FloatingMenu.ts +68 -0
- package/src/menus/index.ts +2 -0
- package/src/useEditor.ts +1 -1
- package/dist/BubbleMenu.d.ts +0 -61
- package/dist/BubbleMenu.d.ts.map +0 -1
- package/dist/Editor.d.ts +0 -24
- package/dist/Editor.d.ts.map +0 -1
- package/dist/EditorContent.d.ts +0 -18
- package/dist/EditorContent.d.ts.map +0 -1
- package/dist/FloatingMenu.d.ts +0 -49
- package/dist/FloatingMenu.d.ts.map +0 -1
- package/dist/NodeViewContent.d.ts +0 -14
- package/dist/NodeViewContent.d.ts.map +0 -1
- package/dist/NodeViewWrapper.d.ts +0 -14
- package/dist/NodeViewWrapper.d.ts.map +0 -1
- package/dist/VueNodeViewRenderer.d.ts +0 -63
- package/dist/VueNodeViewRenderer.d.ts.map +0 -1
- package/dist/VueRenderer.d.ts +0 -37
- package/dist/VueRenderer.d.ts.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.umd.js +0 -570
- package/dist/index.umd.js.map +0 -1
- package/dist/useEditor.d.ts +0 -4
- package/dist/useEditor.d.ts.map +0 -1
- package/src/BubbleMenu.ts +0 -71
- package/src/FloatingMenu.ts +0 -66
package/dist/index.js
CHANGED
|
@@ -1,553 +1,563 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
export * from '@tiptap/core';
|
|
5
|
-
import { FloatingMenuPlugin } from '@tiptap/extension-floating-menu';
|
|
6
|
-
|
|
7
|
-
const BubbleMenu = defineComponent({
|
|
8
|
-
name: 'BubbleMenu',
|
|
9
|
-
props: {
|
|
10
|
-
pluginKey: {
|
|
11
|
-
type: [String, Object],
|
|
12
|
-
default: 'bubbleMenu',
|
|
13
|
-
},
|
|
14
|
-
editor: {
|
|
15
|
-
type: Object,
|
|
16
|
-
required: true,
|
|
17
|
-
},
|
|
18
|
-
updateDelay: {
|
|
19
|
-
type: Number,
|
|
20
|
-
default: undefined,
|
|
21
|
-
},
|
|
22
|
-
tippyOptions: {
|
|
23
|
-
type: Object,
|
|
24
|
-
default: () => ({}),
|
|
25
|
-
},
|
|
26
|
-
shouldShow: {
|
|
27
|
-
type: Function,
|
|
28
|
-
default: null,
|
|
29
|
-
},
|
|
30
|
-
},
|
|
31
|
-
setup(props, { slots }) {
|
|
32
|
-
const root = ref(null);
|
|
33
|
-
onMounted(() => {
|
|
34
|
-
const { updateDelay, editor, pluginKey, shouldShow, tippyOptions, } = props;
|
|
35
|
-
editor.registerPlugin(BubbleMenuPlugin({
|
|
36
|
-
updateDelay,
|
|
37
|
-
editor,
|
|
38
|
-
element: root.value,
|
|
39
|
-
pluginKey,
|
|
40
|
-
shouldShow,
|
|
41
|
-
tippyOptions,
|
|
42
|
-
}));
|
|
43
|
-
});
|
|
44
|
-
onBeforeUnmount(() => {
|
|
45
|
-
const { pluginKey, editor } = props;
|
|
46
|
-
editor.unregisterPlugin(pluginKey);
|
|
47
|
-
});
|
|
48
|
-
return () => { var _a; return h('div', { ref: root }, (_a = slots.default) === null || _a === void 0 ? void 0 : _a.call(slots)); };
|
|
49
|
-
},
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
/* eslint-disable react-hooks/rules-of-hooks */
|
|
1
|
+
// src/Editor.ts
|
|
2
|
+
import { Editor as CoreEditor } from "@tiptap/core";
|
|
3
|
+
import { customRef, markRaw } from "vue";
|
|
53
4
|
function useDebouncedRef(value) {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
trigger();
|
|
67
|
-
});
|
|
68
|
-
});
|
|
69
|
-
},
|
|
70
|
-
};
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
class Editor extends Editor$1 {
|
|
74
|
-
constructor(options = {}) {
|
|
75
|
-
super(options);
|
|
76
|
-
this.contentComponent = null;
|
|
77
|
-
this.appContext = null;
|
|
78
|
-
this.reactiveState = useDebouncedRef(this.view.state);
|
|
79
|
-
this.reactiveExtensionStorage = useDebouncedRef(this.extensionStorage);
|
|
80
|
-
this.on('beforeTransaction', ({ nextState }) => {
|
|
81
|
-
this.reactiveState.value = nextState;
|
|
82
|
-
this.reactiveExtensionStorage.value = this.extensionStorage;
|
|
5
|
+
return customRef((track, trigger) => {
|
|
6
|
+
return {
|
|
7
|
+
get() {
|
|
8
|
+
track();
|
|
9
|
+
return value;
|
|
10
|
+
},
|
|
11
|
+
set(newValue) {
|
|
12
|
+
value = newValue;
|
|
13
|
+
requestAnimationFrame(() => {
|
|
14
|
+
requestAnimationFrame(() => {
|
|
15
|
+
trigger();
|
|
16
|
+
});
|
|
83
17
|
});
|
|
84
|
-
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
var Editor = class extends CoreEditor {
|
|
23
|
+
constructor(options = {}) {
|
|
24
|
+
super(options);
|
|
25
|
+
this.contentComponent = null;
|
|
26
|
+
this.appContext = null;
|
|
27
|
+
this.reactiveState = useDebouncedRef(this.view.state);
|
|
28
|
+
this.reactiveExtensionStorage = useDebouncedRef(this.extensionStorage);
|
|
29
|
+
this.on("beforeTransaction", ({ nextState }) => {
|
|
30
|
+
this.reactiveState.value = nextState;
|
|
31
|
+
this.reactiveExtensionStorage.value = this.extensionStorage;
|
|
32
|
+
});
|
|
33
|
+
return markRaw(this);
|
|
34
|
+
}
|
|
35
|
+
get state() {
|
|
36
|
+
return this.reactiveState ? this.reactiveState.value : this.view.state;
|
|
37
|
+
}
|
|
38
|
+
get storage() {
|
|
39
|
+
return this.reactiveExtensionStorage ? this.reactiveExtensionStorage.value : super.storage;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Register a ProseMirror plugin.
|
|
43
|
+
*/
|
|
44
|
+
registerPlugin(plugin, handlePlugins) {
|
|
45
|
+
const nextState = super.registerPlugin(plugin, handlePlugins);
|
|
46
|
+
if (this.reactiveState) {
|
|
47
|
+
this.reactiveState.value = nextState;
|
|
101
48
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
49
|
+
return nextState;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Unregister a ProseMirror plugin.
|
|
53
|
+
*/
|
|
54
|
+
unregisterPlugin(nameOrPluginKey) {
|
|
55
|
+
const nextState = super.unregisterPlugin(nameOrPluginKey);
|
|
56
|
+
if (this.reactiveState && nextState) {
|
|
57
|
+
this.reactiveState.value = nextState;
|
|
111
58
|
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
name: 'EditorContent',
|
|
116
|
-
props: {
|
|
117
|
-
editor: {
|
|
118
|
-
default: null,
|
|
119
|
-
type: Object,
|
|
120
|
-
},
|
|
121
|
-
},
|
|
122
|
-
setup(props) {
|
|
123
|
-
const rootEl = ref();
|
|
124
|
-
const instance = getCurrentInstance();
|
|
125
|
-
watchEffect(() => {
|
|
126
|
-
const editor = props.editor;
|
|
127
|
-
if (editor && editor.options.element && rootEl.value) {
|
|
128
|
-
nextTick(() => {
|
|
129
|
-
if (!rootEl.value || !editor.options.element.firstChild) {
|
|
130
|
-
return;
|
|
131
|
-
}
|
|
132
|
-
const element = unref(rootEl.value);
|
|
133
|
-
rootEl.value.append(...editor.options.element.childNodes);
|
|
134
|
-
// @ts-ignore
|
|
135
|
-
editor.contentComponent = instance.ctx._;
|
|
136
|
-
if (instance) {
|
|
137
|
-
editor.appContext = {
|
|
138
|
-
...instance.appContext,
|
|
139
|
-
// Vue internally uses prototype chain to forward/shadow injects across the entire component chain
|
|
140
|
-
// so don't use object spread operator or 'Object.assign' and just set `provides` as is on editor's appContext
|
|
141
|
-
// @ts-expect-error forward instance's 'provides' into appContext
|
|
142
|
-
provides: instance.provides,
|
|
143
|
-
};
|
|
144
|
-
}
|
|
145
|
-
editor.setOptions({
|
|
146
|
-
element,
|
|
147
|
-
});
|
|
148
|
-
editor.createNodeViews();
|
|
149
|
-
});
|
|
150
|
-
}
|
|
151
|
-
});
|
|
152
|
-
onBeforeUnmount(() => {
|
|
153
|
-
const editor = props.editor;
|
|
154
|
-
if (!editor) {
|
|
155
|
-
return;
|
|
156
|
-
}
|
|
157
|
-
editor.contentComponent = null;
|
|
158
|
-
editor.appContext = null;
|
|
159
|
-
});
|
|
160
|
-
return { rootEl };
|
|
161
|
-
},
|
|
162
|
-
render() {
|
|
163
|
-
return h('div', {
|
|
164
|
-
ref: (el) => { this.rootEl = el; },
|
|
165
|
-
});
|
|
166
|
-
},
|
|
167
|
-
});
|
|
59
|
+
return nextState;
|
|
60
|
+
}
|
|
61
|
+
};
|
|
168
62
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
63
|
+
// src/EditorContent.ts
|
|
64
|
+
import { defineComponent, getCurrentInstance, h, nextTick, onBeforeUnmount, ref, unref, watchEffect } from "vue";
|
|
65
|
+
var EditorContent = defineComponent({
|
|
66
|
+
name: "EditorContent",
|
|
67
|
+
props: {
|
|
68
|
+
editor: {
|
|
69
|
+
default: null,
|
|
70
|
+
type: Object
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
setup(props) {
|
|
74
|
+
const rootEl = ref();
|
|
75
|
+
const instance = getCurrentInstance();
|
|
76
|
+
watchEffect(() => {
|
|
77
|
+
const editor = props.editor;
|
|
78
|
+
if (editor && editor.options.element && rootEl.value) {
|
|
79
|
+
nextTick(() => {
|
|
80
|
+
var _a;
|
|
81
|
+
if (!rootEl.value || !((_a = editor.options.element) == null ? void 0 : _a.firstChild)) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
const element = unref(rootEl.value);
|
|
85
|
+
rootEl.value.append(...editor.options.element.childNodes);
|
|
86
|
+
editor.contentComponent = instance.ctx._;
|
|
87
|
+
if (instance) {
|
|
88
|
+
editor.appContext = {
|
|
89
|
+
...instance.appContext,
|
|
90
|
+
// Vue internally uses prototype chain to forward/shadow injects across the entire component chain
|
|
91
|
+
// so don't use object spread operator or 'Object.assign' and just set `provides` as is on editor's appContext
|
|
92
|
+
// @ts-expect-error forward instance's 'provides' into appContext
|
|
93
|
+
provides: instance.provides
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
editor.setOptions({
|
|
97
|
+
element
|
|
98
|
+
});
|
|
99
|
+
editor.createNodeViews();
|
|
206
100
|
});
|
|
207
|
-
|
|
208
|
-
}
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
onBeforeUnmount(() => {
|
|
104
|
+
const editor = props.editor;
|
|
105
|
+
if (!editor) {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
editor.contentComponent = null;
|
|
109
|
+
editor.appContext = null;
|
|
110
|
+
});
|
|
111
|
+
return { rootEl };
|
|
112
|
+
},
|
|
113
|
+
render() {
|
|
114
|
+
return h("div", {
|
|
115
|
+
ref: (el) => {
|
|
116
|
+
this.rootEl = el;
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
}
|
|
209
120
|
});
|
|
210
121
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
122
|
+
// src/NodeViewContent.ts
|
|
123
|
+
import { defineComponent as defineComponent2, h as h2 } from "vue";
|
|
124
|
+
var NodeViewContent = defineComponent2({
|
|
125
|
+
name: "NodeViewContent",
|
|
126
|
+
props: {
|
|
127
|
+
as: {
|
|
128
|
+
type: String,
|
|
129
|
+
default: "div"
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
render() {
|
|
133
|
+
return h2(this.as, {
|
|
134
|
+
style: {
|
|
135
|
+
whiteSpace: "pre-wrap"
|
|
136
|
+
},
|
|
137
|
+
"data-node-view-content": ""
|
|
138
|
+
});
|
|
139
|
+
}
|
|
227
140
|
});
|
|
228
141
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
142
|
+
// src/NodeViewWrapper.ts
|
|
143
|
+
import { defineComponent as defineComponent3, h as h3 } from "vue";
|
|
144
|
+
var NodeViewWrapper = defineComponent3({
|
|
145
|
+
name: "NodeViewWrapper",
|
|
146
|
+
props: {
|
|
147
|
+
as: {
|
|
148
|
+
type: String,
|
|
149
|
+
default: "div"
|
|
150
|
+
}
|
|
151
|
+
},
|
|
152
|
+
inject: ["onDragStart", "decorationClasses"],
|
|
153
|
+
render() {
|
|
154
|
+
var _a, _b;
|
|
155
|
+
return h3(
|
|
156
|
+
this.as,
|
|
157
|
+
{
|
|
158
|
+
// @ts-ignore
|
|
159
|
+
class: this.decorationClasses,
|
|
160
|
+
style: {
|
|
161
|
+
whiteSpace: "normal"
|
|
235
162
|
},
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
style: {
|
|
244
|
-
whiteSpace: 'normal',
|
|
245
|
-
},
|
|
246
|
-
'data-node-view-wrapper': '',
|
|
247
|
-
// @ts-ignore (https://github.com/vuejs/vue-next/issues/3031)
|
|
248
|
-
onDragstart: this.onDragStart,
|
|
249
|
-
}, (_b = (_a = this.$slots).default) === null || _b === void 0 ? void 0 : _b.call(_a));
|
|
250
|
-
},
|
|
163
|
+
"data-node-view-wrapper": "",
|
|
164
|
+
// @ts-ignore (https://github.com/vuejs/vue-next/issues/3031)
|
|
165
|
+
onDragstart: this.onDragStart
|
|
166
|
+
},
|
|
167
|
+
(_b = (_a = this.$slots).default) == null ? void 0 : _b.call(_a)
|
|
168
|
+
);
|
|
169
|
+
}
|
|
251
170
|
});
|
|
252
171
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
172
|
+
// src/useEditor.ts
|
|
173
|
+
import { onBeforeUnmount as onBeforeUnmount2, onMounted, shallowRef } from "vue";
|
|
174
|
+
var useEditor = (options = {}) => {
|
|
175
|
+
const editor = shallowRef();
|
|
176
|
+
onMounted(() => {
|
|
177
|
+
editor.value = new Editor(options);
|
|
178
|
+
});
|
|
179
|
+
onBeforeUnmount2(() => {
|
|
180
|
+
var _a, _b, _c;
|
|
181
|
+
const nodes = (_a = editor.value) == null ? void 0 : _a.options.element;
|
|
182
|
+
const newEl = nodes == null ? void 0 : nodes.cloneNode(true);
|
|
183
|
+
(_b = nodes == null ? void 0 : nodes.parentNode) == null ? void 0 : _b.replaceChild(newEl, nodes);
|
|
184
|
+
(_c = editor.value) == null ? void 0 : _c.destroy();
|
|
185
|
+
});
|
|
186
|
+
return editor;
|
|
267
187
|
};
|
|
268
188
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
189
|
+
// src/VueMarkViewRenderer.ts
|
|
190
|
+
import { MarkView } from "@tiptap/core";
|
|
191
|
+
import { defineComponent as defineComponent4, h as h5 } from "vue";
|
|
192
|
+
|
|
193
|
+
// src/VueRenderer.ts
|
|
194
|
+
import { h as h4, markRaw as markRaw2, reactive, render } from "vue";
|
|
195
|
+
var VueRenderer = class {
|
|
196
|
+
constructor(component, { props = {}, editor }) {
|
|
197
|
+
this.editor = editor;
|
|
198
|
+
this.component = markRaw2(component);
|
|
199
|
+
this.el = document.createElement("div");
|
|
200
|
+
this.props = reactive(props);
|
|
201
|
+
this.renderedComponent = this.renderComponent();
|
|
202
|
+
}
|
|
203
|
+
get element() {
|
|
204
|
+
return this.renderedComponent.el;
|
|
205
|
+
}
|
|
206
|
+
get ref() {
|
|
207
|
+
var _a, _b, _c, _d;
|
|
208
|
+
if ((_b = (_a = this.renderedComponent.vNode) == null ? void 0 : _a.component) == null ? void 0 : _b.exposed) {
|
|
209
|
+
return this.renderedComponent.vNode.component.exposed;
|
|
279
210
|
}
|
|
280
|
-
|
|
281
|
-
|
|
211
|
+
return (_d = (_c = this.renderedComponent.vNode) == null ? void 0 : _c.component) == null ? void 0 : _d.proxy;
|
|
212
|
+
}
|
|
213
|
+
renderComponent() {
|
|
214
|
+
let vNode = h4(this.component, this.props);
|
|
215
|
+
if (this.editor.appContext) {
|
|
216
|
+
vNode.appContext = this.editor.appContext;
|
|
282
217
|
}
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
// Composition API
|
|
286
|
-
if ((_b = (_a = this.renderedComponent.vNode) === null || _a === void 0 ? void 0 : _a.component) === null || _b === void 0 ? void 0 : _b.exposed) {
|
|
287
|
-
return this.renderedComponent.vNode.component.exposed;
|
|
288
|
-
}
|
|
289
|
-
// Option API
|
|
290
|
-
return (_d = (_c = this.renderedComponent.vNode) === null || _c === void 0 ? void 0 : _c.component) === null || _d === void 0 ? void 0 : _d.proxy;
|
|
218
|
+
if (typeof document !== "undefined" && this.el) {
|
|
219
|
+
render(vNode, this.el);
|
|
291
220
|
}
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
221
|
+
const destroy = () => {
|
|
222
|
+
if (this.el) {
|
|
223
|
+
render(null, this.el);
|
|
224
|
+
}
|
|
225
|
+
this.el = null;
|
|
226
|
+
vNode = null;
|
|
227
|
+
};
|
|
228
|
+
return { vNode, destroy, el: this.el ? this.el.firstElementChild : null };
|
|
229
|
+
}
|
|
230
|
+
updateProps(props = {}) {
|
|
231
|
+
Object.entries(props).forEach(([key, value]) => {
|
|
232
|
+
this.props[key] = value;
|
|
233
|
+
});
|
|
234
|
+
this.renderComponent();
|
|
235
|
+
}
|
|
236
|
+
destroy() {
|
|
237
|
+
this.renderedComponent.destroy();
|
|
238
|
+
}
|
|
239
|
+
};
|
|
240
|
+
|
|
241
|
+
// src/VueMarkViewRenderer.ts
|
|
242
|
+
var markViewProps = {
|
|
243
|
+
editor: {
|
|
244
|
+
type: Object,
|
|
245
|
+
required: true
|
|
246
|
+
},
|
|
247
|
+
mark: {
|
|
248
|
+
type: Object,
|
|
249
|
+
required: true
|
|
250
|
+
},
|
|
251
|
+
extension: {
|
|
252
|
+
type: Object,
|
|
253
|
+
required: true
|
|
254
|
+
},
|
|
255
|
+
inline: {
|
|
256
|
+
type: Boolean,
|
|
257
|
+
required: true
|
|
258
|
+
},
|
|
259
|
+
view: {
|
|
260
|
+
type: Object,
|
|
261
|
+
required: true
|
|
262
|
+
}
|
|
263
|
+
};
|
|
264
|
+
var MarkViewContent = defineComponent4({
|
|
265
|
+
name: "MarkViewContent",
|
|
266
|
+
props: {
|
|
267
|
+
as: {
|
|
268
|
+
type: String,
|
|
269
|
+
default: "span"
|
|
308
270
|
}
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
271
|
+
},
|
|
272
|
+
render() {
|
|
273
|
+
return h5(this.as, {
|
|
274
|
+
style: {
|
|
275
|
+
whiteSpace: "inherit"
|
|
276
|
+
},
|
|
277
|
+
"data-mark-view-content": ""
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
});
|
|
281
|
+
var VueMarkView = class extends MarkView {
|
|
282
|
+
constructor(component, props, options) {
|
|
283
|
+
super(component, props, options);
|
|
284
|
+
const extendedComponent = defineComponent4({
|
|
285
|
+
extends: { ...component },
|
|
286
|
+
props: Object.keys(props),
|
|
287
|
+
template: this.component.template,
|
|
288
|
+
setup: (reactiveProps) => {
|
|
289
|
+
var _a;
|
|
290
|
+
return (_a = component.setup) == null ? void 0 : _a.call(component, reactiveProps, {
|
|
291
|
+
expose: () => void 0
|
|
312
292
|
});
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
293
|
+
},
|
|
294
|
+
// Add support for scoped styles
|
|
295
|
+
__scopeId: component.__scopeId,
|
|
296
|
+
__cssModules: component.__cssModules,
|
|
297
|
+
__name: component.__name,
|
|
298
|
+
__file: component.__file
|
|
299
|
+
});
|
|
300
|
+
this.renderer = new VueRenderer(extendedComponent, {
|
|
301
|
+
editor: this.editor,
|
|
302
|
+
props
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
get dom() {
|
|
306
|
+
return this.renderer.element;
|
|
307
|
+
}
|
|
308
|
+
get contentDOM() {
|
|
309
|
+
return this.dom.querySelector("[data-mark-view-content]");
|
|
310
|
+
}
|
|
311
|
+
destroy() {
|
|
312
|
+
this.renderer.destroy();
|
|
313
|
+
}
|
|
314
|
+
};
|
|
315
|
+
function VueMarkViewRenderer(component, options = {}) {
|
|
316
|
+
return (props) => {
|
|
317
|
+
if (!props.editor.contentComponent) {
|
|
318
|
+
return {};
|
|
317
319
|
}
|
|
320
|
+
return new VueMarkView(component, props, options);
|
|
321
|
+
};
|
|
318
322
|
}
|
|
319
323
|
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
324
|
+
// src/VueNodeViewRenderer.ts
|
|
325
|
+
import { NodeView } from "@tiptap/core";
|
|
326
|
+
import { defineComponent as defineComponent5, provide, ref as ref2 } from "vue";
|
|
327
|
+
var nodeViewProps = {
|
|
328
|
+
editor: {
|
|
329
|
+
type: Object,
|
|
330
|
+
required: true
|
|
331
|
+
},
|
|
332
|
+
node: {
|
|
333
|
+
type: Object,
|
|
334
|
+
required: true
|
|
335
|
+
},
|
|
336
|
+
decorations: {
|
|
337
|
+
type: Object,
|
|
338
|
+
required: true
|
|
339
|
+
},
|
|
340
|
+
selected: {
|
|
341
|
+
type: Boolean,
|
|
342
|
+
required: true
|
|
343
|
+
},
|
|
344
|
+
extension: {
|
|
345
|
+
type: Object,
|
|
346
|
+
required: true
|
|
347
|
+
},
|
|
348
|
+
getPos: {
|
|
349
|
+
type: Function,
|
|
350
|
+
required: true
|
|
351
|
+
},
|
|
352
|
+
updateAttributes: {
|
|
353
|
+
type: Function,
|
|
354
|
+
required: true
|
|
355
|
+
},
|
|
356
|
+
deleteNode: {
|
|
357
|
+
type: Function,
|
|
358
|
+
required: true
|
|
359
|
+
},
|
|
360
|
+
view: {
|
|
361
|
+
type: Object,
|
|
362
|
+
required: true
|
|
363
|
+
},
|
|
364
|
+
innerDecorations: {
|
|
365
|
+
type: Object,
|
|
366
|
+
required: true
|
|
367
|
+
},
|
|
368
|
+
HTMLAttributes: {
|
|
369
|
+
type: Object,
|
|
370
|
+
required: true
|
|
371
|
+
}
|
|
366
372
|
};
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
});
|
|
395
|
-
},
|
|
396
|
-
// add support for scoped styles
|
|
397
|
-
// @ts-ignore
|
|
398
|
-
// eslint-disable-next-line
|
|
399
|
-
__scopeId: this.component.__scopeId,
|
|
400
|
-
// add support for CSS Modules
|
|
401
|
-
// @ts-ignore
|
|
402
|
-
// eslint-disable-next-line
|
|
403
|
-
__cssModules: this.component.__cssModules,
|
|
404
|
-
// add support for vue devtools
|
|
405
|
-
// @ts-ignore
|
|
406
|
-
// eslint-disable-next-line
|
|
407
|
-
__name: this.component.__name,
|
|
408
|
-
// @ts-ignore
|
|
409
|
-
// eslint-disable-next-line
|
|
410
|
-
__file: this.component.__file,
|
|
411
|
-
});
|
|
412
|
-
this.handleSelectionUpdate = this.handleSelectionUpdate.bind(this);
|
|
413
|
-
this.editor.on('selectionUpdate', this.handleSelectionUpdate);
|
|
414
|
-
this.renderer = new VueRenderer(extendedComponent, {
|
|
415
|
-
editor: this.editor,
|
|
416
|
-
props,
|
|
373
|
+
var VueNodeView = class extends NodeView {
|
|
374
|
+
mount() {
|
|
375
|
+
const props = {
|
|
376
|
+
editor: this.editor,
|
|
377
|
+
node: this.node,
|
|
378
|
+
decorations: this.decorations,
|
|
379
|
+
innerDecorations: this.innerDecorations,
|
|
380
|
+
view: this.view,
|
|
381
|
+
selected: false,
|
|
382
|
+
extension: this.extension,
|
|
383
|
+
HTMLAttributes: this.HTMLAttributes,
|
|
384
|
+
getPos: () => this.getPos(),
|
|
385
|
+
updateAttributes: (attributes = {}) => this.updateAttributes(attributes),
|
|
386
|
+
deleteNode: () => this.deleteNode()
|
|
387
|
+
};
|
|
388
|
+
const onDragStart = this.onDragStart.bind(this);
|
|
389
|
+
this.decorationClasses = ref2(this.getDecorationClasses());
|
|
390
|
+
const extendedComponent = defineComponent5({
|
|
391
|
+
extends: { ...this.component },
|
|
392
|
+
props: Object.keys(props),
|
|
393
|
+
template: this.component.template,
|
|
394
|
+
setup: (reactiveProps) => {
|
|
395
|
+
var _a, _b;
|
|
396
|
+
provide("onDragStart", onDragStart);
|
|
397
|
+
provide("decorationClasses", this.decorationClasses);
|
|
398
|
+
return (_b = (_a = this.component).setup) == null ? void 0 : _b.call(_a, reactiveProps, {
|
|
399
|
+
expose: () => void 0
|
|
417
400
|
});
|
|
401
|
+
},
|
|
402
|
+
// add support for scoped styles
|
|
403
|
+
// @ts-ignore
|
|
404
|
+
// eslint-disable-next-line
|
|
405
|
+
__scopeId: this.component.__scopeId,
|
|
406
|
+
// add support for CSS Modules
|
|
407
|
+
// @ts-ignore
|
|
408
|
+
// eslint-disable-next-line
|
|
409
|
+
__cssModules: this.component.__cssModules,
|
|
410
|
+
// add support for vue devtools
|
|
411
|
+
// @ts-ignore
|
|
412
|
+
// eslint-disable-next-line
|
|
413
|
+
__name: this.component.__name,
|
|
414
|
+
// @ts-ignore
|
|
415
|
+
// eslint-disable-next-line
|
|
416
|
+
__file: this.component.__file
|
|
417
|
+
});
|
|
418
|
+
this.handleSelectionUpdate = this.handleSelectionUpdate.bind(this);
|
|
419
|
+
this.editor.on("selectionUpdate", this.handleSelectionUpdate);
|
|
420
|
+
this.renderer = new VueRenderer(extendedComponent, {
|
|
421
|
+
editor: this.editor,
|
|
422
|
+
props
|
|
423
|
+
});
|
|
424
|
+
}
|
|
425
|
+
/**
|
|
426
|
+
* Return the DOM element.
|
|
427
|
+
* This is the element that will be used to display the node view.
|
|
428
|
+
*/
|
|
429
|
+
get dom() {
|
|
430
|
+
if (!this.renderer.element || !this.renderer.element.hasAttribute("data-node-view-wrapper")) {
|
|
431
|
+
throw Error("Please use the NodeViewWrapper component for your node view.");
|
|
418
432
|
}
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
433
|
+
return this.renderer.element;
|
|
434
|
+
}
|
|
435
|
+
/**
|
|
436
|
+
* Return the content DOM element.
|
|
437
|
+
* This is the element that will be used to display the rich-text content of the node.
|
|
438
|
+
*/
|
|
439
|
+
get contentDOM() {
|
|
440
|
+
if (this.node.isLeaf) {
|
|
441
|
+
return null;
|
|
428
442
|
}
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
443
|
+
return this.dom.querySelector("[data-node-view-content]");
|
|
444
|
+
}
|
|
445
|
+
/**
|
|
446
|
+
* On editor selection update, check if the node is selected.
|
|
447
|
+
* If it is, call `selectNode`, otherwise call `deselectNode`.
|
|
448
|
+
*/
|
|
449
|
+
handleSelectionUpdate() {
|
|
450
|
+
const { from, to } = this.editor.state.selection;
|
|
451
|
+
const pos = this.getPos();
|
|
452
|
+
if (typeof pos !== "number") {
|
|
453
|
+
return;
|
|
438
454
|
}
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
if (from <= pos && to >= pos + this.node.nodeSize) {
|
|
450
|
-
if (this.renderer.props.selected) {
|
|
451
|
-
return;
|
|
452
|
-
}
|
|
453
|
-
this.selectNode();
|
|
454
|
-
}
|
|
455
|
-
else {
|
|
456
|
-
if (!this.renderer.props.selected) {
|
|
457
|
-
return;
|
|
458
|
-
}
|
|
459
|
-
this.deselectNode();
|
|
460
|
-
}
|
|
455
|
+
if (from <= pos && to >= pos + this.node.nodeSize) {
|
|
456
|
+
if (this.renderer.props.selected) {
|
|
457
|
+
return;
|
|
458
|
+
}
|
|
459
|
+
this.selectNode();
|
|
460
|
+
} else {
|
|
461
|
+
if (!this.renderer.props.selected) {
|
|
462
|
+
return;
|
|
463
|
+
}
|
|
464
|
+
this.deselectNode();
|
|
461
465
|
}
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
if (node.type !== this.node.type) {
|
|
489
|
-
return false;
|
|
490
|
-
}
|
|
491
|
-
if (node === this.node && this.decorations === decorations && this.innerDecorations === innerDecorations) {
|
|
492
|
-
return true;
|
|
493
|
-
}
|
|
494
|
-
this.node = node;
|
|
495
|
-
this.decorations = decorations;
|
|
496
|
-
this.innerDecorations = innerDecorations;
|
|
497
|
-
rerenderComponent({ node, decorations, innerDecorations });
|
|
498
|
-
return true;
|
|
466
|
+
}
|
|
467
|
+
/**
|
|
468
|
+
* On update, update the React component.
|
|
469
|
+
* To prevent unnecessary updates, the `update` option can be used.
|
|
470
|
+
*/
|
|
471
|
+
update(node, decorations, innerDecorations) {
|
|
472
|
+
const rerenderComponent = (props) => {
|
|
473
|
+
this.decorationClasses.value = this.getDecorationClasses();
|
|
474
|
+
this.renderer.updateProps(props);
|
|
475
|
+
};
|
|
476
|
+
if (typeof this.options.update === "function") {
|
|
477
|
+
const oldNode = this.node;
|
|
478
|
+
const oldDecorations = this.decorations;
|
|
479
|
+
const oldInnerDecorations = this.innerDecorations;
|
|
480
|
+
this.node = node;
|
|
481
|
+
this.decorations = decorations;
|
|
482
|
+
this.innerDecorations = innerDecorations;
|
|
483
|
+
return this.options.update({
|
|
484
|
+
oldNode,
|
|
485
|
+
oldDecorations,
|
|
486
|
+
newNode: node,
|
|
487
|
+
newDecorations: decorations,
|
|
488
|
+
oldInnerDecorations,
|
|
489
|
+
innerDecorations,
|
|
490
|
+
updateProps: () => rerenderComponent({ node, decorations, innerDecorations })
|
|
491
|
+
});
|
|
499
492
|
}
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
* Add the `selected` prop and the `ProseMirror-selectednode` class.
|
|
503
|
-
*/
|
|
504
|
-
selectNode() {
|
|
505
|
-
this.renderer.updateProps({
|
|
506
|
-
selected: true,
|
|
507
|
-
});
|
|
508
|
-
if (this.renderer.element) {
|
|
509
|
-
this.renderer.element.classList.add('ProseMirror-selectednode');
|
|
510
|
-
}
|
|
493
|
+
if (node.type !== this.node.type) {
|
|
494
|
+
return false;
|
|
511
495
|
}
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
* Remove the `selected` prop and the `ProseMirror-selectednode` class.
|
|
515
|
-
*/
|
|
516
|
-
deselectNode() {
|
|
517
|
-
this.renderer.updateProps({
|
|
518
|
-
selected: false,
|
|
519
|
-
});
|
|
520
|
-
if (this.renderer.element) {
|
|
521
|
-
this.renderer.element.classList.remove('ProseMirror-selectednode');
|
|
522
|
-
}
|
|
496
|
+
if (node === this.node && this.decorations === decorations && this.innerDecorations === innerDecorations) {
|
|
497
|
+
return true;
|
|
523
498
|
}
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
499
|
+
this.node = node;
|
|
500
|
+
this.decorations = decorations;
|
|
501
|
+
this.innerDecorations = innerDecorations;
|
|
502
|
+
rerenderComponent({ node, decorations, innerDecorations });
|
|
503
|
+
return true;
|
|
504
|
+
}
|
|
505
|
+
/**
|
|
506
|
+
* Select the node.
|
|
507
|
+
* Add the `selected` prop and the `ProseMirror-selectednode` class.
|
|
508
|
+
*/
|
|
509
|
+
selectNode() {
|
|
510
|
+
this.renderer.updateProps({
|
|
511
|
+
selected: true
|
|
512
|
+
});
|
|
513
|
+
if (this.renderer.element) {
|
|
514
|
+
this.renderer.element.classList.add("ProseMirror-selectednode");
|
|
530
515
|
}
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
516
|
+
}
|
|
517
|
+
/**
|
|
518
|
+
* Deselect the node.
|
|
519
|
+
* Remove the `selected` prop and the `ProseMirror-selectednode` class.
|
|
520
|
+
*/
|
|
521
|
+
deselectNode() {
|
|
522
|
+
this.renderer.updateProps({
|
|
523
|
+
selected: false
|
|
524
|
+
});
|
|
525
|
+
if (this.renderer.element) {
|
|
526
|
+
this.renderer.element.classList.remove("ProseMirror-selectednode");
|
|
534
527
|
}
|
|
535
|
-
}
|
|
528
|
+
}
|
|
529
|
+
getDecorationClasses() {
|
|
530
|
+
return this.decorations.map((item) => item.type.attrs.class).flat().join(" ");
|
|
531
|
+
}
|
|
532
|
+
destroy() {
|
|
533
|
+
this.renderer.destroy();
|
|
534
|
+
this.editor.off("selectionUpdate", this.handleSelectionUpdate);
|
|
535
|
+
}
|
|
536
|
+
};
|
|
536
537
|
function VueNodeViewRenderer(component, options) {
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
// check for class-component and normalize if neccessary
|
|
545
|
-
const normalizedComponent = typeof component === 'function' && '__vccOpts' in component
|
|
546
|
-
? component.__vccOpts
|
|
547
|
-
: component;
|
|
548
|
-
return new VueNodeView(normalizedComponent, props, options);
|
|
549
|
-
};
|
|
538
|
+
return (props) => {
|
|
539
|
+
if (!props.editor.contentComponent) {
|
|
540
|
+
return {};
|
|
541
|
+
}
|
|
542
|
+
const normalizedComponent = typeof component === "function" && "__vccOpts" in component ? component.__vccOpts : component;
|
|
543
|
+
return new VueNodeView(normalizedComponent, props, options);
|
|
544
|
+
};
|
|
550
545
|
}
|
|
551
546
|
|
|
552
|
-
|
|
553
|
-
|
|
547
|
+
// src/index.ts
|
|
548
|
+
export * from "@tiptap/core";
|
|
549
|
+
export {
|
|
550
|
+
Editor,
|
|
551
|
+
EditorContent,
|
|
552
|
+
MarkViewContent,
|
|
553
|
+
NodeViewContent,
|
|
554
|
+
NodeViewWrapper,
|
|
555
|
+
VueMarkView,
|
|
556
|
+
VueMarkViewRenderer,
|
|
557
|
+
VueNodeViewRenderer,
|
|
558
|
+
VueRenderer,
|
|
559
|
+
markViewProps,
|
|
560
|
+
nodeViewProps,
|
|
561
|
+
useEditor
|
|
562
|
+
};
|
|
563
|
+
//# sourceMappingURL=index.js.map
|