Skip to content

Commit b721f25

Browse files
fix: Blocks being deleted when dropped outside editor container (#1443)
* Fixed blocks disappearing when dropped outside editor container * Small fix * Small fix
1 parent 4aa4f25 commit b721f25

File tree

1 file changed

+49
-39
lines changed

1 file changed

+49
-39
lines changed

packages/core/src/extensions/SideMenu/SideMenuPlugin.ts

Lines changed: 49 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -283,47 +283,57 @@ export class SideMenuView<
283283

284284
this.editor._tiptapEditor.commands.blur();
285285

286-
// When ProseMirror handles a drop event on the editor while
287-
// `view.dragging` is set, it deletes the selected content. However, if
288-
// a block from a different editor is being dropped, this causes some
289-
// issues that the code below fixes:
290-
if (!this.isDragOrigin && this.pmView.dom.contains(event.target as Node)) {
291-
// 1. Because the editor selection is unrelated to the dragged content,
292-
// we don't want PM to delete its content. Therefore, we collapse the
293-
// selection.
294-
this.pmView.dispatch(
295-
this.pmView.state.tr.setSelection(
296-
TextSelection.create(
297-
this.pmView.state.tr.doc,
298-
this.pmView.state.tr.selection.to
286+
// Finds the BlockNote editor element that the drop event occurred in (if
287+
// any).
288+
const parentEditorElement =
289+
event.target instanceof Node
290+
? (event.target instanceof HTMLElement
291+
? event.target
292+
: event.target.parentElement
293+
)?.closest(".bn-editor") || null
294+
: null;
295+
296+
// Drop event occurred within an editor.
297+
if (parentEditorElement) {
298+
// When ProseMirror handles a drop event on the editor while
299+
// `view.dragging` is set, it deletes the selected content. However, if
300+
// a block from a different editor is being dropped, this causes some
301+
// issues that the code below fixes:
302+
if (!this.isDragOrigin && this.pmView.dom === parentEditorElement) {
303+
// 1. Because the editor selection is unrelated to the dragged content,
304+
// we don't want PM to delete its content. Therefore, we collapse the
305+
// selection.
306+
this.pmView.dispatch(
307+
this.pmView.state.tr.setSelection(
308+
TextSelection.create(
309+
this.pmView.state.tr.doc,
310+
this.pmView.state.tr.selection.to
311+
)
299312
)
300-
)
301-
);
302-
} else if (
303-
this.isDragOrigin &&
304-
!this.pmView.dom.contains(event.target as Node)
305-
) {
306-
// 2. Because the editor from which the block originates doesn't get a
307-
// drop event on it, PM doesn't delete its selected content. Therefore, we
308-
// need to do so manually.
309-
//
310-
// Note: Deleting the selected content from the editor from which the
311-
// block originates, may change its height. This can cause the position of
312-
// the editor in which the block is being dropping to shift, before it
313-
// can handle the drop event. That in turn can cause the drop to happen
314-
// somewhere other than the user intended. To get around this, we delay
315-
// deleting the selected content until all editors have had the chance to
316-
// handle the event.
317-
setTimeout(
318-
() => this.pmView.dispatch(this.pmView.state.tr.deleteSelection()),
319-
0
320-
);
313+
);
314+
} else if (this.isDragOrigin && this.pmView.dom !== parentEditorElement) {
315+
// 2. Because the editor from which the block originates doesn't get a
316+
// drop event on it, PM doesn't delete its selected content. Therefore, we
317+
// need to do so manually.
318+
//
319+
// Note: Deleting the selected content from the editor from which the
320+
// block originates, may change its height. This can cause the position of
321+
// the editor in which the block is being dropping to shift, before it
322+
// can handle the drop event. That in turn can cause the drop to happen
323+
// somewhere other than the user intended. To get around this, we delay
324+
// deleting the selected content until all editors have had the chance to
325+
// handle the event.
326+
setTimeout(
327+
() => this.pmView.dispatch(this.pmView.state.tr.deleteSelection()),
328+
0
329+
);
330+
}
331+
// 3. PM only clears `view.dragging` on the editor that the block was
332+
// dropped, so we manually have to clear it on all the others. However,
333+
// PM also needs to read `view.dragging` while handling the event, so we
334+
// use a `setTimeout` to ensure it's only cleared after that.
335+
setTimeout(() => (this.pmView.dragging = null), 0);
321336
}
322-
// 3. PM only clears `view.dragging` on the editor that the block was
323-
// dropped, so we manually have to clear it on all the others. However,
324-
// PM also needs to read `view.dragging` while handling the event, so we
325-
// use a `setTimeout` to ensure it's only cleared after that.
326-
setTimeout(() => (this.pmView.dragging = null), 0);
327337

328338
if (
329339
this.sideMenuDetection === "editor" ||

0 commit comments

Comments
 (0)