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/table.ts b/packages/editor/src/core/extensions/table/table/table.ts index 66e54adcdaf..e20f42cfbab 100644 --- a/packages/editor/src/core/extensions/table/table/table.ts +++ b/packages/editor/src/core/extensions/table/table/table.ts @@ -7,8 +7,6 @@ import { addRowBefore, CellSelection, columnResizing, - deleteColumn, - deleteRow, deleteTable, fixTables, goToNextCell, @@ -27,6 +25,8 @@ 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 { 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"; @@ -140,10 +140,7 @@ export const Table = Node.create({ () => ({ state, dispatch }) => addColumnAfter(state, dispatch), - deleteColumn: - () => - ({ state, dispatch }) => - deleteColumn(state, dispatch), + deleteColumn: deleteColumnOrTable, addRowBefore: () => ({ state, dispatch }) => @@ -152,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-column.ts b/packages/editor/src/core/extensions/table/table/utilities/delete-column.ts new file mode 100644 index 00000000000..9cbcdd0a3eb --- /dev/null +++ b/packages/editor/src/core/extensions/table/table/utilities/delete-column.ts @@ -0,0 +1,39 @@ +import type { Command } from "@tiptap/core"; +import { deleteColumn, deleteTable } from "@tiptap/pm/tables"; +// local imports +import { isCellSelection } from "./helpers"; + +export const deleteColumnOrTable: () => Command = + () => + ({ state, dispatch }) => { + const { selection } = state; + + // Check if we're in a table and have a cell selection + if (!isCellSelection(selection)) { + 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); + }; 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..4a7d161d123 --- /dev/null +++ b/packages/editor/src/core/extensions/table/table/utilities/delete-row.ts @@ -0,0 +1,32 @@ +import type { Command } from "@tiptap/core"; +import { deleteRow, deleteTable } from "@tiptap/pm/tables"; +// local imports +import { isCellSelection } from "./helpers"; + +export const deleteRowOrTable: () => Command = + () => + ({ state, dispatch }) => { + const { selection } = state; + + // Check if we're in a ProseMirrorTable and have a cell selection + if (!isCellSelection(selection)) { + 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 + const totalRows = selectedTable.childCount; + + // 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); + }; 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";