Commit Graph
11 Commits
Author SHA1 Message Date
wkhandClaude Sonnet 5 67b011637d Make the formula bar mouse-resizable and wrapping
Switches the formula bar from a single-line <input> to a <textarea>:

- A plain <textarea> gets a free, native mouse-draggable resize handle in
  its bottom-right corner (CSS resize: vertical) -- exactly the "erweiterbar/
  erhöhbar mit der Maus" ask, no custom drag code needed.
- Unlike the old <input>, it actually wraps a long formula instead of just
  scrolling it sideways, so dragging the handle taller has something to
  show (min-height keeps the collapsed case looking like before; max-height
  caps it at half the viewport).
- Brought its keyboard handling in line with the in-cell editor from the
  last two changes: Alt+Enter/Cmd+Enter insert a literal newline, F4 cycles
  every reference a selection overlaps, Escape reverts and blurs.
- .formula-bar switches to align-items: flex-start (with matching top
  margins on the labels) so the cell-name/fx labels stay pinned to the
  first line instead of vertically centering in a now-tall box.

Verified interactively: dragging the handle down 80px grows the bar from
~34px to ~113px; Alt+Enter inserts a real newline in the (now multi-line-
capable) field.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-02 11:11:01 +02:00
wkhandClaude Sonnet 5 8c9f3bbc87 Fix Alt+Enter newline not registering on Mac: add Cmd+Enter fallback
macOS's Option key is a compose key (used to type accented/special
characters), which can make it unreliable as a plain modifier in some
browser/layout combinations -- Alt+Enter alone wasn't reaching the handler
for this user on Mac. Microsoft's own Mac Excel shortcut for this is
inconsistent across versions too (Control+Option+Return traditionally,
plain Option+Return only in 365).

- onEditKeydown now accepts Enter with either altKey OR metaKey (Cmd),
  giving a Mac-safe alternative that doesn't depend on Option's compose
  behavior.
- Also checks e.code ('Enter'/'NumpadEnter') alongside e.key, in case
  composition ever alters what .key reports for the combination (.code
  reflects the physical key regardless).

