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