From 48fbca6b041a5320becd3b0482846cd6d40c64c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89mile=20R=C3=A9?= Date: Wed, 25 Mar 2026 16:09:42 +0400 Subject: [PATCH] Add split cells action MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Émile Ré --- packages/ui/src/RichEditor/RichEditor.tsx | 3 +- packages/ui/src/RichEditor/TableCellMenu.tsx | 34 +++++++++++++++++++- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/packages/ui/src/RichEditor/RichEditor.tsx b/packages/ui/src/RichEditor/RichEditor.tsx index 8ec54ce8e..6feed0514 100644 --- a/packages/ui/src/RichEditor/RichEditor.tsx +++ b/packages/ui/src/RichEditor/RichEditor.tsx @@ -17,7 +17,7 @@ import { Strike } from "@tiptap/extension-strike"; import { TableKit } from "@tiptap/extension-table"; import { Text } from "@tiptap/extension-text"; import { Underline } from "@tiptap/extension-underline"; -import { Dropcursor, Gapcursor, UndoRedo } from "@tiptap/extensions"; +import { Dropcursor, UndoRedo } from "@tiptap/extensions"; import { type Content, EditorContent, useEditor, useEditorState } from "@tiptap/react"; import { type ComponentProps, useEffect, useRef } from "react"; import { tv } from "tailwind-variants"; @@ -59,7 +59,6 @@ const extensions = [ color: "#0081f1", width: 2, }), - Gapcursor, UndoRedo, TableKit.configure({ table: { resizable: true }, diff --git a/packages/ui/src/RichEditor/TableCellMenu.tsx b/packages/ui/src/RichEditor/TableCellMenu.tsx index 6c4a19884..33918977e 100644 --- a/packages/ui/src/RichEditor/TableCellMenu.tsx +++ b/packages/ui/src/RichEditor/TableCellMenu.tsx @@ -12,7 +12,7 @@ import { useFloatingRootContext, useInteractions, } from "@floating-ui/react"; -import { BroomIcon, CircleIcon, DotsThreeCircleVerticalIcon, IntersectIcon } from "@phosphor-icons/react"; +import { BroomIcon, CircleIcon, DotsThreeCircleVerticalIcon, IntersectIcon, SplitHorizontalIcon } from "@phosphor-icons/react"; import { TextSelection } from "@tiptap/pm/state"; import { cellAround, CellSelection, TableMap } from "@tiptap/pm/tables"; import { type useEditor, useEditorState } from "@tiptap/react"; @@ -263,6 +263,32 @@ export function TableCellMenu({ editor }: TableCellMenuProps) { setMenuOpen(false); }; + const hasSpannedCell = (): boolean => { + const { selection } = editor.state; + + if (selection instanceof CellSelection) { + let found = false; + selection.forEachCell((node) => { + if (node.attrs.colspan > 1 || node.attrs.rowspan > 1) { + found = true; + } + }); + return found; + } + + const $pos = editor.state.doc.resolve(selection.from); + const cell = cellAround($pos); + if (!cell) return false; + const cellNode = editor.state.doc.nodeAt(cell.pos); + if (!cellNode) return false; + return cellNode.attrs.colspan > 1 || cellNode.attrs.rowspan > 1; + }; + + const handleSplitCell = () => { + editor.chain().focus().splitCell().run(); + setMenuOpen(false); + }; + const handleClearContents = () => { const { state, dispatch } = editor.view; const { selection, schema } = state; @@ -346,6 +372,12 @@ export function TableCellMenu({ editor }: TableCellMenuProps) { Merge cells + {hasSpannedCell() && ( + + + Split cells + + )} Clear contents