@tiptap/vue-3 3.22.0 → 3.22.2

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tiptap/vue-3",
3
3
  "description": "Vue components for tiptap",
4
- "version": "3.22.0",
4
+ "version": "3.22.2",
5
5
  "homepage": "https://tiptap.dev",
6
6
  "keywords": [
7
7
  "tiptap",
@@ -40,18 +40,18 @@
40
40
  ],
41
41
  "devDependencies": {
42
42
  "vue": "^3.5.13",
43
- "@tiptap/core": "^3.22.0",
44
- "@tiptap/pm": "^3.22.0"
43
+ "@tiptap/pm": "^3.22.2",
44
+ "@tiptap/core": "^3.22.2"
45
45
  },
46
46
  "optionalDependencies": {
47
- "@tiptap/extension-bubble-menu": "^3.22.0",
48
- "@tiptap/extension-floating-menu": "^3.22.0"
47
+ "@tiptap/extension-bubble-menu": "^3.22.2",
48
+ "@tiptap/extension-floating-menu": "^3.22.2"
49
49
  },
50
50
  "peerDependencies": {
51
51
  "vue": "^3.0.0",
52
52
  "@floating-ui/dom": "^1.0.0",
53
- "@tiptap/pm": "^3.22.0",
54
- "@tiptap/core": "^3.22.0"
53
+ "@tiptap/core": "^3.22.2",
54
+ "@tiptap/pm": "^3.22.2"
55
55
  },
56
56
  "repository": {
57
57
  "type": "git",
@@ -1,6 +1,6 @@
1
1
  /* eslint-disable no-underscore-dangle */
2
2
  import type { DecorationWithType, NodeViewProps, NodeViewRenderer, NodeViewRendererOptions } from '@tiptap/core'
3
- import { NodeView } from '@tiptap/core'
3
+ import { cancelPositionCheck, NodeView, schedulePositionCheck } from '@tiptap/core'
4
4
  import type { Node as ProseMirrorNode } from '@tiptap/pm/model'
5
5
  import type { Decoration, DecorationSource, NodeView as ProseMirrorNodeView } from '@tiptap/pm/view'
6
6
  import type { Component, PropType, Ref } from 'vue'
@@ -75,6 +75,18 @@ class VueNodeView extends NodeView<Component, Editor, VueNodeViewRendererOptions
75
75
 
76
76
  decorationClasses!: Ref<string>
77
77
 
78
+ /**
79
+ * The last known position of this node view, used to detect position-only
80
+ * changes that don't produce a new node object reference.
81
+ */
82
+ private currentPos: number | undefined
83
+
84
+ /**
85
+ * Callback registered with the per-editor position-update registry.
86
+ * Stored so it can be unregistered in destroy().
87
+ */
88
+ private positionCheckCallback: (() => void) | null = null
89
+
78
90
  private cachedExtensionWithSyncedStorage: NodeViewProps['extension'] | null = null
79
91
 
80
92
  /**
@@ -150,6 +162,27 @@ class VueNodeView extends NodeView<Component, Editor, VueNodeViewRendererOptions
150
162
 
151
163
  this.handleSelectionUpdate = this.handleSelectionUpdate.bind(this)
152
164
  this.editor.on('selectionUpdate', this.handleSelectionUpdate)
165
+ this.currentPos = this.getPos()
166
+
167
+ this.positionCheckCallback = () => {
168
+ // Guard against the callback firing before the renderer is fully initialized.
169
+ if (!this.renderer) {
170
+ return
171
+ }
172
+
173
+ const newPos = this.getPos()
174
+
175
+ if (typeof newPos !== 'number' || newPos === this.currentPos) {
176
+ return
177
+ }
178
+
179
+ this.currentPos = newPos
180
+
181
+ // Pass a fresh getPos reference so Vue's reactivity detects a prop change.
182
+ this.renderer.updateProps({ getPos: () => this.getPos() })
183
+ }
184
+
185
+ schedulePositionCheck(this.editor, this.positionCheckCallback)
153
186
 
154
187
  this.renderer = new VueRenderer(extendedComponent, {
155
188
  editor: this.editor,
@@ -226,6 +259,7 @@ class VueNodeView extends NodeView<Component, Editor, VueNodeViewRendererOptions
226
259
  this.node = node
227
260
  this.decorations = decorations
228
261
  this.innerDecorations = innerDecorations
262
+ this.currentPos = this.getPos()
229
263
 
230
264
  return this.options.update({
231
265
  oldNode,
@@ -243,13 +277,31 @@ class VueNodeView extends NodeView<Component, Editor, VueNodeViewRendererOptions
243
277
  return false
244
278
  }
245
279
 
280
+ const newPos = this.getPos()
281
+
246
282
  if (node === this.node && this.decorations === decorations && this.innerDecorations === innerDecorations) {
283
+ if (newPos === this.currentPos) {
284
+ return true
285
+ }
286
+
287
+ // Position changed without a content/decoration change — trigger re-render
288
+ // so the component receives an up-to-date value from getPos().
289
+ // Pass a fresh getPos reference so Vue's reactivity detects a prop change.
290
+ this.currentPos = newPos
291
+ rerenderComponent({
292
+ node,
293
+ decorations,
294
+ innerDecorations,
295
+ extension: this.extensionWithSyncedStorage,
296
+ getPos: () => this.getPos(),
297
+ })
247
298
  return true
248
299
  }
249
300
 
250
301
  this.node = node
251
302
  this.decorations = decorations
252
303
  this.innerDecorations = innerDecorations
304
+ this.currentPos = newPos
253
305
 
254
306
  rerenderComponent({ node, decorations, innerDecorations, extension: this.extensionWithSyncedStorage })
255
307
 
@@ -294,6 +346,11 @@ class VueNodeView extends NodeView<Component, Editor, VueNodeViewRendererOptions
294
346
  destroy() {
295
347
  this.renderer.destroy()
296
348
  this.editor.off('selectionUpdate', this.handleSelectionUpdate)
349
+
350
+ if (this.positionCheckCallback) {
351
+ cancelPositionCheck(this.editor, this.positionCheckCallback)
352
+ this.positionCheckCallback = null
353
+ }
297
354
  }
298
355
  }
299
356