Add the fill handle: drag the selection's corner to copy/fill, Excel-style

- store: fillSelection(tableId, source, target) repeats a source rectangle's
  cells (values, formulas -- reference-adjusted via the same shiftFormula()
  a copy uses -- and formatting) across a target rectangle. target may
  extend the source in any single direction (up/down/left/right); a source
  bigger than one row/column cycles through modulo its own size, so it
  still fills correctly past a non-exact-multiple trailing repetition.
- TableGrid.vue: replaces the old decorative per-active-cell square with a
  proper fill handle -- a small square overlaid at the bottom-right corner
  of the *selection* (not just the anchor cell), draggable. Dragging shows
  a live dashed preview of the cells about to be filled (snapping to
  whichever axis -- vertical or horizontal -- is dragged furthest along,
  same as Excel), and on mouseup commits via fillSelection() and grows the
  selection to source + filled area, keeping the original anchor active.

Verified interactively against the dev server with Playwright: a formula
(=A1*2) filled down four rows lands as =A2*2/=A3*2/=A4*2 with correct
values, and a two-row source dragged right/down six cells cycles its
pattern correctly (1,2,1,2,1,2, including the trailing partial cycle).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
wkh
2026-09-02 10:43:54 +02:00
co-authored by Claude Sonnet 5
parent fafb118db6
commit 830dcb8eeb
4 changed files with 231 additions and 9 deletions
+14 -3
View File
@@ -13,7 +13,7 @@ Vorbild von **Apple Numbers**. Zwei Dinge stehen im Mittelpunkt:
```bash
npm install
npm run dev # Vite-Devserver
npm run test # Vitest-Suite (Engine + Store + IO), 121 Tests
npm run test # Vitest-Suite (Engine + Store + IO), 127 Tests
npm run build # Typecheck + Produktionsbuild
npm run lint # ESLint (flat config)
```
@@ -75,7 +75,14 @@ umbenennen, löschen, per Drag sortieren). Zoom 40–200 % pro Blatt
oder Einzelzell-Auswahl verankert die kopierte Fläche dort und läuft darüber
hinaus. Formeln werden dabei **bezugsangepasst** wie in Excel/Numbers — siehe
„`$`-Bezüge sperren" unten; ein gestrichelter Rahmen markiert die
Kopierquelle, `Esc` verwirft den Puffer.
Kopierquelle (mit eigenem Rahmen um deren erste Zelle, bleibt stehen, auch
wenn die aktuelle Auswahl längst woanders ist), `Esc` verwirft den Puffer.
- **Ausfüllkästchen** (das kleine Quadrat unten rechts an der Auswahl, wie in
Excel/Numbers): ziehen wiederholt die Auswahl — Werte, Formeln
(bezugsangepasst) und Formatierung — in die überstrichenen Zellen. Nur eine
Achse gleichzeitig (rein runter/hoch/rechts/links, je nachdem wohin weiter
gezogen wird); ein mehrzeiliger/-spaltiger Ausgangsbereich wird zyklisch
wiederholt, auch über eine unvollständige letzte Wiederholung hinweg.
**Tastaturnavigation (Excel-nah)** — Fokus in der Tabelle:
@@ -308,7 +315,7 @@ Grundrechenarten: `Übersicht!B2 = =SUM(Umsatz!B2:E2)`, `D2 = =B2-C2`,
## Tests
`npm run test` — Vitest, 121 Tests:
`npm run test` — Vitest, 127 Tests:
- **lexer / parser** — Präzedenz & Assoziativität (`^` vor `*/` vor `+-`, `^`
rechts, `-2^2 = -(2^2)`), lokale/qualifizierte/quoted Bezüge, `!` **und** `::`,
@@ -353,6 +360,10 @@ Grundrechenarten: `Übersicht!B2 = =SUM(Umsatz!B2:E2)`, `D2 = =B2-C2`,
wird mitkopiert und am Ziel ersetzt; Ausschneiden folgt trotz `$` der
verschobenen Zelle, lässt aber unbeteiligte und tabellenfremde Referenzen
unangetastet und leert die Quelle; `Esc` verwirft den Puffer.
- **Ausfüllkästchen** — füllt runter/rechts mit bezugsangepassten Formeln;
ein mehrzeiliger/-spaltiger Quellbereich wiederholt sich zyklisch, auch bei
einer unvollständigen letzten Wiederholung; füllt ebenso hoch/links;
Formatierung wird mitkopiert.
- **IO** — JSON verlustfreier Round-Trip (identisch), defekte/leere Datei →
Fehler ohne Nebenwirkung, unbekannter Tabellenname → `#REF`, v1→v2 beim
Import; CSV Übersicht-Export→Re-Import gleiche Zahlen, RFC-4180-Quoting,