From d0ea3cca32f92bc561eeebe51972621789f0c75f Mon Sep 17 00:00:00 2001 From: Matthew Lipski Date: Mon, 8 Jun 2026 10:38:22 +0200 Subject: [PATCH 1/3] Fixed error triggered when moving blocks in some cases with multi-columns --- .../commands/moveBlocks/moveBlocks.ts | 26 ++- .../commands/replaceBlocks/replaceBlocks.ts | 21 ++- .../__snapshots__/moveBlocks.test.ts.snap | 178 ++++++++++++++++++ .../src/test/commands/moveBlocks.test.ts | 47 ++++- 4 files changed, 266 insertions(+), 6 deletions(-) diff --git a/packages/core/src/api/blockManipulation/commands/moveBlocks/moveBlocks.ts b/packages/core/src/api/blockManipulation/commands/moveBlocks/moveBlocks.ts index bb2f08dfca..1ba40df652 100644 --- a/packages/core/src/api/blockManipulation/commands/moveBlocks/moveBlocks.ts +++ b/packages/core/src/api/blockManipulation/commands/moveBlocks/moveBlocks.ts @@ -11,6 +11,9 @@ import type { BlockNoteEditor } from "../../../../editor/BlockNoteEditor"; import { BlockIdentifier } from "../../../../schema/index.js"; import { getNearestBlockPos } from "../../../getBlockInfoFromPos.js"; import { getNodeById } from "../../../nodeUtil.js"; +import { insertBlocks } from "../insertBlocks/insertBlocks.js"; +import { removeAndInsertBlocks } from "../replaceBlocks/replaceBlocks.js"; +import { fixColumnList } from "../replaceBlocks/util/fixColumnList.js"; type BlockSelectionData = ( | { @@ -148,7 +151,7 @@ export function moveBlocks( referenceBlock: BlockIdentifier, placement: "before" | "after", ) { - editor.transact(() => { + editor.transact((tr) => { // A `columnList` reference can be dissolved by `fixColumnList` when its // `column`s are removed, leaving its ID invalid for re-insertion. Anchor // to an adjacent block instead, which is unaffected by the removal. @@ -164,8 +167,25 @@ export function moveBlocks( } } - editor.removeBlocks(blocks); - editor.insertBlocks(flattenColumns(blocks), referenceBlock, placement); + // Don't fix columns/columnLists in the removal step. Otherwise, the + // following case breaks: + // + // + // Paragraph + // + // When the non-empty block is moved up, the column is now seen as empty + // and collapsed in the removal step, so the following insertion fails. + const { affectedColumnLists } = removeAndInsertBlocks(tr, blocks, [], { + fixColumns: false, + }); + insertBlocks(tr, flattenColumns(blocks), referenceBlock, placement); + + affectedColumnLists.forEach((id) => { + const posInfo = getNodeById(id, tr.doc); + if (posInfo) { + fixColumnList(tr, posInfo.posBeforeNode); + } + }); }); } diff --git a/packages/core/src/api/blockManipulation/commands/replaceBlocks/replaceBlocks.ts b/packages/core/src/api/blockManipulation/commands/replaceBlocks/replaceBlocks.ts index f1e946f909..4942689570 100644 --- a/packages/core/src/api/blockManipulation/commands/replaceBlocks/replaceBlocks.ts +++ b/packages/core/src/api/blockManipulation/commands/replaceBlocks/replaceBlocks.ts @@ -20,9 +20,13 @@ export function removeAndInsertBlocks< tr: Transaction, blocksToRemove: BlockIdentifier[], blocksToInsert: PartialBlock[], + options: { + fixColumns?: boolean; + } = {}, ): { insertedBlocks: Block[]; removedBlocks: Block[]; + affectedColumnLists: string[]; } { const pmSchema = getPmSchema(tr); // Converts the `PartialBlock`s to ProseMirror nodes to insert them into the @@ -112,12 +116,25 @@ export function removeAndInsertBlocks< ); } - columnListPositions.forEach((pos) => fixColumnList(tr, pos)); + // Saves IDs of columnLists containing removed blocks. If `fixColumns` is + // explicitly false, these are needed to run `fixColumnList` manually later. + const affectedColumnLists: string[] = []; + columnListPositions.forEach((pos) => { + const columnList = tr.doc.resolve(pos).nodeAfter; + if (columnList?.type.name === "columnList") { + affectedColumnLists.push(columnList.attrs.id); + } + }); + + // Collapses empty columns/columnLists + if (options.fixColumns !== false) { + columnListPositions.forEach((pos) => fixColumnList(tr, pos)); + } // Converts the nodes created from `blocksToInsert` into full `Block`s. const insertedBlocks = nodesToInsert.map((node) => nodeToBlock(node, pmSchema), ) as Block[]; - return { insertedBlocks, removedBlocks }; + return { insertedBlocks, removedBlocks, affectedColumnLists }; } diff --git a/packages/xl-multi-column/src/test/commands/__snapshots__/moveBlocks.test.ts.snap b/packages/xl-multi-column/src/test/commands/__snapshots__/moveBlocks.test.ts.snap index 4d6a2cf1f7..6eaa4edfd0 100644 --- a/packages/xl-multi-column/src/test/commands/__snapshots__/moveBlocks.test.ts.snap +++ b/packages/xl-multi-column/src/test/commands/__snapshots__/moveBlocks.test.ts.snap @@ -1,5 +1,183 @@ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html +exports[`Move past empty sibling within a column > Move down below empty sibling 1`] = ` +[ + { + "children": [ + { + "children": [ + { + "children": [], + "content": [ + { + "styles": {}, + "text": "Text 0", + "type": "text", + }, + ], + "id": "text-0", + "props": { + "backgroundColor": "default", + "textAlignment": "left", + "textColor": "default", + }, + "type": "paragraph", + }, + { + "children": [], + "content": [], + "id": "empty-0", + "props": { + "backgroundColor": "default", + "textAlignment": "left", + "textColor": "default", + }, + "type": "paragraph", + }, + ], + "content": undefined, + "id": "column-empty-0", + "props": { + "width": 1, + }, + "type": "column", + }, + { + "children": [ + { + "children": [], + "content": [], + "id": "empty-1", + "props": { + "backgroundColor": "default", + "textAlignment": "left", + "textColor": "default", + }, + "type": "paragraph", + }, + { + "children": [], + "content": [ + { + "styles": {}, + "text": "Text 1", + "type": "text", + }, + ], + "id": "text-1", + "props": { + "backgroundColor": "default", + "textAlignment": "left", + "textColor": "default", + }, + "type": "paragraph", + }, + ], + "content": undefined, + "id": "column-empty-1", + "props": { + "width": 1, + }, + "type": "column", + }, + ], + "content": undefined, + "id": "column-list-empty", + "props": {}, + "type": "columnList", + }, +] +`; + +exports[`Move past empty sibling within a column > Move up above empty sibling 1`] = ` +[ + { + "children": [ + { + "children": [ + { + "children": [], + "content": [ + { + "styles": {}, + "text": "Text 0", + "type": "text", + }, + ], + "id": "text-0", + "props": { + "backgroundColor": "default", + "textAlignment": "left", + "textColor": "default", + }, + "type": "paragraph", + }, + { + "children": [], + "content": [], + "id": "empty-0", + "props": { + "backgroundColor": "default", + "textAlignment": "left", + "textColor": "default", + }, + "type": "paragraph", + }, + ], + "content": undefined, + "id": "column-empty-0", + "props": { + "width": 1, + }, + "type": "column", + }, + { + "children": [ + { + "children": [], + "content": [], + "id": "empty-1", + "props": { + "backgroundColor": "default", + "textAlignment": "left", + "textColor": "default", + }, + "type": "paragraph", + }, + { + "children": [], + "content": [ + { + "styles": {}, + "text": "Text 1", + "type": "text", + }, + ], + "id": "text-1", + "props": { + "backgroundColor": "default", + "textAlignment": "left", + "textColor": "default", + }, + "type": "paragraph", + }, + ], + "content": undefined, + "id": "column-empty-1", + "props": { + "width": 1, + }, + "type": "column", + }, + ], + "content": undefined, + "id": "column-list-empty", + "props": {}, + "type": "columnList", + }, +] +`; + exports[`Test moveBlocksDown > Move into column list 1`] = ` [ { diff --git a/packages/xl-multi-column/src/test/commands/moveBlocks.test.ts b/packages/xl-multi-column/src/test/commands/moveBlocks.test.ts index 156895be44..6970c6c036 100644 --- a/packages/xl-multi-column/src/test/commands/moveBlocks.test.ts +++ b/packages/xl-multi-column/src/test/commands/moveBlocks.test.ts @@ -1,4 +1,4 @@ -import { describe, expect, it } from "vite-plus/test"; +import { beforeEach, describe, expect, it } from "vite-plus/test"; import { setupTestEnv } from "../setupTestEnv.js"; @@ -151,3 +151,48 @@ describe("Test moveBlocksDown", () => { expect(getEditor().document).toMatchSnapshot(); }); }); + +describe("Move past empty sibling within a column", () => { + beforeEach(() => { + getEditor().replaceBlocks(getEditor().document, [ + { + id: "column-list-empty", + type: "columnList", + children: [ + { + id: "column-empty-0", + type: "column", + children: [ + { id: "empty-0", type: "paragraph" }, + { id: "text-0", type: "paragraph", content: "Text 0" }, + ], + }, + { + id: "column-empty-1", + type: "column", + children: [ + { id: "empty-1", type: "paragraph" }, + { id: "text-1", type: "paragraph", content: "Text 1" }, + ], + }, + ], + }, + ]); + }); + + it("Move up above empty sibling", () => { + getEditor().setTextCursorPosition("text-0"); + + expect(() => getEditor().moveBlocksUp()).not.toThrow(); + + expect(getEditor().document).toMatchSnapshot(); + }); + + it("Move down below empty sibling", () => { + getEditor().setTextCursorPosition("empty-0"); + + expect(() => getEditor().moveBlocksDown()).not.toThrow(); + + expect(getEditor().document).toMatchSnapshot(); + }); +}); From 2f1af8fbfc94e80b24837a28f970d3fc362f8c1e Mon Sep 17 00:00:00 2001 From: yousefed Date: Mon, 6 Jul 2026 20:53:35 +0200 Subject: [PATCH 2/3] fix: don't collapse emptied columns when moving blocks Moves are rearrangements rather than deletions, so columns that a move empties out are deliberately left as-is instead of being collapsed. This keeps moves free of side effects (and reversible by moving back), matches dragging a block out of a column, and fixes the original error: collapsing a transiently-empty column mid-move broke the re-insertion. Also simplifies `removeAndInsertBlocks` (plain `fixColumns` opt-out, no `affectedColumnLists` return) and removes the columnList reference anchoring workaround in `moveBlocks`, which guarded against mid-move collapsing that can no longer happen. Co-Authored-By: Claude Fable 5 --- .../commands/moveBlocks/moveBlocks.ts | 39 +- .../commands/replaceBlocks/replaceBlocks.ts | 17 +- .../__snapshots__/moveBlocks.test.ts.snap | 614 +++++++++++------- 3 files changed, 398 insertions(+), 272 deletions(-) diff --git a/packages/core/src/api/blockManipulation/commands/moveBlocks/moveBlocks.ts b/packages/core/src/api/blockManipulation/commands/moveBlocks/moveBlocks.ts index 1ba40df652..cb8c3547cc 100644 --- a/packages/core/src/api/blockManipulation/commands/moveBlocks/moveBlocks.ts +++ b/packages/core/src/api/blockManipulation/commands/moveBlocks/moveBlocks.ts @@ -13,7 +13,6 @@ import { getNearestBlockPos } from "../../../getBlockInfoFromPos.js"; import { getNodeById } from "../../../nodeUtil.js"; import { insertBlocks } from "../insertBlocks/insertBlocks.js"; import { removeAndInsertBlocks } from "../replaceBlocks/replaceBlocks.js"; -import { fixColumnList } from "../replaceBlocks/util/fixColumnList.js"; type BlockSelectionData = ( | { @@ -152,40 +151,20 @@ export function moveBlocks( placement: "before" | "after", ) { editor.transact((tr) => { - // A `columnList` reference can be dissolved by `fixColumnList` when its - // `column`s are removed, leaving its ID invalid for re-insertion. Anchor - // to an adjacent block instead, which is unaffected by the removal. - const refBlock = editor.getBlock(referenceBlock); - if (refBlock?.type === "columnList") { - const adjacent = - placement === "after" - ? editor.getNextBlock(refBlock) - : editor.getPrevBlock(refBlock); - if (adjacent) { - referenceBlock = adjacent; - placement = placement === "after" ? "before" : "after"; - } - } - - // Don't fix columns/columnLists in the removal step. Otherwise, the - // following case breaks: + // Don't fix columns/columnLists in the removal step. Since a move is a + // rearrangement rather than a deletion, columns that it empties out are + // deliberately left as-is instead of being collapsed - this keeps moves + // free of side effects (and reversible by moving back), and matches + // dragging a block out of a column, which doesn't collapse it either. + // Fixing them mid-move also broke the following case: // // // Paragraph // - // When the non-empty block is moved up, the column is now seen as empty - // and collapsed in the removal step, so the following insertion fails. - const { affectedColumnLists } = removeAndInsertBlocks(tr, blocks, [], { - fixColumns: false, - }); + // When the non-empty block is moved up, the column is seen as empty and + // collapsed in the removal step, so the following insertion fails. + removeAndInsertBlocks(tr, blocks, [], { fixColumns: false }); insertBlocks(tr, flattenColumns(blocks), referenceBlock, placement); - - affectedColumnLists.forEach((id) => { - const posInfo = getNodeById(id, tr.doc); - if (posInfo) { - fixColumnList(tr, posInfo.posBeforeNode); - } - }); }); } diff --git a/packages/core/src/api/blockManipulation/commands/replaceBlocks/replaceBlocks.ts b/packages/core/src/api/blockManipulation/commands/replaceBlocks/replaceBlocks.ts index 4942689570..a4f5b8da89 100644 --- a/packages/core/src/api/blockManipulation/commands/replaceBlocks/replaceBlocks.ts +++ b/packages/core/src/api/blockManipulation/commands/replaceBlocks/replaceBlocks.ts @@ -26,7 +26,6 @@ export function removeAndInsertBlocks< ): { insertedBlocks: Block[]; removedBlocks: Block[]; - affectedColumnLists: string[]; } { const pmSchema = getPmSchema(tr); // Converts the `PartialBlock`s to ProseMirror nodes to insert them into the @@ -116,17 +115,9 @@ export function removeAndInsertBlocks< ); } - // Saves IDs of columnLists containing removed blocks. If `fixColumns` is - // explicitly false, these are needed to run `fixColumnList` manually later. - const affectedColumnLists: string[] = []; - columnListPositions.forEach((pos) => { - const columnList = tr.doc.resolve(pos).nodeAfter; - if (columnList?.type.name === "columnList") { - affectedColumnLists.push(columnList.attrs.id); - } - }); - - // Collapses empty columns/columnLists + // Collapses empty columns/columnLists. Callers where the removal isn't a + // deletion can opt out - e.g. `moveBlocks` re-inserts the blocks elsewhere + // and deliberately leaves emptied columns as-is. if (options.fixColumns !== false) { columnListPositions.forEach((pos) => fixColumnList(tr, pos)); } @@ -136,5 +127,5 @@ export function removeAndInsertBlocks< nodeToBlock(node, pmSchema), ) as Block[]; - return { insertedBlocks, removedBlocks, affectedColumnLists }; + return { insertedBlocks, removedBlocks }; } diff --git a/packages/xl-multi-column/src/test/commands/__snapshots__/moveBlocks.test.ts.snap b/packages/xl-multi-column/src/test/commands/__snapshots__/moveBlocks.test.ts.snap index 6eaa4edfd0..d9021ec0e0 100644 --- a/packages/xl-multi-column/src/test/commands/__snapshots__/moveBlocks.test.ts.snap +++ b/packages/xl-multi-column/src/test/commands/__snapshots__/moveBlocks.test.ts.snap @@ -743,21 +743,60 @@ exports[`Test moveBlocksDown > Selection across columns 1`] = ` "type": "paragraph", }, { - "children": [], - "content": [ + "children": [ { - "styles": {}, - "text": "Column Paragraph 0", - "type": "text", + "children": [ + { + "children": [], + "content": [ + { + "styles": {}, + "text": "Column Paragraph 0", + "type": "text", + }, + ], + "id": "column-paragraph-0", + "props": { + "backgroundColor": "default", + "textAlignment": "left", + "textColor": "default", + }, + "type": "paragraph", + }, + ], + "content": undefined, + "id": "column-0", + "props": { + "width": 1, + }, + "type": "column", + }, + { + "children": [ + { + "children": [], + "content": [], + "id": "1", + "props": { + "backgroundColor": "default", + "textAlignment": "left", + "textColor": "default", + }, + "type": "paragraph", + }, + ], + "content": undefined, + "id": "0", + "props": { + "width": 1, + }, + "type": "column", }, ], - "id": "column-paragraph-0", - "props": { - "backgroundColor": "default", - "textAlignment": "left", - "textColor": "default", - }, - "type": "paragraph", + "content": undefined, + "id": "column-list-0", + "props": {}, + "type": "columnList", }, { "children": [], @@ -2245,72 +2284,111 @@ exports[`Test moveBlocksUp > Selection across columns 1`] = ` "type": "paragraph", }, { - "children": [], - "content": [ - { - "styles": {}, - "text": "Column Paragraph 1", - "type": "text", - }, - ], - "id": "column-paragraph-1", - "props": { - "backgroundColor": "default", - "textAlignment": "left", - "textColor": "default", - }, - "type": "paragraph", - }, - { - "children": [], - "content": [ - { - "styles": {}, - "text": "Column Paragraph 2", - "type": "text", - }, - ], - "id": "column-paragraph-2", - "props": { - "backgroundColor": "default", - "textAlignment": "left", - "textColor": "default", - }, - "type": "paragraph", - }, - { - "children": [], - "content": [ + "children": [ { - "styles": {}, - "text": "Column Paragraph 3", - "type": "text", + "children": [ + { + "children": [], + "content": [ + { + "styles": {}, + "text": "Column Paragraph 1", + "type": "text", + }, + ], + "id": "column-paragraph-1", + "props": { + "backgroundColor": "default", + "textAlignment": "left", + "textColor": "default", + }, + "type": "paragraph", + }, + { + "children": [], + "content": [ + { + "styles": {}, + "text": "Column Paragraph 2", + "type": "text", + }, + ], + "id": "column-paragraph-2", + "props": { + "backgroundColor": "default", + "textAlignment": "left", + "textColor": "default", + }, + "type": "paragraph", + }, + { + "children": [], + "content": [ + { + "styles": {}, + "text": "Column Paragraph 3", + "type": "text", + }, + ], + "id": "column-paragraph-3", + "props": { + "backgroundColor": "default", + "textAlignment": "left", + "textColor": "default", + }, + "type": "paragraph", + }, + { + "children": [], + "content": [ + { + "styles": {}, + "text": "Column Paragraph 0", + "type": "text", + }, + ], + "id": "column-paragraph-0", + "props": { + "backgroundColor": "default", + "textAlignment": "left", + "textColor": "default", + }, + "type": "paragraph", + }, + ], + "content": undefined, + "id": "column-0", + "props": { + "width": 1, + }, + "type": "column", }, - ], - "id": "column-paragraph-3", - "props": { - "backgroundColor": "default", - "textAlignment": "left", - "textColor": "default", - }, - "type": "paragraph", - }, - { - "children": [], - "content": [ { - "styles": {}, - "text": "Column Paragraph 0", - "type": "text", + "children": [ + { + "children": [], + "content": [], + "id": "1", + "props": { + "backgroundColor": "default", + "textAlignment": "left", + "textColor": "default", + }, + "type": "paragraph", + }, + ], + "content": undefined, + "id": "0", + "props": { + "width": 1, + }, + "type": "column", }, ], - "id": "column-paragraph-0", - "props": { - "backgroundColor": "default", - "textAlignment": "left", - "textColor": "default", - }, - "type": "paragraph", + "content": undefined, + "id": "column-list-0", + "props": {}, + "type": "columnList", }, { "children": [], @@ -2557,89 +2635,128 @@ exports[`Test moveBlocksUp > Selection starts in column, ends outside 1`] = ` "type": "paragraph", }, { - "children": [], - "content": [ - { - "styles": {}, - "text": "Column Paragraph 0", - "type": "text", - }, - ], - "id": "column-paragraph-0", - "props": { - "backgroundColor": "default", - "textAlignment": "left", - "textColor": "default", - }, - "type": "paragraph", - }, - { - "children": [], - "content": [ + "children": [ { - "styles": {}, - "text": "Column Paragraph 1", - "type": "text", - }, - ], - "id": "column-paragraph-1", - "props": { - "backgroundColor": "default", - "textAlignment": "left", - "textColor": "default", - }, - "type": "paragraph", - }, - { - "children": [], - "content": [ - { - "styles": {}, - "text": "Column Paragraph 2", - "type": "text", - }, - ], - "id": "column-paragraph-2", - "props": { - "backgroundColor": "default", - "textAlignment": "left", - "textColor": "default", - }, - "type": "paragraph", - }, - { - "children": [], - "content": [ - { - "styles": {}, - "text": "Column Paragraph 3", - "type": "text", + "children": [ + { + "children": [], + "content": [ + { + "styles": {}, + "text": "Column Paragraph 0", + "type": "text", + }, + ], + "id": "column-paragraph-0", + "props": { + "backgroundColor": "default", + "textAlignment": "left", + "textColor": "default", + }, + "type": "paragraph", + }, + { + "children": [], + "content": [ + { + "styles": {}, + "text": "Column Paragraph 1", + "type": "text", + }, + ], + "id": "column-paragraph-1", + "props": { + "backgroundColor": "default", + "textAlignment": "left", + "textColor": "default", + }, + "type": "paragraph", + }, + { + "children": [], + "content": [ + { + "styles": {}, + "text": "Column Paragraph 2", + "type": "text", + }, + ], + "id": "column-paragraph-2", + "props": { + "backgroundColor": "default", + "textAlignment": "left", + "textColor": "default", + }, + "type": "paragraph", + }, + { + "children": [], + "content": [ + { + "styles": {}, + "text": "Column Paragraph 3", + "type": "text", + }, + ], + "id": "column-paragraph-3", + "props": { + "backgroundColor": "default", + "textAlignment": "left", + "textColor": "default", + }, + "type": "paragraph", + }, + { + "children": [], + "content": [ + { + "styles": {}, + "text": "Paragraph 2", + "type": "text", + }, + ], + "id": "paragraph-2", + "props": { + "backgroundColor": "default", + "textAlignment": "left", + "textColor": "default", + }, + "type": "paragraph", + }, + ], + "content": undefined, + "id": "column-0", + "props": { + "width": 1, + }, + "type": "column", }, - ], - "id": "column-paragraph-3", - "props": { - "backgroundColor": "default", - "textAlignment": "left", - "textColor": "default", - }, - "type": "paragraph", - }, - { - "children": [], - "content": [ { - "styles": {}, - "text": "Paragraph 2", - "type": "text", + "children": [ + { + "children": [], + "content": [], + "id": "0", + "props": { + "backgroundColor": "default", + "textAlignment": "left", + "textColor": "default", + }, + "type": "paragraph", + }, + ], + "content": undefined, + "id": "column-1", + "props": { + "width": 1, + }, + "type": "column", }, ], - "id": "paragraph-2", - "props": { - "backgroundColor": "default", - "textAlignment": "left", - "textColor": "default", - }, - "type": "paragraph", + "content": undefined, + "id": "column-list-0", + "props": {}, + "type": "columnList", }, ] `; @@ -2699,89 +2816,128 @@ exports[`Test moveBlocksUp > Selection starts in first column, ends outside 1`] "type": "paragraph", }, { - "children": [], - "content": [ - { - "styles": {}, - "text": "Column Paragraph 1", - "type": "text", - }, - ], - "id": "column-paragraph-1", - "props": { - "backgroundColor": "default", - "textAlignment": "left", - "textColor": "default", - }, - "type": "paragraph", - }, - { - "children": [], - "content": [ - { - "styles": {}, - "text": "Column Paragraph 2", - "type": "text", - }, - ], - "id": "column-paragraph-2", - "props": { - "backgroundColor": "default", - "textAlignment": "left", - "textColor": "default", - }, - "type": "paragraph", - }, - { - "children": [], - "content": [ - { - "styles": {}, - "text": "Column Paragraph 3", - "type": "text", - }, - ], - "id": "column-paragraph-3", - "props": { - "backgroundColor": "default", - "textAlignment": "left", - "textColor": "default", - }, - "type": "paragraph", - }, - { - "children": [], - "content": [ + "children": [ { - "styles": {}, - "text": "Paragraph 2", - "type": "text", + "children": [ + { + "children": [], + "content": [ + { + "styles": {}, + "text": "Column Paragraph 1", + "type": "text", + }, + ], + "id": "column-paragraph-1", + "props": { + "backgroundColor": "default", + "textAlignment": "left", + "textColor": "default", + }, + "type": "paragraph", + }, + { + "children": [], + "content": [ + { + "styles": {}, + "text": "Column Paragraph 2", + "type": "text", + }, + ], + "id": "column-paragraph-2", + "props": { + "backgroundColor": "default", + "textAlignment": "left", + "textColor": "default", + }, + "type": "paragraph", + }, + { + "children": [], + "content": [ + { + "styles": {}, + "text": "Column Paragraph 3", + "type": "text", + }, + ], + "id": "column-paragraph-3", + "props": { + "backgroundColor": "default", + "textAlignment": "left", + "textColor": "default", + }, + "type": "paragraph", + }, + { + "children": [], + "content": [ + { + "styles": {}, + "text": "Paragraph 2", + "type": "text", + }, + ], + "id": "paragraph-2", + "props": { + "backgroundColor": "default", + "textAlignment": "left", + "textColor": "default", + }, + "type": "paragraph", + }, + { + "children": [], + "content": [ + { + "styles": {}, + "text": "Column Paragraph 0", + "type": "text", + }, + ], + "id": "column-paragraph-0", + "props": { + "backgroundColor": "default", + "textAlignment": "left", + "textColor": "default", + }, + "type": "paragraph", + }, + ], + "content": undefined, + "id": "column-0", + "props": { + "width": 1, + }, + "type": "column", }, - ], - "id": "paragraph-2", - "props": { - "backgroundColor": "default", - "textAlignment": "left", - "textColor": "default", - }, - "type": "paragraph", - }, - { - "children": [], - "content": [ { - "styles": {}, - "text": "Column Paragraph 0", - "type": "text", + "children": [ + { + "children": [], + "content": [], + "id": "1", + "props": { + "backgroundColor": "default", + "textAlignment": "left", + "textColor": "default", + }, + "type": "paragraph", + }, + ], + "content": undefined, + "id": "0", + "props": { + "width": 1, + }, + "type": "column", }, ], - "id": "column-paragraph-0", - "props": { - "backgroundColor": "default", - "textAlignment": "left", - "textColor": "default", - }, - "type": "paragraph", + "content": undefined, + "id": "column-list-0", + "props": {}, + "type": "columnList", }, ] `; From 1de86a2e808ae011b769c2a6a6973cfc9c562723 Mon Sep 17 00:00:00 2001 From: yousefed Date: Mon, 6 Jul 2026 20:59:14 +0200 Subject: [PATCH 3/3] fix build --- .../blockManipulation/commands/moveBlocks/moveBlocks.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/core/src/api/blockManipulation/commands/moveBlocks/moveBlocks.ts b/packages/core/src/api/blockManipulation/commands/moveBlocks/moveBlocks.ts index cb8c3547cc..26774c3d24 100644 --- a/packages/core/src/api/blockManipulation/commands/moveBlocks/moveBlocks.ts +++ b/packages/core/src/api/blockManipulation/commands/moveBlocks/moveBlocks.ts @@ -164,7 +164,12 @@ export function moveBlocks( // When the non-empty block is moved up, the column is seen as empty and // collapsed in the removal step, so the following insertion fails. removeAndInsertBlocks(tr, blocks, [], { fixColumns: false }); - insertBlocks(tr, flattenColumns(blocks), referenceBlock, placement); + insertBlocks( + tr, + flattenColumns(blocks), + referenceBlock, + placement, + ); }); }