@tiptap/vue-2 3.30.1 → 3.30.3

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.js CHANGED
@@ -1,470 +1,392 @@
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
- }
1
+ import { Editor as Editor$1, NodeView, createWidgetDecoration, isNodeViewSelected } from "@tiptap/core";
2
+ import { booleanProp, functionProp, objectProp } from "vue-ts-types";
3
+ import VueDefault from "vue";
4
+ export * from "@tiptap/core";
5
+ //#region src/Editor.ts
6
+ var Editor = class extends Editor$1 {
7
+ constructor(..._args) {
8
+ super(..._args);
9
+ this.contentComponent = null;
10
+ }
8
11
  };
9
-
10
- // src/EditorContent.ts
11
- var EditorContent = {
12
- name: "EditorContent",
13
- props: {
14
- editor: {
15
- default: null,
16
- type: Object
17
- }
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.view.dom) == null ? void 0 : _a.parentNode)) {
28
- return;
29
- }
30
- element.append(...editor.view.dom.parentNode.childNodes);
31
- editor.contentComponent = this;
32
- editor.setOptions({
33
- element
34
- });
35
- editor.createNodeViews();
36
- });
37
- }
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.view.dom) == null ? void 0 : _a.parentNode)) {
57
- return;
58
- }
59
- const newElement = document.createElement("div");
60
- newElement.append(...editor.view.dom.parentNode.childNodes);
61
- editor.setOptions({
62
- element: newElement
63
- });
64
- }
12
+ //#endregion
13
+ //#region src/EditorContent.ts
14
+ const EditorContent = {
15
+ name: "EditorContent",
16
+ props: { editor: {
17
+ default: null,
18
+ type: Object
19
+ } },
20
+ watch: { editor: {
21
+ immediate: true,
22
+ handler(editor) {
23
+ if (editor && editor.options.element) this.$nextTick(() => {
24
+ var _editor$view$dom;
25
+ const element = this.$el;
26
+ if (!element || !((_editor$view$dom = editor.view.dom) === null || _editor$view$dom === void 0 ? void 0 : _editor$view$dom.parentNode)) return;
27
+ element.append(...editor.view.dom.parentNode.childNodes);
28
+ editor.contentComponent = this;
29
+ editor.setOptions({ element });
30
+ editor.createNodeViews();
31
+ });
32
+ }
33
+ } },
34
+ render(createElement) {
35
+ return createElement("div");
36
+ },
37
+ beforeDestroy() {
38
+ var _editor$view$dom2;
39
+ const { editor } = this;
40
+ if (!editor) return;
41
+ if (!editor.isDestroyed) editor.view.setProps({ nodeViews: {} });
42
+ editor.contentComponent = null;
43
+ if (!((_editor$view$dom2 = editor.view.dom) === null || _editor$view$dom2 === void 0 ? void 0 : _editor$view$dom2.parentNode)) return;
44
+ const newElement = document.createElement("div");
45
+ newElement.append(...editor.view.dom.parentNode.childNodes);
46
+ editor.setOptions({ element: newElement });
47
+ }
65
48
  };
