Repository navigation
Commit 7526058
Fixes #21284
Clause-②: no
## What changed
An `object-master-detail-form` detail entry has two describes that say
what an omitted key means: `inlineMode` and `formFields`. Both now state
the renderer's two paths. The reference page that lifts them
(`content/docs/references/ui/component.mdx`) is regenerated by
`check:generated --fix`. No schema accepts or refuses anything new.
There is no shape, default or nullability change, and no edit to
objectui or `packages/lint`.
`inlineMode`, before:
> Inline-edit form factor: 'grid' = editable cells; 'form' = read-only
list + per-row full form. Resolved from the relationship field's
`inlineEdit` when omitted
after:
> Inline-edit form factor: 'grid' = editable cells; 'form' = read-only
list + per-row full form. When omitted it is resolved from the
relationship field's `inlineEdit`, else from the child object's shape —
except on an entry that names both `relationshipField` and at least one
column, which is kept as authored: nothing is resolved, the collection
renders as a grid, and the per-row form is offered only when
`formFields` lists more fields than `columns`
`formFields`, before:
> Child field names for the per-row expand form (derived from the child
object's editable fields when omitted)
after:
> Child field names for the per-row expand form. When omitted they are
derived from the child object's fields — except on an entry that names
both `relationshipField` and at least one column, which is kept as
authored: nothing is derived, and the per-row form is offered only when
`inlineMode` is 'form', where it draws the child object's full field
list
## What the renderer does (objectui at the `.objectui-sha` pin
`31971ff1e28f`, read with `git show`)
`packages/plugin-form/src/MasterDetailForm.tsx`:
- 927–929, `needsDerive`: an entry needs resolution when it has no
`relationshipField`, no columns, or an untyped column.
- 967, the fast path: `relationshipField` set and every column typed.
The entry is returned unchanged (`{ ...entry, status: 'ready' }`).
- 1048–1055, the hydrate path: `relationshipField` set and `columns`
non-empty. The config becomes `{ ...d, columns: derived.columns,
amountField, sortField }`, so `formFields` and `inlineMode` stay as
authored.
- 1056–1069, the derived path: `formFields: d.formFields ??
derived.formFields` (1063) and `inlineMode: d.inlineMode ??
derived.mode` (1064). `derived.mode` comes from `resolveInlineMode`
(`deriveMasterDetail.ts` 536–539 and 456–470). It is the relationship
field's `inlineEdit` when that is `grid` or `form`, and otherwise a
default chosen from the child object's shape.
- 847: the per-row expand control is offered when `d.inlineMode ===
'form'`, or when `formFields` is longer than `columns`. At 850,
`displayMode` is `list` only for `form`; otherwise it is `grid`.
- 1821: the row form receives `fields` only when `formFields` is
non-empty. Without them, `ObjectForm` (`ObjectForm.tsx` 961) draws
`Object.keys(objectSchema.fields)`, which is every field the child
object declares.
So, for the question the card left open about `formFields` on the
kept-as-authored path: when it is omitted, nothing is derived. A grid
never offers the per-row form, because zero fields is never more than
the column count. The form is offered only when `inlineMode` is `form`,
and it then draws the child object's full field list. The old text was
false there, so this PR rewords it. It also drops "editable": the
derived list keeps `readonly` fields (`deriveFormFields` at the pin,
404–420, and `deriveInlineRowFormFields` in
`packages/spec/src/data/inline-grid-columns.ts`).
The wording matches what the spec already says about both paths. "Kept
as authored" means an entry that names both `relationshipField` and at
least one column, as in the `creditAuthoredRowForm` docblock in
`packages/lint/src/validate-field-consumers.ts`. The offer condition is
`isInlineRowFormOffered` in `@objectstack/spec/data`.
## A bounded in-place fix, declared
The `masterDetailDetailEntry` factory's TSDoc (`component.zod.ts`, the
paragraph above the factory) said `inlineMode`'s "absence takes the
relationship's own resolution". That is the same claim, true on only one
path, and it ships in the tarball under `src/**/*.zod.ts`. It now says
this holds only on an entry the renderer derives, and points to the
describe. This is outside the claim's declared file surface, which names
the two describes. It is made under the bounded in-place rule: it is the
same defect, this card's ruling fixes its form, no other claim holds
that region of the file, and it adds no new gate. It is a comment-only
change of one added line.
## Released surface
The card says the sentence "is not yet in a release". Measured today,
`@objectstack/spec@17.6.0` is published as `latest`, and its tarball
carries the sentence once each in `src/ui/component.zod.ts` and
`dist/ui/index.js`. So 17.6.0 already ships it. This `patch` corrects it
in the next release.
## Acceptance notes
- `sortField`'s describe, "(derived from a `position` / `sort_order` / …
field when omitted)", is false on the fast path. At 967, an entry with
`relationshipField` and every column typed is returned as authored, so
an omitted `sortField` is not derived. The hydrate path at 1037–1051
does derive it, since objectui#11144. This PR does not touch it: it is
outside this card's surface, and someone must decide whether the
renderer's fast path or the describe changes. It is reported to the
seat.
## Verification (every reading below is on HEAD `e21f622b65`)
- `pnpm --filter @objectstack/spec build`: `VERDICT command-exit 0`.
- `pnpm --filter @objectstack/spec check:generated`: the first run
reported `1 of 15 artifact(s) stale: content/docs/references/**`, and
every other artifact was current, the authorable surface and JSON
schemas included. `--fix` regenerated that one, and its re-check gave `✓
check:docs`. Run again in the gate union: exit 0.
- `pnpm --filter @objectstack/spec typecheck`: exit 0.
- `pnpm --filter @objectstack/spec exec vitest run --project local
--maxWorkers=2`: `Test Files 597 passed (597)`, `Tests 17484 passed | 1
todo`.
- `node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack
--commands`, run with no paths: 102 commands, the same set as the
dispatch's derivation. All were run, and `--ran` answers `102 derived
famil(ies) accounted for — 101 run, 1 NOT-MEASURED`.
- Five gates first exited 3 because their prerequisite packages were not
built: `check:doc-formula-expressions`, `check:doc-security-posture`,
`check:skill-examples`, `check:docs-transcript-drift` and
`check:lean-entry-closure`. After building that closure (`turbo run
build` for formula, lint, client-react and objectql: 34 tasks), all five
exit 0.
- NOT MEASURED: `pnpm check:dual-build-cjs-loads`. It needs every
workspace package's `dist`, which needs a full-repo build. As a narrower
check, all 19 `require` entry points of `@objectstack/spec` load. CI
runs the full gate.
- eslint, narrowed: of the diff's three files, only `component.zod.ts`
is in eslint's population. For the `.md` and `.mdx` files, eslint
answers "File ignored because no matching configuration was supplied".
`--format json` reports 1 file, 0 errors and 0 warnings. That file's
resolved config has `parserOptions` without `project`, so linting is not
type-aware and this diff cannot change the verdict for any untouched
file. The full `pnpm lint` runs in CI.
---
_Generated by [Claude
Code](https://claude.ai/code/session_01UtnxvdiN376GF3sgXwAw4d)_
---------
Co-authored-by: Claude <noreply@anthropic.com>
1 parent dabd1c5 commit 7526058
3 files changed
Lines changed: 18 additions & 5 deletions
File tree
- .changeset
- content/docs/references/ui
- packages/spec/src/ui
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
976 | 976 | | |
977 | 977 | | |
978 | 978 | | |
979 | | - | |
980 | | - | |
| 979 | + | |
| 980 | + | |
981 | 981 | | |
982 | 982 | | |
983 | 983 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
5006 | 5006 | | |
5007 | 5007 | | |
5008 | 5008 | | |
5009 | | - | |
| 5009 | + | |
| 5010 | + | |
5010 | 5011 | | |
5011 | 5012 | | |
5012 | 5013 | | |
| |||
5030 | 5031 | | |
5031 | 5032 | | |
5032 | 5033 | | |
5033 | | - | |
5034 | | - | |
| 5034 | + | |
| 5035 | + | |
5035 | 5036 | | |
5036 | 5037 | | |
5037 | 5038 | | |
| |||
0 commit comments