mirror of
https://github.com/ueberdosis/tiptap.git
synced 2024-12-12 08:49:04 +08:00
feat: allow support for drag-and-drop between multiple editors (#5893)
* feat: drag and drop across multi editors * feat: drag and drop across multi editors optimize * feat: drag and drop across multi editors optimize * added changeset --------- Co-authored-by: songhandong <songhandong@baidu.com> Co-authored-by: songispm <38745323+songispm@users.noreply.github.com> Co-authored-by: songispm <songispm@gmail.com>
This commit is contained in:
parent
01547d5b2f
commit
ca6269e928
5
.changeset/many-glasses-reflect.md
Normal file
5
.changeset/many-glasses-reflect.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
"@tiptap/core": patch
|
||||
---
|
||||
|
||||
Added support for drag-and-drop between multiple editors
|
@ -44,7 +44,8 @@ export default Extension.create({
|
||||
}
|
||||
|
||||
function dragStart(e, view) {
|
||||
view.composing = true
|
||||
// Must delete this line, Otherwise: Uncaught TypeError: Cannot set property composing of #<EditorView> which has only a getter
|
||||
// view.composing = true
|
||||
|
||||
if (!e.dataTransfer) {
|
||||
return
|
||||
@ -75,6 +76,11 @@ export default Extension.create({
|
||||
}
|
||||
}
|
||||
|
||||
function dragEnd(e, view) {
|
||||
// reset the dragging, otherwise wrong content after dragging across multi editors repeatedly
|
||||
view.dragging = null
|
||||
}
|
||||
|
||||
let dropElement
|
||||
const WIDTH = 28
|
||||
|
||||
@ -86,8 +92,10 @@ export default Extension.create({
|
||||
element.draggable = 'true'
|
||||
element.classList.add('global-drag-handle')
|
||||
element.addEventListener('dragstart', e => dragStart(e, editorView))
|
||||
element.addEventListener('dragend', e => dragEnd(e, editorView))
|
||||
dropElement = element
|
||||
document.body.appendChild(dropElement)
|
||||
// append to editor's parentNode (not document.body), to match the logic of dragging across multi editors in pasteRule.ts
|
||||
editorView.dom.parentNode.appendChild(dropElement)
|
||||
|
||||
return {
|
||||
// update(view, prevState) {
|
||||
|
@ -32,6 +32,7 @@
|
||||
import Bold from '@tiptap/extension-bold'
|
||||
import Collaboration from '@tiptap/extension-collaboration'
|
||||
import Document from '@tiptap/extension-document'
|
||||
import DropCursor from '@tiptap/extension-dropcursor'
|
||||
import Heading from '@tiptap/extension-heading'
|
||||
import Paragraph from '@tiptap/extension-paragraph'
|
||||
import TaskItem from '@tiptap/extension-task-item'
|
||||
@ -75,6 +76,8 @@ export default {
|
||||
levels: [2],
|
||||
}),
|
||||
Text,
|
||||
Bold,
|
||||
DropCursor,
|
||||
Collaboration.configure({
|
||||
document: this.ydoc,
|
||||
field: 'title',
|
||||
@ -88,6 +91,8 @@ export default {
|
||||
TaskListDocument,
|
||||
Paragraph,
|
||||
Text,
|
||||
Bold,
|
||||
DropCursor,
|
||||
TaskList,
|
||||
CustomTaskItem,
|
||||
Collaboration.configure({
|
||||
@ -110,6 +115,7 @@ export default {
|
||||
Paragraph,
|
||||
Text,
|
||||
Bold,
|
||||
DropCursor,
|
||||
Collaboration.configure({
|
||||
document: this.ydoc,
|
||||
field: 'description',
|
||||
|
@ -162,6 +162,9 @@ function run(config: {
|
||||
return success
|
||||
}
|
||||
|
||||
// When dragging across editors, must get another editor instance to delete selection content.
|
||||
let tiptapDragFromOtherEditor: Editor | null = null
|
||||
|
||||
const createClipboardPasteEvent = (text: string) => {
|
||||
const event = new ClipboardEvent('paste', {
|
||||
clipboardData: new DataTransfer(),
|
||||
@ -242,13 +245,25 @@ export function pasteRulesPlugin(props: { editor: Editor; rules: PasteRule[] }):
|
||||
dragSourceElement = view.dom.parentElement?.contains(event.target as Element)
|
||||
? view.dom.parentElement
|
||||
: null
|
||||
|
||||
if (dragSourceElement) {
|
||||
tiptapDragFromOtherEditor = editor
|
||||
}
|
||||
}
|
||||
|
||||
const handleDragend = () => {
|
||||
if (tiptapDragFromOtherEditor) {
|
||||
tiptapDragFromOtherEditor = null
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener('dragstart', handleDragstart)
|
||||
window.addEventListener('dragend', handleDragend)
|
||||
|
||||
return {
|
||||
destroy() {
|
||||
window.removeEventListener('dragstart', handleDragstart)
|
||||
window.removeEventListener('dragend', handleDragend)
|
||||
},
|
||||
}
|
||||
},
|
||||
@ -259,6 +274,20 @@ export function pasteRulesPlugin(props: { editor: Editor; rules: PasteRule[] }):
|
||||
isDroppedFromProseMirror = dragSourceElement === view.dom.parentElement
|
||||
dropEvent = event as DragEvent
|
||||
|
||||
if (!isDroppedFromProseMirror) {
|
||||
const dragFromOtherEditor = tiptapDragFromOtherEditor
|
||||
|
||||
if (dragFromOtherEditor) {
|
||||
// setTimeout to avoid the wrong content after drop, timeout arg can't be empty or 0
|
||||
setTimeout(() => {
|
||||
const selection = dragFromOtherEditor.state.selection
|
||||
|
||||
if (selection) {
|
||||
dragFromOtherEditor.commands.deleteRange({ from: selection.from, to: selection.to })
|
||||
}
|
||||
}, 10)
|
||||
}
|
||||
}
|
||||
return false
|
||||
},
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user