@tiptap/vue-2 2.11.7 → 3.0.0-beta.1
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 +340 -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 +298 -391
- package/dist/index.js.map +1 -1
- package/dist/menus/index.cjs +2140 -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 +2112 -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 +18 -29
- 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,325 @@
|
|
|
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
|
-
const oldDecorations = this.decorations;
|
|
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
|
+
return this.dom.querySelector("[data-node-view-content]");
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* On editor selection update, check if the node is selected.
|
|
219
|
+
* If it is, call `selectNode`, otherwise call `deselectNode`.
|
|
220
|
+
*/
|
|
221
|
+
handleSelectionUpdate() {
|
|
222
|
+
const { from, to } = this.editor.state.selection;
|
|
223
|
+
const pos = this.getPos();
|
|
224
|
+
if (typeof pos !== "number") {
|
|
225
|
+
return;
|
|
372
226
|
}
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
227
|
+
if (from <= pos && to >= pos + this.node.nodeSize) {
|
|
228
|
+
if (this.renderer.ref.$props.selected) {
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
this.selectNode();
|
|
232
|
+
} else {
|
|
233
|
+
if (!this.renderer.ref.$props.selected) {
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
this.deselectNode();
|
|
382
237
|
}
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* On update, update the React component.
|
|
241
|
+
* To prevent unnecessary updates, the `update` option can be used.
|
|
242
|
+
*/
|
|
243
|
+
update(node, decorations, innerDecorations) {
|
|
244
|
+
const rerenderComponent = (props) => {
|
|
245
|
+
this.decorationClasses.value = this.getDecorationClasses();
|
|
246
|
+
this.renderer.updateProps(props);
|
|
247
|
+
};
|
|
248
|
+
if (typeof this.options.update === "function") {
|
|
249
|
+
const oldNode = this.node;
|
|
250
|
+
const oldDecorations = this.decorations;
|
|
251
|
+
const oldInnerDecorations = this.innerDecorations;
|
|
252
|
+
this.node = node;
|
|
253
|
+
this.decorations = decorations;
|
|
254
|
+
this.innerDecorations = innerDecorations;
|
|
255
|
+
return this.options.update({
|
|
256
|
+
oldNode,
|
|
257
|
+
oldDecorations,
|
|
258
|
+
newNode: node,
|
|
259
|
+
newDecorations: decorations,
|
|
260
|
+
oldInnerDecorations,
|
|
261
|
+
innerDecorations,
|
|
262
|
+
updateProps: () => rerenderComponent({ node, decorations, innerDecorations })
|
|
263
|
+
});
|
|
392
264
|
}
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
// @ts-ignore
|
|
396
|
-
.map(item => item.type.attrs.class)
|
|
397
|
-
.flat()
|
|
398
|
-
.join(' '));
|
|
265
|
+
if (node.type !== this.node.type) {
|
|
266
|
+
return false;
|
|
399
267
|
}
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
this.editor.off('selectionUpdate', this.handleSelectionUpdate);
|
|
268
|
+
if (node === this.node && this.decorations === decorations && this.innerDecorations === innerDecorations) {
|
|
269
|
+
return true;
|
|
403
270
|
}
|
|
404
|
-
|
|
271
|
+
this.node = node;
|
|
272
|
+
this.decorations = decorations;
|
|
273
|
+
this.innerDecorations = innerDecorations;
|
|
274
|
+
rerenderComponent({ node, decorations, innerDecorations });
|
|
275
|
+
return true;
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Select the node.
|
|
279
|
+
* Add the `selected` prop and the `ProseMirror-selectednode` class.
|
|
280
|
+
*/
|
|
281
|
+
selectNode() {
|
|
282
|
+
this.renderer.updateProps({
|
|
283
|
+
selected: true
|
|
284
|
+
});
|
|
285
|
+
this.renderer.element.classList.add("ProseMirror-selectednode");
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Deselect the node.
|
|
289
|
+
* Remove the `selected` prop and the `ProseMirror-selectednode` class.
|
|
290
|
+
*/
|
|
291
|
+
deselectNode() {
|
|
292
|
+
this.renderer.updateProps({
|
|
293
|
+
selected: false
|
|
294
|
+
});
|
|
295
|
+
this.renderer.element.classList.remove("ProseMirror-selectednode");
|
|
296
|
+
}
|
|
297
|
+
getDecorationClasses() {
|
|
298
|
+
return this.decorations.map((item) => item.type.attrs.class).flat().join(" ");
|
|
299
|
+
}
|
|
300
|
+
destroy() {
|
|
301
|
+
this.renderer.destroy();
|
|
302
|
+
this.editor.off("selectionUpdate", this.handleSelectionUpdate);
|
|
303
|
+
}
|
|
304
|
+
};
|
|
405
305
|
function VueNodeViewRenderer(component, options) {
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
}
|
|
413
|
-
return new VueNodeView(component, props, options);
|
|
414
|
-
};
|
|
306
|
+
return (props) => {
|
|
307
|
+
if (!props.editor.contentComponent) {
|
|
308
|
+
return {};
|
|
309
|
+
}
|
|
310
|
+
return new VueNodeView(component, props, options);
|
|
311
|
+
};
|
|
415
312
|
}
|
|
416
313
|
|
|
417
|
-
|
|
418
|
-
|
|
314
|
+
// src/index.ts
|
|
315
|
+
export * from "@tiptap/core";
|
|
316
|
+
export {
|
|
317
|
+
Editor,
|
|
318
|
+
EditorContent,
|
|
319
|
+
NodeViewContent,
|
|
320
|
+
NodeViewWrapper,
|
|
321
|
+
VueNodeViewRenderer,
|
|
322
|
+
VueRenderer,
|
|
323
|
+
nodeViewProps
|
|
324
|
+
};
|
|
325
|
+
//# sourceMappingURL=index.js.map
|