Skip to content

Commit b5e7ba5

Browse files
feat(spec)!: retire FormView drawerSide / drawerWidth — no form view opens in a drawer (#29287)
domain:spec#1 · os-steve · session_01ADHkmPi25XXKx92Xmg4viS <!-- claude-projects-attribution: {"github_login":"os-steve"} --> _Requested by **Steve** · [project thread](https://claude.ai/code/project/chan_01FdL1XeUyvVNxLreh3F4Qi9?thread=cmsg_01FdL1XeUyvVNxLreh3F4Qi98wYJuaJ1vEnWCa6xuHrcSS)_ Fixes #29012 Clause-②: no (narrowing) Metadata-protocol: narrowed ## 维护者速读 - 改了什么:表单视图(form view)上的 `drawerSide` / `drawerWidth` 两个键退役,写了就在保存时被拒并给出修法;存量数据读取时自动删掉这两个键。React 页面里 `ObjectForm` 组件的同名属性保留不变。 - 为什么改:表单视图早已不能以抽屉方式打开(`type: 'drawer'` 已在本版本退役),控制台、记录表单页和 Studio 都不读这两个键,作者写了能存能发布却毫无效果,属于“声明了但不生效”。 - 风险与回滚:只收窄表单视图的可写键;已存的表单视图读取时被转换,界面上看到的完全一样。回滚即还原本 PR。 - 先看:`packages/spec/src/ui/view.zod.ts`(两个墓碑和提示文案)、`packages/spec/src/ui/react-blocks.ts`(两个属性改由 `ObjectForm` 自己声明)、`packages/spec/src/conversions/registry.ts` 的 `form-view-drawer-keys-removed`。 - 两分钟验证:`pnpm --filter @objectstack/spec exec vitest run --project repo src/ui/form-view-drawer-keys-retirement.test.ts`,应看到 29 个用例全部通过。 - 需要你做的:无,席位落地。 ## What changes - **`FormViewSchema.drawerSide` / `drawerWidth` are `retiredKey()` tombstones** (`packages/spec/src/ui/view.zod.ts`). Each is refused at every form-view door (a view's `form`, `formViews.*`, a form view item record, a flattened form overlay, `defineStack` as `STACK_SCHEMA_INVALID` / 422) with a prescription that says why it was inert, what to do instead (`navigation.mode` / `navigation.size` for a list's record drawer; the React `ObjectForm` block's own props for a page drawer) and the `os migrate meta --from 17` sentence. TypeScript rejects both at a `FormView` position. The describe that deferred the question to closed #27153 is gone. - **The React `ObjectForm` block keeps both props** (`packages/spec/src/ui/react-blocks.ts`). They leave the block's `dataProps` (which read `FormViewSchema`) and move to its overlay as `binding` props with the same types; `drawerSide` keeps its description, and `drawerWidth`'s drops the form view's `[DEPRECATED → size buckets]` tag (the block's drawer has no size bucket) and says what `DrawerForm` does with the value: the drawer's width from the left or right edge, its height from the top or bottom, the #9392 rule for a prop only the react tier reads. The overlay entry shares the tombstone's name, so `REACT_OVERLAY_SHADOWS.ObjectForm` ledgers it with that reason. The regenerated `skills/objectstack-ui/references/react-blocks.md` moves the two rows from the data group to the binding group; `validate-react-page-props` reads the overlay, so a React page's `drawerSide="right"` stays known. - **ADR-0087 kit.** D2 conversion `form-view-drawer-keys-removed` (`toMajor: 18`, `retiredFromLoadPath`, `retiredAfter: '18.2.0'`, `stripKeys` on every form payload and the assembled `viewItems` channel; never walks page components, so the `object-form` page block keeps its keys). D3 semantic entry `ui-form-view-drawer-keys-retired`. `RETIRED_KEYS_BY_MAJOR[18]` entries `ui/FormView:drawerSide` and `ui/FormView:drawerWidth`. Step-18 rationale fragment. Removal-version pin rows. - **Ledger and generated artifacts.** `liveness/view.json`: both rows `dead` with the tombstone note (view counts 75/8 → 73/10). Regenerated `authorable-surface/ui.json` (two `[RETIRED]` rows), `content/docs/references/{api/protocol,ui/view}.mdx`, `liveness/state-counts/view.md`, the react-blocks contract. - **Changeset** `.changeset/29012-form-view-drawer-keys-retired.md`: BREAKING, `minor` on `@objectstack/spec` and `patch` on `@objectstack/skills` (the regenerated `skills/objectstack-ui/references/react-blocks.md` ships there, as in #27159's changeset), FROM → TO, the one-line fix, `registered` ADR-0087 marker. ### Forced test edits - `src/ui/form-view-type-layout-retirement.test.ts`: the "STATED BOUNDARY: `drawerSide`, `drawerWidth` and `modalSize` stay declared" pin now holds `modalSize` only, and its stored-row case uses `modalSize: 'lg'` as the bystander instead of `drawerSide: 'left'` (the new conversion strips that). The header's bookkeeping line points at the new pin. - `src/conversions/registry.ts` `form-view-presentation-types-removed` fixture: the `quick` form's bystander is `title: 'Quick'` instead of `drawerSide: 'left'`, because fixtures must stay disjoint under whole-table replay. Its docblock now says the drawer keys left later in the same release. - `src/ui/view-metadata-schema.test.ts`: the "a FormView key nobody would think to allow-list" probe uses `showStepIndicator` instead of `drawerSide`. - `src/system/metadata-form-zod-reconciliation.test.ts`: the `omit` row for `view.drawerWidth` is dropped, as the ledger asks for a key that became a tombstone. ### New pin `src/ui/form-view-drawer-keys-retirement.test.ts` (repo project, listed in `vitest.repo-tests.json`): both keys refused at five doors with the prescription's first sentence and the migrate sentence; a `modalSize` control at each door; `defineStack` envelope; `RETIRED_KEYS_BY_MAJOR`; `@ts-expect-error` at the authoring site; the block overlay publishes both and the `object-form` page block still accepts them; the conversion on a stored container and a form view item record, never on a page block, idempotent, off the load path, wired into step 18, with its D3 entry; tree-scoped absence over the five roots spec#test already declares. ## Why Triage ruling on the card (comment 6571544001): retire under ADR-0049. Measured at `origin/main` 104cd1a: - **No form-view surface reads either key.** The only code that hands them to `DrawerForm` is `ui/packages/plugin-form/src/ObjectFormContainer.tsx`, which serves the `object-form` block's `formType='drawer'`; a form view's `type` cannot be `drawer` since #27155. `ui/packages/plugin-designer/src/FieldDesigner.tsx` composes its own `DrawerFormSchema` in code. The console form page, the New / Edit dialogs (which read `modalSize` only) and the record form page never read them. - **The ui prop types are the block's own.** `DrawerForm.tsx` declares `drawerSide?` / `drawerWidth?` on `DrawerFormSchema`, and `@object-ui/types` `ObjectFormSchema` declares its own; neither derives from `FormViewSchema`, so `ui/` needs no edit (checklist 4 measured, below). - **`drawerWidth`'s size-bucket deprecation had no conversion.** The only conversion text naming it was the presentation-types docblock saying it stays. This entry deletes it; the prescription names `navigation.size`. - **Authored uses on a form view: 0.** `examples/`: 0 form views (2 hits are `ObjectForm formType="drawer" drawerSide="right"` JSX on React pages, the block, unaffected); `skills/`: 0 (the generated block contract only). Control leg: the live form-view key `submitBehavior` reads 8 in `examples/` on the same tree. HotCRM fixtures are not in this repository: NOT MEASURED. ## Tests All runs went through `os-verify-lock` (each VERDICT `command-exit 0` unless stated). `@objectstack/spec`, `@objectstack/lint` and the spec repo project ran at `0dc8fcc3`, whose tree differs from the head `8c7bfc30` only by the changeset file; `ui/` plugin-form, the gates and dogfood ran at `8c7bfc30`. Round 2 re-ran at the head `ffc3fe89`, under `os-verify-lock`: `turbo run build --filter='./packages/**'` exit 0; `@objectstack/spec` test Test Files 790 passed (790), Tests 23373 passed; `@objectstack/lint` test Test Files 189 passed (189), Tests 7830 passed; `dispatch-gates --commands` 112 derived, 112 run, reconciled with `--ran` as a DERIVED zero, every exit 0 except `check-empty-changeset --base origin/main` (exit 1 by design, above). The spec repo project, ui plugin-form and dogfood readings are from `8c7bfc30`; since then the code delta is one description string in `react-blocks.ts` plus its regenerated row, and the rest is changeset prose. - `pnpm --filter @objectstack/spec typecheck`: exit 0 (compiles the new pin's two `@ts-expect-error` lines). - `pnpm --filter @objectstack/spec test` (local project): Test Files 789 passed, 1 skipped (790); Tests 23371 passed, 1 skipped, 1 todo. - `pnpm --filter @objectstack/spec test:repo` (repo project, run locally because this diff adds and edits repo-project tests): Test Files 88 passed (88); Tests 1477 passed. - Consumer `@objectstack/lint` (`validate-react-page-props` reads the block overlay; `lint-liveness-properties` reads the ledger): `pnpm --filter @objectstack/lint test`: Test Files 189 passed (189); Tests 7825 passed, 5 skipped. - Consumer `ui/packages/plugin-form` (run from `ui/`): `pnpm --filter @object-ui/plugin-form test`: Test Files 217 passed (217); Tests 2407 passed, 1 skipped. The first run failed 3 files on a prerequisite (`@objectstack/client` unbuilt in a fresh container: "Failed to resolve import"); green after building it. - `ui/` type-check: NOT MEASURED locally (prerequisite: `@object-ui/plugin-form type-check` needs the ui workspace's own packages built, TS2307 on `@object-ui/types` and siblings). By source: no `ui/` type derives `drawerSide` / `drawerWidth` from `FormView` (`DrawerFormSchema` and `ObjectFormSchema` declare their own; `git grep` of `ui/` for `FormView[` indexes names only `modalSize`, `defaultTab`, `tabPosition`, `layout`, `buttons`, `defaults`). `Type Check UI` on this PR is the reading. - `packages/metadata`: no tombstone or conversion pin there names these keys (`git grep drawerSide drawerWidth -- packages/` outside `packages/spec` is empty), so no run is owed. <details><summary>Ablations (each restored, blob == HEAD and git diff HEAD empty, by scripts/ablation-replace.mjs)</summary> - Tombstone: `drawerSide: retiredKey(FORM_VIEW_DRAWER_SIDE_RETIRED)` replaced by the old `z.enum([...]).optional()`. The new pin went red: Tests 7 failed, 22 passed (29) — the five door refusals, the `defineStack` envelope and the `@ts-expect-error` case. Restored. - Conversion: the `stripKeys(form, ['drawerSide', 'drawerWidth'], emit, path)` call replaced by a pass-through. `conversions.test.ts` fixture replay for `form-view-drawer-keys-removed` and the pin's two stored-row cases went red: Tests 3 failed, 235 passed (238). Restored. (An earlier attempt used a replacement that threw instead of passing through and reddened every form-view fixture; it was discarded and rerun as the pass-through above.) </details> - Dogfood (title carries `!` and the `(narrowing)` arm) at `8c7bfc30`, after `turbo run build --filter='./packages/**'` (78/78): `pnpm --filter @objectstack/dogfood test` under the lock, VERDICT `command-exit 0`; Test Files 388 passed, 3 skipped (391); Tests 3208 passed, 28 skipped. No failures. ## Acceptance notes - `.changeset/27155-form-view-type-layout-only.md` (pending, 18.3.0) had an "Unchanged" bullet saying `splitDirection`, `drawerSide`, `drawerWidth` and `modalSize` stay declared. All three notes ship in the same 18.3.0 release, so this PR corrects it: only `modalSize` stays declared (the console reads it for its record dialog), `splitDirection` (#27159) and `drawerSide` / `drawerWidth` (#29012) retire from the form view in the same release, and the React `ObjectForm` block keeps the drawer pair as its own props. This is a DELIBERATE CORRECTION of a pending release note: `check-empty-changeset` exits 1 on it by design, and `Check Changeset` is not a required context. Do not restore the original sentence and do not add `skip-changeset`. - `ui/packages/types/src/objectql.ts` (the `ObjectFormSchema` key taxonomy docblock) still lists `drawerSide` / `drawerWidth` among the `[spec-aligned]` FormView keys. They are now the block's own props on both sides; a comment only, outside this card's file surface. - `docs/qa/platform-checklist/areas/studio-authoring.json` rows that score the drawer keys as "fail today" now meet a save refusal instead of an inert save; the QA lane re-scores them. - `skills/objectstack-ui/references/react-blocks.md` is the generator-owned `spec-react-blocks` row: this diff regenerates it from `react-blocks.ts` and does not touch `packages/spec/scripts/`. ## Verification - `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` at `8c7bfc30`: 112 derived families, all run; reconciled with `--ran`: "112 derived famil(ies) accounted for — 112 run, 0 NOT-MEASURED (a DERIVED zero)". First pass had six prerequisite exits in the fresh container (`check-plugin-teardown-shape --self-test` needed its pinned commit fetched; `check:doc-formula-expressions`, `check:doc-security-posture`, `check:skill-examples`, `check:dts-closure`, `check:dual-build-cjs-loads` needed built packages); each exit 0 after `turbo run build --filter='./packages/**'` (78/78). - `pnpm --filter @objectstack/spec check:generated` after regeneration: in the gate list, exit 0 (first pass named react-blocks, docs and liveness counts stale; regenerated with `gen:react-blocks`, `gen:docs`, `gen:liveness-counts`). - `node scripts/check-adr-0087-registration.mjs --base origin/main`: "1 declared-breaking changeset(s), each carrying an ADR-0087 disposition … registered form-view-drawer-keys-removed, ui-form-view-drawer-keys-retired (new here: both)". - `node scripts/check-changeset-no-major.mjs --base origin/main --event` on this body: LEVEL AXIS ✓ for `no (narrowing)` + `narrowed`, minor. - `node scripts/check-empty-changeset.mjs --base origin/main`: exit 1 by design at `ffc3fe89` (DELIBERATE CORRECTION of the pending 27155 note, see Acceptance notes; the same red is `Check Changeset` on CI). `--self-test` exit 0. - `node scripts/pm/check-governed-merges.mjs --test` on the 20-path list: "0 of 20 path(s) hit the register after 1 generated-artifact lift(s) … NOT governed"; `react-blocks.md` is a pure regeneration. - Every family CI runs is read from this PR's check-runs. ## Human Minimum - [x] 1. Schemas start as Zod; `packages/spec` holds no runtime logic. - [x] 2. Every name I added uses the casing for its kind. - [x] 3. No formatter ran; `pnpm lint` passes (CI-owned run). - [x] 4. One issue, one branch off an up-to-date `main`, one pull request. - [x] 5. A change that publishes carries a changeset, and both declaration lines are filled in here and in the changeset. - [x] 6. `packages/spec` touched: its generated artifacts are regenerated and committed. - [x] 7. No hand edits to `content/docs/references/`, `packages/*/CHANGELOG.md` or `content/docs/releases/`. - [x] 8. Title, body and comments are in English. - [x] The *Before Submitting* list in CONTRIBUTING.md is done. --- _Generated by [Claude Code](https://claude.ai/code/session_01ADHkmSVA1CYQ5wh8VMGZ5r)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 2f380dd commit b5e7ba5

21 files changed

Lines changed: 709 additions & 65 deletions

‎.changeset/27155-form-view-type-layout-only.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,6 @@ The model: `type` says how the form lays out its sections. Where a form opens is
1818
- **FROM → TO.** `type: 'split'` → `type: 'tabbed'` (one tab per section) or delete the value for `simple`; delete each section's `pane` and the form's `splitSize` / `splitResizable`; declare `subforms` to edit child records beside the parent. `type: 'drawer'` or `type: 'modal'` → delete the value for `simple`, or write the layout you want. A list opens a clicked record as its `navigation.mode` says (the drawer by default), and the console's New and Edit entries open the record form themselves, sized by the form's `modalSize`.
1919
- **The one-line fix.** Delete the retired value and the three split-only keys. `os migrate meta --from 17` lists the edits for existing sources, and `--write` applies them. A stored `sys_metadata` row is converted when it is read (the `form-view-presentation-types-removed` conversion), so a form view saved with one of the three values keeps loading as a `simple` form.
2020
- **What the parse says.** Each retired value is refused by name with its prescription, for example "'modal' was removed from the form view `type` enum in @objectstack/spec 18.3.0 (ADR-0050) — …", at every form view door (a view's `form` and `formViews.*`, a form view item record, a flattened form overlay) and at `defineStack` as `STACK_SCHEMA_INVALID` / 422. `pane`, `splitSize` and `splitResizable` are refused on every layout. TypeScript rejects each at the authoring site. A misspelt value keeps zod's own message.
21-
- **Unchanged.** `splitDirection`, `drawerSide`, `drawerWidth` and `modalSize` stay declared: the console reads `modalSize` for its record dialog, and the React `ObjectForm` block contract still takes the other three from this schema until its renderer follows.
21+
- **Unchanged.** `modalSize` stays declared: the console reads it for its record dialog. `splitDirection` (#27159) and `drawerSide` / `drawerWidth` (#29012) retire from the form view in the same release; the React `ObjectForm` block keeps the drawer pair as its own props.
2222

2323
The console (`@object-ui/app-shell`): Studio's New View form offers the three form layouts only. It offered all six, and a form view created with `split`, `drawer` or `modal` would now be refused when saved.
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
---
2+
'@objectstack/spec': minor
3+
'@objectstack/skills': patch
4+
---
5+
6+
feat(spec)!: a form view no longer declares `drawerSide` / `drawerWidth`; no form view opens in a drawer, so neither key was ever read there
7+
8+
Clause-②: no (narrowing)
9+
10+
Metadata-protocol: narrowed
11+
12+
Skills-docs: regenerated here — `skills/objectstack-ui/references/react-blocks.md` (`gen:react-blocks`) lists `<ObjectForm>`'s `drawerSide` / `drawerWidth` as binding props from the block's overlay instead of data props from the form view schema, with the same types; `drawerWidth`'s description drops the form view's `[DEPRECATED → size buckets]` tag (the block's drawer has no size bucket) and says the value is the drawer's width, or its height from the top or bottom edge; no hand-written file under `skills/**` teaches either key on a form view (a `git grep` of `skills/` names only that contract and `rules/record-page.md`'s list-drawer width on `navigation`, which this does not touch).
13+
14+
<!-- adr-0087: registered form-view-drawer-keys-removed, ui-form-view-drawer-keys-retired -->
15+
16+
**BREAKING** accept-set narrowing on the form view surface (`@objectstack/spec`), ADR-0049 enforce-or-remove.
17+
18+
`type: 'drawer'` left the form view earlier in this release, so no form view opens in a drawer. No form-view surface read the two keys either: the console's form page, its New and Edit dialogs, the record form page and Studio all ignored them, so a form view saved with `drawerSide: 'left', drawerWidth: '480px'` was accepted, served and drawn exactly as one without them.
19+
20+
- **FROM → TO.** `form: { …, drawerSide, drawerWidth }` (and `formViews.<key>`, a form view item's `config`) → `form: { … }`. Nothing on the form view replaces them. A list opens a clicked record in its drawer (`navigation.mode`) and sizes it with the `navigation.size` bucket; a React page that opens a form in a drawer writes the props on the block, `ObjectForm` with `formType='drawer'`.
21+
- **The one-line fix.** Delete `drawerSide` and `drawerWidth` from the form view. `os migrate meta --from 17` lists the edits for existing sources, and `--write` applies them. A stored `sys_metadata` row is converted when it is read (the `form-view-drawer-keys-removed` conversion), so a form view saved with the keys keeps loading, and nothing a reader sees changes.
22+
- **What the parse says.** "`view.form.drawerSide` was removed in @objectstack/spec 18.3.0 (ADR-0049) — no form view opens in a drawer, so no form view ever read it. …" (and the same for `drawerWidth`), at every form view door (a view's `form` and `formViews.*`, a form view item record, a flattened form overlay) and at `defineStack` as `STACK_SCHEMA_INVALID` / 422. TypeScript rejects the keys at the authoring site.
23+
- **Unchanged.** The React `ObjectForm` block still takes `drawerSide` / `drawerWidth` for the drawer it opens with `formType='drawer'`: the react-tier contract now declares them on the block itself, with the same types and descriptions. The `object-form` page block keeps both in its own props. `modalSize` stays on the form view; the console's record dialog reads it.

‎content/docs/references/api/protocol.mdx‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1916,8 +1916,8 @@ The published metadata item body, opaque by ruling (1C). Shape is the item's own
19161916
| **splitDirection** | `never` | optional | [REMOVED] `view.form.splitDirection` was removed in @objectstack/spec 18.3.0 (ADR-0050) — it set the pane orientation of a split form, and the split form renderer retired in the same release, so no form draws panes. Delete the key. Run `os migrate meta --from 17` to list the mechanical edits for existing sources; `--write` applies the ones it can prove, and you apply the rest by hand. |
19171917
| **splitSize** | `never` | optional | [REMOVED] `view.form.splitSize` was removed in @objectstack/spec 18.3.0 (ADR-0050) — it sized the primary pane of a `type: 'split'` form, and `split` left the form view `type` in the same release, so no form view draws panes. Delete the key. Run `os migrate meta --from 17` to list the mechanical edits for existing sources; `--write` applies the ones it can prove, and you apply the rest by hand. |
19181918
| **splitResizable** | `never` | optional | [REMOVED] `view.form.splitResizable` was removed in @objectstack/spec 18.3.0 (ADR-0050) — it made the panes of a `type: 'split'` form resizable, and `split` left the form view `type` in the same release, so no form view draws panes. Delete the key. Run `os migrate meta --from 17` to list the mechanical edits for existing sources; `--write` applies the ones it can prove, and you apply the rest by hand. |
1919-
| **drawerSide** | `Enum<'top' \| 'bottom' \| 'left' \| 'right'>` | optional | Edge the drawer container opens from, when the React `ObjectForm` block opens this form with formType 'drawer' |
1920-
| **drawerWidth** | `string` | optional | [DEPRECATED → size buckets] Width of the drawer container the React `ObjectForm` block opens with formType 'drawer', e.g. "480px". A pixel width cannot be chosen without knowing the client viewport — the renderer derives it. |
1919+
| **drawerSide** | `never` | optional | [REMOVED] `view.form.drawerSide` was removed in @objectstack/spec 18.3.0 (ADR-0049) — no form view opens in a drawer, so no form view ever read it. Delete the key: a list opens a clicked record in its drawer (`navigation.mode`), and the React `ObjectForm` block keeps its own `drawerSide` prop for the drawer it opens with `formType='drawer'`. Run `os migrate meta --from 17` to list the mechanical edits for existing sources; `--write` applies the ones it can prove, and you apply the rest by hand. |
1920+
| **drawerWidth** | `never` | optional | [REMOVED] `view.form.drawerWidth` was removed in @objectstack/spec 18.3.0 (ADR-0049) — no form view opens in a drawer, so no form view ever read it, and a pixel width cannot be chosen without knowing the client viewport. Delete the key: a list's record drawer takes its starting width from the `navigation.size` bucket, and the React `ObjectForm` block keeps its own `drawerWidth` prop for the drawer it opens. Run `os migrate meta --from 17` to list the mechanical edits for existing sources; `--write` applies the ones it can prove, and you apply the rest by hand. |
19211921
| **modalSize** | `Enum<'sm' \| 'default' \| 'lg' \| 'xl' \| 'full'>` | optional | Size bucket of the dialog a caller opens this form in: the console's New / Edit dialog, or the modal container of the React `ObjectForm` block (formType 'modal') |
19221922
| **data** | `{ provider: 'object'; object: string } \| { provider: 'value'; items: any[] } \| { provider: 'schema'; schemaId: string; schema?: Record<string, any> }` | optional | Data source configuration (defaults to "object" provider) |
19231923
| **sections** | `{ name?: string; label?: string \| Record<string, string>; description?: string; collapsible?: boolean; … }[]` | optional | |
@@ -1995,8 +1995,8 @@ The published metadata item body, opaque by ruling (1C). Shape is the item's own
19951995
| **splitDirection** | `never` | optional | [REMOVED] `view.form.splitDirection` was removed in @objectstack/spec 18.3.0 (ADR-0050) — it set the pane orientation of a split form, and the split form renderer retired in the same release, so no form draws panes. Delete the key. Run `os migrate meta --from 17` to list the mechanical edits for existing sources; `--write` applies the ones it can prove, and you apply the rest by hand. |
19961996
| **splitSize** | `never` | optional | [REMOVED] `view.form.splitSize` was removed in @objectstack/spec 18.3.0 (ADR-0050) — it sized the primary pane of a `type: 'split'` form, and `split` left the form view `type` in the same release, so no form view draws panes. Delete the key. Run `os migrate meta --from 17` to list the mechanical edits for existing sources; `--write` applies the ones it can prove, and you apply the rest by hand. |
19971997
| **splitResizable** | `never` | optional | [REMOVED] `view.form.splitResizable` was removed in @objectstack/spec 18.3.0 (ADR-0050) — it made the panes of a `type: 'split'` form resizable, and `split` left the form view `type` in the same release, so no form view draws panes. Delete the key. Run `os migrate meta --from 17` to list the mechanical edits for existing sources; `--write` applies the ones it can prove, and you apply the rest by hand. |
1998-
| **drawerSide** | `Enum<'top' \| 'bottom' \| 'left' \| 'right'>` | optional | Edge the drawer container opens from, when the React `ObjectForm` block opens this form with formType 'drawer' |
1999-
| **drawerWidth** | `string` | optional | [DEPRECATED → size buckets] Width of the drawer container the React `ObjectForm` block opens with formType 'drawer', e.g. "480px". A pixel width cannot be chosen without knowing the client viewport — the renderer derives it. |
1998+
| **drawerSide** | `never` | optional | [REMOVED] `view.form.drawerSide` was removed in @objectstack/spec 18.3.0 (ADR-0049) — no form view opens in a drawer, so no form view ever read it. Delete the key: a list opens a clicked record in its drawer (`navigation.mode`), and the React `ObjectForm` block keeps its own `drawerSide` prop for the drawer it opens with `formType='drawer'`. Run `os migrate meta --from 17` to list the mechanical edits for existing sources; `--write` applies the ones it can prove, and you apply the rest by hand. |
1999+
| **drawerWidth** | `never` | optional | [REMOVED] `view.form.drawerWidth` was removed in @objectstack/spec 18.3.0 (ADR-0049) — no form view opens in a drawer, so no form view ever read it, and a pixel width cannot be chosen without knowing the client viewport. Delete the key: a list's record drawer takes its starting width from the `navigation.size` bucket, and the React `ObjectForm` block keeps its own `drawerWidth` prop for the drawer it opens. Run `os migrate meta --from 17` to list the mechanical edits for existing sources; `--write` applies the ones it can prove, and you apply the rest by hand. |
20002000
| **modalSize** | `Enum<'sm' \| 'default' \| 'lg' \| 'xl' \| 'full'>` | optional | Size bucket of the dialog a caller opens this form in: the console's New / Edit dialog, or the modal container of the React `ObjectForm` block (formType 'modal') |
20012001
| **data** | `{ provider: 'object'; object: string } \| { provider: 'value'; items: any[] } \| { provider: 'schema'; schemaId: string; schema?: Record<string, any> }` | optional | Data source configuration (defaults to "object" provider) |
20022002
| **sections** | `{ name?: string; label?: string \| Record<string, string>; description?: string; collapsible?: boolean; … }[]` | optional | |

0 commit comments

Comments
 (0)