@tiptap/core 3.22.0 → 3.22.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/dist/index.cjs +45 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +13 -1
- package/dist/index.d.ts +13 -1
- package/dist/index.js +43 -1
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/NodeView.ts +10 -1
- package/src/utilities/index.ts +1 -0
- package/src/utilities/nodeViewPositionRegistry.ts +70 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tiptap/core",
|
|
3
3
|
"description": "headless rich text editor",
|
|
4
|
-
"version": "3.22.
|
|
4
|
+
"version": "3.22.1",
|
|
5
5
|
"homepage": "https://tiptap.dev",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"tiptap",
|
|
@@ -52,10 +52,10 @@
|
|
|
52
52
|
"jsx-dev-runtime"
|
|
53
53
|
],
|
|
54
54
|
"devDependencies": {
|
|
55
|
-
"@tiptap/pm": "^3.22.
|
|
55
|
+
"@tiptap/pm": "^3.22.1"
|
|
56
56
|
},
|
|
57
57
|
"peerDependencies": {
|
|
58
|
-
"@tiptap/pm": "^3.22.
|
|
58
|
+
"@tiptap/pm": "^3.22.1"
|
|
59
59
|
},
|
|
60
60
|
"repository": {
|
|
61
61
|
"type": "git",
|
package/src/NodeView.ts
CHANGED
|
@@ -173,6 +173,7 @@ export class NodeView<
|
|
|
173
173
|
}
|
|
174
174
|
|
|
175
175
|
const isDragEvent = event.type.startsWith('drag')
|
|
176
|
+
const isDragOverEnterEvent = event.type === 'dragover' || event.type === 'dragenter'
|
|
176
177
|
const isDropEvent = event.type === 'drop'
|
|
177
178
|
const isInput = ['INPUT', 'BUTTON', 'SELECT', 'TEXTAREA'].includes(target.tagName) || target.isContentEditable
|
|
178
179
|
|
|
@@ -237,7 +238,15 @@ export class NodeView<
|
|
|
237
238
|
}
|
|
238
239
|
|
|
239
240
|
// these events are handled by prosemirror
|
|
240
|
-
if (
|
|
241
|
+
if (
|
|
242
|
+
isDragging ||
|
|
243
|
+
isDragOverEnterEvent ||
|
|
244
|
+
isDropEvent ||
|
|
245
|
+
isCopyEvent ||
|
|
246
|
+
isPasteEvent ||
|
|
247
|
+
isCutEvent ||
|
|
248
|
+
(isClickEvent && isSelectable)
|
|
249
|
+
) {
|
|
241
250
|
return false
|
|
242
251
|
}
|
|
243
252
|
|
package/src/utilities/index.ts
CHANGED
|
@@ -23,5 +23,6 @@ export * as markdown from './markdown/index.js'
|
|
|
23
23
|
export * from './mergeAttributes.js'
|
|
24
24
|
export * from './mergeDeep.js'
|
|
25
25
|
export * from './minMax.js'
|
|
26
|
+
export * from './nodeViewPositionRegistry.js'
|
|
26
27
|
export * from './objectIncludes.js'
|
|
27
28
|
export * from './removeDuplicates.js'
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import type { Editor } from '../Editor.js'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Per-editor registry for centralized NodeView position-change checks.
|
|
5
|
+
* A single editor.on('update') listener + rAF is shared across all NodeViews
|
|
6
|
+
* for a given editor, keeping overhead bounded regardless of NodeView count.
|
|
7
|
+
*
|
|
8
|
+
* This is consumed by React, Vue 3, and Vue 2 NodeView renderers.
|
|
9
|
+
*/
|
|
10
|
+
interface PositionUpdateRegistry {
|
|
11
|
+
callbacks: Set<() => void>
|
|
12
|
+
rafId: number | null
|
|
13
|
+
handler: () => void
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const positionUpdateRegistries = new WeakMap<Editor, PositionUpdateRegistry>()
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Register a callback to be called (via a shared rAF) after every editor
|
|
20
|
+
* update transaction. If this is the first registration for the given editor,
|
|
21
|
+
* a new registry entry and a single `editor.on('update')` listener are created.
|
|
22
|
+
*/
|
|
23
|
+
export function schedulePositionCheck(editor: Editor, callback: () => void): void {
|
|
24
|
+
let registry = positionUpdateRegistries.get(editor)
|
|
25
|
+
|
|
26
|
+
if (!registry) {
|
|
27
|
+
const newRegistry: PositionUpdateRegistry = {
|
|
28
|
+
callbacks: new Set(),
|
|
29
|
+
rafId: null,
|
|
30
|
+
handler: () => {
|
|
31
|
+
if (newRegistry.rafId !== null) {
|
|
32
|
+
cancelAnimationFrame(newRegistry.rafId)
|
|
33
|
+
}
|
|
34
|
+
newRegistry.rafId = requestAnimationFrame(() => {
|
|
35
|
+
newRegistry.rafId = null
|
|
36
|
+
newRegistry.callbacks.forEach(cb => cb())
|
|
37
|
+
})
|
|
38
|
+
},
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
positionUpdateRegistries.set(editor, newRegistry)
|
|
42
|
+
editor.on('update', newRegistry.handler)
|
|
43
|
+
registry = newRegistry
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
registry.callbacks.add(callback)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Unregister a previously registered callback. When the last callback for an
|
|
51
|
+
* editor is removed, the shared listener and any pending rAF are also cleaned up.
|
|
52
|
+
*/
|
|
53
|
+
export function cancelPositionCheck(editor: Editor, callback: () => void): void {
|
|
54
|
+
const registry = positionUpdateRegistries.get(editor)
|
|
55
|
+
|
|
56
|
+
if (!registry) {
|
|
57
|
+
return
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
registry.callbacks.delete(callback)
|
|
61
|
+
|
|
62
|
+
if (registry.callbacks.size === 0) {
|
|
63
|
+
if (registry.rafId !== null) {
|
|
64
|
+
cancelAnimationFrame(registry.rafId)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
editor.off('update', registry.handler)
|
|
68
|
+
positionUpdateRegistries.delete(editor)
|
|
69
|
+
}
|
|
70
|
+
}
|