From 8f59509e73cf79fcf115d6f2e890029964830396 Mon Sep 17 00:00:00 2001 From: Daniel Dybing Date: Sun, 21 Dec 2025 20:17:05 +0100 Subject: [PATCH] feat(editor): add delete key support for table view (#14119) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR allows the user to use the `Delete` key to delete the content of one or more cells in a Table View. Previously, this was only possible to do with the `Backspace` key. Both keys can now be used, which is often the norm in other tools - such as Notion and Excel. In short, the logic for the `Backspace` key has been moved to a separate function which is called by keyevents from both the `Backspace` and `Delete` keys. Affected files: - blocksuite/affine/data-view/src/view-presets/table/pc-virtual/controller/hotkeys.ts - blocksuite/affine/data-view/src/view-presets/table/pc/controller/hotkeys.ts ## Summary by CodeRabbit * **Refactor** * Optimized table hotkey handling logic to consolidate delete and backspace operations for improved code maintainability. ✏️ Tip: You can customize this high-level summary in your review settings. --- .../table/pc-virtual/controller/hotkeys.ts | 102 +++++++++--------- .../table/pc/controller/hotkeys.ts | 102 +++++++++--------- 2 files changed, 104 insertions(+), 100 deletions(-) diff --git a/blocksuite/affine/data-view/src/view-presets/table/pc-virtual/controller/hotkeys.ts b/blocksuite/affine/data-view/src/view-presets/table/pc-virtual/controller/hotkeys.ts index 24e268fbb..a7c8994ea 100644 --- a/blocksuite/affine/data-view/src/view-presets/table/pc-virtual/controller/hotkeys.ts +++ b/blocksuite/affine/data-view/src/view-presets/table/pc-virtual/controller/hotkeys.ts @@ -20,60 +20,62 @@ export class TableHotkeysController implements ReactiveController { return this.logic.ui$.value; } + private _handleDeleteOrBackspace() { + const selection = this.selectionController.selection; + if (!selection) { + return; + } + if (TableViewRowSelection.is(selection)) { + const rows = TableViewRowSelection.rowsIds(selection); + this.selectionController.selection = undefined; + this.logic.view.rowsDelete(rows); + this.logic.ui$.value?.requestUpdate(); + return; + } + const { focus, rowsSelection, columnsSelection, isEditing, groupKey } = + selection; + if (focus && !isEditing) { + if (rowsSelection && columnsSelection) { + // multi cell + for (let i = rowsSelection.start; i <= rowsSelection.end; i++) { + const { start, end } = columnsSelection; + for (let j = start; j <= end; j++) { + const container = this.selectionController.getCellContainer( + groupKey, + i, + j + ); + const rowId = container?.dataset.rowId; + const columnId = container?.dataset.columnId; + if (rowId && columnId) { + container?.column$.value?.valueSetFromString(rowId, ''); + } + } + } + } else { + // single cell + const container = this.selectionController.getCellContainer( + groupKey, + focus.rowIndex, + focus.columnIndex + ); + const rowId = container?.dataset.rowId; + const columnId = container?.dataset.columnId; + if (rowId && columnId) { + container?.column$.value?.valueSetFromString(rowId, ''); + } + } + } + } + hostConnected() { this.disposables.add( this.logic.bindHotkey({ Backspace: () => { - const selection = this.selectionController.selection; - if (!selection) { - return; - } - if (TableViewRowSelection.is(selection)) { - const rows = TableViewRowSelection.rowsIds(selection); - this.selectionController.selection = undefined; - this.logic.view.rowsDelete(rows); - this.logic.ui$.value?.requestUpdate(); - return; - } - const { - focus, - rowsSelection, - columnsSelection, - isEditing, - groupKey, - } = selection; - if (focus && !isEditing) { - if (rowsSelection && columnsSelection) { - // multi cell - for (let i = rowsSelection.start; i <= rowsSelection.end; i++) { - const { start, end } = columnsSelection; - for (let j = start; j <= end; j++) { - const container = this.selectionController.getCellContainer( - groupKey, - i, - j - ); - const rowId = container?.dataset.rowId; - const columnId = container?.dataset.columnId; - if (rowId && columnId) { - container?.column$.value?.valueSetFromString(rowId, ''); - } - } - } - } else { - // single cell - const container = this.selectionController.getCellContainer( - groupKey, - focus.rowIndex, - focus.columnIndex - ); - const rowId = container?.dataset.rowId; - const columnId = container?.dataset.columnId; - if (rowId && columnId) { - container?.column$.value?.valueSetFromString(rowId, ''); - } - } - } + this._handleDeleteOrBackspace(); + }, + Delete: () => { + this._handleDeleteOrBackspace(); }, Escape: () => { const selection = this.selectionController.selection; diff --git a/blocksuite/affine/data-view/src/view-presets/table/pc/controller/hotkeys.ts b/blocksuite/affine/data-view/src/view-presets/table/pc/controller/hotkeys.ts index 8cca5307f..e497df91e 100644 --- a/blocksuite/affine/data-view/src/view-presets/table/pc/controller/hotkeys.ts +++ b/blocksuite/affine/data-view/src/view-presets/table/pc/controller/hotkeys.ts @@ -18,60 +18,62 @@ export class TableHotkeysController implements ReactiveController { return this.logic.ui$.value; } + private _handleDeleteOrBackspace() { + const selection = this.selectionController.selection; + if (!selection) { + return; + } + if (TableViewRowSelection.is(selection)) { + const rows = TableViewRowSelection.rowsIds(selection); + this.selectionController.selection = undefined; + this.logic.view.rowsDelete(rows); + this.logic.ui$.value?.requestUpdate(); + return; + } + const { focus, rowsSelection, columnsSelection, isEditing, groupKey } = + selection; + if (focus && !isEditing) { + if (rowsSelection && columnsSelection) { + // multi cell + for (let i = rowsSelection.start; i <= rowsSelection.end; i++) { + const { start, end } = columnsSelection; + for (let j = start; j <= end; j++) { + const container = this.selectionController.getCellContainer( + groupKey, + i, + j + ); + const rowId = container?.dataset.rowId; + const columnId = container?.dataset.columnId; + if (rowId && columnId) { + container?.column.valueSetFromString(rowId, ''); + } + } + } + } else { + // single cell + const container = this.selectionController.getCellContainer( + groupKey, + focus.rowIndex, + focus.columnIndex + ); + const rowId = container?.dataset.rowId; + const columnId = container?.dataset.columnId; + if (rowId && columnId) { + container?.column.valueSetFromString(rowId, ''); + } + } + } + } + hostConnected() { this.host?.disposables.add( this.logic.bindHotkey({ Backspace: () => { - const selection = this.selectionController.selection; - if (!selection) { - return; - } - if (TableViewRowSelection.is(selection)) { - const rows = TableViewRowSelection.rowsIds(selection); - this.selectionController.selection = undefined; - this.logic.view.rowsDelete(rows); - this.logic.ui$.value?.requestUpdate(); - return; - } - const { - focus, - rowsSelection, - columnsSelection, - isEditing, - groupKey, - } = selection; - if (focus && !isEditing) { - if (rowsSelection && columnsSelection) { - // multi cell - for (let i = rowsSelection.start; i <= rowsSelection.end; i++) { - const { start, end } = columnsSelection; - for (let j = start; j <= end; j++) { - const container = this.selectionController.getCellContainer( - groupKey, - i, - j - ); - const rowId = container?.dataset.rowId; - const columnId = container?.dataset.columnId; - if (rowId && columnId) { - container?.column.valueSetFromString(rowId, ''); - } - } - } - } else { - // single cell - const container = this.selectionController.getCellContainer( - groupKey, - focus.rowIndex, - focus.columnIndex - ); - const rowId = container?.dataset.rowId; - const columnId = container?.dataset.columnId; - if (rowId && columnId) { - container?.column.valueSetFromString(rowId, ''); - } - } - } + this._handleDeleteOrBackspace(); + }, + Delete: () => { + this._handleDeleteOrBackspace(); }, Escape: () => { const selection = this.selectionController.selection;