diff --git a/packages/lexical-playground/__tests__/e2e/Tables.spec.mjs b/packages/lexical-playground/__tests__/e2e/Tables.spec.mjs
index 694f9c86e4b..e7de6a82786 100644
--- a/packages/lexical-playground/__tests__/e2e/Tables.spec.mjs
+++ b/packages/lexical-playground/__tests__/e2e/Tables.spec.mjs
@@ -24,6 +24,7 @@ import {
copyToClipboard,
deleteTableColumns,
deleteTableRows,
+ expect,
focusEditor,
html,
initialize,
@@ -246,62 +247,30 @@ test.describe.parallel('Tables', () => {
});
});
- test(`Can exit the first cell of a nested table into the parent table cell`, async ({
+ test('Can not table node insert table cell', async ({
page,
isPlainText,
isCollab,
}) => {
await initialize({isCollab, page});
test.skip(isPlainText);
-
await focusEditor(page);
await insertTable(page, 2, 2);
- await insertTable(page, 2, 2);
-
- await assertSelection(page, {
- anchorOffset: 0,
- anchorPath: [1, 0, 0, 1, 0, 0, 0],
- focusOffset: 0,
- focusPath: [1, 0, 0, 1, 0, 0, 0],
- });
-
- await moveLeft(page, 1);
- await assertSelection(page, {
- anchorOffset: 0,
- anchorPath: [1, 0, 0, 0],
- focusOffset: 0,
- focusPath: [1, 0, 0, 0],
- });
});
+ });
- test(`Can exit the last cell of a nested table into the parent table cell`, async ({
- page,
- isPlainText,
- isCollab,
- }) => {
- await initialize({isCollab, page});
- test.skip(isPlainText);
-
- await focusEditor(page);
- await insertTable(page, 2, 2);
- await insertTable(page, 2, 2);
-
- await moveRight(page, 3);
- await assertSelection(page, {
- anchorOffset: 0,
- anchorPath: [1, 0, 0, 1, 1, 1, 0],
- focusOffset: 0,
- focusPath: [1, 0, 0, 1, 1, 1, 0],
- });
+ test('After the cursor is positioned on the table, the toolbar does not display the inserted table', async ({
+ page,
+ isPlainText,
+ isCollab,
+ }) => {
+ await initialize({isCollab, page});
+ test.skip(isPlainText);
+ await focusEditor(page);
+ await insertTable(page, 2, 2);
+ const element = await page.$('.toolbar-item[aria-label="Insert table"]');
- await moveRight(page, 1);
- await assertSelection(page, {
- anchorOffset: 0,
- anchorPath: [1, 0, 0, 2],
- focusOffset: 0,
- focusPath: [1, 0, 0, 2],
- });
- });
+ expect(element).toEqual(null);
});
test(`Can insert a paragraph after a table, that is the last node, with the "Enter" key`, async ({
diff --git a/packages/lexical-playground/src/plugins/ComponentPickerPlugin/index.tsx b/packages/lexical-playground/src/plugins/ComponentPickerPlugin/index.tsx
index 19406089056..f3e49b17ee0 100644
--- a/packages/lexical-playground/src/plugins/ComponentPickerPlugin/index.tsx
+++ b/packages/lexical-playground/src/plugins/ComponentPickerPlugin/index.tsx
@@ -367,13 +367,18 @@ export default function ComponentPickerMenuPlugin(): JSX.Element {
options={options}
menuRenderFn={(
anchorElementRef,
- {selectedIndex, selectOptionAndCleanUp, setHighlightedIndex},
+ {
+ selectedIndex,
+ selectOptionAndCleanUp,
+ setHighlightedIndex,
+ options: menuOptions,
+ },
) =>
- anchorElementRef.current && options.length
+ anchorElementRef.current && menuOptions.length
? ReactDOM.createPortal(
- {options.map((option, i: number) => (
+ {menuOptions.map((option, i: number) => (
('');
const [isEditable, setIsEditable] = useState(() => editor.isEditable());
const [isImageCaption, setIsImageCaption] = useState(false);
+ const [isLocatedTable, setIsLocatedTable] = useState(false);
const $updateToolbar = useCallback(() => {
const selection = $getSelection();
@@ -599,8 +600,10 @@ export default function ToolbarPlugin({
const tableNode = $findMatchingParent(node, $isTableNode);
if ($isTableNode(tableNode)) {
+ setIsLocatedTable(true);
setRootType('table');
} else {
+ setIsLocatedTable(false);
setRootType('root');
}
@@ -1137,19 +1140,21 @@ export default function ToolbarPlugin({
Excalidraw
- {
- showModal('Insert Table', (onClose) => (
-
- ));
- }}
- className="item">
-
- Table
-
+ {!isLocatedTable && (
+ {
+ showModal('Insert Table', (onClose) => (
+
+ ));
+ }}
+ className="item">
+
+ Table
+
+ )}
{
showModal('Insert Poll', (onClose) => (
diff --git a/packages/lexical-react/src/LexicalTablePlugin.ts b/packages/lexical-react/src/LexicalTablePlugin.ts
index 2ae1dfd94f7..7e5f4589280 100644
--- a/packages/lexical-react/src/LexicalTablePlugin.ts
+++ b/packages/lexical-react/src/LexicalTablePlugin.ts
@@ -36,7 +36,11 @@ import {
} from '@lexical/utils';
import {
$createParagraphNode,
+ $findMatchingParent,
$getNodeByKey,
+ $getPreviousSelection,
+ $getSelection,
+ $isRangeSelection,
$isTextNode,
COMMAND_PRIORITY_EDITOR,
} from 'lexical';
@@ -71,6 +75,20 @@ export function TablePlugin({
Number(columns),
includeHeaders,
);
+
+ const selection = $getSelection() || $getPreviousSelection();
+
+ if ($isRangeSelection(selection)) {
+ const {anchor, focus} = selection;
+ const focusNode = focus.getNode();
+ const anchorNode = anchor.getNode();
+ if (
+ $findMatchingParent(focusNode, $isTableRowNode) ||
+ $findMatchingParent(anchorNode, $isTableRowNode)
+ ) {
+ return false;
+ }
+ }
$insertNodeToNearestRoot(tableNode);
const firstDescendant = tableNode.getFirstDescendant();
diff --git a/packages/lexical-react/src/LexicalTypeaheadMenuPlugin.tsx b/packages/lexical-react/src/LexicalTypeaheadMenuPlugin.tsx
index af59b530f59..21e18162009 100644
--- a/packages/lexical-react/src/LexicalTypeaheadMenuPlugin.tsx
+++ b/packages/lexical-react/src/LexicalTypeaheadMenuPlugin.tsx
@@ -14,7 +14,9 @@ import type {
} from './shared/LexicalMenu';
import {useLexicalComposerContext} from '@lexical/react/LexicalComposerContext';
+import {$isTableNode} from '@lexical/table';
import {
+ $findMatchingParent,
$getSelection,
$isRangeSelection,
$isTextNode,
@@ -26,7 +28,7 @@ import {
RangeSelection,
TextNode,
} from 'lexical';
-import {useCallback, useEffect, useState} from 'react';
+import {useCallback, useEffect, useMemo, useState} from 'react';
import * as React from 'react';
import {LexicalMenu, MenuOption, useMenuAnchorRef} from './shared/LexicalMenu';
@@ -220,6 +222,7 @@ export function LexicalTypeaheadMenuPlugin({
}: TypeaheadMenuPluginProps): JSX.Element | null {
const [editor] = useLexicalComposerContext();
const [resolution, setResolution] = useState(null);
+ const [isLocatedTable, setIsLocatedTable] = useState(false);
const anchorElementRef = useMenuAnchorRef(
resolution,
setResolution,
@@ -274,6 +277,17 @@ export function LexicalTypeaheadMenuPlugin({
range,
editorWindow,
);
+
+ const tableNode = $findMatchingParent(
+ selection.anchor.getNode(),
+ $isTableNode,
+ );
+ if (tableNode) {
+ setIsLocatedTable(true);
+ } else {
+ setIsLocatedTable(false);
+ }
+
if (isRangePositioned !== null) {
startTransition(() =>
openTypeahead({
@@ -302,13 +316,20 @@ export function LexicalTypeaheadMenuPlugin({
openTypeahead,
]);
+ const internalOptions = useMemo(() => {
+ if (isLocatedTable) {
+ return options.filter((option) => option.key !== 'Table');
+ }
+ return options;
+ }, [isLocatedTable, options]);
+
return resolution === null || editor === null ? null : (