66
-
67
- // src/NodeViewContent.ts
68
- var NodeViewContent = {
69
- props: {
70
- as: {
71
- type: String,
72
- default: "div"
73
- }
74
- },
75
- inject: {
76
- nodeViewContentRef: { default: void 0 }
77
- },
78
- mounted() {
79
- if (this.nodeViewContentRef && this.$el) {
80
- this.nodeViewContentRef(this.$el);
81
- }
82
- },
83
- beforeDestroy() {
84
- if (this.nodeViewContentRef) {
85
- this.nodeViewContentRef(null);
86
- }
87
- },
88
- render(createElement) {
89
- return createElement(this.as, {
90
- style: {
91
- whiteSpace: "pre-wrap"
92
- },
93
- attrs: {
94
- "data-node-view-content": ""
95
- }
96
- });
97
- }
49
+ //#endregion
50
+ //#region src/NodeViewContent.ts
51
+ const NodeViewContent = {
52
+ props: { as: {
53
+ type: String,
54
+ default: "div"
55
+ } },
56
+ inject: { nodeViewContentRef: { default: void 0 } },
57
+ mounted() {
58
+ if (this.nodeViewContentRef && this.$el) this.nodeViewContentRef(this.$el);
59
+ },
60
+ beforeDestroy() {
61
+ if (this.nodeViewContentRef) this.nodeViewContentRef(null);
62
+ },
63
+ render(createElement) {
64
+ return createElement(this.as, {
65
+ style: { whiteSpace: "pre-wrap" },
66
+ attrs: { "data-node-view-content": "" }
67
+ });
68
+ }
98
69
  };
99
-
100
- // src/NodeViewWrapper.ts
101
- var NodeViewWrapper = {
102
- props: {
103
- as: {
104
- type: String,
105
- default: "div"
106
- }
107
- },
108
- inject: ["onDragStart", "decorationClasses"],
109
- render(createElement) {
110
- return createElement(
111
- this.as,
112
- {
113
- class: this.decorationClasses.value,
114
- style: {
115
- whiteSpace: "normal"
116
- },
117
- attrs: {
118
- "data-node-view-wrapper": ""
119
- },
120
- on: {
121
- dragstart: this.onDragStart
122
- }
123
- },
124
- this.$slots.default
125
- );
126
- }
70
+ //#endregion
71
+ //#region src/NodeViewWrapper.ts
72
+ const NodeViewWrapper = {
73
+ props: { as: {
74
+ type: String,
75
+ default: "div"
76
+ } },
77
+ inject: ["onDragStart", "decorationClasses"],
78
+ render(createElement) {
79
+ return createElement(this.as, {
80
+ class: this.decorationClasses.value,
81
+ style: { whiteSpace: "normal" },
82
+ attrs: { "data-node-view-wrapper": "" },
83
+ on: { dragstart: this.onDragStart }
84
+ }, this.$slots.default);
85
+ }
127
86
  };
128
-
129
- // src/VueNodeViewRenderer.ts
130
- import { isNodeViewSelected, NodeView } from "@tiptap/core";
131
- import { booleanProp, functionProp, objectProp } from "vue-ts-types";
132
-
133
- // src/Vue.ts
134
- import VueDefault from "vue";
135
- var Vue = VueDefault;
136
-
137
- // src/VueRenderer.ts
87
+ //#endregion
88
+ //#region src/Vue.ts
89
+ const Vue = VueDefault;
90
+ //#endregion
91
+ //#region src/VueRenderer.ts
92
+ /**
93
+ * The VueRenderer class is responsible for rendering a Vue component as a ProseMirror node view.
94
+ */
138
95
  var VueRenderer = class {
139
- constructor(component, props) {
140
- const Component = typeof component === "function" ? component : Vue.extend(component);
141
- this.ref = new Component(props).$mount();
142
- }
143
- get element() {
144
- return this.ref.$el;
145
- }
146
- updateProps(props = {}) {
147
- var _a, _b, _c;
148
- if (!this.ref.$props) {
149
- return;
150
- }
151
- const currentVueConstructor = (_c = (_b = (_a = this.ref.$props.editor) == null ? void 0 : _a.contentComponent) == null ? void 0 : _b.$options._base) != null ? _c : Vue;
152
- const originalSilent = currentVueConstructor.config.silent;
153
- currentVueConstructor.config.silent = true;
154
- Object.entries(props).forEach(([key, value]) => {
155
- this.ref.$props[key] = value;
156
- });
157
- currentVueConstructor.config.silent = originalSilent;
158
- }
159
- destroy() {
160
- this.ref.$destroy();
161
- }
96
+ constructor(component, props) {
97
+ const Component = typeof component === "function" ? component : Vue.extend(component);
98
+ this.ref = new Component(props).$mount();
99
+ }
100
+ get element() {
101
+ return this.ref.$el;
102
+ }
103
+ updateProps(props = {}) {
104
+ var _this$ref$$props$edit, _this$ref$$props$edit2;
105
+ if (!this.ref.$props) return;
106
+ const currentVueConstructor = (_this$ref$$props$edit = (_this$ref$$props$edit2 = this.ref.$props.editor) === null || _this$ref$$props$edit2 === void 0 || (_this$ref$$props$edit2 = _this$ref$$props$edit2.contentComponent) === null || _this$ref$$props$edit2 === void 0 ? void 0 : _this$ref$$props$edit2.$options._base) !== null && _this$ref$$props$edit !== void 0 ? _this$ref$$props$edit : Vue;
107
+ const originalSilent = currentVueConstructor.config.silent;
108
+ currentVueConstructor.config.silent = true;
109
+ Object.entries(props).forEach(([key, value]) => {
110
+ this.ref.$props[key] = value;
111
+ });
112
+ currentVueConstructor.config.silent = originalSilent;
113
+ }
114
+ destroy() {
115
+ this.ref.$destroy();
116
+ }
162
117
  };
163
-
164
- // src/VueNodeViewRenderer.ts
165
- var nodeViewProps = {
166
- editor: objectProp().required,
167
- node: objectProp().required,
168
- decorations: objectProp().required,
169
- selected: booleanProp().required,
170
- extension: objectProp().required,
171
- getPos: functionProp().required,
172
- updateAttributes: functionProp().required,
173
- deleteNode: functionProp().required
118
+ //#endregion
119
+ //#region src/VueNodeViewRenderer.ts
120
+ const nodeViewProps = {
121
+ editor: objectProp().required,
122
+ node: objectProp().required,
123
+ decorations: objectProp().required,
124
+ selected: booleanProp().required,
125
+ extension: objectProp().required,
126
+ getPos: functionProp().required,
127
+ updateAttributes: functionProp().required,
128
+ deleteNode: functionProp().required
174
129
  };
175
130
  var VueNodeView = class extends NodeView {
176
- constructor(component, props, options) {
177
- super(component, props, options);
178
- this.handlePositionUpdate = () => {
179
- const newPos = this.getPos();
180
- if (typeof newPos !== "number" || newPos === this.currentPos) {
181
- return;
182
- }
183
- this.currentPos = newPos;
184
- this.renderer.updateProps({ getPos: () => this.getPos() });
185
- };
186
- if (this.options.trackNodeViewPosition) {
187
- this.editor.on("update", this.handlePositionUpdate);
188
- }
189
- }
190
- /**
191
- * Called when the node view is mounted.
192
- */
193
- mount() {
194
- var _a, _b;
195
- const props = {
196
- editor: this.editor,
197
- node: this.node,
198
- decorations: this.decorations,
199
- innerDecorations: this.innerDecorations,
200
- view: this.view,
201
- selected: false,
202
- extension: this.extension,
203
- HTMLAttributes: this.HTMLAttributes,
204
- getPos: () => this.getPos(),
205
- updateAttributes: (attributes = {}) => this.updateAttributes(attributes),
206
- deleteNode: () => this.deleteNode()
207
- };
208
- const mountProps = props;
209
- const onDragStart = this.onDragStart.bind(this);
210
- this.decorationClasses = Vue.observable({
211
- value: this.getDecorationClasses()
212
- });
213
- const vue = (_b = (_a = this.editor.contentComponent) == null ? void 0 : _a.$options._base) != null ? _b : Vue;
214
- const Component = vue.extend(this.component).extend({
215
- props: Object.keys(props),
216
- provide: () => {
217
- return {
218
- onDragStart,
219
- decorationClasses: this.decorationClasses,
220
- nodeViewContentRef: (el) => {
221
- if (!this.contentDOMElement) return;
222
- if (el && el.firstChild !== this.contentDOMElement) {
223
- el.appendChild(this.contentDOMElement);
224
- }
225
- }
226
- };
227
- }
228
- });
229
- this.handleSelectionUpdate = this.handleSelectionUpdate.bind(this);
230
- this.editor.on("selectionUpdate", this.handleSelectionUpdate);
231
- this.currentPos = this.getPos();
232
- if (!this.node.isLeaf) {
233
- if (this.options.contentDOMElementTag) {
234
- this.contentDOMElement = document.createElement(this.options.contentDOMElementTag);
235
- } else {
236
- this.contentDOMElement = document.createElement(this.node.isInline ? "span" : "div");
237
- }
238
- this.contentDOMElement.style.whiteSpace = "inherit";
239
- this.contentDOMElement.dataset.nodeViewContentVue = "";
240
- }
241
- this.renderer = new VueRenderer(Component, {
242
- parent: this.editor.contentComponent,
243
- propsData: mountProps
244
- });
245
- }
246
- /**
247
- * Return the DOM element.
248
- * This is the element that will be used to display the node view.
249
- */
250
- get dom() {
251
- if (!this.renderer.element.hasAttribute("data-node-view-wrapper")) {
252
- throw Error("Please use the NodeViewWrapper component for your node view.");
253
- }
254
- return this.renderer.element;
255
- }
256
- /**
257
- * Return the content DOM element.
258
- * This is the element that will be used to display the rich-text content of the node.
259
- */
260
- get contentDOM() {
261
- if (this.node.isLeaf) {
262
- return null;
263
- }
264
- return this.contentDOMElement;
265
- }
266
- /**
267
- * On editor selection update, check if the node is selected.
268
- * If it is, call `selectNode`, otherwise call `deselectNode`.
269
- */
270
- handleSelectionUpdate() {
271
- const pos = this.getPos();
272
- if (typeof pos !== "number") {
273
- return;
274
- }
275
- const isSelected = isNodeViewSelected({
276
- selection: this.editor.state.selection,
277
- pos,
278
- nodeSize: this.node.nodeSize,
279
- selectedOnTextSelection: this.options.selectedOnTextSelection
280
- });
281
- if (isSelected) {
282
- if (this.renderer.ref.$props.selected) {
283
- return;
284
- }
285
- this.selectNode();
286
- } else {
287
- if (!this.renderer.ref.$props.selected) {
288
- return;
289
- }
290
- this.deselectNode();
291
- }
292
- }
293
- /**
294
- * On update, update the React component.
295
- * To prevent unnecessary updates, the `update` option can be used.
296
- */
297
- update(node, decorations, innerDecorations) {
298
- const rerenderComponent = (props) => {
299
- this.decorationClasses.value = this.getDecorationClasses();
300
- this.renderer.updateProps(props);
301
- };
302
- if (typeof this.options.update === "function") {
303
- const oldNode = this.node;
304
- const oldDecorations = this.decorations;
305
- const oldInnerDecorations = this.innerDecorations;
306
- this.node = node;
307
- this.decorations = decorations;
308
- this.innerDecorations = innerDecorations;
309
- return this.options.update({
310
- oldNode,
311
- oldDecorations,
312
- newNode: node,
313
- newDecorations: decorations,
314
- oldInnerDecorations,
315
- innerDecorations,
316
- updateProps: () => rerenderComponent({ node, decorations, innerDecorations })
317
- });
318
- }
319
- if (node.type !== this.node.type) {
320
- return false;
321
- }
322
- const nodeChanged = node !== this.node;
323
- if (!nodeChanged) {
324
- this.node = node;
325
- this.decorations = decorations;
326
- this.innerDecorations = innerDecorations;
327
- this.decorationClasses.value = this.getDecorationClasses();
328
- return true;
329
- }
330
- this.node = node;
331
- this.decorations = decorations;
332
- this.innerDecorations = innerDecorations;
333
- this.currentPos = this.getPos();
334
- const extraProps = {
335
- node,
336
- decorations,
337
- innerDecorations
338
- };
339
- if (this.options.trackNodeViewPosition) {
340
- extraProps.getPos = () => this.getPos();
341
- }
342
- rerenderComponent(extraProps);
343
- return true;
344
- }
345
- /**
346
- * Select the node.
347
- * Add the `selected` prop and the `ProseMirror-selectednode` class.
348
- */
349
- selectNode() {
350
- this.renderer.updateProps({
351
- selected: true
352
- });
353
- this.renderer.element.classList.add("ProseMirror-selectednode");
354
- }
355
- /**
356
- * Deselect the node.
357
- * Remove the `selected` prop and the `ProseMirror-selectednode` class.
358
- */
359
- deselectNode() {
360
- this.renderer.updateProps({
361
- selected: false
362
- });
363
- this.renderer.element.classList.remove("ProseMirror-selectednode");
364
- }
365
- getDecorationClasses() {
366
- return this.decorations.flatMap((item) => item.type.attrs.class).join(" ");
367
- }
368
- destroy() {
369
- this.renderer.destroy();
370
- this.editor.off("selectionUpdate", this.handleSelectionUpdate);
371
- if (this.options.trackNodeViewPosition) {
372
- this.editor.off("update", this.handlePositionUpdate);
373
- }
374
- this.contentDOMElement = null;
375
- }
131
+ constructor(component, props, options) {
132
+ super(component, props, options);
133
+ this.handlePositionUpdate = () => {
134
+ const newPos = this.getPos();
135
+ if (typeof newPos !== "number" || newPos === this.currentPos) return;
136
+ this.currentPos = newPos;
137
+ this.renderer.updateProps({ getPos: () => this.getPos() });
138
+ };
139
+ if (this.options.trackNodeViewPosition) this.editor.on("update", this.handlePositionUpdate);
140
+ }
141
+ /**
142
+ * Called when the node view is mounted.
143
+ */
144
+ mount() {
145
+ var _this$editor$contentC, _this$editor$contentC2;
146
+ const props = {
147
+ editor: this.editor,
148
+ node: this.node,
149
+ decorations: this.decorations,
150
+ innerDecorations: this.innerDecorations,
151
+ view: this.view,
152
+ selected: false,
153
+ extension: this.extension,
154
+ HTMLAttributes: this.HTMLAttributes,
155
+ getPos: () => this.getPos(),
156
+ updateAttributes: (attributes = {}) => this.updateAttributes(attributes),
157
+ deleteNode: () => this.deleteNode()
158
+ };
159
+ const mountProps = props;
160
+ const onDragStart = this.onDragStart.bind(this);
161
+ this.decorationClasses = Vue.observable({ value: this.getDecorationClasses() });
162
+ const Component = ((_this$editor$contentC = (_this$editor$contentC2 = this.editor.contentComponent) === null || _this$editor$contentC2 === void 0 ? void 0 : _this$editor$contentC2.$options._base) !== null && _this$editor$contentC !== void 0 ? _this$editor$contentC : Vue).extend(this.component).extend({
163
+ props: Object.keys(props),
164
+ provide: () => {
165
+ return {
166
+ onDragStart,
167
+ decorationClasses: this.decorationClasses,
168
+ nodeViewContentRef: (el) => {
169
+ if (!this.contentDOMElement) return;
170
+ if (el && el.firstChild !== this.contentDOMElement) el.appendChild(this.contentDOMElement);
171
+ }
172
+ };
173
+ }
174
+ });
175
+ this.handleSelectionUpdate = this.handleSelectionUpdate.bind(this);
176
+ this.editor.on("selectionUpdate", this.handleSelectionUpdate);
177
+ this.currentPos = this.getPos();
178
+ if (!this.node.isLeaf) {
179
+ if (this.options.contentDOMElementTag) this.contentDOMElement = document.createElement(this.options.contentDOMElementTag);
180
+ else this.contentDOMElement = document.createElement(this.node.isInline ? "span" : "div");
181
+ this.contentDOMElement.style.whiteSpace = "inherit";
182
+ this.contentDOMElement.dataset.nodeViewContentVue = "";
183
+ }
184
+ this.renderer = new VueRenderer(Component, {
185
+ parent: this.editor.contentComponent,
186
+ propsData: mountProps
187
+ });
188
+ }
189
+ /**
190
+ * Return the DOM element.
191
+ * This is the element that will be used to display the node view.
192
+ */
193
+ get dom() {
194
+ if (!this.renderer.element.hasAttribute("data-node-view-wrapper")) throw Error("Please use the NodeViewWrapper component for your node view.");
195
+ return this.renderer.element;
196
+ }
197
+ /**
198
+ * Return the content DOM element.
199
+ * This is the element that will be used to display the rich-text content of the node.
200
+ */
201
+ get contentDOM() {
202
+ if (this.node.isLeaf) return null;
203
+ return this.contentDOMElement;
204
+ }
205
+ /**
206
+ * On editor selection update, check if the node is selected.
207
+ * If it is, call `selectNode`, otherwise call `deselectNode`.
208
+ */
209
+ handleSelectionUpdate() {
210
+ const pos = this.getPos();
211
+ if (typeof pos !== "number") return;
212
+ if (isNodeViewSelected({
213
+ selection: this.editor.state.selection,
214
+ pos,
215
+ nodeSize: this.node.nodeSize,
216
+ selectedOnTextSelection: this.options.selectedOnTextSelection
217
+ })) {
218
+ if (this.renderer.ref.$props.selected) return;
219
+ this.selectNode();
220
+ } else {
221
+ if (!this.renderer.ref.$props.selected) return;
222
+ this.deselectNode();
223
+ }
224
+ }
225
+ /**
226
+ * On update, update the React component.
227
+ * To prevent unnecessary updates, the `update` option can be used.
228
+ */
229
+ update(node, decorations, innerDecorations) {
230
+ const rerenderComponent = (props) => {
231
+ this.decorationClasses.value = this.getDecorationClasses();
232
+ this.renderer.updateProps(props);
233
+ };
234
+ if (typeof this.options.update === "function") {
235
+ const oldNode = this.node;
236
+ const oldDecorations = this.decorations;
237
+ const oldInnerDecorations = this.innerDecorations;
238
+ this.node = node;
239
+ this.decorations = decorations;
240
+ this.innerDecorations = innerDecorations;
241
+ return this.options.update({
242
+ oldNode,
243
+ oldDecorations,
244
+ newNode: node,
245
+ newDecorations: decorations,
246
+ oldInnerDecorations,
247
+ innerDecorations,
248
+ updateProps: () => rerenderComponent({
249
+ node,
250
+ decorations,
251
+ innerDecorations
252
+ })
253
+ });
254
+ }
255
+ if (node.type !== this.node.type) return false;
256
+ if (!(node !== this.node)) {
257
+ this.node = node;
258
+ this.decorations = decorations;
259
+ this.innerDecorations = innerDecorations;
260
+ this.decorationClasses.value = this.getDecorationClasses();
261
+ return true;
262
+ }
263
+ this.node = node;
264
+ this.decorations = decorations;
265
+ this.innerDecorations = innerDecorations;
266
+ this.currentPos = this.getPos();
267
+ const extraProps = {
268
+ node,
269
+ decorations,
270
+ innerDecorations
271
+ };
272
+ if (this.options.trackNodeViewPosition) extraProps.getPos = () => this.getPos();
273
+ rerenderComponent(extraProps);
274
+ return true;
275
+ }
276
+ /**
277
+ * Select the node.
278
+ * Add the `selected` prop and the `ProseMirror-selectednode` class.
279
+ */
280
+ selectNode() {
281
+ this.renderer.updateProps({ selected: true });
282
+ this.renderer.element.classList.add("ProseMirror-selectednode");
283
+ }
284
+ /**
285
+ * Deselect the node.
286
+ * Remove the `selected` prop and the `ProseMirror-selectednode` class.
287
+ */
288
+ deselectNode() {
289
+ this.renderer.updateProps({ selected: false });
290
+ this.renderer.element.classList.remove("ProseMirror-selectednode");
291
+ }
292
+ getDecorationClasses() {
293
+ return this.decorations.flatMap((item) => item.type.attrs.class).join(" ");
294
+ }
295
+ destroy() {
296
+ this.renderer.destroy();
297
+ this.editor.off("selectionUpdate", this.handleSelectionUpdate);
298
+ if (this.options.trackNodeViewPosition) this.editor.off("update", this.handlePositionUpdate);
299
+ this.contentDOMElement = null;
300
+ }
376
301
  };
377
302
  function VueNodeViewRenderer(component, options) {
378
- return (props) => {
379
- if (!props.editor.contentComponent) {
380
- return {};
381
- }
382
- return new VueNodeView(component, props, options);
383
- };
303
+ return (props) => {
304
+ if (!props.editor.contentComponent) return {};
305
+ return new VueNodeView(component, props, options);
306
+ };
384
307
  }
385
-
386
- // src/VueWidgetRenderer.ts
387
- import { createWidgetDecoration } from "@tiptap/core";
388
-
389
- // src/utils/createWidgetConstructor.ts
308
+ //#endregion
309
+ //#region src/utils/createWidgetConstructor.ts
310
+ /**
311
+ * Builds the Vue 2 constructor for a widget component.
312
+ *
313
+ * Extends the editor's own Vue constructor so the widget shares its context,
314
+ * then auto-declares every passed prop the component does not declare itself.
315
+ * Vue 2 fixes the prop list at construction, so undeclared keys would be
316
+ * dropped. Existing declarations keep their type, default and validator.
317
+ *
318
+ * @param base The editor's Vue constructor, or undefined to fall back to `Vue`.
319
+ * @param component The widget component.
320
+ * @param props The props the widget is mounted with.
321
+ * @returns A constructor that accepts every key in `props`.
322
+ * @example
323
+ * createWidgetConstructor(undefined, MyWidget, { editor, getPos, label: 'a' })
324
+ */
390
325
  function createWidgetConstructor(base, component, props) {
391
- const VueBase = base != null ? base : Vue;
392
- const Extended = VueBase.extend(component);
393
- const declaredProps = {
394
- ...Extended.options.props
395
- };
396
- for (const name of Object.keys(props)) {
397
- if (!Object.prototype.hasOwnProperty.call(declaredProps, name)) {
398
- declaredProps[name] = null;
399
- }
400
- }
401
- return Extended.extend({ props: declaredProps });
326
+ const Extended = (base !== null && base !== void 0 ? base : Vue).extend(component);
327
+ const declaredProps = { ...Extended.options.props };
328
+ for (const name of Object.keys(props)) if (!Object.prototype.hasOwnProperty.call(declaredProps, name)) declaredProps[name] = null;
329
+ return Extended.extend({ props: declaredProps });
402
330
  }
403
-
404
- // src/VueWidgetRenderer.ts
405
- var WIDGET_CACHE = /* @__PURE__ */ Symbol("tiptapVue2WidgetCache");
406
- var isDev = process.env.NODE_ENV !== "production";
331
+ //#endregion
332
+ //#region src/VueWidgetRenderer.ts
333
+ const WIDGET_CACHE = Symbol("tiptapVue2WidgetCache");
334
+ const isDev = process.env.NODE_ENV !== "production";
407
335
  function warnUndeclaredProps(renderer, props, key) {
408
- var _a;
409
- if (!isDev) {
410
- return;
411
- }
412
- const declared = (_a = renderer.ref.$props) != null ? _a : {};
413
- for (const name of Object.keys(props)) {
414
- if (!(name in declared)) {
415
- console.warn(
416
- `[tiptap warn]: VueWidgetRenderer prop "${name}" was not passed on first mount for widget "${key}".`,
417
- "Vue 2 cannot declare new props after mount, so this value is ignored."
418
- );
419
- }
420
- }
336
+ var _renderer$ref$$props;
337
+ if (!isDev) return;
338
+ const declared = (_renderer$ref$$props = renderer.ref.$props) !== null && _renderer$ref$$props !== void 0 ? _renderer$ref$$props : {};
339
+ for (const name of Object.keys(props)) if (!(name in declared)) console.warn(`[tiptap warn]: VueWidgetRenderer prop "${name}" was not passed on first mount for widget "${key}".`, "Vue 2 cannot declare new props after mount, so this value is ignored.");
421
340
  }
422
341
  function withPropWarnings(renderer, key) {
423
- return {
424
- renderer,
425
- updateProps: (props) => {
426
- warnUndeclaredProps(renderer, props, key);
427
- renderer.updateProps(props);
428
- },
429
- destroy: () => renderer.destroy()
430
- };
342
+ return {
343
+ renderer,
344
+ updateProps: (props) => {
345
+ warnUndeclaredProps(renderer, props, key);
346
+ renderer.updateProps(props);
347
+ },
348
+ destroy: () => renderer.destroy()
349
+ };
431
350
  }
351
+ /**
352
+ * Renders a Vue 2 component into a ProseMirror widget decoration.
353
+ * Reuses Tiptap's `VueRenderer` so the component is mounted under the editor's
354
+ * content component (inject/provide works as usual). Use a stable `key` for
355
+ * stateful widgets. The component must render a single root element.
356
+ * @example
357
+ * addDecorations() {
358
+ * return {
359
+ * create: ({ editor, state }) =>
360
+ * findMatches(state.doc).map(match =>
361
+ * VueWidgetRenderer(MyWidget, {
362
+ * editor, pos: match.pos, key: `match-${match.id}`,
363
+ * props: { label: match.label },
364
+ * }),
365
+ * ),
366
+ * }
367
+ * }
368
+ */
432
369
  function VueWidgetRenderer(component, options) {
433
- const { editor, key, props = {} } = options;
434
- return createWidgetDecoration({
435
- // Forwards editor, pos, key and the ProseMirror widget options unchanged.
436
- ...options,
437
- props,
438
- cacheKey: WIDGET_CACHE,
439
- // `view` is not passed on purpose: Vue 2 deeply observes props and
440
- // observing a ProseMirror view corrupts its internals.
441
- context: (getPos) => ({ editor, getPos }),
442
- create: (renderProps) => {
443
- var _a, _b;
444
- const base = (_b = (_a = editor.contentComponent) == null ? void 0 : _a.$options) == null ? void 0 : _b._base;
445
- const Constructor = createWidgetConstructor(base, component, renderProps);
446
- return withPropWarnings(
447
- new VueRenderer(Constructor, {
448
- parent: editor.contentComponent,
449
- propsData: renderProps
450
- }),
451
- key
452
- );
453
- },
454
- materialize: (entry) => entry.renderer.element
455
- });
370
+ const { editor, key, props = {} } = options;
371
+ return createWidgetDecoration({
372
+ ...options,
373
+ props,
374
+ cacheKey: WIDGET_CACHE,
375
+ context: (getPos) => ({
376
+ editor,
377
+ getPos
378
+ }),
379
+ create: (renderProps) => {
380
+ var _editor$contentCompon;
381
+ return withPropWarnings(new VueRenderer(createWidgetConstructor((_editor$contentCompon = editor.contentComponent) === null || _editor$contentCompon === void 0 || (_editor$contentCompon = _editor$contentCompon.$options) === null || _editor$contentCompon === void 0 ? void 0 : _editor$contentCompon._base, component, renderProps), {
382
+ parent: editor.contentComponent,
383
+ propsData: renderProps
384
+ }), key);
385
+ },
386
+ materialize: (entry) => entry.renderer.element
387
+ });
456
388
  }
389
+ //#endregion
390
+ export { Editor, EditorContent, NodeViewContent, NodeViewWrapper, VueNodeViewRenderer, VueRenderer, VueWidgetRenderer, nodeViewProps };
457
391
 
458
- // src/index.ts
459
- export * from "@tiptap/core";
460
- export {
461
- Editor,
462
- EditorContent,
463
- NodeViewContent,
464
- NodeViewWrapper,
465
- VueNodeViewRenderer,
466
- VueRenderer,
467
- VueWidgetRenderer,
468
- nodeViewProps
469
- };
470
392
  //# sourceMappingURL=index.js.map