Keep the first-selected cell marked as active during a multi-cell selection

The active cell (bold border/handle, formula bar target) used to track
selection.focus, so it followed the mouse/cursor while dragging or
shift-extending a range. Switch it to selection.anchor -- the first cell of
the current selection action -- so it stays put while the range grows,
matching Excel/Numbers. Tab/Enter data-entry flow already keeps anchor ==
focus while it moves the cursor, so that behaviour is unaffected.

- document.ts: activeCell/activeCellName/activeCellInput read the anchor.
- FormulaBar.vue: commits to the anchor cell to match what it displays.
- TableGrid.vue: isActive() (border + handle) and F2/type-to-edit target
  the anchor; Home/End keep using the cursor's row via s.focus.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
wkh
2026-09-02 09:59:29 +02:00
co-authored by Claude Sonnet 5
parent 44f3314137
commit e45cdfd077
4 changed files with 18 additions and 9 deletions
+8 -4
View File
@@ -111,8 +111,12 @@ const mine = computed(
);
/** All selected rectangles (primary + any additional) for this table. */
const selRects = computed(() => (mine.value ? store.selectionRects(mine.value) : []));
/** The active cell is the anchor -- the first cell of the current selection --
* so it stays marked while a multi-cell selection is dragged/extended out
* from it (Excel/Numbers behaviour). During Tab/Enter data-entry flow the
* anchor is kept equal to the flowing cell, so this still tracks it there. */
const isActive = (c: number, r: number) =>
!!mine.value && mine.value.focus.col === c && mine.value.focus.row === r;
!!mine.value && mine.value.anchor.col === c && mine.value.anchor.row === r;
const inSelection = (c: number, r: number) =>
selRects.value.some((k) => c >= k.c0 && c <= k.c1 && r >= k.r0 && r <= k.r1);
const colHot = (c: number) => selRects.value.some((k) => c >= k.c0 && c <= k.c1);
@@ -481,7 +485,7 @@ function onKeydown(e: KeyboardEvent) {
const s = mine.value;
const t = table.value;
if (!s || !t) return;
const { col, row } = s.focus;
const { row } = s.focus; // Home/End jump within the cursor's current row
const ext = e.shiftKey;
const mod = e.ctrlKey || e.metaKey;
@@ -532,7 +536,7 @@ function onKeydown(e: KeyboardEvent) {
case 'F2':
e.preventDefault();
e.stopPropagation();
return beginEdit(col, row);
return beginEdit(s.anchor.col, s.anchor.row);
case 'Home':
e.preventDefault();
e.stopPropagation();
@@ -566,7 +570,7 @@ function onKeydown(e: KeyboardEvent) {
if (e.key.length === 1 && !e.ctrlKey && !e.metaKey && !e.altKey) {
e.preventDefault();
e.stopPropagation();
beginEdit(col, row, e.key);
beginEdit(s.anchor.col, s.anchor.row, e.key);
}
}
}