Files
AFFiNE-Mirror/blocksuite/affine/data-view/src/view-presets/table/utils.ts
T
Richard Lora a8c18cd631 feat(editor): streamline cell editing and navigation with improved keyboard support (#12770)
https://github.com/user-attachments/assets/6bce5fa3-fb25-4906-bef1-50d4da4a13f6

This PR addresses #12769 and improves table editing UX by making Enter
commit changes and move focus down, and Tab/Shift+Tab move focus
horizontally—matching spreadsheet-like behavior.

Typing now immediately enters edit mode for selected cells without
double-clicking.
These updates apply to both the standard and virtual table views.

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

- **New Features**
- You can now start editing a table cell by simply typing any character
while the cell is selected.
- **Improvements**
- Pressing Enter while editing a cell will exit editing and move focus
down.
- Pressing Tab or Shift-Tab while editing a cell will exit editing and
move focus right or left, respectively.
- **Tests**
- Added unit tests for table cell hotkey behaviors to ensure reliable
editing and navigation.
- **Chores**
- Introduced Vitest configuration for streamlined testing and coverage
reporting.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: L-Sun <zover.v@gmail.com>
2025-06-23 20:24:22 +08:00

59 lines
1.5 KiB
TypeScript

import type { TableViewSelectionWithType } from './selection';
import { TableViewRowSelection } from './selection';
export interface TableCell {
rowId: string;
}
export type ColumnAccessor<T extends TableCell> = (
cell: T
) => { valueSetFromString(rowId: string, value: string): void } | undefined;
export interface StartEditOptions<T extends TableCell> {
event: KeyboardEvent;
selection: TableViewSelectionWithType | undefined;
getCellContainer: (
groupKey: string | undefined,
rowIndex: number,
columnIndex: number
) => T | undefined;
updateSelection: (sel: TableViewSelectionWithType) => void;
getColumn: ColumnAccessor<T>;
}
export function handleCharStartEdit<T extends TableCell>(
options: StartEditOptions<T>
): boolean {
const { event, selection, getCellContainer, updateSelection, getColumn } =
options;
const target = event.target as HTMLElement | null;
if (target && (target.tagName === 'INPUT' || target.tagName === 'TEXTAREA')) {
return false;
}
if (
selection &&
!TableViewRowSelection.is(selection) &&
!selection.isEditing &&
!event.metaKey &&
!event.ctrlKey &&
!event.altKey &&
event.key.length === 1
) {
const cell = getCellContainer(
selection.groupKey,
selection.focus.rowIndex,
selection.focus.columnIndex
);
if (cell) {
const column = getColumn(cell);
column?.valueSetFromString(cell.rowId, event.key);
updateSelection({ ...selection, isEditing: true });
event.preventDefault();
return true;
}
}
return false;
}