Repository navigation
fix(plugin-grid): a fixed-currency field shows its own currency in the grid cell and the summary footer (#10354) - #10418
Conversation
…e release The pending changeset said `decimals` still reads `column.precision`. That has been false since objectui#9295, which moved the percent footer's width to `scale`. Body only; the frontmatter is byte-identical. Part of objectui#10354. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BP8CMtACxTdLjqR6rhd33C
…s currencyConfig
`@objectstack/spec` refuses a field-level `currency`, so a fixed currency is
declared only as `currencyConfig: { currencyMode: 'fixed', defaultCurrency }`.
`resolveFieldCurrency` reads it, but the grid never handed it that key: the
three configured-column cell bags copied `currency` / `precision` / `scale`
only, and the footer's column hints carried no `currencyConfig`. A JPY-fixed
amount in a USD tenant therefore read `$1,234` in the cell and the footer,
while the metric tile and every whole-def cell read `¥1,234`.
Both halves move together: each cell bag copies `currencyConfig` verbatim, and
`useColumnSummary` hands the field's `currencyConfig` to the same resolver, so
the cell and the footer cannot split again.
The README's percent-footer sentence now names `scale`, the width it has read
since objectui#9295.
Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BP8CMtACxTdLjqR6rhd33C
…e column paths A USD tenant with a JPY-fixed field: the cell on each configured-column path and the summary footer (through the grid and through the public hook) read `¥1,234`, while a field with no `currencyConfig` still reads the tenant `$`. An agreement table holds the grid to the real `CurrencyCellRenderer` given the whole field def, so it restates no resolution rule. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BP8CMtACxTdLjqR6rhd33C
The controls are GREEN on the base tree by design, so each one now reads as its own case instead of trailing a fixed-currency assertion that fails first. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BP8CMtACxTdLjqR6rhd33C
…ace; add the changeset The auto-generated columns hand the cell the whole field def and build no bag, so they already read the field's own currency. The new case is GREEN on the base tree by design and names the face the configured paths now match. The changeset is a `patch` for `@object-ui/plugin-grid`, with the dynamic-mode consequence stated. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BP8CMtACxTdLjqR6rhd33C
… spec's CurrencyConfig
A restated `{ defaultCurrency?: string }` refused a field def written in the
spec's own shape: an object literal carrying `currencyMode` failed the excess
property check. The member is now `CurrencyConfig` from `@objectstack/spec/data`,
and the hook's pin passes a typed literal with no cast so `type-check` reads it.
Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BP8CMtACxTdLjqR6rhd33C
|
changeset-claim-re-read
|
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
Contract reviewServed-tier: Rendered by an isolated review subagent spawned by the ① Derived judgments
② Semver level
③ Boundary flags
Implemented-by: VERDICT: PASS Generated by Claude Code |
Fixes #10354
A fixed-currency field (
currencyConfig: { currencyMode: 'fixed', defaultCurrency: 'JPY' }) now shows its own currency in the grid cell and in the column-summary footer. Before this change, both faces showed the tenant's currency: a JPY-fixed1234in a USD tenant read$1,234.What changed, in the triage comment's order
.changeset/9269-grid-summary-percent-converged.mdsaid "decimalsstill readscolumn.precision, unchanged". That has been false since objectui#9295. The sentence now namesscale. Only the body changed; the frontmatter bytes match the base (compared withod -c).ObjectGrid.tsx: each of the three configured-column cell bags (ListColumn objects, a string array, inline rows with afieldsprojection) now copies the field'scurrencyConfigas declared.useColumnSummary.ts: the column hints now pass the field'scurrencyConfigtoresolveFieldCurrency. The hook'sfieldMetadataparameter type gainscurrencyConfig?: CurrencyConfig, using the spec's own type from@objectstack/spec/data.packages/plugin-grid/README.md, the percent-footer sentence now says the width comes fromscale, notprecision.packages/plugin-grid/src/__tests__/gridFixedCurrency-10354.test.tsx, has 15 cases (see below).Mechanism assumptions, measured
currencyConfigthrough verbatim.resolveFieldCurrencyin@object-ui/i18nchecksfield.currencyfirst, thenfield.currencyConfig?.defaultCurrency, then a legacydefaultCurrency, and finally the tenant default. It does not readcurrencyMode. So the grid hands over the whole object and adds no mode rule of its own: whatever the resolver decides a mode means, the grid now agrees. One consequence: adynamic-mode field that has acurrencyConfignow also showsdefaultCurrencyon these two faces. The auto-generated columns, the detail view and the metric tile already did. See Acceptance notes.currencyConfigfrom the FIELD only.ListColumnSchema(spec 17.4.0) declares nocurrencyConfig, so reading it off the column would create a second, undeclared spelling (Commandment #0.1).fieldMeta.currency =). Two other cell paths exist: the auto-generated columns and the record-detail panel. Both hand the renderer the whole field def and build no bag, so they need no change.origin/main(read at 2fc2a24) has not changed any touched file since the base 721d1e0, so no merge was needed.Pins and ablation
Fixture: a USD tenant.
amountis fixed to JPY (1234).dynis dynamic EUR (3456) and appears only in the agreement cases.plainis a currency field with nocurrencyConfig(5678) and serves as the control.CurrencyCellRenderergiven the whole def, three pathsEach ablation ran on committed code. A trap restored the files afterwards, and each restore was proven by an empty
git diff HEADplus a blob hash equal to HEAD's.Tests 9 failed | 6 passed (15). A typical failure isexpected 'Yen Amount: Sum: $1,234' to be 'Yen Amount: Sum: ¥1,234', and the grid's cells read["1Open","Tower","$1,234","$3,456","$5,678"].ObjectGrid.tsxreverted (at cd2b7d8, which had 14 cases): 6 failed, all of them cell cases; the footer cases stayed green.useColumnSummary.tsreverted (same head): 3 failed, all of them footer cases; the cell cases stayed green.ablation-replace.mjs: 2 failed, both of them 'ListColumn objects' cell cases.The two half-reverts show that each half has its own pins: reverting either one splits the cell from the footer again.
A reverse check on the type ran at 975365b with
tsc -p tsconfig.test.json:currencyMode: 'fixd'in the typed hook fixture fails with TS2820;Local verification (at 975365b unless noted)
ObjectGrid.tsx,useColumnSummaryor the plugin-grid README, plusmachineLocaleCensus-9909. All 1193 tests passed.turbo run build --filter='@object-ui/plugin-grid^...', 13 tasks),pnpm --filter @object-ui/plugin-grid type-checkpassed.tsc -p tsconfig.test.json --listFilesOnlylists the new test file.check-changeset-presence,check-changeset-no-major,check-changeset-overwrite(report-only; it reports the intended 9269 body edit),check-changeset-fixed,check:changeset-claims(7 pending changesets name a touched file; I read each one, and none is made false).check:new-line-citations(0 new),check:control-bytes.check:spec-symbols,check:phantom-deps,check:esm-specifiers,check:self-import,check:designer-field-key-parity.check:doc-fences,check:handler-key-reads,check:test-path-roots,check:unreferenced-sources,check:vi-mock-specifiers,check:metadata-write-doors,check:comment-mask-corpus.check:spec-floors: plugin-grid measured, 10 other packages not. After building plugin-grid, the gate reports no plugin-grid finding. The newCurrencyConfigimport is exported from./dataat the declared^17.0.0floor, which I also confirmed in the 17.0.0 tarball. The gate still exits 1 because 10 other packages have no build output here (no-artifact). Those 10 are NOT MEASURED, reason: they need a whole-tree build, which CI does.check:readme-exports: NOT MEASURED, reason: 23 of 40 packages are unbuilt, so the gate's population floor was not met. The README hunk is prose, with no fenced block.--format jsonon the 3 touched source and test files: 3 files, 0 errors.ObjectGrid.tsxhas 208 anduseColumnSummary.tshas 6, the same counts as on the base. The new test has 2no-explicit-anywarnings.packages/plugin-gridis linted with the rooteslint.config.js.parserOptions.projectorprojectService, so linting is not type-aware and this diff cannot change the verdict on an untouched file. The fullpnpm lintrun belongs to CI.Acceptance notes
resolveFieldCurrencyreadscurrencyConfig.defaultCurrencyin every mode, and no objectui source readscurrencyMode.dynamicas "user selectable". Its field-key guidance says "A field without one uses the tenant default at runtime", where "one" means a fixed currency.currency. The cell bag still copies a field-levelcurrency, which the spec refuses by name. I left it unchanged because it is out of scope.useColumnSummary's parameters and return shape are untouched". That sentence describes the 9269 change and is still true of it. This PR's own changeset states the parameter type change this PR makes.Changeset
.changeset/10354-grid-fixed-currency-cell-footer.md: apatchfor@object-ui/plugin-grid.Session:
https://claude.ai/code/session_01BP8CMtACxTdLjqR6rhd33CGenerated by Claude Code