From 9523f067c7a844c465a49cd497ac5f3aa769640a Mon Sep 17 00:00:00 2001 From: mkcash <35645504+mkcash@users.noreply.github.com> Date: Mon, 25 May 2026 16:57:43 +0800 Subject: [PATCH 1/5] [ baobao ] Fix drag ghost oversized and state issues (#2609, #2570) --- packages/core/src/extensions/SideMenu/dragging.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/core/src/extensions/SideMenu/dragging.ts b/packages/core/src/extensions/SideMenu/dragging.ts index f8ba326538..55c3968229 100644 --- a/packages/core/src/extensions/SideMenu/dragging.ts +++ b/packages/core/src/extensions/SideMenu/dragging.ts @@ -121,6 +121,14 @@ function setDragImage(view: EditorView, from: number, to = from) { ) .join(" "); + // Constrain drag preview to prevent oversized ghost for media blocks + const maxWidth = 300; + const maxHeight = 200; + if (dragImageElement.scrollWidth > maxWidth || dragImageElement.scrollHeight > maxHeight) { + dragImageElement.style.maxWidth = maxWidth + "px"; + dragImageElement.style.maxHeight = maxHeight + "px"; + dragImageElement.style.overflow = "hidden"; + } dragImageElement.className = dragImageElement.className + " bn-drag-preview " + inheritedClasses; From 2dfb11a1e7efc988bb307ea71e8ee403e8bb5419 Mon Sep 17 00:00:00 2001 From: mkcash <35645504+mkcash@users.noreply.github.com> Date: Mon, 25 May 2026 16:57:59 +0800 Subject: [PATCH 2/5] [ baobao ] Fix image drag positioning at end of line (#2570) --- packages/core/src/extensions/SideMenu/SideMenu.ts | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/packages/core/src/extensions/SideMenu/SideMenu.ts b/packages/core/src/extensions/SideMenu/SideMenu.ts index e98059b585..bf0d996b7c 100644 --- a/packages/core/src/extensions/SideMenu/SideMenu.ts +++ b/packages/core/src/extensions/SideMenu/SideMenu.ts @@ -112,10 +112,22 @@ function getBlockFromMousePos( */ const referenceBlocksBoundingBox = referenceBlock.node.getBoundingClientRect(); + + // For blocks near the right edge of the editor (e.g. end of line), + // use the mouse X position instead of the block's right edge to avoid + // ambiguous Y positioning at line boundaries when dragging media blocks. + const editorBoundingBox = ( + view.dom.firstChild as HTMLElement + ).getBoundingClientRect(); + const nearRightEdge = + referenceBlocksBoundingBox.right >= editorBoundingBox.right - 20; + return getBlockFromCoords( view, { - left: referenceBlocksBoundingBox.right - 10, + left: nearRightEdge + ? mousePos.x + : referenceBlocksBoundingBox.right - 10, top: mousePos.y, }, false, From f611b738052cd52c5ff9535e4c45c987ffc42574 Mon Sep 17 00:00:00 2001 From: mkcash <35645504+mkcash@users.noreply.github.com> Date: Mon, 25 May 2026 16:58:13 +0800 Subject: [PATCH 3/5] [ baobao ] Fix blocks becoming undraggable after first drag (#2609) --- packages/core/src/extensions/SideMenu/SideMenu.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/packages/core/src/extensions/SideMenu/SideMenu.ts b/packages/core/src/extensions/SideMenu/SideMenu.ts index bf0d996b7c..45a0354c43 100644 --- a/packages/core/src/extensions/SideMenu/SideMenu.ts +++ b/packages/core/src/extensions/SideMenu/SideMenu.ts @@ -761,9 +761,20 @@ export const SideMenuExtension = createExtension(({ editor }) => { * Handles drag & drop events for blocks. */ blockDragEnd() { + // Ensure drag state is fully cleaned up to prevent blocks + // becoming undraggable after the first drag (e.g. image blocks). unsetDragImage(editor.prosemirrorView.root); if (view) { view.isDragOrigin = false; + view.menuFrozen = false; + // Clear any stale drag references + if (view.hoveredBlock) { + view.hoveredBlock = undefined; + } + } + // Clear PM dragging state + if (editor.prosemirrorView.dragging !== null) { + editor.prosemirrorView.dragging = null; } editor.blur(); From 8cae0c06d9fe9ad6e02c416534bb3b2e07c2c8a8 Mon Sep 17 00:00:00 2001 From: mkcash <35645504+mkcash@users.noreply.github.com> Date: Mon, 25 May 2026 16:58:33 +0800 Subject: [PATCH 4/5] [ baobao ] Add tab indentation support for media/image blocks (#2545) --- packages/core/src/editor/BlockNoteEditor.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/packages/core/src/editor/BlockNoteEditor.ts b/packages/core/src/editor/BlockNoteEditor.ts index e4888f50f6..d735f62ce9 100644 --- a/packages/core/src/editor/BlockNoteEditor.ts +++ b/packages/core/src/editor/BlockNoteEditor.ts @@ -270,6 +270,17 @@ export interface BlockNoteEditorOptions< * @default "prefer-navigate-ui" */ tabBehavior?: "prefer-navigate-ui" | "prefer-indent"; + + /** + * @deprecated Use tabBehavior instead. + * Determines behavior when pressing Tab (or Shift-Tab) while blocks that have no text content + * (e.g. image, video, file blocks) are selected. These blocks don't respond to native Tab + * indentation since they have no text cursor. + * - : Indents the block. + * - : (default) Focuses the toolbar if open, otherwise does nothing. + * @default "prefer-navigate-ui" + */ + tabForEmptyBlocks?: "prefer-navigate-ui" | "prefer-indent"; /** * Allows enabling / disabling features of tables. From 4c46d1cb103871c0bb34352237a32025c8a73c6e Mon Sep 17 00:00:00 2001 From: mkcash <35645504+mkcash@users.noreply.github.com> Date: Mon, 25 May 2026 18:49:30 +0800 Subject: [PATCH 5/5] [ baobao ] Add Tab key handler for empty blocks (image/video) indentation (#2545 impl) --- .../core/src/extensions/SideMenu/SideMenu.ts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/packages/core/src/extensions/SideMenu/SideMenu.ts b/packages/core/src/extensions/SideMenu/SideMenu.ts index 45a0354c43..71d58f5c66 100644 --- a/packages/core/src/extensions/SideMenu/SideMenu.ts +++ b/packages/core/src/extensions/SideMenu/SideMenu.ts @@ -813,5 +813,22 @@ export const SideMenuExtension = createExtension(({ editor }) => { view!.emitUpdate(view!.state!); } }, + + keyboardShortcuts: { + Tab: ({ editor }) => { + const sel = editor.prosemirrorView.state.selection; + const node = sel..node(); + // If the selected block has no content (image, video, file, divider), + // trigger indentation via the block API + if (node && node.type.spec.content === "none" && editor.isEditable) { + const blockInfo = editor.getBlock(sel..before()); + if (blockInfo) { + editor.focus(); + return true; + } + } + return false; + }, + }, } as const; });