feat(editor): add delete key support for table view (#14119)

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

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Refactor**
* Optimized table hotkey handling logic to consolidate delete and
backspace operations for improved code maintainability.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
Daniel Dybing
2025-12-21 20:17:05 +01:00
committed by GitHub
parent 321965a424
commit 8f59509e73
2 changed files with 104 additions and 100 deletions

View File

@@ -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;

View File

@@ -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;