Fix/misc calc improvements#20
Conversation
1. Delete key should only clear content, not formatting 2. Multi-select header tint — selecting multiple rows/cols only tints the first header green 3. Top-left corner cell should select all 4. Paste Special → "Format only" should include number/cell format and colors as well 5. Paste Special → "Format only" keyboard shortcut doesn’t work as advertised
Adds a new toolbar button that copies formatting (text+colors+number format) and then applies it to a click/drag target, with Excel-style row-major source→destination mapping and wrap. Also works for whole rows / columns.
Follow-up cleanups on the format-painter feature surfaced in review: 1. Paintbrush cursor was a no-op. The painter set a `--calc-grid-cursor` CSS variable on <html> that no rule ever consumed, so the cursor never changed when the painter was armed. Replace it with a `calc-format-painter-active` class toggled on <html>, and add a rule in the overlay's injected stylesheet that applies an Excel-style paintbrush cursor (inline SVG data-URI, white outline halo + blue bristle tip, hotspot at the tip, `copy` system fallback). The `!important` + `*` selector overrides the per-cell cursors. 2. Apply logic was duplicated three ways. The "expand a single-cell target to the source dimensions, then tile" logic lived inline in Cell onPress, the Cell PanResponder onDragEnd, and Grid's applyFormatPainterIfActive. Extract it into applyFormatPainterToDest() in style-helpers and route all three call sites through it. Header clicks always produce multi-cell selections, so unifying the header path is behavior-preserving. readCellStyle's potential Y.Doc reference aliasing was reviewed and left as-is: the re-apply goes through setYCellStyle (a deep-merge patch), so it is safe in practice regardless. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The first paintbrush-only cursor read as an ugly blob. Replace it with the classic Excel format-painter glyph: a bold white cross (the click target, hotspot at its center) with a small paintbrush to the right. White fills with a black outline so it stays legible on any cell background. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Fill the unit-test gaps for the recent fixes and the format-painter feature — all pure / Y.Doc-level functions, no React harness needed: 1. applyFormatPainterStyles / applyFormatPainterToDest — row-major modulo tiling, the single-cell→source-size expansion, and multi-cell targets left un-expanded. 2. clearYCellContent — wipes value fields while preserving the style map, and removes the entry entirely when the cell has no style. 3. Clipboard numFmt round-trip — guards that Paste → Format only carries number format (and colors) through the HTML encode/decode path. 4. selectAll store action — scope/anchor/range and empty-grid clamp, the action the corner-cell click depends on. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The HTML clipboard decoder stored colors sans `#` (e.g. `FF0000`) while the color picker writes `#`-prefixed hex (e.g. `#B00020`) to font.color / fill.fgColor. Both render fine via normalizeColor, but the forms aren't byte-identical, so swatch active-matching (ColorPickerGrid compares with `selected === swatch.hex`) and any color equality break for pasted cells. Make parseCssColor emit canonical `#RRGGBB` uppercase for both hex and rgb() inputs, matching the picker. Update the decode tests accordingly. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
nathanstitt
left a comment
There was a problem hiding this comment.
This looks great! I don't feel strongly about any of the comments so up to you if you want to update or not
| import type { WorkbookFileActions } from '../hooks/use-workbook-file-actions' | ||
| import { useAllYSheets, useYSheets } from '../hooks/use-y-sheets' | ||
| import { classifyCellKey } from '../lib/cell-key-action' | ||
| import type { CellStyle } from '../lib/workbook-types' |
There was a problem hiding this comment.
This is where CI's Typecheck & Unit job is probably failing , biome probably doesn't like that workbook-types sorts after conditional-format/a1 (line 36), so Biome wants this line moved down. Same import-ordering issue in components/grid/Body.tsx (the FormatPainterOverlay import) and hooks/grid-store.ts (the CellStyle import).
It slipped through locally because npx tinycld-pkg check runs only tsc + vitest — Biome runs only ecosystem-wide via npm run lint from app/, which is what member CI invokes. One-liner fix from the workspace root:
cd ~/code/tinycld/app && npm run lint:fixthen commit the reformatted files.
There was a problem hiding this comment.
ah darn, I don't get myself around to installing biome. When I tried the above, then it failed because of a minor version mismatch (2.4.15 against 2.4.16) and I realized, that there's no package-lock.json anywhere. I assume that's due to the bootstrapped install from the workspace root? Isn't that a significant security risk these days? Fixed the linting in the end 👍
aa0613b to
fe052cf
Compare
fe052cf to
2c034d1
Compare
This addresses a Safari paste failure. The root cause was that Safari rejects the async navigator.clipboard.read()/readText() when invoked from a keydown-driven tinykeys shortcut (after any await, the user-gesture context is lost and permission is required). The fix: 1. Removes the $mod+v tinykeys shortcut (use-calc-shortcuts.ts) so the browser fires its native paste event instead of swallowing the key. 2. Adds a native paste listener in Grid.tsx that reads event.clipboardData synchronously — no permission, works in all browsers. 3. readFromClipboardEvent mirrors the existing async readFromOsClipboard logic exactly (html → marker → fidelity store → fallback to tsv), so paste fidelity is preserved.
|
@nathanstitt I implemented the suggested suggestions and tacked one more fix on top: pasting content in calc was actually never working on Mac, because of the strict way that Safari handles native paste events (must be directly invoked by a user action, a minor await will kill that, which seems what tinykeys is doing). |
Here's another maxi-PR with some fixes and improvements for the calc app:
fix: misc fixes
feat: format paintbrush
Adds a new toolbar button that copies formatting (text+colors+number format) and then applies it to a click/drag target, with Excel-style row-major source→destination mapping and wrap. Also works for whole rows / columns.
review comments and fixes
Follow-up cleanups on the format-painter feature surfaced in review:
Paintbrush cursor was a no-op. The painter set a
--calc-grid-cursorCSS variable on that no rule ever consumed, so the cursor never
changed when the painter was armed. Replace it with a
calc-format-painter-activeclass toggled on , and add a rule inthe overlay's injected stylesheet that applies an Excel-style paintbrush
cursor (inline SVG data-URI, white outline halo + blue bristle tip,
hotspot at the tip,
copysystem fallback). The!important+*selector overrides the per-cell cursors.
Apply logic was duplicated three ways. The "expand a single-cell target
to the source dimensions, then tile" logic lived inline in Cell onPress,
the Cell PanResponder onDragEnd, and Grid's applyFormatPainterIfActive.
Extract it into applyFormatPainterToDest() in style-helpers and route all
three call sites through it. Header clicks always produce multi-cell
selections, so unifying the header path is behavior-preserving.
readCellStyle's potential Y.Doc reference aliasing was reviewed and left
as-is: the re-apply goes through setYCellStyle (a deep-merge patch), so it
is safe in practice regardless.