feat(grid): spreadsheet-style line-item editor (computed cells, ghost row, keyboard nav)#1564
Merged
Merged
Conversation
… row, keyboard nav) Rework GridField's editable grid mode into a real enterprise line-item editor (the QuickBooks / Stripe / NetSuite pattern), generalised so every inline grid benefits — not just invoices: - Computed read-only columns: a child field carrying an arithmetic `expression` (e.g. amount = quantity × unit_price) renders read-only, recomputes live as its inputs change, and writes the result back into the row so it persists and the running total reflects it. A tiny safe arithmetic evaluator (no eval) over `+ - * / %`, parens and `record.<field>` refs powers it. - Always-present trailing "ghost" row: start-with-one + auto-append. Typing in the ghost materialises a real row (index-stable so focus/caret survive), so you keep entering lines without clicking "Add". - Borderless click-to-focus cells + role-based column widths (description flexes, qty/price/amount stay narrow) — reads as a table, not a wall of boxes. - Keyboard navigation: Enter / ArrowUp / ArrowDown move between rows in the same column; Tab falls through the natural order into the ghost row. - Per-row "expand to full form" is gated: shown in form mode (it is the editor) and in grid mode only when the grid omits fields — no redundant expand on a thin line like an invoice row. - deriveColumns surfaces `expression` as a computed column; the running-total column now prefers the computed/last-currency column over the first numeric. - Blank/ghost rows are filtered from the persisted batch (isBlankRow), so an untouched trailing line never saves as an empty child. Live e2e: New Invoice grid computes amount live, persists it, rolls up the total, and skips the blank ghost line. Dropped row-expand.spec (its grid-mode-expand-on-a-thin-line scenario is intentionally gone; per-row form editing stays covered by the form-mode master-detail spec). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
Contributor
✅ Console Performance Budget
📦 Bundle Size Report
Size Limits
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Even the invoice line grid felt poor: Amount was a manual field, the running total stayed
0, columns were mis-sized, you had to click "Add line" repeatedly, and a redundant per-row "expand" sat on every thin line. This rebuildsGridField's editable grid mode into a real enterprise line-item editor — the QuickBooks / Stripe / NetSuite pattern — generalised so every inline grid benefits, not just invoices.What
expression(e.g.amount = quantity × unit_price) renders read-only, recomputes live as its inputs change, and writes the result back into the row so it persists and the running total reflects it. A tiny safe arithmetic evaluator (noeval/Function) over+ - * / %, parens andrecord.<field>refs powers it.deriveColumnssurfaces a fieldexpressionas a computed column; the running-total column now prefers the computed/last-currency column over the first numeric. Blank/ghost rows are filtered from the persisted batch (isBlankRow) so an untouched line never saves as an empty child.Verification
GridField,deriveMasterDetail,masterDetailTx(computed mapping, ghost auto-append, keyboard nav, blank-row filtering).Dropped
row-expand.spec— its "grid-mode expand on a thin line" scenario is intentionally gone; per-row form editing stays covered by the form-modemaster-detailspec.🤖 Generated with Claude Code