Skip to content

fix: drag & drop issues #1458

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Feb 25, 2025
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 22 additions & 9 deletions packages/core/src/extensions/SideMenu/SideMenuPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,11 @@ export class SideMenuView<
this.onDrop as EventListener,
true
);
this.pmView.root.addEventListener(
"dragend",
this.onDragEnd as EventListener,
true
);
initializeESMDependencies();

// Shows or updates menu position whenever the cursor moves, if the menu isn't frozen.
Expand Down Expand Up @@ -300,8 +305,8 @@ export class SideMenuView<
// a block from a different editor is being dropped, this causes some
// issues that the code below fixes:
if (!this.isDragOrigin && this.pmView.dom === parentEditorElement) {
// 1. Because the editor selection is unrelated to the dragged content,
// we don't want PM to delete its content. Therefore, we collapse the
// Because the editor selection is unrelated to the dragged content, we
// don't want PM to delete its content. Therefore, we collapse the
// selection.
this.pmView.dispatch(
this.pmView.state.tr.setSelection(
Expand All @@ -312,8 +317,8 @@ export class SideMenuView<
)
);
} else if (this.isDragOrigin && this.pmView.dom !== parentEditorElement) {
// 2. Because the editor from which the block originates doesn't get a
// drop event on it, PM doesn't delete its selected content. Therefore, we
// Because the editor from which the block originates doesn't get a drop
// event on it, PM doesn't delete its selected content. Therefore, we
// need to do so manually.
//
// Note: Deleting the selected content from the editor from which the
Expand All @@ -328,11 +333,6 @@ export class SideMenuView<
0
);
}
// 3. PM only clears `view.dragging` on the editor that the block was
// dropped, so we manually have to clear it on all the others. However,
// PM also needs to read `view.dragging` while handling the event, so we
// use a `setTimeout` to ensure it's only cleared after that.
setTimeout(() => (this.pmView.dragging = null), 0);
}

if (
Expand Down Expand Up @@ -360,6 +360,14 @@ export class SideMenuView<
}
};

onDragEnd = () => {
// When the user starts dragging a block, `view.dragging` is set on all
// BlockNote editors. However, when the drag ends, only the editor that the
// drag originated in automatically clears `view.dragging`. Therefore, we
// have to manually clear it on all editors.
this.pmView.dragging = null;
};

/**
* If a block is being dragged, ProseMirror usually gets the context of what's
* being dragged from `view.dragging`, which is automatically set when a
Expand Down Expand Up @@ -580,6 +588,11 @@ export class SideMenuView<
this.onDrop as EventListener,
true
);
this.pmView.root.removeEventListener(
"dragend",
this.onDragEnd as EventListener,
true
);
this.pmView.root.removeEventListener(
"keydown",
this.onKeyDown as EventListener,
Expand Down
6 changes: 5 additions & 1 deletion packages/core/src/extensions/UniqueID/UniqueID.ts
Original file line number Diff line number Diff line change
Expand Up @@ -265,9 +265,13 @@ const UniqueID = Extension.create({
? void 0
: _a.effectAllowed) === "copy"
) {
dragSourceElement = null;
transformPasted = true;
} else {
transformPasted = false;
}

dragSourceElement = null;

return false;
},
// always create new ids on pasted content
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,12 @@ export function multiColumnDropCursor(
editor.schema.styleSchema
);

// The user is dropping next to the original block being dragged - do
// nothing.
if (block.id === draggedBlock.id) {
return;
}

const blocks =
position === "left" ? [draggedBlock, block] : [block, draggedBlock];
editor.removeBlocks([draggedBlock]);
Expand Down
Loading