From f72abf6e4e1bf9cf881f101308e219a6ff50a96d Mon Sep 17 00:00:00 2001 From: Aaryan Khandelwal Date: Fri, 11 Jul 2025 13:31:52 +0530 Subject: [PATCH 1/5] fix: delete column not working --- .../src/core/extensions/table/table/table.ts | 34 +++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/packages/editor/src/core/extensions/table/table/table.ts b/packages/editor/src/core/extensions/table/table/table.ts index 66e54adcdaf..1db4fecef4d 100644 --- a/packages/editor/src/core/extensions/table/table/table.ts +++ b/packages/editor/src/core/extensions/table/table/table.ts @@ -142,8 +142,38 @@ export const Table = Node.create({ addColumnAfter(state, dispatch), deleteColumn: () => - ({ state, dispatch }) => - deleteColumn(state, dispatch), + ({ state, dispatch }) => { + const { selection } = state; + + // Check if we're in a table and have a cell selection + if (!(selection instanceof CellSelection)) { + return false; + } + + // Get the ProseMirrorTable and calculate total columns + const tableStart = selection.$anchorCell.start(-1); + const selectedTable = state.doc.nodeAt(tableStart - 1); + + if (!selectedTable) return false; + + // Count total columns by examining the first row + const firstRow = selectedTable.firstChild; + if (!firstRow) return false; + + let totalColumns = 0; + for (let i = 0; i < firstRow.childCount; i++) { + const cell = firstRow.child(i); + totalColumns += cell.attrs.colspan || 1; + } + + // If only one column exists, delete the entire ProseMirrorTable + if (totalColumns === 1) { + return deleteTable(state, dispatch); + } + + // Otherwise, proceed with normal column deletion + return deleteColumn(state, dispatch); + }, addRowBefore: () => ({ state, dispatch }) => From 9ec29c2feccc6d3d9049d81367d2d6296de8b575 Mon Sep 17 00:00:00 2001 From: Aaryan Khandelwal Date: Fri, 11 Jul 2025 13:39:43 +0530 Subject: [PATCH 2/5] refactor: delete column commad --- .../src/core/extensions/table/table/table.ts | 37 +------------------ .../table/table/utilities/delete-column.ts | 37 +++++++++++++++++++ 2 files changed, 39 insertions(+), 35 deletions(-) create mode 100644 packages/editor/src/core/extensions/table/table/utilities/delete-column.ts diff --git a/packages/editor/src/core/extensions/table/table/table.ts b/packages/editor/src/core/extensions/table/table/table.ts index 1db4fecef4d..a0f422e719c 100644 --- a/packages/editor/src/core/extensions/table/table/table.ts +++ b/packages/editor/src/core/extensions/table/table/table.ts @@ -7,7 +7,6 @@ import { addRowBefore, CellSelection, columnResizing, - deleteColumn, deleteRow, deleteTable, fixTables, @@ -27,6 +26,7 @@ import { TableInsertPlugin } from "../plugins/insert-handlers/plugin"; import { tableControls } from "./table-controls"; import { TableView } from "./table-view"; import { createTable } from "./utilities/create-table"; +import { deleteColumnOrTable } from "./utilities/delete-column"; import { deleteTableWhenAllCellsSelected } from "./utilities/delete-table-when-all-cells-selected"; import { insertLineAboveTableAction } from "./utilities/insert-line-above-table-action"; import { insertLineBelowTableAction } from "./utilities/insert-line-below-table-action"; @@ -140,40 +140,7 @@ export const Table = Node.create({ () => ({ state, dispatch }) => addColumnAfter(state, dispatch), - deleteColumn: - () => - ({ state, dispatch }) => { - const { selection } = state; - - // Check if we're in a table and have a cell selection - if (!(selection instanceof CellSelection)) { - return false; - } - - // Get the ProseMirrorTable and calculate total columns - const tableStart = selection.$anchorCell.start(-1); - const selectedTable = state.doc.nodeAt(tableStart - 1); - - if (!selectedTable) return false; - - // Count total columns by examining the first row - const firstRow = selectedTable.firstChild; - if (!firstRow) return false; - - let totalColumns = 0; - for (let i = 0; i < firstRow.childCount; i++) { - const cell = firstRow.child(i); - totalColumns += cell.attrs.colspan || 1; - } - - // If only one column exists, delete the entire ProseMirrorTable - if (totalColumns === 1) { - return deleteTable(state, dispatch); - } - - // Otherwise, proceed with normal column deletion - return deleteColumn(state, dispatch); - }, + deleteColumn: deleteColumnOrTable, addRowBefore: () => ({ state, dispatch }) => diff --git a/packages/editor/src/core/extensions/table/table/utilities/delete-column.ts b/packages/editor/src/core/extensions/table/table/utilities/delete-column.ts new file mode 100644 index 00000000000..906c73c4535 --- /dev/null +++ b/packages/editor/src/core/extensions/table/table/utilities/delete-column.ts @@ -0,0 +1,37 @@ +import type { Command } from "@tiptap/core"; +import { deleteColumn, deleteTable, CellSelection } from "@tiptap/pm/tables"; + +export const deleteColumnOrTable: () => Command = + () => + ({ state, dispatch }) => { + const { selection } = state; + + // Check if we're in a table and have a cell selection + if (!(selection instanceof CellSelection)) { + return false; + } + + // Get the ProseMirrorTable and calculate total columns + const tableStart = selection.$anchorCell.start(-1); + const selectedTable = state.doc.nodeAt(tableStart - 1); + + if (!selectedTable) return false; + + // Count total columns by examining the first row + const firstRow = selectedTable.firstChild; + if (!firstRow) return false; + + let totalColumns = 0; + for (let i = 0; i < firstRow.childCount; i++) { + const cell = firstRow.child(i); + totalColumns += cell.attrs.colspan || 1; + } + + // If only one column exists, delete the entire ProseMirrorTable + if (totalColumns === 1) { + return deleteTable(state, dispatch); + } + + // Otherwise, proceed with normal column deletion + return deleteColumn(state, dispatch); + }; From 5931475821335e8898a08b47953fe2a0bd434305 Mon Sep 17 00:00:00 2001 From: Aaryan Khandelwal Date: Fri, 11 Jul 2025 14:26:38 +0530 Subject: [PATCH 3/5] fix: delete last row logic --- .../src/core/extensions/table/table/table.ts | 7 ++-- .../table/table/utilities/delete-row.ts | 35 +++++++++++++++++++ 2 files changed, 37 insertions(+), 5 deletions(-) create mode 100644 packages/editor/src/core/extensions/table/table/utilities/delete-row.ts diff --git a/packages/editor/src/core/extensions/table/table/table.ts b/packages/editor/src/core/extensions/table/table/table.ts index a0f422e719c..e20f42cfbab 100644 --- a/packages/editor/src/core/extensions/table/table/table.ts +++ b/packages/editor/src/core/extensions/table/table/table.ts @@ -7,7 +7,6 @@ import { addRowBefore, CellSelection, columnResizing, - deleteRow, deleteTable, fixTables, goToNextCell, @@ -27,6 +26,7 @@ import { tableControls } from "./table-controls"; import { TableView } from "./table-view"; import { createTable } from "./utilities/create-table"; import { deleteColumnOrTable } from "./utilities/delete-column"; +import { deleteRowOrTable } from "./utilities/delete-row"; import { deleteTableWhenAllCellsSelected } from "./utilities/delete-table-when-all-cells-selected"; import { insertLineAboveTableAction } from "./utilities/insert-line-above-table-action"; import { insertLineBelowTableAction } from "./utilities/insert-line-below-table-action"; @@ -149,10 +149,7 @@ export const Table = Node.create({ () => ({ state, dispatch }) => addRowAfter(state, dispatch), - deleteRow: - () => - ({ state, dispatch }) => - deleteRow(state, dispatch), + deleteRow: deleteRowOrTable, deleteTable: () => ({ state, dispatch }) => diff --git a/packages/editor/src/core/extensions/table/table/utilities/delete-row.ts b/packages/editor/src/core/extensions/table/table/utilities/delete-row.ts new file mode 100644 index 00000000000..abb83859bbf --- /dev/null +++ b/packages/editor/src/core/extensions/table/table/utilities/delete-row.ts @@ -0,0 +1,35 @@ +import type { Command } from "@tiptap/core"; +import { deleteRow, deleteTable, CellSelection } from "@tiptap/pm/tables"; + +export const deleteRowOrTable: () => Command = + () => + ({ state, dispatch }) => { + const { selection } = state; + + // Check if we're in a ProseMirrorTable and have a cell selection + if (!(selection instanceof CellSelection)) { + return false; + } + + // Get the ProseMirrorTable and calculate total rows + const tableStart = selection.$anchorCell.start(-1); + const selectedTable = state.doc.nodeAt(tableStart - 1); + + if (!selectedTable) return false; + + // Count total rows by examining the table's children + let totalRows = 0; + for (let i = 0; i < selectedTable.childCount; i++) { + const row = selectedTable.child(i); + // Count each table row (accounting for potential rowspan) + totalRows += row.attrs.rowspan || 1; + } + + // If only one row exists, delete the entire ProseMirrorTable + if (totalRows === 1) { + return deleteTable(state, dispatch); + } + + // Otherwise, proceed with normal row deletion + return deleteRow(state, dispatch); + }; From 9198a4312fee12109a09c35f170b9e4e46038289 Mon Sep 17 00:00:00 2001 From: Aaryan Khandelwal Date: Mon, 14 Jul 2025 17:06:40 +0530 Subject: [PATCH 4/5] refactor: row count logic --- .../core/extensions/table/table/utilities/delete-row.ts | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/packages/editor/src/core/extensions/table/table/utilities/delete-row.ts b/packages/editor/src/core/extensions/table/table/utilities/delete-row.ts index abb83859bbf..d8144bc30d8 100644 --- a/packages/editor/src/core/extensions/table/table/utilities/delete-row.ts +++ b/packages/editor/src/core/extensions/table/table/utilities/delete-row.ts @@ -18,12 +18,7 @@ export const deleteRowOrTable: () => Command = if (!selectedTable) return false; // Count total rows by examining the table's children - let totalRows = 0; - for (let i = 0; i < selectedTable.childCount; i++) { - const row = selectedTable.child(i); - // Count each table row (accounting for potential rowspan) - totalRows += row.attrs.rowspan || 1; - } + const totalRows = selectedTable.childCount; // If only one row exists, delete the entire ProseMirrorTable if (totalRows === 1) { From 1729ff76a158115c0ea68fa61e8b3d01a8db90bc Mon Sep 17 00:00:00 2001 From: Aaryan Khandelwal Date: Mon, 14 Jul 2025 17:11:46 +0530 Subject: [PATCH 5/5] refactor: isCellSelection utility function --- .../src/core/components/menus/bubble-menu/root.tsx | 5 +++-- .../extensions/table/table/utilities/delete-column.ts | 6 ++++-- .../core/extensions/table/table/utilities/delete-row.ts | 6 ++++-- .../utilities/delete-table-when-all-cells-selected.ts | 2 +- .../src/core/extensions/table/table/utilities/helpers.ts | 9 +++++++++ .../table/table/utilities/is-cell-selection.ts | 5 ----- packages/editor/src/index.ts | 2 +- 7 files changed, 22 insertions(+), 13 deletions(-) create mode 100644 packages/editor/src/core/extensions/table/table/utilities/helpers.ts delete mode 100644 packages/editor/src/core/extensions/table/table/utilities/is-cell-selection.ts diff --git a/packages/editor/src/core/components/menus/bubble-menu/root.tsx b/packages/editor/src/core/components/menus/bubble-menu/root.tsx index fa5427c3b44..3a557921811 100644 --- a/packages/editor/src/core/components/menus/bubble-menu/root.tsx +++ b/packages/editor/src/core/components/menus/bubble-menu/root.tsx @@ -21,10 +21,11 @@ import { import { COLORS_LIST } from "@/constants/common"; import { CORE_EXTENSIONS } from "@/constants/extension"; // extensions -import { isCellSelection } from "@/extensions/table/table/utilities/is-cell-selection"; +import { isCellSelection } from "@/extensions/table/table/utilities/helpers"; +// types +import { TEditorCommands } from "@/types"; // local components import { TextAlignmentSelector } from "./alignment-selector"; -import { TEditorCommands } from "@/types"; type EditorBubbleMenuProps = Omit; diff --git a/packages/editor/src/core/extensions/table/table/utilities/delete-column.ts b/packages/editor/src/core/extensions/table/table/utilities/delete-column.ts index 906c73c4535..9cbcdd0a3eb 100644 --- a/packages/editor/src/core/extensions/table/table/utilities/delete-column.ts +++ b/packages/editor/src/core/extensions/table/table/utilities/delete-column.ts @@ -1,5 +1,7 @@ import type { Command } from "@tiptap/core"; -import { deleteColumn, deleteTable, CellSelection } from "@tiptap/pm/tables"; +import { deleteColumn, deleteTable } from "@tiptap/pm/tables"; +// local imports +import { isCellSelection } from "./helpers"; export const deleteColumnOrTable: () => Command = () => @@ -7,7 +9,7 @@ export const deleteColumnOrTable: () => Command = const { selection } = state; // Check if we're in a table and have a cell selection - if (!(selection instanceof CellSelection)) { + if (!isCellSelection(selection)) { return false; } diff --git a/packages/editor/src/core/extensions/table/table/utilities/delete-row.ts b/packages/editor/src/core/extensions/table/table/utilities/delete-row.ts index d8144bc30d8..4a7d161d123 100644 --- a/packages/editor/src/core/extensions/table/table/utilities/delete-row.ts +++ b/packages/editor/src/core/extensions/table/table/utilities/delete-row.ts @@ -1,5 +1,7 @@ import type { Command } from "@tiptap/core"; -import { deleteRow, deleteTable, CellSelection } from "@tiptap/pm/tables"; +import { deleteRow, deleteTable } from "@tiptap/pm/tables"; +// local imports +import { isCellSelection } from "./helpers"; export const deleteRowOrTable: () => Command = () => @@ -7,7 +9,7 @@ export const deleteRowOrTable: () => Command = const { selection } = state; // Check if we're in a ProseMirrorTable and have a cell selection - if (!(selection instanceof CellSelection)) { + if (!isCellSelection(selection)) { return false; } diff --git a/packages/editor/src/core/extensions/table/table/utilities/delete-table-when-all-cells-selected.ts b/packages/editor/src/core/extensions/table/table/utilities/delete-table-when-all-cells-selected.ts index 5c84b8617da..31afd53a82a 100644 --- a/packages/editor/src/core/extensions/table/table/utilities/delete-table-when-all-cells-selected.ts +++ b/packages/editor/src/core/extensions/table/table/utilities/delete-table-when-all-cells-selected.ts @@ -2,7 +2,7 @@ import { findParentNodeClosestToPos, KeyboardShortcutCommand } from "@tiptap/cor // constants import { CORE_EXTENSIONS } from "@/constants/extension"; // extensions -import { isCellSelection } from "@/extensions/table/table/utilities/is-cell-selection"; +import { isCellSelection } from "@/extensions/table/table/utilities/helpers"; export const deleteTableWhenAllCellsSelected: KeyboardShortcutCommand = ({ editor }) => { const { selection } = editor.state; diff --git a/packages/editor/src/core/extensions/table/table/utilities/helpers.ts b/packages/editor/src/core/extensions/table/table/utilities/helpers.ts new file mode 100644 index 00000000000..d5540a27b68 --- /dev/null +++ b/packages/editor/src/core/extensions/table/table/utilities/helpers.ts @@ -0,0 +1,9 @@ +import type { Selection } from "@tiptap/pm/state"; +import { CellSelection } from "@tiptap/pm/tables"; + +/** + * @description Check if the selection is a cell selection + * @param {Selection} selection - The selection to check + * @returns {boolean} True if the selection is a cell selection, false otherwise + */ +export const isCellSelection = (selection: Selection): selection is CellSelection => selection instanceof CellSelection; diff --git a/packages/editor/src/core/extensions/table/table/utilities/is-cell-selection.ts b/packages/editor/src/core/extensions/table/table/utilities/is-cell-selection.ts deleted file mode 100644 index 42ea5759c9b..00000000000 --- a/packages/editor/src/core/extensions/table/table/utilities/is-cell-selection.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { CellSelection } from "@tiptap/pm/tables"; - -export function isCellSelection(value: unknown): value is CellSelection { - return value instanceof CellSelection; -} diff --git a/packages/editor/src/index.ts b/packages/editor/src/index.ts index 5484d0affaf..9cb374dce24 100644 --- a/packages/editor/src/index.ts +++ b/packages/editor/src/index.ts @@ -15,7 +15,7 @@ export { RichTextEditorWithRef, } from "@/components/editors"; -export { isCellSelection } from "@/extensions/table/table/utilities/is-cell-selection"; +export { isCellSelection } from "@/extensions/table/table/utilities/helpers"; // constants export * from "@/constants/common";