|
| 1 | +--- |
| 2 | +"@objectstack/spec": minor |
| 3 | +--- |
| 4 | + |
| 5 | +feat(spec)!: retire the `inline` and `grid` arms of form `layout` — every renderer folded both to `vertical`, and multi-column is `columns` (ADR-0049) |
| 6 | + |
| 7 | +<!-- adr-0087: registered form-layout-inline-grid-to-vertical, ui-form-layout-inline-grid-retired --> |
| 8 | + |
| 9 | +**BREAKING** — form `layout` accepts exactly `'vertical' | 'horizontal'` on both surfaces |
| 10 | +that declared the four-arm enum: the `object-form` page component |
| 11 | +(`ObjectFormPropsSchema.layout`) and the form view (`FormViewSchema.layout` — `view.form`, |
| 12 | +`view.formViews.*`, a form view item's `config`, and the flattened form overlay, which |
| 13 | +spreads the form view's shape). `'inline'` and `'grid'` are refused at parse, each with a |
| 14 | +prescription naming what to write instead. |
| 15 | + |
| 16 | +| surface | before | after | |
| 17 | +|:--|:--|:--| |
| 18 | +| `object-form` `layout: 'grid'` | parsed clean, rendered as `vertical` | refused — write `'vertical'` (or omit `layout`); for multi-column set `columns` | |
| 19 | +| `object-form` `layout: 'inline'` | parsed clean, rendered as `vertical` | refused — write `'vertical'` (or omit `layout`) | |
| 20 | +| form view `layout: 'grid'` | parsed clean, rendered as `vertical` | refused — write `'vertical'` (or omit `layout`); for multi-column set `columns` | |
| 21 | +| form view `layout: 'inline'` | parsed clean, rendered as `vertical` | refused — write `'vertical'` (or omit `layout`) | |
| 22 | +| `layout: 'vertical'` / `'horizontal'` | accepted | **unchanged** | |
| 23 | +| `columns` | honoured under every layout | **unchanged** — the key multi-column always lived under | |
| 24 | + |
| 25 | +**What was actually wrong.** No renderer ever gave either value a behaviour of its own. |
| 26 | +Measured at the `.objectui-sha` pin this repo builds against (`f8a9d0fb0`): the simple |
| 27 | +`object-form` arm folds both to `vertical` (`ObjectForm.tsx:1406-1410`, under the comment |
| 28 | +"Map 'grid' and 'inline' to 'vertical' as fallback"); the drawer and modal arms |
| 29 | +(`ObjectForm.tsx:463`, `:499`) and `DrawerForm.tsx:575` / `ModalForm.tsx:597` pass only |
| 30 | +`vertical` / `horizontal` through; `TabbedForm.tsx:556`, `SplitForm.tsx:445` and |
| 31 | +`WizardForm.tsx:1075` hard-code `vertical`. So both values were a green parse for a value the |
| 32 | +renderer threw away. The spec had admitted them from two declarations — the designer palette |
| 33 | +and the registry `inputs` offered all four — never from a read. |
| 34 | + |
| 35 | +Under the maintainer's ADR-0049 family criterion (the capability exists on mainstream |
| 36 | +platforms ⇒ build the consumer; it does not ⇒ retire), multi-column — what `grid` would |
| 37 | +mean — already exists here under another key, `columns`, which the renderer honours under |
| 38 | +every arm; `inline` is a toolbar / filter-row pattern, not a record-form layout. The two arms |
| 39 | +are redundant vocabulary, retired with no alias window. |
| 40 | + |
| 41 | +## What to write instead |
| 42 | + |
| 43 | +```ts |
| 44 | +// before — parsed clean, rendered single-column 'vertical' |
| 45 | +{ type: 'object-form', properties: { objectName: 'crm_lead', layout: 'grid' } } |
| 46 | +// after — what it rendered; add `columns` if a multi-column form was the intent |
| 47 | +{ type: 'object-form', properties: { objectName: 'crm_lead', layout: 'vertical', columns: 2 } } |
| 48 | +``` |
| 49 | + |
| 50 | +`'inline'` → `'vertical'` (or delete `layout`: `'vertical'` is the renderer default). A form |
| 51 | +that wrote `'grid'` without `columns` always rendered single-column; only its author knows |
| 52 | +whether more columns were meant — set `columns` to the count you meant. |
| 53 | + |
| 54 | +Existing sources: `os migrate meta --from 17` lists the mechanical edits; apply them by hand. |
| 55 | + |
| 56 | +The retirement kit: |
| 57 | + |
| 58 | +- both enums narrowed to `'vertical' | 'horizontal'`, each with a per-value error map keyed on |
| 59 | + the input (the `record:chatter` `position` precedent), so only a value that used to be legal |
| 60 | + is told it "was removed"; a never-vocabulary value keeps zod's own enum refusal |
| 61 | +- the D2 conversion `form-layout-inline-grid-to-vertical` (protocol 18, retired from the load |
| 62 | + path) rewrites both values to `'vertical'` and leaves `columns` untouched — on `object-form` |
| 63 | + page components, on every form payload a view carries, and on the assembled-manifest |
| 64 | + `viewItems` channel, so stored rows and assembled artifacts replay clean; wired into the |
| 65 | + protocol-18 chain step |
| 66 | +- one D3 entry for the family, `ui-form-layout-inline-grid-retired`, carrying the one judgement |
| 67 | + the chain cannot make: whether a form that said `grid` wanted columns it never declared |
| 68 | +- pin tests (`ui/form-layout-inline-grid-retired.test.ts`): both values refused with the |
| 69 | + prescription on five doors (`ObjectFormPropsSchema`, the `object-form` props-map row, |
| 70 | + `FormViewSchema`, a view container's `formViews`, the flattened form overlay), `vertical` / |
| 71 | + `horizontal` green on each as controls, the conversion's rewrite parsing green on the door |
| 72 | + that refused its input, and the chain registration |
| 73 | +- the `columns` descriptions no longer say "grid layout"; the generated references |
| 74 | + (`content/docs/references/**`, `skills/objectstack-ui/references/react-blocks.md`, the JSON |
| 75 | + Schema) print the two-arm enum; the hand-written `layout-dsl` page and the `form.layout` |
| 76 | + liveness row (still `live`) are updated |
| 77 | +- `api-surface/` and `authorable-surface/` are unchanged, correctly: they ratchet export and |
| 78 | + key existence, and no export or key leaves — `layout` is still declared, two values narrower |
| 79 | + |
| 80 | +Clause-②: no (narrowing) |
0 commit comments