1- import React from 'react' ;
1+ import React , { useCallback , useEffect } from 'react' ;
22
33import type { Path , PluginConfig } from 'platejs' ;
44import type { DropTargetMonitor } from 'react-dnd' ;
@@ -67,9 +67,6 @@ export const DndPlugin = createTPlatePlugin<DndConfig>({
6767 editor . setOption ( plugin , '_isOver' , true ) ;
6868 } ,
6969 onDrop : ( { getOptions, setOption } ) => {
70- setOption ( '_isOver' , false ) ;
71- setOption ( 'dropTarget' , undefined ) ;
72-
7370 return getOptions ( ) . isDragging ;
7471 } ,
7572 onFocus : ( { editor, plugin } ) => {
@@ -88,6 +85,43 @@ export const DndPlugin = createTPlatePlugin<DndConfig>({
8885 isDragging : false ,
8986 multiplePreviewRef : null ,
9087 } ,
88+ useHooks : ( { setOption } ) => {
89+ const handleDocumentDragLeave = useCallback (
90+ ( 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 ) ;
96+ }
97+ } ,
98+ [ setOption ]
99+ ) ;
100+
101+ // We listen for the drop event on the document and not only inside the editor, because we want to
102+ // remove the dropTarget, and therefore hide the drop line, also when the drop happened outside of
103+ // the editor. Needed, if the drag did not start inside the editor, but for example by dragging a
104+ // file from the filesystem
105+ const handleDocumentDrop = useCallback ( ( ) => {
106+ setOption ( '_isOver' , false ) ;
107+ setOption ( 'dropTarget' , undefined ) ;
108+ } , [ setOption ] ) ;
109+
110+ useEffect ( ( ) => {
111+ document . addEventListener ( 'dragleave' , handleDocumentDragLeave , true ) ;
112+ document . addEventListener ( 'drop' , handleDocumentDrop , true ) ;
113+
114+ return ( ) => {
115+ document . removeEventListener (
116+ 'dragleave' ,
117+ handleDocumentDragLeave ,
118+ true
119+ ) ;
120+
121+ document . removeEventListener ( 'drop' , handleDocumentDrop , true ) ;
122+ } ;
123+ } , [ handleDocumentDragLeave , handleDocumentDrop ] ) ;
124+ } ,
91125} ) . extend ( ( { getOptions } ) => ( {
92126 render : {
93127 afterEditable : getOptions ( ) . enableScroller
0 commit comments