From d0411a03da6a2245c9177d125ee2f4e0c4952e28 Mon Sep 17 00:00:00 2001 From: fantasticit Date: Wed, 21 Dec 2022 16:54:42 +0800 Subject: [PATCH] improve dragable --- .../src/tiptap/core/extensions/dragable.ts | 55 +++++++++++++++++-- 1 file changed, 50 insertions(+), 5 deletions(-) diff --git a/packages/client/src/tiptap/core/extensions/dragable.ts b/packages/client/src/tiptap/core/extensions/dragable.ts index 1a081b4b..b3190d74 100644 --- a/packages/client/src/tiptap/core/extensions/dragable.ts +++ b/packages/client/src/tiptap/core/extensions/dragable.ts @@ -1,8 +1,8 @@ import { Extension } from '@tiptap/core'; import { Plugin, PluginKey, Selection } from 'prosemirror-state'; -import { NodeSelection } from 'prosemirror-state'; +import { NodeSelection, TextSelection } from 'prosemirror-state'; import { __serializeForClipboard, EditorView } from 'prosemirror-view'; -import { ActiveNode, getNodeAtPos, removePossibleTable, selectRootNodeByDom } from 'tiptap/prose-utils'; +import { ActiveNode, getNodeAtPos, removePossibleTable, safePos, selectRootNodeByDom } from 'tiptap/prose-utils'; export const DragablePluginKey = new PluginKey('dragable'); @@ -15,6 +15,7 @@ export const Dragable = Extension.create({ let activeNode: ActiveNode; let activeSelection: Selection; let dragging = false; + let mouseleaveTimer = null; const createDragHandleDOM = () => { const dom = document.createElement('div'); @@ -51,6 +52,18 @@ export const Dragable = Extension.create({ showDragHandleDOM(); }; + const handleMouseEnter = () => { + if (!activeNode) return null; + + clearTimeout(mouseleaveTimer); + showDragHandleDOM(); + }; + + const handleMouseLeave = () => { + if (!activeNode) return null; + hideDragHandleDOM(); + }; + const handleMouseDown = () => { if (!activeNode) return null; @@ -75,13 +88,14 @@ export const Dragable = Extension.create({ const handleDragStart = (event) => { dragging = true; if (event.dataTransfer && activeSelection) { - const brokenClipboardAPI = false; const slice = activeSelection.content(); event.dataTransfer.effectAllowed = 'copyMove'; const { dom, text } = __serializeForClipboard(editorView, slice); event.dataTransfer.clearData(); - event.dataTransfer.setData(brokenClipboardAPI ? 'Text' : 'text/html', dom.innerHTML); - if (!brokenClipboardAPI) event.dataTransfer.setData('text/plain', text); + event.dataTransfer.setData('text/html', dom.innerHTML); + event.dataTransfer.setData('text/plain', text); + event.dataTransfer.setDragImage(activeNode?.el as any, 0, 0); + editorView.dragging = { slice, move: true, @@ -95,6 +109,8 @@ export const Dragable = Extension.create({ view: (view) => { if (view.editable) { dragHandleDOM = createDragHandleDOM(); + dragHandleDOM.addEventListener('mouseenter', handleMouseEnter); + dragHandleDOM.addEventListener('mouseleave', handleMouseLeave); dragHandleDOM.addEventListener('mousedown', handleMouseDown); dragHandleDOM.addEventListener('mouseup', handleMouseUp); dragHandleDOM.addEventListener('dragstart', handleDragStart); @@ -108,6 +124,8 @@ export const Dragable = Extension.create({ destroy: () => { if (!dragHandleDOM) return; + dragHandleDOM.removeEventListener('mouseenter', handleMouseEnter); + dragHandleDOM.removeEventListener('mouseleave', handleMouseLeave); dragHandleDOM.removeEventListener('mousedown', handleMouseDown); dragHandleDOM.removeEventListener('mouseup', handleMouseUp); dragHandleDOM.removeEventListener('dragstart', handleDragStart); @@ -125,6 +143,26 @@ export const Dragable = Extension.create({ return true; } + setTimeout(() => { + if (activeSelection) { + [ + 'ProseMirror-selectednode', + 'ProseMirror-selectedblocknode-dragable', + 'ProseMirror-selectedblocknode-normal', + ].forEach((cls) => { + (view.dom as HTMLElement).querySelectorAll(`.${cls}`).forEach((dom) => dom.classList.remove(cls)); + }); + const noneSelection = new TextSelection( + view.state.doc.resolve(safePos(view.state, eventPos?.pos ?? 0)) + ); + view.dispatch(view.state.tr.setSelection(noneSelection)); + this.editor.commands.blur(); + + activeSelection = null; + activeNode = null; + } + }, 100); + const $mouse = view.state.doc.resolve(eventPos.pos); /** @@ -196,6 +234,13 @@ export const Dragable = Extension.create({ renderDragHandleDOM(view, result.el); return false; }, + mouseleave: () => { + clearTimeout(mouseleaveTimer); + mouseleaveTimer = setTimeout(() => { + hideDragHandleDOM(); + }, 400); + return false; + }, keydown: () => { if (!editorView.editable || !dragHandleDOM) return false; hideDragHandleDOM();