Verified interactively: Alt+Enter, Cmd+Enter, and plain Enter (still
commits normally) all produce the expected value/behavior.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-02 11:08:21 +02:00
wkhandClaude Sonnet 5 cc76ea547f Auto-sizing cell editor, multi-ref F4, and Alt+Enter line breaks
1. In-cell editor width/height ("nur in der Breite der Zelle angezeigt"):
   the editor now lives as an overlay (like the clip/fill markers) instead
   of inside its <td>, so it can grow past the cell -- width first, up to
   an approximated display-width cap, then wrapping and growing height.
   Sized via a hidden mirror element (same font/padding, real DOM
   measurement -- a <textarea> can't self-size to content with CSS alone).

2. F4 now cycles every reference a real text selection overlaps, each from
   its own lock state, not just the one at the caret -- select a stretch of
   formula spanning several references and F4 adjusts all of them at once,
   same as Excel. cycleReferenceLock(formula, caret) -> cycleReferenceLocks
   (formula, start, end); a collapsed selection (start === end) keeps the
   old single-reference caret behaviour. Wired into both the in-cell editor
   and the formula bar.

3. Alt+Enter inserts a literal newline in the editor instead of committing
   (explicit splice at the caret, not relying on the textarea's native
   Enter handling, which isn't consistently reachable for Alt+Enter). A
   cell holding a newline displays it wrapped (.cell.multiline) instead of
   collapsing to one ellipsised line.

Along the way: a <td>'s own max-height doesn't cap table-row growth in any
browser (a table-layout quirk) -- a wrapped multi-line cell was silently
growing its row past rowH(r), which would have desynced every pixel
position computed from rowH()/rowTop() (the overlays, sticky frozen panes,
the row-resize handle). Fixed by moving cell text into its own block-level
.cell-content child, which *does* respect max-height + overflow:hidden.

Verified interactively against the dev server with Playwright: a long
formula gets a ~300px editor instead of the 104px cell; Alt+Enter produces
a real "\n" that survives commit and displays wrapped, with the row height
unchanged (26px, not the ~40px it grew to before the .cell-content fix);
F4 on a full-formula selection turns every reference absolute in one press
and keeps cycling all of them on repeated presses; existing selection,
copy/paste and fill-handle behaviour all regression-checked clean.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-02 11:04:45 +02:00
wkhandClaude Sonnet 5 830dcb8eeb 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>
2026-09-02 10:43:54 +02:00
wkhandClaude Sonnet 5 fafb118db6 Keep marking the copy source's first cell after the selection moves on
Copying a range showed the dashed marquee around the whole source, but the
distinct border on its first (anchor) cell disappeared the moment you
selected something else -- that border was drawn from the *live* selection's
anchor, which had just moved to the new (paste-destination) cell.

- ClipboardData now also stores the copy/cut selection's own anchor -- the
  cell the drag/shift-selection actually started from, which isn't always
  rect's top-left corner (a drag can start at any corner).
- clipboardRect exposes it; TableGrid renders a second small overlay,
  .clip-anchor, positioned on just that one cell -- independent of the
  current selection, so it stays visible for as long as the marquee does.

Verified interactively: copy B2:B5, click a cell elsewhere -- the marquee
and the solid border on B2 both remain, while the new cell gets its own
live-selection border.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-02 10:35:35 +02:00
wkhandClaude Sonnet 5 47afe8fc20 Fix copy marquee (one rectangle, not per-cell) and arrow-key collapse point
- Copy source marker: was outline:dashed on every td in the copied range,
  so each cell got its own little dashed box. Replaced with one absolutely
  positioned .clip-marquee overlay sized/positioned from the range's pixel
  bounds (colLeft/rowTop), giving a single dashed rectangle around the whole
  range, same as Excel/Numbers.
- Arrow keys (no Shift) after selecting a multi-cell range collapsed beside
  the *focus* (wherever the drag/shift-selection ended), not the *anchor*
  (the active, first-selected cell) -- inconsistent with the anchor-stays-
  active fix from the previous change and with Excel/Numbers, where a plain
  arrow key always steps from the active cell. navigate()/jumpTo()/Home/End
  now step from the anchor when collapsing (ext=false) and keep stepping
  from the focus when extending (Shift/Ctrl+Shift), which is unchanged.

Verified interactively against the dev server with Playwright (isolated
empty sheet, to sidestep the seed data's cascaded/overlapping tables):
selecting B2:B5 keeps the active-cell border on B2, copying shows exactly
one .clip-marquee, and ArrowLeft afterwards lands on A2, not A5.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-02 10:23:06 +02:00
wkhandClaude Sonnet 5 8e43cc294c Support $-locked references: relative, mixed and absolute
The engine already anticipated $A1/A$1/$A$1 in its grammar comment, but the
lexer had no rule for '$' at all -- any formula using it failed to parse.

- lexer.ts: '$' is now a valid word character, so "$A$1" tokenizes as one
  IDENT, same as any other bare word (the lexer still doesn't interpret it,
  per its "dumb lexer" design -- the parser/evaluator stay untouched, since
  evaluation is purely positional and $ has no effect on a value).
- refs.ts: parseA1()/toA1() now carry colAbs/rowAbs through the $ markers
  (backward compatible -- existing {col,row} destructuring is unaffected).
  Added cycleReferenceLock() for Excel/Numbers-style F4: relative ->
  absolute -> row-locked -> col-locked -> relative, toggling whichever
  reference sits at the caret (and the correct side of an A1:B2 range).
- document.ts: shiftFormula() now honors the lock on copy (a locked axis
  stays exactly as typed) but not on cut (a moved cell's reference follows
  it regardless of $, since cut relocates the cell itself rather than
  filling a relative offset).
- TableGrid.vue's inline cell editor and FormulaBar.vue both wire up F4 via
  the shared cycleReferenceLock() helper.
- Tests: lexer/parser coverage for $ tokenizing/parsing, a new refs.spec.ts
  for parseA1/toA1 round-tripping and the F4 cycle (incl. range side-
  picking), and document.spec.ts cases for locked-axis copy vs. cut.
- README.md / src/engine/README.md: documented the $ semantics, F4, and
  corrected a couple of now-stale claims (test count, "$ is ignored, there's
  no copy/fill", "active cell is always the last-clicked one").

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-02 10:11:10 +02:00
wkhandClaude Sonnet 5 e45cdfd077 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>
2026-09-02 09:59:29 +02:00
wkhandClaude Sonnet 5 44f3314137 Add cell selection copy/cut/paste with formula reference adjustment
- store: copySelection/cutSelection/pasteClipboard/cancelClipboard hold an
  in-memory (unpersisted) clipboard buffer of raw cell inputs + formatting.
- shiftFormula rewrites every relative cell reference in a copied/cut formula
  by the move delta (the engine has no $-absolute refs, so all refs qualify).
  Copy shifts every reference uniformly; cut only follows references that
  point inside the moved block itself, leaving refs to untouched cells alone
  and never touching a qualified Table!A1 reference.
- paste anchors on a smaller/single-cell selection (and overflows past it),
  or tiles across a selection that's an exact larger multiple of the buffer.
- TableGrid: Strg+C/X/V shortcuts, context-menu entries, a dashed "clip-src"
  source marker, and Escape drops a pending buffer.
- document.spec.ts: coverage for reference shifting, tiled/fill paste, cut's
  inside/outside reference split, format copy, and Escape cancelling.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-02 09:55:09 +02:00
wkh 31108977b9 - before copy paste 2026-09-02 09:45:44 +02:00
wkh c7885067e7 - init 2026-08-29 17:47:12 +02:00