diff --git a/packages/lexical-playground/__tests__/e2e/Tables.spec.mjs b/packages/lexical-playground/__tests__/e2e/Tables.spec.mjs
index 75bda0f018b..0624d80d30f 100644
--- a/packages/lexical-playground/__tests__/e2e/Tables.spec.mjs
+++ b/packages/lexical-playground/__tests__/e2e/Tables.spec.mjs
@@ -25,6 +25,7 @@ import {
copyToClipboard,
deleteTableColumns,
deleteTableRows,
+ expect,
focusEditor,
html,
initialize,
@@ -1360,6 +1361,47 @@ test.describe.parallel('Tables', () => {
);
});
+ test('Can delete all with range selection anchored in table', async ({
+ page,
+ isCollab,
+ isPlainText,
+ }) => {
+ test.skip(isPlainText || isCollab);
+ await initialize({isCollab, page});
+ await focusEditor(page);
+ await insertTable(page, 1, 1);
+ // Remove paragraph before
+ await moveUp(page);
+ await page.keyboard.press('Backspace');
+ await assertHTML(
+ page,
+ html`
+
+
+ `,
+ );
+ // Select all but from the table
+ const modifier = process.platform === 'darwin' ? 'Meta' : 'Control';
+ await page.keyboard.press(`${modifier}+A`);
+ // The observer is active
+ await expect(page.locator('.table-cell-action-button')).toBeVisible();
+ await page.keyboard.press('Backspace');
+ await assertHTML(
+ page,
+ html`
+
+ `,
+ );
+ });
+
test(`Horizontal rule inside cell`, async ({page, isPlainText, isCollab}) => {
await initialize({isCollab, page});
test.skip(isPlainText);
diff --git a/packages/lexical-table/src/LexicalTableSelectionHelpers.ts b/packages/lexical-table/src/LexicalTableSelectionHelpers.ts
index 4353604567e..be84112c306 100644
--- a/packages/lexical-table/src/LexicalTableSelectionHelpers.ts
+++ b/packages/lexical-table/src/LexicalTableSelectionHelpers.ts
@@ -336,22 +336,30 @@ export function applyTableHandlers(
event: KeyboardEvent | ClipboardEvent | null,
): boolean => {
const selection = $getSelection();
+ if (!($isTableSelection(selection) || $isRangeSelection(selection))) {
+ return false;
+ }
- if (!$isSelectionInTable(selection, tableNode)) {
- const nodes = selection ? selection.getNodes() : null;
- if (nodes) {
- const table = nodes.find(
- (node) =>
- $isTableNode(node) && node.getKey() === tableObserver.tableNodeKey,
- );
- if ($isTableNode(table)) {
- const parentNode = table.getParent();
- if (!parentNode) {
- return false;
- }
- table.remove();
- }
- }
+ // If the selection is inside the table but should remove the whole table
+ // we expand the selection so that both the anchor and focus are outside
+ // the table and the editor's command listener will handle the delete
+ const isAnchorInside = tableNode.isParentOf(selection.anchor.getNode());
+ const isFocusInside = tableNode.isParentOf(selection.focus.getNode());
+ if (isAnchorInside !== isFocusInside) {
+ const tablePoint = isAnchorInside ? 'anchor' : 'focus';
+ const outerPoint = isAnchorInside ? 'focus' : 'anchor';
+ // Preserve the outer point
+ const {key, offset, type} = selection[outerPoint];
+ // Expand the selection around the table
+ const newSelection =
+ tableNode[
+ selection[tablePoint].isBefore(selection[outerPoint])
+ ? 'selectPrevious'
+ : 'selectNext'
+ ]();
+ // Restore the outer point of the selection
+ newSelection[outerPoint].set(key, offset, type);
+ // Let the base implementation handle the rest
return false;
}
@@ -363,15 +371,6 @@ export function applyTableHandlers(
tableObserver.clearText();
return true;
- } else if ($isRangeSelection(selection)) {
- const tableCellNode = $findMatchingParent(
- selection.anchor.getNode(),
- (n) => $isTableCellNode(n),
- );
-
- if (!$isTableCellNode(tableCellNode)) {
- return false;
- }
}
return false;