@tiptap/vue-2 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 +341 -407
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +79 -0
- package/dist/index.d.ts +78 -9
- package/dist/index.js +299 -391
- package/dist/index.js.map +1 -1
- package/dist/menus/index.cjs +2166 -0
- package/dist/menus/index.cjs.map +1 -0
- package/dist/menus/index.d.cts +131 -0
- package/dist/menus/index.d.ts +131 -0
- package/dist/menus/index.js +2138 -0
- package/dist/menus/index.js.map +1 -0
- package/package.json +25 -13
- package/src/Editor.ts +1 -1
- package/src/EditorContent.ts +7 -5
- package/src/NodeViewContent.ts +3 -2
- package/src/NodeViewWrapper.ts +6 -5
- package/src/VueNodeViewRenderer.ts +17 -26
- package/src/VueRenderer.ts +5 -7
- package/src/index.ts +0 -2
- package/src/menus/BubbleMenu.ts +85 -0
- package/src/{FloatingMenu.ts → menus/FloatingMenu.ts} +24 -15
- package/src/menus/index.ts +2 -0
- package/dist/BubbleMenu.d.ts +0 -11
- package/dist/BubbleMenu.d.ts.map +0 -1
- package/dist/Editor.d.ts +0 -6
- package/dist/Editor.d.ts.map +0 -1
- package/dist/EditorContent.d.ts +0 -7
- package/dist/EditorContent.d.ts.map +0 -1
- package/dist/FloatingMenu.d.ts +0 -10
- package/dist/FloatingMenu.d.ts.map +0 -1
- package/dist/NodeViewContent.d.ts +0 -6
- package/dist/NodeViewContent.d.ts.map +0 -1
- package/dist/NodeViewWrapper.d.ts +0 -10
- package/dist/NodeViewWrapper.d.ts.map +0 -1
- package/dist/VueNodeViewRenderer.d.ts +0 -40
- package/dist/VueNodeViewRenderer.d.ts.map +0 -1
- package/dist/VueRenderer.d.ts +0 -13
- package/dist/VueRenderer.d.ts.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.umd.js +0 -433
- package/dist/index.umd.js.map +0 -1
- package/src/BubbleMenu.ts +0 -70
package/dist/index.js
CHANGED
|
@@ -1,418 +1,326 @@
|
|
|
1
|
-
|
|
2
|
-
import { Editor as
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const BubbleMenu = {
|
|
9
|
-
name: 'BubbleMenu',
|
|
10
|
-
props: {
|
|
11
|
-
pluginKey: {
|
|
12
|
-
type: [String, Object],
|
|
13
|
-
default: 'bubbleMenu',
|
|
14
|
-
},
|
|
15
|
-
editor: {
|
|
16
|
-
type: Object,
|
|
17
|
-
required: true,
|
|
18
|
-
},
|
|
19
|
-
updateDelay: {
|
|
20
|
-
type: Number,
|
|
21
|
-
},
|
|
22
|
-
tippyOptions: {
|
|
23
|
-
type: Object,
|
|
24
|
-
default: () => ({}),
|
|
25
|
-
},
|
|
26
|
-
shouldShow: {
|
|
27
|
-
type: Function,
|
|
28
|
-
default: null,
|
|
29
|
-
},
|
|
30
|
-
},
|
|
31
|
-
watch: {
|
|
32
|
-
editor: {
|
|
33
|
-
immediate: true,
|
|
34
|
-
handler(editor) {
|
|
35
|
-
if (!editor) {
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
|
-
this.$nextTick(() => {
|
|
39
|
-
editor.registerPlugin(BubbleMenuPlugin({
|
|
40
|
-
updateDelay: this.updateDelay,
|
|
41
|
-
editor,
|
|
42
|
-
element: this.$el,
|
|
43
|
-
pluginKey: this.pluginKey,
|
|
44
|
-
shouldShow: this.shouldShow,
|
|
45
|
-
tippyOptions: this.tippyOptions,
|
|
46
|
-
}));
|
|
47
|
-
});
|
|
48
|
-
},
|
|
49
|
-
},
|
|
50
|
-
},
|
|
51
|
-
render(createElement) {
|
|
52
|
-
return createElement('div', { style: { visibility: 'hidden' } }, this.$slots.default);
|
|
53
|
-
},
|
|
54
|
-
beforeDestroy() {
|
|
55
|
-
this.editor.unregisterPlugin(this.pluginKey);
|
|
56
|
-
},
|
|
1
|
+
// src/Editor.ts
|
|
2
|
+
import { Editor as CoreEditor } from "@tiptap/core";
|
|
3
|
+
var Editor = class extends CoreEditor {
|
|
4
|
+
constructor() {
|
|
5
|
+
super(...arguments);
|
|
6
|
+
this.contentComponent = null;
|
|
7
|
+
}
|
|
57
8
|
};
|
|
58
9
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
10
|
+
// src/EditorContent.ts
|
|
11
|
+
var EditorContent = {
|
|
12
|
+
name: "EditorContent",
|
|
13
|
+
props: {
|
|
14
|
+
editor: {
|
|
15
|
+
default: null,
|
|
16
|
+
type: Object
|
|
63
17
|
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
editor
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
const element = this.$el;
|
|
81
|
-
if (!element || !editor.options.element.firstChild) {
|
|
82
|
-
return;
|
|
83
|
-
}
|
|
84
|
-
element.append(...editor.options.element.childNodes);
|
|
85
|
-
editor.contentComponent = this;
|
|
86
|
-
editor.setOptions({
|
|
87
|
-
element,
|
|
88
|
-
});
|
|
89
|
-
editor.createNodeViews();
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
},
|
|
93
|
-
},
|
|
94
|
-
},
|
|
95
|
-
render(createElement) {
|
|
96
|
-
return createElement('div');
|
|
97
|
-
},
|
|
98
|
-
beforeDestroy() {
|
|
99
|
-
const { editor } = this;
|
|
100
|
-
if (!editor) {
|
|
101
|
-
return;
|
|
102
|
-
}
|
|
103
|
-
if (!editor.isDestroyed) {
|
|
104
|
-
editor.view.setProps({
|
|
105
|
-
nodeViews: {},
|
|
18
|
+
},
|
|
19
|
+
watch: {
|
|
20
|
+
editor: {
|
|
21
|
+
immediate: true,
|
|
22
|
+
handler(editor) {
|
|
23
|
+
if (editor && editor.options.element) {
|
|
24
|
+
this.$nextTick(() => {
|
|
25
|
+
var _a;
|
|
26
|
+
const element = this.$el;
|
|
27
|
+
if (!element || !((_a = editor.options.element) == null ? void 0 : _a.firstChild)) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
element.append(...editor.options.element.childNodes);
|
|
31
|
+
editor.contentComponent = this;
|
|
32
|
+
editor.setOptions({
|
|
33
|
+
element
|
|
106
34
|
});
|
|
35
|
+
editor.createNodeViews();
|
|
36
|
+
});
|
|
107
37
|
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
render(createElement) {
|
|
42
|
+
return createElement("div");
|
|
43
|
+
},
|
|
44
|
+
beforeDestroy() {
|
|
45
|
+
var _a;
|
|
46
|
+
const { editor } = this;
|
|
47
|
+
if (!editor) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (!editor.isDestroyed) {
|
|
51
|
+
editor.view.setProps({
|
|
52
|
+
nodeViews: {}
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
editor.contentComponent = null;
|
|
56
|
+
if (!((_a = editor.options.element) == null ? void 0 : _a.firstChild)) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
const newElement = document.createElement("div");
|
|
60
|
+
newElement.append(...editor.options.element.childNodes);
|
|
61
|
+
editor.setOptions({
|
|
62
|
+
element: newElement
|
|
63
|
+
});
|
|
64
|
+
}
|
|
118
65
|
};
|
|
119
66
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
},
|
|
139
|
-
},
|
|
140
|
-
watch: {
|
|
141
|
-
editor: {
|
|
142
|
-
immediate: true,
|
|
143
|
-
handler(editor) {
|
|
144
|
-
if (!editor) {
|
|
145
|
-
return;
|
|
146
|
-
}
|
|
147
|
-
this.$nextTick(() => {
|
|
148
|
-
editor.registerPlugin(FloatingMenuPlugin({
|
|
149
|
-
pluginKey: this.pluginKey,
|
|
150
|
-
editor,
|
|
151
|
-
element: this.$el,
|
|
152
|
-
tippyOptions: this.tippyOptions,
|
|
153
|
-
shouldShow: this.shouldShow,
|
|
154
|
-
}));
|
|
155
|
-
});
|
|
156
|
-
},
|
|
157
|
-
},
|
|
158
|
-
},
|
|
159
|
-
render(createElement) {
|
|
160
|
-
return createElement('div', { style: { visibility: 'hidden' } }, this.$slots.default);
|
|
161
|
-
},
|
|
162
|
-
beforeDestroy() {
|
|
163
|
-
this.editor.unregisterPlugin(this.pluginKey);
|
|
164
|
-
},
|
|
67
|
+
// src/NodeViewContent.ts
|
|
68
|
+
var NodeViewContent = {
|
|
69
|
+
props: {
|
|
70
|
+
as: {
|
|
71
|
+
type: String,
|
|
72
|
+
default: "div"
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
render(createElement) {
|
|
76
|
+
return createElement(this.as, {
|
|
77
|
+
style: {
|
|
78
|
+
whiteSpace: "pre-wrap"
|
|
79
|
+
},
|
|
80
|
+
attrs: {
|
|
81
|
+
"data-node-view-content": ""
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
}
|
|
165
85
|
};
|
|
166
86
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
87
|
+
// src/NodeViewWrapper.ts
|
|
88
|
+
var NodeViewWrapper = {
|
|
89
|
+
props: {
|
|
90
|
+
as: {
|
|
91
|
+
type: String,
|
|
92
|
+
default: "div"
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
inject: ["onDragStart", "decorationClasses"],
|
|
96
|
+
render(createElement) {
|
|
97
|
+
return createElement(
|
|
98
|
+
this.as,
|
|
99
|
+
{
|
|
100
|
+
class: this.decorationClasses.value,
|
|
101
|
+
style: {
|
|
102
|
+
whiteSpace: "normal"
|
|
172
103
|
},
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
return createElement(this.as, {
|
|
176
|
-
style: {
|
|
177
|
-
whiteSpace: 'pre-wrap',
|
|
178
|
-
},
|
|
179
|
-
attrs: {
|
|
180
|
-
'data-node-view-content': '',
|
|
181
|
-
},
|
|
182
|
-
});
|
|
183
|
-
},
|
|
184
|
-
};
|
|
185
|
-
|
|
186
|
-
const NodeViewWrapper = {
|
|
187
|
-
props: {
|
|
188
|
-
as: {
|
|
189
|
-
type: String,
|
|
190
|
-
default: 'div',
|
|
104
|
+
attrs: {
|
|
105
|
+
"data-node-view-wrapper": ""
|
|
191
106
|
},
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
},
|
|
200
|
-
attrs: {
|
|
201
|
-
'data-node-view-wrapper': '',
|
|
202
|
-
},
|
|
203
|
-
on: {
|
|
204
|
-
dragstart: this.onDragStart,
|
|
205
|
-
},
|
|
206
|
-
}, this.$slots.default);
|
|
207
|
-
},
|
|
107
|
+
on: {
|
|
108
|
+
dragstart: this.onDragStart
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
this.$slots.default
|
|
112
|
+
);
|
|
113
|
+
}
|
|
208
114
|
};
|
|
209
115
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
const originalSilent = currentVueConstructor.config.silent;
|
|
230
|
-
currentVueConstructor.config.silent = true;
|
|
231
|
-
Object
|
|
232
|
-
.entries(props)
|
|
233
|
-
.forEach(([key, value]) => {
|
|
234
|
-
this.ref.$props[key] = value;
|
|
235
|
-
});
|
|
236
|
-
currentVueConstructor.config.silent = originalSilent;
|
|
237
|
-
}
|
|
238
|
-
destroy() {
|
|
239
|
-
this.ref.$destroy();
|
|
116
|
+
// src/VueNodeViewRenderer.ts
|
|
117
|
+
import { NodeView } from "@tiptap/core";
|
|
118
|
+
import Vue2 from "vue";
|
|
119
|
+
import { booleanProp, functionProp, objectProp } from "vue-ts-types";
|
|
120
|
+
|
|
121
|
+
// src/VueRenderer.ts
|
|
122
|
+
import Vue from "vue";
|
|
123
|
+
var VueRenderer = class {
|
|
124
|
+
constructor(component, props) {
|
|
125
|
+
const Component = typeof component === "function" ? component : Vue.extend(component);
|
|
126
|
+
this.ref = new Component(props).$mount();
|
|
127
|
+
}
|
|
128
|
+
get element() {
|
|
129
|
+
return this.ref.$el;
|
|
130
|
+
}
|
|
131
|
+
updateProps(props = {}) {
|
|
132
|
+
var _a, _b, _c;
|
|
133
|
+
if (!this.ref.$props) {
|
|
134
|
+
return;
|
|
240
135
|
}
|
|
241
|
-
|
|
136
|
+
const currentVueConstructor = (_c = (_b = (_a = this.ref.$props.editor) == null ? void 0 : _a.contentComponent) == null ? void 0 : _b.$options._base) != null ? _c : Vue;
|
|
137
|
+
const originalSilent = currentVueConstructor.config.silent;
|
|
138
|
+
currentVueConstructor.config.silent = true;
|
|
139
|
+
Object.entries(props).forEach(([key, value]) => {
|
|
140
|
+
this.ref.$props[key] = value;
|
|
141
|
+
});
|
|
142
|
+
currentVueConstructor.config.silent = originalSilent;
|
|
143
|
+
}
|
|
144
|
+
destroy() {
|
|
145
|
+
this.ref.$destroy();
|
|
146
|
+
}
|
|
147
|
+
};
|
|
242
148
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
149
|
+
// src/VueNodeViewRenderer.ts
|
|
150
|
+
var nodeViewProps = {
|
|
151
|
+
editor: objectProp().required,
|
|
152
|
+
node: objectProp().required,
|
|
153
|
+
decorations: objectProp().required,
|
|
154
|
+
selected: booleanProp().required,
|
|
155
|
+
extension: objectProp().required,
|
|
156
|
+
getPos: functionProp().required,
|
|
157
|
+
updateAttributes: functionProp().required,
|
|
158
|
+
deleteNode: functionProp().required
|
|
252
159
|
};
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
160
|
+
var VueNodeView = class extends NodeView {
|
|
161
|
+
mount() {
|
|
162
|
+
var _a, _b;
|
|
163
|
+
const props = {
|
|
164
|
+
editor: this.editor,
|
|
165
|
+
node: this.node,
|
|
166
|
+
decorations: this.decorations,
|
|
167
|
+
innerDecorations: this.innerDecorations,
|
|
168
|
+
view: this.view,
|
|
169
|
+
selected: false,
|
|
170
|
+
extension: this.extension,
|
|
171
|
+
HTMLAttributes: this.HTMLAttributes,
|
|
172
|
+
getPos: () => this.getPos(),
|
|
173
|
+
updateAttributes: (attributes = {}) => this.updateAttributes(attributes),
|
|
174
|
+
deleteNode: () => this.deleteNode()
|
|
175
|
+
};
|
|
176
|
+
const onDragStart = this.onDragStart.bind(this);
|
|
177
|
+
this.decorationClasses = Vue2.observable({
|
|
178
|
+
value: this.getDecorationClasses()
|
|
179
|
+
});
|
|
180
|
+
const vue = (_b = (_a = this.editor.contentComponent) == null ? void 0 : _a.$options._base) != null ? _b : Vue2;
|
|
181
|
+
const Component = vue.extend(this.component).extend({
|
|
182
|
+
props: Object.keys(props),
|
|
183
|
+
provide: () => {
|
|
184
|
+
return {
|
|
185
|
+
onDragStart,
|
|
186
|
+
decorationClasses: this.decorationClasses
|
|
268
187
|
};
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
this.editor.on('selectionUpdate', this.handleSelectionUpdate);
|
|
286
|
-
this.renderer = new VueRenderer(Component, {
|
|
287
|
-
parent: this.editor.contentComponent,
|
|
288
|
-
propsData: props,
|
|
289
|
-
});
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
this.handleSelectionUpdate = this.handleSelectionUpdate.bind(this);
|
|
191
|
+
this.editor.on("selectionUpdate", this.handleSelectionUpdate);
|
|
192
|
+
this.renderer = new VueRenderer(Component, {
|
|
193
|
+
parent: this.editor.contentComponent,
|
|
194
|
+
propsData: props
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Return the DOM element.
|
|
199
|
+
* This is the element that will be used to display the node view.
|
|
200
|
+
*/
|
|
201
|
+
get dom() {
|
|
202
|
+
if (!this.renderer.element.hasAttribute("data-node-view-wrapper")) {
|
|
203
|
+
throw Error("Please use the NodeViewWrapper component for your node view.");
|
|
290
204
|
}
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
}
|
|
301
|
-
/**
|
|
302
|
-
* Return the content DOM element.
|
|
303
|
-
* This is the element that will be used to display the rich-text content of the node.
|
|
304
|
-
*/
|
|
305
|
-
get contentDOM() {
|
|
306
|
-
if (this.node.isLeaf) {
|
|
307
|
-
return null;
|
|
308
|
-
}
|
|
309
|
-
const contentElement = this.dom.querySelector('[data-node-view-content]');
|
|
310
|
-
return (contentElement || this.dom);
|
|
311
|
-
}
|
|
312
|
-
/**
|
|
313
|
-
* On editor selection update, check if the node is selected.
|
|
314
|
-
* If it is, call `selectNode`, otherwise call `deselectNode`.
|
|
315
|
-
*/
|
|
316
|
-
handleSelectionUpdate() {
|
|
317
|
-
const { from, to } = this.editor.state.selection;
|
|
318
|
-
const pos = this.getPos();
|
|
319
|
-
if (typeof pos !== 'number') {
|
|
320
|
-
return;
|
|
321
|
-
}
|
|
322
|
-
if (from <= pos && to >= pos + this.node.nodeSize) {
|
|
323
|
-
if (this.renderer.ref.$props.selected) {
|
|
324
|
-
return;
|
|
325
|
-
}
|
|
326
|
-
this.selectNode();
|
|
327
|
-
}
|
|
328
|
-
else {
|
|
329
|
-
if (!this.renderer.ref.$props.selected) {
|
|
330
|
-
return;
|
|
331
|
-
}
|
|
332
|
-
this.deselectNode();
|
|
333
|
-
}
|
|
205
|
+
return this.renderer.element;
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Return the content DOM element.
|
|
209
|
+
* This is the element that will be used to display the rich-text content of the node.
|
|
210
|
+
*/
|
|
211
|
+
get contentDOM() {
|
|
212
|
+
if (this.node.isLeaf) {
|
|
213
|
+
return null;
|
|
334
214
|
}
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
const oldInnerDecorations = this.innerDecorations;
|
|
348
|
-
this.node = node;
|
|
349
|
-
this.decorations = decorations;
|
|
350
|
-
this.innerDecorations = innerDecorations;
|
|
351
|
-
return this.options.update({
|
|
352
|
-
oldNode,
|
|
353
|
-
oldDecorations,
|
|
354
|
-
newNode: node,
|
|
355
|
-
newDecorations: decorations,
|
|
356
|
-
oldInnerDecorations,
|
|
357
|
-
innerDecorations,
|
|
358
|
-
updateProps: () => rerenderComponent({ node, decorations, innerDecorations }),
|
|
359
|
-
});
|
|
360
|
-
}
|
|
361
|
-
if (node.type !== this.node.type) {
|
|
362
|
-
return false;
|
|
363
|
-
}
|
|
364
|
-
if (node === this.node && this.decorations === decorations && this.innerDecorations === innerDecorations) {
|
|
365
|
-
return true;
|
|
366
|
-
}
|
|
367
|
-
this.node = node;
|
|
368
|
-
this.decorations = decorations;
|
|
369
|
-
this.innerDecorations = innerDecorations;
|
|
370
|
-
rerenderComponent({ node, decorations, innerDecorations });
|
|
371
|
-
return true;
|
|
215
|
+
const contentElement = this.dom.querySelector("[data-node-view-content]");
|
|
216
|
+
return contentElement || this.dom;
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* On editor selection update, check if the node is selected.
|
|
220
|
+
* If it is, call `selectNode`, otherwise call `deselectNode`.
|
|
221
|
+
*/
|
|
222
|
+
handleSelectionUpdate() {
|
|
223
|
+
const { from, to } = this.editor.state.selection;
|
|
224
|
+
const pos = this.getPos();
|
|
225
|
+
if (typeof pos !== "number") {
|
|
226
|
+
return;
|
|
372
227
|
}
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
228
|
+
if (from <= pos && to >= pos + this.node.nodeSize) {
|
|
229
|
+
if (this.renderer.ref.$props.selected) {
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
this.selectNode();
|
|
233
|
+
} else {
|
|
234
|
+
if (!this.renderer.ref.$props.selected) {
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
this.deselectNode();
|
|
382
238
|
}
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* On update, update the React component.
|
|
242
|
+
* To prevent unnecessary updates, the `update` option can be used.
|
|
243
|
+
*/
|
|
244
|
+
update(node, decorations, innerDecorations) {
|
|
245
|
+
const rerenderComponent = (props) => {
|
|
246
|
+
this.decorationClasses.value = this.getDecorationClasses();
|
|
247
|
+
this.renderer.updateProps(props);
|
|
248
|
+
};
|
|
249
|
+
if (typeof this.options.update === "function") {
|
|
250
|
+
const oldNode = this.node;
|
|
251
|
+
const oldDecorations = this.decorations;
|
|
252
|
+
const oldInnerDecorations = this.innerDecorations;
|
|
253
|
+
this.node = node;
|
|
254
|
+
this.decorations = decorations;
|
|
255
|
+
this.innerDecorations = innerDecorations;
|
|
256
|
+
return this.options.update({
|
|
257
|
+
oldNode,
|
|
258
|
+
oldDecorations,
|
|
259
|
+
newNode: node,
|
|
260
|
+
newDecorations: decorations,
|
|
261
|
+
oldInnerDecorations,
|
|
262
|
+
innerDecorations,
|
|
263
|
+
updateProps: () => rerenderComponent({ node, decorations, innerDecorations })
|
|
264
|
+
});
|
|
392
265
|
}
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
// @ts-ignore
|
|
396
|
-
.map(item => item.type.attrs.class)
|
|
397
|
-
.flat()
|
|
398
|
-
.join(' '));
|
|
266
|
+
if (node.type !== this.node.type) {
|
|
267
|
+
return false;
|
|
399
268
|
}
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
this.editor.off('selectionUpdate', this.handleSelectionUpdate);
|
|
269
|
+
if (node === this.node && this.decorations === decorations && this.innerDecorations === innerDecorations) {
|
|
270
|
+
return true;
|
|
403
271
|
}
|
|
404
|
-
|
|
272
|
+
this.node = node;
|
|
273
|
+
this.decorations = decorations;
|
|
274
|
+
this.innerDecorations = innerDecorations;
|
|
275
|
+
rerenderComponent({ node, decorations, innerDecorations });
|
|
276
|
+
return true;
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Select the node.
|
|
280
|
+
* Add the `selected` prop and the `ProseMirror-selectednode` class.
|
|
281
|
+
*/
|
|
282
|
+
selectNode() {
|
|
283
|
+
this.renderer.updateProps({
|
|
284
|
+
selected: true
|
|
285
|
+
});
|
|
286
|
+
this.renderer.element.classList.add("ProseMirror-selectednode");
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Deselect the node.
|
|
290
|
+
* Remove the `selected` prop and the `ProseMirror-selectednode` class.
|
|
291
|
+
*/
|
|
292
|
+
deselectNode() {
|
|
293
|
+
this.renderer.updateProps({
|
|
294
|
+
selected: false
|
|
295
|
+
});
|
|
296
|
+
this.renderer.element.classList.remove("ProseMirror-selectednode");
|
|
297
|
+
}
|
|
298
|
+
getDecorationClasses() {
|
|
299
|
+
return this.decorations.map((item) => item.type.attrs.class).flat().join(" ");
|
|
300
|
+
}
|
|
301
|
+
destroy() {
|
|
302
|
+
this.renderer.destroy();
|
|
303
|
+
this.editor.off("selectionUpdate", this.handleSelectionUpdate);
|
|
304
|
+
}
|
|
305
|
+
};
|
|
405
306
|
function VueNodeViewRenderer(component, options) {
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
}
|
|
413
|
-
return new VueNodeView(component, props, options);
|
|
414
|
-
};
|
|
307
|
+
return (props) => {
|
|
308
|
+
if (!props.editor.contentComponent) {
|
|
309
|
+
return {};
|
|
310
|
+
}
|
|
311
|
+
return new VueNodeView(component, props, options);
|
|
312
|
+
};
|
|
415
313
|
}
|
|
416
314
|
|
|
417
|
-
|
|
418
|
-
|
|
315
|
+
// src/index.ts
|
|
316
|
+
export * from "@tiptap/core";
|
|
317
|
+
export {
|
|
318
|
+
Editor,
|
|
319
|
+
EditorContent,
|
|
320
|
+
NodeViewContent,
|
|
321
|
+
NodeViewWrapper,
|
|
322
|
+
VueNodeViewRenderer,
|
|
323
|
+
VueRenderer,
|
|
324
|
+
nodeViewProps
|
|
325
|
+
};
|
|
326
|
+
//# sourceMappingURL=index.js.map
|