@tiptap/extension-drag-handle 2.24.1 → 3.0.0-beta.10
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/dist/index.cjs +463 -457
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +68 -0
- package/dist/index.d.ts +68 -5
- package/dist/index.js +441 -450
- package/dist/index.js.map +1 -1
- package/package.json +20 -18
- package/src/drag-handle-plugin.ts +233 -236
- package/src/drag-handle.ts +42 -28
- package/src/helpers/dragHandler.ts +8 -8
- package/src/helpers/findNextElementFromCursor.ts +3 -5
- package/src/helpers/getInnerCoords.ts +3 -7
- package/src/helpers/getOuterNode.ts +1 -1
- package/dist/drag-handle-plugin.d.ts +0 -20
- package/dist/drag-handle-plugin.d.ts.map +0 -1
- package/dist/drag-handle.d.ts +0 -44
- package/dist/drag-handle.d.ts.map +0 -1
- package/dist/helpers/cloneElement.d.ts +0 -2
- package/dist/helpers/cloneElement.d.ts.map +0 -1
- package/dist/helpers/dragHandler.d.ts +0 -3
- package/dist/helpers/dragHandler.d.ts.map +0 -1
- package/dist/helpers/findNextElementFromCursor.d.ts +0 -14
- package/dist/helpers/findNextElementFromCursor.d.ts.map +0 -1
- package/dist/helpers/getComputedStyle.d.ts +0 -2
- package/dist/helpers/getComputedStyle.d.ts.map +0 -1
- package/dist/helpers/getInnerCoords.d.ts +0 -6
- package/dist/helpers/getInnerCoords.d.ts.map +0 -1
- package/dist/helpers/getOuterNode.d.ts +0 -4
- package/dist/helpers/getOuterNode.d.ts.map +0 -1
- package/dist/helpers/minMax.d.ts +0 -2
- package/dist/helpers/minMax.d.ts.map +0 -1
- package/dist/helpers/removeNode.d.ts +0 -2
- package/dist/helpers/removeNode.d.ts.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.umd.js +0 -499
- package/dist/index.umd.js.map +0 -1
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { type ComputePositionConfig, computePosition } from '@floating-ui/dom'
|
|
2
|
+
import type { Editor } from '@tiptap/core'
|
|
2
3
|
import { isChangeOrigin } from '@tiptap/extension-collaboration'
|
|
3
|
-
import { Node } from '@tiptap/pm/model'
|
|
4
|
+
import type { Node } from '@tiptap/pm/model'
|
|
5
|
+
import { type EditorState, type Transaction, Plugin, PluginKey } from '@tiptap/pm/state'
|
|
6
|
+
import type { EditorView } from '@tiptap/pm/view'
|
|
4
7
|
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
import tippy, { Instance, Props as TippyProps } from 'tippy.js'
|
|
10
|
-
import { absolutePositionToRelativePosition, relativePositionToAbsolutePosition, ySyncPluginKey } from 'y-prosemirror'
|
|
8
|
+
absolutePositionToRelativePosition,
|
|
9
|
+
relativePositionToAbsolutePosition,
|
|
10
|
+
ySyncPluginKey,
|
|
11
|
+
} from '@tiptap/y-tiptap'
|
|
11
12
|
|
|
12
13
|
import { dragHandler } from './helpers/dragHandler.js'
|
|
13
14
|
import { findElementNextToCoords } from './helpers/findNextElementFromCursor.js'
|
|
@@ -15,8 +16,8 @@ import { getOuterNode, getOuterNodePos } from './helpers/getOuterNode.js'
|
|
|
15
16
|
import { removeNode } from './helpers/removeNode.js'
|
|
16
17
|
|
|
17
18
|
type PluginState = {
|
|
18
|
-
locked: boolean
|
|
19
|
-
}
|
|
19
|
+
locked: boolean
|
|
20
|
+
}
|
|
20
21
|
|
|
21
22
|
const getRelativePos = (state: EditorState, absolutePos: number) => {
|
|
22
23
|
const ystate = ySyncPluginKey.getState(state)
|
|
@@ -28,6 +29,7 @@ const getRelativePos = (state: EditorState, absolutePos: number) => {
|
|
|
28
29
|
return absolutePositionToRelativePosition(absolutePos, ystate.type, ystate.binding.mapping)
|
|
29
30
|
}
|
|
30
31
|
|
|
32
|
+
// biome-ignore lint/suspicious/noExplicitAny: y-prosemirror (and y-tiptap by extension) does not have types for relative positions
|
|
31
33
|
const getAbsolutePos = (state: EditorState, relativePos: any) => {
|
|
32
34
|
const ystate = ySyncPluginKey.getState(state)
|
|
33
35
|
|
|
@@ -42,7 +44,7 @@ const getOuterDomNode = (view: EditorView, domNode: HTMLElement) => {
|
|
|
42
44
|
let tmpDomNode = domNode
|
|
43
45
|
|
|
44
46
|
// Traverse to top level node.
|
|
45
|
-
while (tmpDomNode
|
|
47
|
+
while (tmpDomNode?.parentNode) {
|
|
46
48
|
if (tmpDomNode.parentNode === view.dom) {
|
|
47
49
|
break
|
|
48
50
|
}
|
|
@@ -54,11 +56,11 @@ const getOuterDomNode = (view: EditorView, domNode: HTMLElement) => {
|
|
|
54
56
|
}
|
|
55
57
|
|
|
56
58
|
export interface DragHandlePluginProps {
|
|
57
|
-
pluginKey?: PluginKey | string
|
|
58
|
-
editor: Editor
|
|
59
|
-
element: HTMLElement
|
|
60
|
-
onNodeChange?: (data: { editor: Editor; node: Node | null; pos: number }) => void
|
|
61
|
-
|
|
59
|
+
pluginKey?: PluginKey | string
|
|
60
|
+
editor: Editor
|
|
61
|
+
element: HTMLElement
|
|
62
|
+
onNodeChange?: (data: { editor: Editor; node: Node | null; pos: number }) => void
|
|
63
|
+
computePositionConfig?: ComputePositionConfig
|
|
62
64
|
}
|
|
63
65
|
|
|
64
66
|
export const dragHandlePluginDefaultKey = new PluginKey('dragHandle')
|
|
@@ -67,17 +69,54 @@ export const DragHandlePlugin = ({
|
|
|
67
69
|
pluginKey = dragHandlePluginDefaultKey,
|
|
68
70
|
element,
|
|
69
71
|
editor,
|
|
70
|
-
|
|
72
|
+
computePositionConfig,
|
|
71
73
|
onNodeChange,
|
|
72
74
|
}: DragHandlePluginProps) => {
|
|
73
75
|
const wrapper = document.createElement('div')
|
|
74
|
-
let popup: Instance | null = null
|
|
75
76
|
let locked = false
|
|
76
77
|
let currentNode: Node | null = null
|
|
77
78
|
let currentNodePos = -1
|
|
79
|
+
// biome-ignore lint/suspicious/noExplicitAny: See above - relative positions in y-prosemirror are not typed
|
|
78
80
|
let currentNodeRelPos: any
|
|
79
81
|
|
|
80
|
-
|
|
82
|
+
function hideHandle() {
|
|
83
|
+
if (!element) {
|
|
84
|
+
return
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
element.style.visibility = 'hidden'
|
|
88
|
+
element.style.pointerEvents = 'none'
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function showHandle() {
|
|
92
|
+
if (!element) {
|
|
93
|
+
return
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (!editor.isEditable) {
|
|
97
|
+
hideHandle()
|
|
98
|
+
return
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
element.style.visibility = ''
|
|
102
|
+
element.style.pointerEvents = 'auto'
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function repositionDragHandle(dom: Element) {
|
|
106
|
+
const virtualElement = {
|
|
107
|
+
getBoundingClientRect: () => dom.getBoundingClientRect(),
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
computePosition(virtualElement, element, computePositionConfig).then(val => {
|
|
111
|
+
Object.assign(element.style, {
|
|
112
|
+
position: val.strategy,
|
|
113
|
+
left: `${val.x}px`,
|
|
114
|
+
top: `${val.y}px`,
|
|
115
|
+
})
|
|
116
|
+
})
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function onDragStart(e: DragEvent) {
|
|
81
120
|
// Push this to the end of the event cue
|
|
82
121
|
// Fixes bug where incorrect drag pos is returned if drag handle has position: absolute
|
|
83
122
|
// @ts-ignore
|
|
@@ -88,283 +127,241 @@ export const DragHandlePlugin = ({
|
|
|
88
127
|
element.style.pointerEvents = 'none'
|
|
89
128
|
}
|
|
90
129
|
}, 0)
|
|
91
|
-
}
|
|
130
|
+
}
|
|
92
131
|
|
|
93
|
-
|
|
132
|
+
function onDragEnd() {
|
|
133
|
+
hideHandle()
|
|
94
134
|
if (element) {
|
|
95
135
|
element.style.pointerEvents = 'auto'
|
|
96
136
|
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
return new Plugin({
|
|
100
|
-
key: typeof pluginKey === 'string' ? new PluginKey(pluginKey) : pluginKey,
|
|
101
|
-
|
|
102
|
-
state: {
|
|
103
|
-
init() {
|
|
104
|
-
return { locked: false }
|
|
105
|
-
},
|
|
106
|
-
apply(tr: Transaction, value: PluginState, oldState: EditorState, state: EditorState) {
|
|
107
|
-
const isLocked = tr.getMeta('lockDragHandle')
|
|
108
|
-
const hideDragHandle = tr.getMeta('hideDragHandle')
|
|
109
|
-
|
|
110
|
-
if (isLocked !== undefined) {
|
|
111
|
-
locked = isLocked
|
|
112
|
-
}
|
|
137
|
+
}
|
|
113
138
|
|
|
114
|
-
|
|
115
|
-
|
|
139
|
+
element.addEventListener('dragstart', onDragStart)
|
|
140
|
+
element.addEventListener('dragend', onDragEnd)
|
|
116
141
|
|
|
117
|
-
|
|
118
|
-
currentNode = null
|
|
119
|
-
currentNodePos = -1
|
|
142
|
+
wrapper.appendChild(element)
|
|
120
143
|
|
|
121
|
-
|
|
144
|
+
return {
|
|
145
|
+
unbind() {
|
|
146
|
+
element.removeEventListener('dragstart', onDragStart)
|
|
147
|
+
element.removeEventListener('dragend', onDragEnd)
|
|
148
|
+
},
|
|
149
|
+
plugin: new Plugin({
|
|
150
|
+
key: typeof pluginKey === 'string' ? new PluginKey(pluginKey) : pluginKey,
|
|
122
151
|
|
|
123
|
-
|
|
124
|
-
|
|
152
|
+
state: {
|
|
153
|
+
init() {
|
|
154
|
+
return { locked: false }
|
|
155
|
+
},
|
|
156
|
+
apply(tr: Transaction, value: PluginState, _oldState: EditorState, state: EditorState) {
|
|
157
|
+
const isLocked = tr.getMeta('lockDragHandle')
|
|
158
|
+
const hideDragHandle = tr.getMeta('hideDragHandle')
|
|
125
159
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
// If change comes from another user …
|
|
130
|
-
if (isChangeOrigin(tr)) {
|
|
131
|
-
// https://discuss.yjs.dev/t/y-prosemirror-mapping-a-single-relative-position-when-doc-changes/851/3
|
|
132
|
-
const newPos = getAbsolutePos(state, currentNodeRelPos)
|
|
160
|
+
if (isLocked !== undefined) {
|
|
161
|
+
locked = isLocked
|
|
162
|
+
}
|
|
133
163
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
currentNodePos = newPos
|
|
164
|
+
if (hideDragHandle) {
|
|
165
|
+
hideHandle()
|
|
137
166
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
// … otherwise use ProseMirror mapping to update the position.
|
|
142
|
-
const newPos = tr.mapping.map(currentNodePos)
|
|
167
|
+
locked = false
|
|
168
|
+
currentNode = null
|
|
169
|
+
currentNodePos = -1
|
|
143
170
|
|
|
144
|
-
|
|
145
|
-
// TODO: Remove
|
|
146
|
-
// console.log('Position has changed …', { old: currentNodePos, new: newPos }, tr);
|
|
171
|
+
onNodeChange?.({ editor, node: null, pos: -1 })
|
|
147
172
|
|
|
148
|
-
|
|
149
|
-
|
|
173
|
+
return value
|
|
174
|
+
}
|
|
150
175
|
|
|
151
|
-
|
|
152
|
-
|
|
176
|
+
// Something has changed and drag handler is visible…
|
|
177
|
+
if (tr.docChanged && currentNodePos !== -1 && element) {
|
|
178
|
+
// Yjs replaces the entire document on every incoming change and needs a special handling.
|
|
179
|
+
// If change comes from another user …
|
|
180
|
+
if (isChangeOrigin(tr)) {
|
|
181
|
+
// https://discuss.yjs.dev/t/y-prosemirror-mapping-a-single-relative-position-when-doc-changes/851/3
|
|
182
|
+
const newPos = getAbsolutePos(state, currentNodeRelPos)
|
|
153
183
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
}
|
|
184
|
+
if (newPos !== currentNodePos) {
|
|
185
|
+
// Set the new position for our current node.
|
|
186
|
+
currentNodePos = newPos
|
|
158
187
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
188
|
+
// We will get the outer node with data and position in views update method.
|
|
189
|
+
}
|
|
190
|
+
} else {
|
|
191
|
+
// … otherwise use ProseMirror mapping to update the position.
|
|
192
|
+
const newPos = tr.mapping.map(currentNodePos)
|
|
162
193
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
194
|
+
if (newPos !== currentNodePos) {
|
|
195
|
+
// TODO: Remove
|
|
196
|
+
// console.log('Position has changed …', { old: currentNodePos, new: newPos }, tr);
|
|
166
197
|
|
|
167
|
-
|
|
198
|
+
// Set the new position for our current node.
|
|
199
|
+
currentNodePos = newPos
|
|
168
200
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
wrapper.style.position = 'absolute'
|
|
172
|
-
wrapper.style.top = '0'
|
|
173
|
-
wrapper.style.left = '0'
|
|
201
|
+
// Memorize relative position to retrieve absolute position in case of collaboration
|
|
202
|
+
currentNodeRelPos = getRelativePos(state, currentNodePos)
|
|
174
203
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
return
|
|
204
|
+
// We will get the outer node with data and position in views update method.
|
|
205
|
+
}
|
|
206
|
+
}
|
|
179
207
|
}
|
|
180
208
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
return
|
|
185
|
-
}
|
|
209
|
+
return value
|
|
210
|
+
},
|
|
211
|
+
},
|
|
186
212
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
interactive: true,
|
|
191
|
-
trigger: 'manual',
|
|
192
|
-
placement: 'left-start',
|
|
193
|
-
hideOnClick: false,
|
|
194
|
-
duration: 100,
|
|
195
|
-
popperOptions: {
|
|
196
|
-
modifiers: [
|
|
197
|
-
{ name: 'flip', enabled: false },
|
|
198
|
-
{
|
|
199
|
-
name: 'preventOverflow',
|
|
200
|
-
options: {
|
|
201
|
-
rootBoundary: 'document',
|
|
202
|
-
mainAxis: false,
|
|
203
|
-
},
|
|
204
|
-
},
|
|
205
|
-
],
|
|
206
|
-
},
|
|
207
|
-
...tippyOptions,
|
|
208
|
-
appendTo: wrapper,
|
|
209
|
-
content: element,
|
|
210
|
-
})
|
|
211
|
-
}
|
|
213
|
+
view: view => {
|
|
214
|
+
element.draggable = true
|
|
215
|
+
element.style.pointerEvents = 'auto'
|
|
212
216
|
|
|
213
|
-
|
|
214
|
-
if (locked) {
|
|
215
|
-
element.draggable = false
|
|
216
|
-
} else {
|
|
217
|
-
element.draggable = true
|
|
218
|
-
}
|
|
217
|
+
editor.view.dom.parentElement?.appendChild(wrapper)
|
|
219
218
|
|
|
220
|
-
|
|
221
|
-
|
|
219
|
+
wrapper.style.pointerEvents = 'none'
|
|
220
|
+
wrapper.style.position = 'absolute'
|
|
221
|
+
wrapper.style.top = '0'
|
|
222
|
+
wrapper.style.left = '0'
|
|
222
223
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
224
|
+
return {
|
|
225
|
+
update(_, oldState) {
|
|
226
|
+
if (!element) {
|
|
227
|
+
return
|
|
228
|
+
}
|
|
227
229
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
+
if (!editor.isEditable) {
|
|
231
|
+
hideHandle()
|
|
232
|
+
return
|
|
233
|
+
}
|
|
230
234
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
235
|
+
// Prevent element being draggend while being open.
|
|
236
|
+
if (locked) {
|
|
237
|
+
element.draggable = false
|
|
238
|
+
} else {
|
|
239
|
+
element.draggable = true
|
|
240
|
+
}
|
|
234
241
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
242
|
+
// Recalculate popup position if doc has changend and drag handler is visible.
|
|
243
|
+
if (view.state.doc.eq(oldState.doc) || currentNodePos === -1) {
|
|
244
|
+
return
|
|
245
|
+
}
|
|
239
246
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
return
|
|
243
|
-
}
|
|
247
|
+
// Get domNode from (new) position.
|
|
248
|
+
let domNode = view.nodeDOM(currentNodePos) as HTMLElement
|
|
244
249
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
250
|
+
// Since old element could have been wrapped, we need to find
|
|
251
|
+
// the outer node and take its position and node data.
|
|
252
|
+
domNode = getOuterDomNode(view, domNode)
|
|
248
253
|
|
|
249
|
-
|
|
250
|
-
|
|
254
|
+
// Skip if domNode is editor dom.
|
|
255
|
+
if (domNode === view.dom) {
|
|
256
|
+
return
|
|
257
|
+
}
|
|
251
258
|
|
|
252
|
-
|
|
253
|
-
|
|
259
|
+
// We only want `Element`.
|
|
260
|
+
if (domNode?.nodeType !== 1) {
|
|
261
|
+
return
|
|
262
|
+
}
|
|
254
263
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
// currentNodePos,
|
|
259
|
-
// currentNode,
|
|
260
|
-
// rect: (domNode as Element).getBoundingClientRect(),
|
|
261
|
-
// });
|
|
264
|
+
const domNodePos = view.posAtDOM(domNode, 0)
|
|
265
|
+
const outerNode = getOuterNode(editor.state.doc, domNodePos)
|
|
266
|
+
const outerNodePos = getOuterNodePos(editor.state.doc, domNodePos) // TODO: needed?
|
|
262
267
|
|
|
263
|
-
|
|
268
|
+
currentNode = outerNode
|
|
269
|
+
currentNodePos = outerNodePos
|
|
264
270
|
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
getReferenceClientRect: () => (domNode as Element).getBoundingClientRect(),
|
|
268
|
-
})
|
|
269
|
-
},
|
|
271
|
+
// Memorize relative position to retrieve absolute position in case of collaboration
|
|
272
|
+
currentNodeRelPos = getRelativePos(view.state, currentNodePos)
|
|
270
273
|
|
|
271
|
-
|
|
272
|
-
destroy() {
|
|
273
|
-
popup?.destroy()
|
|
274
|
+
onNodeChange?.({ editor, node: currentNode, pos: currentNodePos })
|
|
274
275
|
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
}
|
|
278
|
-
},
|
|
279
|
-
}
|
|
280
|
-
},
|
|
276
|
+
repositionDragHandle(domNode as Element)
|
|
277
|
+
},
|
|
281
278
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
279
|
+
// TODO: Kills even on hot reload
|
|
280
|
+
destroy() {
|
|
281
|
+
if (element) {
|
|
282
|
+
removeNode(wrapper)
|
|
283
|
+
}
|
|
284
|
+
},
|
|
285
|
+
}
|
|
286
|
+
},
|
|
289
287
|
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
288
|
+
props: {
|
|
289
|
+
handleDOMEvents: {
|
|
290
|
+
mouseleave(_view, e) {
|
|
291
|
+
// Do not hide open popup on mouseleave.
|
|
292
|
+
if (locked) {
|
|
293
|
+
return false
|
|
294
|
+
}
|
|
293
295
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
+
// If e.target is not inside the wrapper, hide.
|
|
297
|
+
if (e.target && !wrapper.contains(e.relatedTarget as HTMLElement)) {
|
|
298
|
+
hideHandle()
|
|
296
299
|
|
|
297
|
-
|
|
298
|
-
|
|
300
|
+
currentNode = null
|
|
301
|
+
currentNodePos = -1
|
|
299
302
|
|
|
300
|
-
|
|
301
|
-
|
|
303
|
+
onNodeChange?.({ editor, node: null, pos: -1 })
|
|
304
|
+
}
|
|
302
305
|
|
|
303
|
-
mousemove(view, e) {
|
|
304
|
-
// Do not continue if popup is not initialized or open.
|
|
305
|
-
if (!element || !popup || locked) {
|
|
306
306
|
return false
|
|
307
|
-
}
|
|
307
|
+
},
|
|
308
308
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
})
|
|
309
|
+
mousemove(view, e) {
|
|
310
|
+
// Do not continue if popup is not initialized or open.
|
|
311
|
+
if (!element || locked) {
|
|
312
|
+
return false
|
|
313
|
+
}
|
|
315
314
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
315
|
+
const nodeData = findElementNextToCoords({
|
|
316
|
+
x: e.clientX,
|
|
317
|
+
y: e.clientY,
|
|
318
|
+
direction: 'right',
|
|
319
|
+
editor,
|
|
320
|
+
})
|
|
320
321
|
|
|
321
|
-
|
|
322
|
+
// Skip if there is no node next to coords
|
|
323
|
+
if (!nodeData.resultElement) {
|
|
324
|
+
return false
|
|
325
|
+
}
|
|
322
326
|
|
|
323
|
-
|
|
327
|
+
let domNode = nodeData.resultElement as HTMLElement
|
|
324
328
|
|
|
325
|
-
|
|
326
|
-
if (domNode === view.dom) {
|
|
327
|
-
return false
|
|
328
|
-
}
|
|
329
|
+
domNode = getOuterDomNode(view, domNode)
|
|
329
330
|
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
331
|
+
// Skip if domNode is editor dom.
|
|
332
|
+
if (domNode === view.dom) {
|
|
333
|
+
return false
|
|
334
|
+
}
|
|
334
335
|
|
|
335
|
-
|
|
336
|
-
|
|
336
|
+
// We only want `Element`.
|
|
337
|
+
if (domNode?.nodeType !== 1) {
|
|
338
|
+
return false
|
|
339
|
+
}
|
|
337
340
|
|
|
338
|
-
|
|
339
|
-
const
|
|
341
|
+
const domNodePos = view.posAtDOM(domNode, 0)
|
|
342
|
+
const outerNode = getOuterNode(editor.state.doc, domNodePos)
|
|
340
343
|
|
|
341
|
-
currentNode
|
|
342
|
-
|
|
344
|
+
if (outerNode !== currentNode) {
|
|
345
|
+
const outerNodePos = getOuterNodePos(editor.state.doc, domNodePos)
|
|
343
346
|
|
|
344
|
-
|
|
345
|
-
|
|
347
|
+
currentNode = outerNode
|
|
348
|
+
currentNodePos = outerNodePos
|
|
346
349
|
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
// domNode,
|
|
350
|
-
// currentNodePos,
|
|
351
|
-
// currentNode,
|
|
352
|
-
// rect: (domNode as Element).getBoundingClientRect(),
|
|
353
|
-
// });
|
|
350
|
+
// Memorize relative position to retrieve absolute position in case of collaboration
|
|
351
|
+
currentNodeRelPos = getRelativePos(view.state, currentNodePos)
|
|
354
352
|
|
|
355
|
-
|
|
353
|
+
onNodeChange?.({ editor, node: currentNode, pos: currentNodePos })
|
|
356
354
|
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
getReferenceClientRect: () => (domNode as Element).getBoundingClientRect(),
|
|
360
|
-
})
|
|
355
|
+
// Set nodes clientRect.
|
|
356
|
+
repositionDragHandle(domNode as Element)
|
|
361
357
|
|
|
362
|
-
|
|
363
|
-
|
|
358
|
+
showHandle()
|
|
359
|
+
}
|
|
364
360
|
|
|
365
|
-
|
|
361
|
+
return false
|
|
362
|
+
},
|
|
366
363
|
},
|
|
367
364
|
},
|
|
368
|
-
},
|
|
369
|
-
}
|
|
365
|
+
}),
|
|
366
|
+
}
|
|
370
367
|
}
|