Split menu components for better responsibility handling

Signed-off-by: Émile Ré <emile@getprobo.com>
This commit is contained in:
Émile Ré
2026-03-26 10:48:16 +04:00
parent 0b02171e4a
commit cc93378996
24 changed files with 1706 additions and 1262 deletions

View File

@@ -0,0 +1,74 @@
// Copyright (c) 2026 Probo Inc <hello@getprobo.com>.
// Use of this source code is governed by the ISC license
// that can be found in the LICENSE file.
import { cellAround, CellSelection } from "@tiptap/pm/tables";
import { type Editor, useEditorState } from "@tiptap/react";
import { cellDomElement } from "../_lib/cellDomElement";
import { useTableDropdownMenu } from "../_lib/useTableDropdownMenu";
import { TableCellMenuContent } from "./TableCellMenuContent";
import { TableCellMenuTrigger } from "./TableCellMenuTrigger";
type TableCellMenuProps = {
editor: Editor;
};
function getActiveCellEl(editor: Editor): HTMLElement | null {
const { selection } = editor.state;
if (selection instanceof CellSelection) {
return cellDomElement(editor, selection.$headCell.pos);
}
const $pos = editor.state.doc.resolve(selection.from);
const cell = cellAround($pos);
if (!cell) return null;
return cellDomElement(editor, cell.pos);
}
export function TableCellMenu({ editor }: TableCellMenuProps) {
const {
menuOpen,
setMenuOpen,
setTriggerEl,
setDropdownEl,
menuRefs,
menuStyles,
getFloatingProps,
} = useTableDropdownMenu();
const activeCellEl = useEditorState({
editor,
selector: ({ editor: e }) => {
if (e.isDestroyed || !e.isEditable) return null;
return getActiveCellEl(e);
},
});
if (!activeCellEl) return null;
return (
<>
<TableCellMenuTrigger
editor={editor}
activeCellEl={activeCellEl}
menuOpen={menuOpen}
setMenuOpen={setMenuOpen}
setTriggerEl={setTriggerEl}
menuRefs={menuRefs}
/>
{menuOpen && (
<TableCellMenuContent
editor={editor}
setMenuOpen={setMenuOpen}
setDropdownEl={setDropdownEl}
menuRefs={menuRefs}
menuStyles={menuStyles}
getFloatingProps={getFloatingProps}
/>
)}
</>
);
}