diff --git a/packages/core/src/blocks/Table/TableExtension.ts b/packages/core/src/blocks/Table/TableExtension.ts index 3660d8c620..1d2cf9d47f 100644 --- a/packages/core/src/blocks/Table/TableExtension.ts +++ b/packages/core/src/blocks/Table/TableExtension.ts @@ -1,5 +1,14 @@ import { callOrReturn, Extension, getExtensionField } from "@tiptap/core"; -import { columnResizing, goToNextCell, tableEditing } from "prosemirror-tables"; +import { TextSelection } from "prosemirror-state"; +import { + columnResizing, + goToNextCell, + isInTable, + moveCellForward, + nextCell, + selectionCell, + tableEditing, +} from "prosemirror-tables"; export const RESIZE_MIN_WIDTH = 35; export const EMPTY_CELL_WIDTH = 120; @@ -24,19 +33,39 @@ export const TableExtension = Extension.create({ addKeyboardShortcuts() { return { - // Makes enter create a new line within the cell. + // Moves the selection to the cell below. Enter: () => { if ( - this.editor.state.selection.empty && - this.editor.state.selection.$head.parent.type.name === - "tableParagraph" + this.editor.state.selection.$head.parent.type.name !== + "tableParagraph" ) { - this.editor.commands.insertContent({ type: "hardBreak" }); - - return true; + return false; } - return false; + return this.editor.commands.command(({ state, dispatch }) => { + if (!isInTable(state)) { + return false; + } + + const $cell = selectionCell(state); + const $nextCell = nextCell($cell, "vert", 1); + + if (!$nextCell) { + return false; + } + + if (dispatch) { + dispatch( + state.tr + .setSelection( + TextSelection.between($nextCell, moveCellForward($nextCell)), + ) + .scrollIntoView(), + ); + } + + return true; + }); }, // Ensures that backspace won't delete the table if the text cursor is at // the start of a cell and the selection is empty. diff --git a/tests/src/end-to-end/tables/tables.test.ts b/tests/src/end-to-end/tables/tables.test.ts index 4d11d597e6..2abfc08c30 100644 --- a/tests/src/end-to-end/tables/tables.test.ts +++ b/tests/src/end-to-end/tables/tables.test.ts @@ -49,4 +49,22 @@ test.describe("Check Table interactions", () => { await compareDocToSnapshot(page, "arrowKeyCells.json"); }); + test("Enter should move to cell below", async ({ page }) => { + await focusOnEditor(page); + await executeSlashCommand(page, "table"); + await page.keyboard.type("Top"); + await page.keyboard.press("Enter"); + await page.keyboard.type("Bottom"); + + await compareDocToSnapshot(page, "enterMovesToCellBelow.json"); + }); + test("Shift+Enter should create a new line within cell", async ({ page }) => { + await focusOnEditor(page); + await executeSlashCommand(page, "table"); + await page.keyboard.type("Line 1"); + await page.keyboard.press("Shift+Enter"); + await page.keyboard.type("Line 2"); + + await compareDocToSnapshot(page, "shiftEnterNewLineInCell.json"); + }); }); diff --git a/tests/src/end-to-end/tables/tables.test.ts-snapshots/enterMovesToCellBelow-json-chromium-linux.json b/tests/src/end-to-end/tables/tables.test.ts-snapshots/enterMovesToCellBelow-json-chromium-linux.json new file mode 100644 index 0000000000..cb17830afd --- /dev/null +++ b/tests/src/end-to-end/tables/tables.test.ts-snapshots/enterMovesToCellBelow-json-chromium-linux.json @@ -0,0 +1,160 @@ +{ + "type": "doc", + "content": [ + { + "type": "blockGroup", + "content": [ + { + "type": "blockContainer", + "attrs": { + "id": "0" + }, + "content": [ + { + "type": "table", + "attrs": { + "textColor": "default" + }, + "content": [ + { + "type": "tableRow", + "content": [ + { + "type": "tableCell", + "attrs": { + "textColor": "default", + "backgroundColor": "default", + "textAlignment": "left", + "colspan": 1, + "rowspan": 1, + "colwidth": null + }, + "content": [ + { + "type": "tableParagraph", + "content": [ + { + "type": "text", + "text": "Top" + } + ] + } + ] + }, + { + "type": "tableCell", + "attrs": { + "textColor": "default", + "backgroundColor": "default", + "textAlignment": "left", + "colspan": 1, + "rowspan": 1, + "colwidth": null + }, + "content": [ + { + "type": "tableParagraph" + } + ] + }, + { + "type": "tableCell", + "attrs": { + "textColor": "default", + "backgroundColor": "default", + "textAlignment": "left", + "colspan": 1, + "rowspan": 1, + "colwidth": null + }, + "content": [ + { + "type": "tableParagraph" + } + ] + } + ] + }, + { + "type": "tableRow", + "content": [ + { + "type": "tableCell", + "attrs": { + "textColor": "default", + "backgroundColor": "default", + "textAlignment": "left", + "colspan": 1, + "rowspan": 1, + "colwidth": null + }, + "content": [ + { + "type": "tableParagraph", + "content": [ + { + "type": "text", + "text": "Bottom" + } + ] + } + ] + }, + { + "type": "tableCell", + "attrs": { + "textColor": "default", + "backgroundColor": "default", + "textAlignment": "left", + "colspan": 1, + "rowspan": 1, + "colwidth": null + }, + "content": [ + { + "type": "tableParagraph" + } + ] + }, + { + "type": "tableCell", + "attrs": { + "textColor": "default", + "backgroundColor": "default", + "textAlignment": "left", + "colspan": 1, + "rowspan": 1, + "colwidth": null + }, + "content": [ + { + "type": "tableParagraph" + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "blockContainer", + "attrs": { + "id": "1" + }, + "content": [ + { + "type": "paragraph", + "attrs": { + "backgroundColor": "default", + "textColor": "default", + "textAlignment": "left" + } + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/tests/src/end-to-end/tables/tables.test.ts-snapshots/enterMovesToCellBelow-json-firefox-linux.json b/tests/src/end-to-end/tables/tables.test.ts-snapshots/enterMovesToCellBelow-json-firefox-linux.json new file mode 100644 index 0000000000..cb17830afd --- /dev/null +++ b/tests/src/end-to-end/tables/tables.test.ts-snapshots/enterMovesToCellBelow-json-firefox-linux.json @@ -0,0 +1,160 @@ +{ + "type": "doc", + "content": [ + { + "type": "blockGroup", + "content": [ + { + "type": "blockContainer", + "attrs": { + "id": "0" + }, + "content": [ + { + "type": "table", + "attrs": { + "textColor": "default" + }, + "content": [ + { + "type": "tableRow", + "content": [ + { + "type": "tableCell", + "attrs": { + "textColor": "default", + "backgroundColor": "default", + "textAlignment": "left", + "colspan": 1, + "rowspan": 1, + "colwidth": null + }, + "content": [ + { + "type": "tableParagraph", + "content": [ + { + "type": "text", + "text": "Top" + } + ] + } + ] + }, + { + "type": "tableCell", + "attrs": { + "textColor": "default", + "backgroundColor": "default", + "textAlignment": "left", + "colspan": 1, + "rowspan": 1, + "colwidth": null + }, + "content": [ + { + "type": "tableParagraph" + } + ] + }, + { + "type": "tableCell", + "attrs": { + "textColor": "default", + "backgroundColor": "default", + "textAlignment": "left", + "colspan": 1, + "rowspan": 1, + "colwidth": null + }, + "content": [ + { + "type": "tableParagraph" + } + ] + } + ] + }, + { + "type": "tableRow", + "content": [ + { + "type": "tableCell", + "attrs": { + "textColor": "default", + "backgroundColor": "default", + "textAlignment": "left", + "colspan": 1, + "rowspan": 1, + "colwidth": null + }, + "content": [ + { + "type": "tableParagraph", + "content": [ + { + "type": "text", + "text": "Bottom" + } + ] + } + ] + }, + { + "type": "tableCell", + "attrs": { + "textColor": "default", + "backgroundColor": "default", + "textAlignment": "left", + "colspan": 1, + "rowspan": 1, + "colwidth": null + }, + "content": [ + { + "type": "tableParagraph" + } + ] + }, + { + "type": "tableCell", + "attrs": { + "textColor": "default", + "backgroundColor": "default", + "textAlignment": "left", + "colspan": 1, + "rowspan": 1, + "colwidth": null + }, + "content": [ + { + "type": "tableParagraph" + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "blockContainer", + "attrs": { + "id": "1" + }, + "content": [ + { + "type": "paragraph", + "attrs": { + "backgroundColor": "default", + "textColor": "default", + "textAlignment": "left" + } + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/tests/src/end-to-end/tables/tables.test.ts-snapshots/enterMovesToCellBelow-json-webkit-linux.json b/tests/src/end-to-end/tables/tables.test.ts-snapshots/enterMovesToCellBelow-json-webkit-linux.json new file mode 100644 index 0000000000..cb17830afd --- /dev/null +++ b/tests/src/end-to-end/tables/tables.test.ts-snapshots/enterMovesToCellBelow-json-webkit-linux.json @@ -0,0 +1,160 @@ +{ + "type": "doc", + "content": [ + { + "type": "blockGroup", + "content": [ + { + "type": "blockContainer", + "attrs": { + "id": "0" + }, + "content": [ + { + "type": "table", + "attrs": { + "textColor": "default" + }, + "content": [ + { + "type": "tableRow", + "content": [ + { + "type": "tableCell", + "attrs": { + "textColor": "default", + "backgroundColor": "default", + "textAlignment": "left", + "colspan": 1, + "rowspan": 1, + "colwidth": null + }, + "content": [ + { + "type": "tableParagraph", + "content": [ + { + "type": "text", + "text": "Top" + } + ] + } + ] + }, + { + "type": "tableCell", + "attrs": { + "textColor": "default", + "backgroundColor": "default", + "textAlignment": "left", + "colspan": 1, + "rowspan": 1, + "colwidth": null + }, + "content": [ + { + "type": "tableParagraph" + } + ] + }, + { + "type": "tableCell", + "attrs": { + "textColor": "default", + "backgroundColor": "default", + "textAlignment": "left", + "colspan": 1, + "rowspan": 1, + "colwidth": null + }, + "content": [ + { + "type": "tableParagraph" + } + ] + } + ] + }, + { + "type": "tableRow", + "content": [ + { + "type": "tableCell", + "attrs": { + "textColor": "default", + "backgroundColor": "default", + "textAlignment": "left", + "colspan": 1, + "rowspan": 1, + "colwidth": null + }, + "content": [ + { + "type": "tableParagraph", + "content": [ + { + "type": "text", + "text": "Bottom" + } + ] + } + ] + }, + { + "type": "tableCell", + "attrs": { + "textColor": "default", + "backgroundColor": "default", + "textAlignment": "left", + "colspan": 1, + "rowspan": 1, + "colwidth": null + }, + "content": [ + { + "type": "tableParagraph" + } + ] + }, + { + "type": "tableCell", + "attrs": { + "textColor": "default", + "backgroundColor": "default", + "textAlignment": "left", + "colspan": 1, + "rowspan": 1, + "colwidth": null + }, + "content": [ + { + "type": "tableParagraph" + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "blockContainer", + "attrs": { + "id": "1" + }, + "content": [ + { + "type": "paragraph", + "attrs": { + "backgroundColor": "default", + "textColor": "default", + "textAlignment": "left" + } + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/tests/src/end-to-end/tables/tables.test.ts-snapshots/shiftEnterNewLineInCell-json-chromium-linux.json b/tests/src/end-to-end/tables/tables.test.ts-snapshots/shiftEnterNewLineInCell-json-chromium-linux.json new file mode 100644 index 0000000000..2c2cb65b20 --- /dev/null +++ b/tests/src/end-to-end/tables/tables.test.ts-snapshots/shiftEnterNewLineInCell-json-chromium-linux.json @@ -0,0 +1,161 @@ +{ + "type": "doc", + "content": [ + { + "type": "blockGroup", + "content": [ + { + "type": "blockContainer", + "attrs": { + "id": "0" + }, + "content": [ + { + "type": "table", + "attrs": { + "textColor": "default" + }, + "content": [ + { + "type": "tableRow", + "content": [ + { + "type": "tableCell", + "attrs": { + "textColor": "default", + "backgroundColor": "default", + "textAlignment": "left", + "colspan": 1, + "rowspan": 1, + "colwidth": null + }, + "content": [ + { + "type": "tableParagraph", + "content": [ + { + "type": "text", + "text": "Line 1" + }, + { + "type": "hardBreak" + }, + { + "type": "text", + "text": "Line 2" + } + ] + } + ] + }, + { + "type": "tableCell", + "attrs": { + "textColor": "default", + "backgroundColor": "default", + "textAlignment": "left", + "colspan": 1, + "rowspan": 1, + "colwidth": null + }, + "content": [ + { + "type": "tableParagraph" + } + ] + }, + { + "type": "tableCell", + "attrs": { + "textColor": "default", + "backgroundColor": "default", + "textAlignment": "left", + "colspan": 1, + "rowspan": 1, + "colwidth": null + }, + "content": [ + { + "type": "tableParagraph" + } + ] + } + ] + }, + { + "type": "tableRow", + "content": [ + { + "type": "tableCell", + "attrs": { + "textColor": "default", + "backgroundColor": "default", + "textAlignment": "left", + "colspan": 1, + "rowspan": 1, + "colwidth": null + }, + "content": [ + { + "type": "tableParagraph" + } + ] + }, + { + "type": "tableCell", + "attrs": { + "textColor": "default", + "backgroundColor": "default", + "textAlignment": "left", + "colspan": 1, + "rowspan": 1, + "colwidth": null + }, + "content": [ + { + "type": "tableParagraph" + } + ] + }, + { + "type": "tableCell", + "attrs": { + "textColor": "default", + "backgroundColor": "default", + "textAlignment": "left", + "colspan": 1, + "rowspan": 1, + "colwidth": null + }, + "content": [ + { + "type": "tableParagraph" + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "blockContainer", + "attrs": { + "id": "1" + }, + "content": [ + { + "type": "paragraph", + "attrs": { + "backgroundColor": "default", + "textColor": "default", + "textAlignment": "left" + } + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/tests/src/end-to-end/tables/tables.test.ts-snapshots/shiftEnterNewLineInCell-json-firefox-linux.json b/tests/src/end-to-end/tables/tables.test.ts-snapshots/shiftEnterNewLineInCell-json-firefox-linux.json new file mode 100644 index 0000000000..2c2cb65b20 --- /dev/null +++ b/tests/src/end-to-end/tables/tables.test.ts-snapshots/shiftEnterNewLineInCell-json-firefox-linux.json @@ -0,0 +1,161 @@ +{ + "type": "doc", + "content": [ + { + "type": "blockGroup", + "content": [ + { + "type": "blockContainer", + "attrs": { + "id": "0" + }, + "content": [ + { + "type": "table", + "attrs": { + "textColor": "default" + }, + "content": [ + { + "type": "tableRow", + "content": [ + { + "type": "tableCell", + "attrs": { + "textColor": "default", + "backgroundColor": "default", + "textAlignment": "left", + "colspan": 1, + "rowspan": 1, + "colwidth": null + }, + "content": [ + { + "type": "tableParagraph", + "content": [ + { + "type": "text", + "text": "Line 1" + }, + { + "type": "hardBreak" + }, + { + "type": "text", + "text": "Line 2" + } + ] + } + ] + }, + { + "type": "tableCell", + "attrs": { + "textColor": "default", + "backgroundColor": "default", + "textAlignment": "left", + "colspan": 1, + "rowspan": 1, + "colwidth": null + }, + "content": [ + { + "type": "tableParagraph" + } + ] + }, + { + "type": "tableCell", + "attrs": { + "textColor": "default", + "backgroundColor": "default", + "textAlignment": "left", + "colspan": 1, + "rowspan": 1, + "colwidth": null + }, + "content": [ + { + "type": "tableParagraph" + } + ] + } + ] + }, + { + "type": "tableRow", + "content": [ + { + "type": "tableCell", + "attrs": { + "textColor": "default", + "backgroundColor": "default", + "textAlignment": "left", + "colspan": 1, + "rowspan": 1, + "colwidth": null + }, + "content": [ + { + "type": "tableParagraph" + } + ] + }, + { + "type": "tableCell", + "attrs": { + "textColor": "default", + "backgroundColor": "default", + "textAlignment": "left", + "colspan": 1, + "rowspan": 1, + "colwidth": null + }, + "content": [ + { + "type": "tableParagraph" + } + ] + }, + { + "type": "tableCell", + "attrs": { + "textColor": "default", + "backgroundColor": "default", + "textAlignment": "left", + "colspan": 1, + "rowspan": 1, + "colwidth": null + }, + "content": [ + { + "type": "tableParagraph" + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "blockContainer", + "attrs": { + "id": "1" + }, + "content": [ + { + "type": "paragraph", + "attrs": { + "backgroundColor": "default", + "textColor": "default", + "textAlignment": "left" + } + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/tests/src/end-to-end/tables/tables.test.ts-snapshots/shiftEnterNewLineInCell-json-webkit-linux.json b/tests/src/end-to-end/tables/tables.test.ts-snapshots/shiftEnterNewLineInCell-json-webkit-linux.json new file mode 100644 index 0000000000..2c2cb65b20 --- /dev/null +++ b/tests/src/end-to-end/tables/tables.test.ts-snapshots/shiftEnterNewLineInCell-json-webkit-linux.json @@ -0,0 +1,161 @@ +{ + "type": "doc", + "content": [ + { + "type": "blockGroup", + "content": [ + { + "type": "blockContainer", + "attrs": { + "id": "0" + }, + "content": [ + { + "type": "table", + "attrs": { + "textColor": "default" + }, + "content": [ + { + "type": "tableRow", + "content": [ + { + "type": "tableCell", + "attrs": { + "textColor": "default", + "backgroundColor": "default", + "textAlignment": "left", + "colspan": 1, + "rowspan": 1, + "colwidth": null + }, + "content": [ + { + "type": "tableParagraph", + "content": [ + { + "type": "text", + "text": "Line 1" + }, + { + "type": "hardBreak" + }, + { + "type": "text", + "text": "Line 2" + } + ] + } + ] + }, + { + "type": "tableCell", + "attrs": { + "textColor": "default", + "backgroundColor": "default", + "textAlignment": "left", + "colspan": 1, + "rowspan": 1, + "colwidth": null + }, + "content": [ + { + "type": "tableParagraph" + } + ] + }, + { + "type": "tableCell", + "attrs": { + "textColor": "default", + "backgroundColor": "default", + "textAlignment": "left", + "colspan": 1, + "rowspan": 1, + "colwidth": null + }, + "content": [ + { + "type": "tableParagraph" + } + ] + } + ] + }, + { + "type": "tableRow", + "content": [ + { + "type": "tableCell", + "attrs": { + "textColor": "default", + "backgroundColor": "default", + "textAlignment": "left", + "colspan": 1, + "rowspan": 1, + "colwidth": null + }, + "content": [ + { + "type": "tableParagraph" + } + ] + }, + { + "type": "tableCell", + "attrs": { + "textColor": "default", + "backgroundColor": "default", + "textAlignment": "left", + "colspan": 1, + "rowspan": 1, + "colwidth": null + }, + "content": [ + { + "type": "tableParagraph" + } + ] + }, + { + "type": "tableCell", + "attrs": { + "textColor": "default", + "backgroundColor": "default", + "textAlignment": "left", + "colspan": 1, + "rowspan": 1, + "colwidth": null + }, + "content": [ + { + "type": "tableParagraph" + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "blockContainer", + "attrs": { + "id": "1" + }, + "content": [ + { + "type": "paragraph", + "attrs": { + "backgroundColor": "default", + "textColor": "default", + "textAlignment": "left" + } + } + ] + } + ] + } + ] +} \ No newline at end of file