Skip to content

Commit 3a2aff0

Browse files
authored
Merge pull request udecode#4597 from DND-IT/enhance-dnd-ux
2 parents 82572fc + e594b25 commit 3a2aff0

2 files changed

Lines changed: 25 additions & 19 deletions

File tree

.changeset/happy-planets-learn.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@platejs/dnd': patch
3+
---
4+
5+
Hide drop line, whenever drag happens outside the editor

packages/dnd/src/DndPlugin.tsx

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -85,42 +85,43 @@ export const DndPlugin = createTPlatePlugin<DndConfig>({
8585
isDragging: false,
8686
multiplePreviewRef: null,
8787
},
88-
useHooks: ({ setOption }) => {
89-
const handleDocumentDragLeave = useCallback(
88+
useHooks: ({ editor, setOption }) => {
89+
const handleDragLeave = useCallback(
9090
(e: DragEvent) => {
91-
// This event fires for every element that receives a drag leave event. If `clientX` and `clientY` are both 0,
92-
// it means the drag has left the viewport. Needed, if the drag did not start inside the editor, but for example
93-
// by dragging a file from the filesystem
94-
if (!e.clientX && !e.clientY) {
95-
setOption('dropTarget', undefined);
91+
// This event fires for every element that receives a drag leave event. As soon as it is fired on the
92+
// editable dom node, or above, we will unset the drop target, and therefore hide the drop line.
93+
// In other words, whenever the drag is not happening inside the editor anymore, we will hide the
94+
// drop line which makes sense, since a potential drop would not insert anything into the editor.
95+
// This will also apply, if the user move the drag operation outside the document.
96+
if (e.target instanceof Node) {
97+
const editorDOMNode = editor.api.toDOMNode(editor);
98+
99+
if (editorDOMNode && !editorDOMNode.contains(e.target)) {
100+
setOption('dropTarget', undefined);
101+
}
96102
}
97103
},
98-
[setOption]
104+
[editor, setOption]
99105
);
100106

101107
// We listen for the drop event on the document and not only inside the editor, because we want to
102108
// remove the dropTarget, and therefore hide the drop line, also when the drop happened outside of
103109
// the editor. Needed, if the drag did not start inside the editor, but for example by dragging a
104110
// file from the filesystem
105-
const handleDocumentDrop = useCallback(() => {
111+
const handleDrop = useCallback(() => {
106112
setOption('_isOver', false);
107113
setOption('dropTarget', undefined);
108114
}, [setOption]);
109115

110116
useEffect(() => {
111-
document.addEventListener('dragleave', handleDocumentDragLeave, true);
112-
document.addEventListener('drop', handleDocumentDrop, true);
117+
document.addEventListener('dragleave', handleDragLeave, true);
118+
document.addEventListener('drop', handleDrop, true);
113119

114120
return () => {
115-
document.removeEventListener(
116-
'dragleave',
117-
handleDocumentDragLeave,
118-
true
119-
);
120-
121-
document.removeEventListener('drop', handleDocumentDrop, true);
121+
document.removeEventListener('dragleave', handleDragLeave, true);
122+
document.removeEventListener('drop', handleDrop, true);
122123
};
123-
}, [handleDocumentDragLeave, handleDocumentDrop]);
124+
}, [handleDragLeave, handleDrop]);
124125
},
125126
}).extend(({ getOptions }) => ({
126127
render: {

0 commit comments

Comments
 (0)