Skip to content

Commit 531429b

Browse files
fix: drag & drop issues (#1458)
* Fixed multi-column drag & drop same block error * Fixed `view.dragging` not always being cleared on drop * Fixed block IDs getting removed when doing drag & drop after paste * Small update * Small fix * Re-added `transformPasted` reset
1 parent 454a91c commit 531429b

File tree

3 files changed

+36
-12
lines changed

3 files changed

+36
-12
lines changed

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

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,11 @@ export class SideMenuView<
178178
this.onDrop as EventListener,
179179
true
180180
);
181+
this.pmView.root.addEventListener(
182+
"dragend",
183+
this.onDragEnd as EventListener,
184+
true
185+
);
181186
initializeESMDependencies();
182187

183188
// Shows or updates menu position whenever the cursor moves, if the menu isn't frozen.
@@ -300,8 +305,8 @@ export class SideMenuView<
300305
// a block from a different editor is being dropped, this causes some
301306
// issues that the code below fixes:
302307
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
308+
// Because the editor selection is unrelated to the dragged content, we
309+
// don't want PM to delete its content. Therefore, we collapse the
305310
// selection.
306311
this.pmView.dispatch(
307312
this.pmView.state.tr.setSelection(
@@ -312,8 +317,8 @@ export class SideMenuView<
312317
)
313318
);
314319
} 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
320+
// Because the editor from which the block originates doesn't get a drop
321+
// event on it, PM doesn't delete its selected content. Therefore, we
317322
// need to do so manually.
318323
//
319324
// Note: Deleting the selected content from the editor from which the
@@ -328,11 +333,6 @@ export class SideMenuView<
328333
0
329334
);
330335
}
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);
336336
}
337337

338338
if (
@@ -360,6 +360,14 @@ export class SideMenuView<
360360
}
361361
};
362362

363+
onDragEnd = () => {
364+
// When the user starts dragging a block, `view.dragging` is set on all
365+
// BlockNote editors. However, when the drag ends, only the editor that the
366+
// drag originated in automatically clears `view.dragging`. Therefore, we
367+
// have to manually clear it on all editors.
368+
this.pmView.dragging = null;
369+
};
370+
363371
/**
364372
* If a block is being dragged, ProseMirror usually gets the context of what's
365373
* being dragged from `view.dragging`, which is automatically set when a
@@ -580,6 +588,11 @@ export class SideMenuView<
580588
this.onDrop as EventListener,
581589
true
582590
);
591+
this.pmView.root.removeEventListener(
592+
"dragend",
593+
this.onDragEnd as EventListener,
594+
true
595+
);
583596
this.pmView.root.removeEventListener(
584597
"keydown",
585598
this.onKeyDown as EventListener,

packages/core/src/extensions/UniqueID/UniqueID.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -252,8 +252,9 @@ const UniqueID = Extension.create({
252252
};
253253
},
254254
props: {
255-
// `handleDOMEvents` is called before `transformPasted`
256-
// so we can do some checks before
255+
// `handleDOMEvents` is called before `transformPasted` so we can do
256+
// some checks before. However, `transformPasted` only runs when
257+
// editor content is pasted - not external content.
257258
handleDOMEvents: {
258259
// only create new ids for dropped content while holding `alt`
259260
// or content is dragged from another editor
@@ -265,9 +266,13 @@ const UniqueID = Extension.create({
265266
? void 0
266267
: _a.effectAllowed) === "copy"
267268
) {
268-
dragSourceElement = null;
269269
transformPasted = true;
270+
} else {
271+
transformPasted = false;
270272
}
273+
274+
dragSourceElement = null;
275+
271276
return false;
272277
},
273278
// always create new ids on pasted content

packages/xl-multi-column/src/extensions/DropCursor/MultiColumnDropCursorPlugin.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,12 @@ export function multiColumnDropCursor(
163163
editor.schema.styleSchema
164164
);
165165

166+
// The user is dropping next to the original block being dragged - do
167+
// nothing.
168+
if (block.id === draggedBlock.id) {
169+
return;
170+
}
171+
166172
const blocks =
167173
position === "left" ? [draggedBlock, block] : [block, draggedBlock];
168174
editor.removeBlocks([draggedBlock]);

0 commit comments

Comments
 (0)