Skip to content

Commit a33fce2

Browse files
feat(plugin-form,spec)!: ObjectForm lays the form out, the object-form block opens drawer/modal, split retires (#27305)
<!-- claude-projects-attribution: {"github_login":"os-warren"} --> _Requested by **Warren** · [project thread](https://claude.ai/code/project/chan_01U5RdnAAmkSQmZbqh6FtqZ8?thread=cmsg_01U5RdnAAmkSQmZbqh6FtqZ8CqY3XxuBymEc8yx73EJkMq)_ Fixes #27159 Clause-②: no (narrowing) Metadata-protocol: narrowed (the `object-form` block's `formType` refuses `split`; its `splitDirection`, `splitSize`, `splitResizable` and `sections[].pane`, the `object-master-detail-form` block's `sections[].pane`, and `FormViewSchema.splitDirection`, are tombstones) Skills-docs: `skills/objectstack-ui/references/react-blocks.md` regenerated by `gen:react-blocks` (the React `ObjectForm` contract drops `split` and `splitDirection`); no hand edit under `skills/**` ## 维护者速读 - 改了什么:`ObjectForm` 只负责表单布局(simple / tabbed / wizard),抽屉和弹窗由新的 `ObjectFormContainer` 承接,`object-form` 区块渲染器在 `formType` 为 drawer / modal 时走它;`formType: 'split'`、`SplitForm` 以及 split 专用键全部退役。 - 为什么改:ADR-0050(裁定 6464210455,A′)规定布局与容器分离,#27155 已收窄表单视图的 `type`,本卡是渲染器这一半。 - 风险与回滚:区块的 drawer / modal 行为不变(同一段代码搬家);直接挂载 `ObjectForm` 并写 `formType: "drawer"` 的宿主现在得到内联表单。回滚即还原本 PR,18.3.0 尚未发布,转换器和 tombstone 一起撤回即可。 - 先看:`ui/packages/plugin-form/src/ObjectFormContainer.tsx`、`index.tsx` 的区块分流、`packages/spec/src/ui/component.zod.ts` 的 tombstone、`conversions/registry.ts` 新增的 `convertBlock`。 - 两分钟验证:`pnpm --dir ui exec vitest run packages/plugin-form/src/__tests__/objectFormContainer-27159.test.tsx`,再跑 `cd packages/spec && npx vitest run src/ui/form-view-type-layout-retirement.test.ts`。 - 需要你做的:等合同复核 PASS 与座位 ACCEPT 后再审批;#27153 上的 drawerSide / drawerWidth 结论见下文 Acceptance notes。 ## What changes ADR-0050 Decision 4, the renderer half of #27155: a form's `formType` is its layout, and the container belongs to the caller. On the `object-form` block, the block itself is that caller. - **`@object-ui/plugin-form`.** `ObjectForm` drops its `split`, `drawer` and `modal` arms and keeps the three layouts (and master-detail routing). The drawer and modal arms move unchanged into the new `ObjectFormContainer.tsx`, which shares `ObjectForm`'s schema preparation through the extracted `usePreparedFormSchema` hook. The registered `object-form` renderer sends `formType: 'drawer' | 'modal'` to `ObjectFormContainer` and everything else to `ObjectForm`. `SplitForm.tsx` is deleted and `SplitForm` / `SplitFormProps` / `SplitFormSchema` leave the exports. The block's published inputs drop `split` and the three split keys. The section `pane` reader (`SECTION_LAYOUT_KEYS`) goes, and the `#6237` diagnostic's remedy no longer names `split`. - **`@objectstack/spec`.** The `object-form` block's `formType` is `enumWithRetiredValues(['simple','tabbed','wizard','drawer','modal'], …)`, so `split` is refused by name with a prescription. `splitDirection`, `splitSize`, `splitResizable` and the block section's `pane` are `retiredKey()` tombstones, and so is `FormViewSchema.splitDirection`, which lost its last reader with `SplitForm`. The React contract (`react-blocks.ts`) drops `split` and `splitDirection`. The `.describe()` strings of `drawerSide`, `drawerWidth`, `modalSize` and `modalCloseButton` now name the block's drawer and modal containers. - **Retirement kit, absorbed into #27155's entry.** `@objectstack/spec` is 18.2.0 on `main`, so 18.3.0 is unreleased and the skill's same-major rule puts this in the existing D2 conversion `form-view-presentation-types-removed`. It now strips `splitDirection` from every form payload and has a new `convertBlock` over `object-form` page blocks (regions, slots and container nesting): it deletes `formType: 'split'`, strips the three keys and every section `pane`, and leaves `drawer` / `modal` alone. The D3 entry `ui-form-view-type-layout-only` is widened to match. Four new `RETIRED_KEYS_BY_MAJOR` entry files cover `ui/FormView:splitDirection` and `ui/ObjectFormProps:{splitDirection,splitSize,splitResizable}`. Also updated: the liveness rows (`splitDirection` is now `dead`/REMOVED; the `drawerSide` / `drawerWidth` notes cite the container), the removal-version pins, and the regenerated references, authorable surface and state counts. - **`@object-ui/types`.** `ObjectFormSchema.formType` drops `split`. The three split keys stay declared, but as the spec's tombstones by reference (the `defaultFilters` precedent), so the parity census still pairs them. The section `pane` member is removed. - **Console and Studio.** The page-block inspector no longer offers `Split` (`block-config.ts`, and the studio string `engine.inspector.pageBlock.option.formType.split` is removed from en and zh). `form-preview.ts` and `RecordFormPage.tsx` drop the dead `'split'` literals and the split keys. `FormPage.tsx`'s `FORM_SPEC_TYPES` is the three layouts. - **Docs.** The plugin-form README and `content/docs/frontend/plugins/plugin-form.mdx` lose the SplitForm and `pane` passages, and the page gains "Where an `object-form` block opens". The `ui/content/docs` pages this PR first edited (`plugins/plugin-form.mdx`, `api/schema-reference.md`) were deleted on main by #27329, so the merge takes the deletion. The #27155 changeset is left as written (a changeset on the base cannot change); this PR's changeset carries the BREAKING FROM → TO and a "Supersedes" bullet correcting #27155's `splitDirection` line. The `object-master-detail-form` block's `sections[].pane` is tombstoned too (the shared section shape) and the D2 conversion strips it there (contract review 6485040701, should-fix 1). ## Tests - New: `ui/packages/plugin-form/src/__tests__/objectFormContainer-27159.test.tsx`. Through `SchemaRenderer`, a `drawer` / `modal` block opens a dialog that holds the form, and a `tabbed` block renders inline. A `drawer` / `modal` node handed straight to `ObjectForm` renders inline, so the container is the caller's (this fails on `main`, where `ObjectForm` opened the drawer). The #1890 pin: a tabbed layout inside the modal container still draws its tabs. CONTROL: a layout handed to the container falls back to the inline form. - Spec: `form-view-type-layout-retirement.test.ts` gains an `object-form` block describe. It pins the vocabulary, the `split` refusal with prescription, a CONTROL that `drawer` / `modal` parse with their keys, the three key tombstones on every `formType`, the section `pane` tombstone, the `RETIRED_KEYS_BY_MAJOR` rows, a tsc pin and a stored-page conversion. The tree walk now also judges any `formType: 'split'`. `splitDirection` joins the form-view tombstone rows and the stored-view conversion pin. - About 20 plugin-form suites that mounted `drawer` / `modal` through `ObjectForm` now mount `ObjectFormContainer`, the block's own route. Split rows are removed from every arms/layout matrix. The `sectionFaultCarry` site census moves 5 → 2 + 2. ## Acceptance notes - **On #27153.** Measured: `drawerSide` and `drawerWidth` keep a live reader. The `object-form` block's drawer container reaches `DrawerForm` (`ObjectFormContainer.tsx` → `DrawerForm.tsx`, which reads `drawerSide` and `drawerWidth`). So neither key is retired here, and the enforce-or-remove question for form views stays open on #27153. `modalSize` is also read by the console's record dialog on every layout. - Premise partly disproved and resolved with the seat: `AppContent.tsx` and `useActionModal.tsx` already mount `ModalForm` directly, so they needed no change. - Not in this PR (outside the claimed paths, comment-only): `SplitForm` mentions in `ui/packages/types/src/data.ts`, `packages/metadata-core/src/form-predicate-root-policy.ts`, `content/docs/protocol/objectui/layout-dsl.mdx` and `ui/packages/app-shell/README.md`. The `object-master-detail-form` prescriptions for `drawer` / `modal` still say "portal dialog". ## Verification All runs below are local, on this branch. The spec and ui suites and dogfood ran on the merged head `6f5071c3`, with 22 commits of `main` merged and the reference docs regenerated. - `node scripts/pm/dispatch-gates.mjs --commands` derived 122 commands, and all 122 exit 0. `--ran` reconciles 122 derived, 122 run, 0 unrun. Three of them first refused on a missing prerequisite and passed after it was provided: `check-plugin-teardown-shape --self-test` needed the pinned fixture fetched (shallow clone), `check:skill-examples` needed a `client-react` build, and `check:dual-build-cjs-loads` needed every dist. One gate found a real problem, `doc-version-claims`, because the docs named a version literal; the literal is removed. - `pnpm --filter @objectstack/spec test`: 749 files and 22377 tests pass. `check:generated` is current. - ui vitest over plugin-form, types, i18n, the console FormPage suites, the app-shell previews and RecordFormPage: 883 files and 16460 tests pass (14 skipped). - `type-check` passes for `@object-ui/plugin-form`, `types`, `app-shell`, `console` and `i18n`, and `pnpm --dir ui run type-check:scripts` passes. - `node scripts/check-sdui-manifest.mjs` passes after `gen-sdui-manifest-node.mjs` regenerated the manifest; the diff is the block's `formType` enum and the three removed inputs. `node scripts/check-platform-checklist.mjs --changed-from origin/main` passes. - Dogfood battery (`packages/qa/dogfood`, `pnpm test`) after rebuilding the closure: 348 files and 2806 tests pass. The CI Dogfood Regression Gate does not run on pull requests, so this local run is the evidence for that gate. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01JQwxbWHWPRD5rZXeY69YvL --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 4145210 commit a33fce2

102 files changed

Lines changed: 1246 additions & 1496 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
---
2+
'@objectstack/spec': minor
3+
'@objectstack/skills': patch
4+
'@object-ui/plugin-form': minor
5+
'@object-ui/types': minor
6+
'@object-ui/i18n': patch
7+
'@object-ui/console': patch
8+
---
9+
10+
feat(spec,plugin-form)!: `ObjectForm` lays a form out and no longer picks its container; the `object-form` block drops `formType: 'split'` and `SplitForm` retires, while the block keeps opening `drawer` and `modal` forms itself
11+
12+
Clause-②: no (narrowing)
13+
14+
Metadata-protocol: narrowed (the `object-form` block's `formType` refuses `split`; its `splitDirection`, `splitSize`, `splitResizable` and `sections[].pane`, the `object-master-detail-form` block's `sections[].pane`, and `FormViewSchema.splitDirection`, are tombstones)
15+
16+
<!-- adr-0087: not-required (already-registered form-view-presentation-types-removed, ui-form-view-type-layout-only) 18.3.0 is unreleased, so this change widens those two entries in place: the conversion now strips splitDirection and reaches object-form page blocks, four new RETIRED_KEYS_BY_MAJOR rows record the tombstoned keys, and the D3 entry names the block -->
17+
18+
**BREAKING** accept-set narrowing on the `object-form` page block and the form view (`@objectstack/spec`), and a removed export (`@object-ui/plugin-form`). ADR-0050, the renderer half of #27155.
19+
20+
The model: a form's `formType` says how it lays out its sections. Where it opens is the caller's. On the `object-form` block the caller is the block itself, so `drawer` and `modal` stay there as the two containers the block opens; `split` drew two panes and had no other reader, so it leaves with its renderer.
21+
22+
- **FROM → TO (block).** `formType: 'split'` → `formType: 'tabbed'` (one tab per section) or delete the value for `simple`; delete each section's `pane` and the block's `splitDirection` / `splitSize` / `splitResizable`. To edit child records beside the parent, use an `object-master-detail-form` block. `formType: 'drawer'` and `formType: 'modal'` are unchanged. The `object-master-detail-form` block's parent `sections` share the shape, so delete each section's `pane` there too.
23+
- **FROM → TO (form view).** `splitDirection` on a form view → delete it. It joins `splitSize` and `splitResizable`, which left in the same release.
24+
- **The one-line fix.** Delete the retired value and keys. `os migrate meta --from 17` lists the edits for existing sources, and `--write` applies them. A stored page or view row is converted when it is read (the `form-view-presentation-types-removed` conversion now reaches `object-form` page blocks, the section `pane` of `object-master-detail-form` blocks, and `splitDirection` too), so a block saved with `split` keeps loading as a `simple` form.
25+
- **What the parse says.** `formType: 'split'` is refused by name with its prescription ("'split' was removed from the `object-form` `formType` enum in @objectstack/spec 18.3.0 (ADR-0050) — …"); each tombstoned key is refused on every `formType`. TypeScript rejects each at the authoring site.
26+
- **`@object-ui/plugin-form`.** `ObjectForm` renders the `simple`, `tabbed` and `wizard` layouts only; a `formType` of `drawer` or `modal` on a node handed straight to `<ObjectForm>` now renders the inline form, and the host opens its own drawer or dialog around it (the console's New and Edit dialogs already mount `ModalForm` themselves). The registered `object-form` block routes `drawer` and `modal` through the new internal `ObjectFormContainer`, which hands the node to `DrawerForm` or `ModalForm` as before. `SplitForm`, `SplitFormProps` and `SplitFormSchema` are no longer exported, and the block no longer publishes the `splitDirection`, `splitSize` and `splitResizable` inputs. FROM `import { SplitForm } from '@object-ui/plugin-form'` → TO a `TabbedForm`, or the `form` renderer's `fieldPanes` for a host that composes panes itself.
27+
- **`@object-ui/types`.** `ObjectFormSchema.formType` is `'simple' | 'tabbed' | 'wizard' | 'drawer' | 'modal'`, and its `splitDirection` / `splitSize` / `splitResizable` are the spec's tombstones by reference; the section `pane` member is gone.
28+
- **Console.** Studio's page-block inspector no longer offers `Split` for an `object-form` (its `engine.inspector.pageBlock.option.formType.split` string is removed from `@object-ui/i18n`), the record page passes no split keys, and a view whose `type` is not one of the three form layouts is no longer taken for a form (`@object-ui/console`).
29+
- **Supersedes one line of the form view `type` entry (#27155).** That entry says `splitDirection` stays declared; in this release it leaves too.
30+
- **Unchanged.** `drawerSide`, `drawerWidth`, `modalSize` and `modalCloseButton` keep their readers: the block's drawer and modal containers. The enforce-or-remove question for `drawerSide` / `drawerWidth` on form views stays on #27153.

‎content/docs/frontend/plugins/plugin-form.mdx‎

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,13 +74,25 @@ its `schema`, but never a `dataSource` — that travels on
7474
one or wraps the component the same way.
7575

7676
The components are on the package's export surface — `ObjectForm`,
77-
`TabbedForm`, `WizardForm`, `SplitForm`, `DrawerForm`, `ModalForm`,
78-
`EmbeddableForm`, `MasterDetailForm`, `LineItemsPanel`, `FormAnalytics`,
77+
`TabbedForm`, `WizardForm`, `DrawerForm`, `ModalForm`, `EmbeddableForm`, `MasterDetailForm`, `LineItemsPanel`, `FormAnalytics`,
7978
`FormSectionContainer` — alongside the layout helpers (`applyAutoLayout`,
8079
`inferColumns`, `filterCreateModeFields`, …) and the per-container schema types
8180
(`TabbedFormSchema`, `WizardFormSchema`, `ModalFormSchema`, …). There is no
8281
aggregate map among them.
8382

83+
### Where an `object-form` block opens
84+
85+
An `object-form`'s `formType` is the form's layout — `simple` (the default),
86+
`tabbed` or `wizard` — or, on the block, the container the block opens it in:
87+
`drawer` or `modal` (ADR-0050). `ObjectForm` only lays the form out; the block
88+
renderer is the caller that supplies the container, handing the node to
89+
`DrawerForm` (with `drawerSide` / `drawerWidth`) or `ModalForm` (with
90+
`modalSize` / `modalCloseButton`). A host that renders `<ObjectForm>` directly,
91+
or registers it under a key of its own as above, gets the inline form and opens
92+
its own drawer or dialog around it. The `split` form type and its `SplitForm`
93+
renderer were removed (ADR-0050): use `tabbed`, or an
94+
`object-master-detail-form` block to edit child records beside the parent.
95+
8496
## What an edit save writes
8597

8698
Which fields an edit save sends, and which fields and line-item actions a caller is offered, is the same in the SDK and the Console. It is documented under [What an edit save writes](/docs/ui/forms#what-an-edit-save-writes).
@@ -103,7 +115,7 @@ The plugin supports these field types:
103115
`@object-ui/types` alongside the rest of the JSON contract. This package imports
104116
them and does not re-export them — the form types on its own entry are the
105117
per-container ones (`TabbedFormSchema`, `WizardFormSchema`, `ModalFormSchema`,
106-
`SplitFormSchema`, `DrawerFormSchema`, `MasterDetailFormSchema`).
118+
`DrawerFormSchema`, `MasterDetailFormSchema`).
107119

108120
```typescript
109121
import type { FormSchema, FormField } from '@object-ui/types';

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

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1906,12 +1906,12 @@ The published metadata item body, opaque by ruling (1C). Shape is the item's own
19061906
| **tabPosition** | `Enum<'top' \| 'bottom' \| 'left' \| 'right'>` | optional | Tab strip position (tabbed forms) |
19071907
| **allowSkip** | `boolean` | optional | Wizard step-gate opt-out: allow entering a later step without submitting the one before it. Navigation freedom, NOT a validation exemption — the final submit still re-validates every step and returns to the first failing one. Default (absent/false): steps unlock in array order as each prior step submits validly. UI admission only, never authorization. |
19081908
| **showStepIndicator** | `boolean` | optional | Show the wizard step indicator (renderer default: shown). Step progress (completed/current/upcoming/invalid) is derived from the step gate — this boolean is the only authorable progress surface. |
1909-
| **splitDirection** | `Enum<'horizontal' \| 'vertical'>` | optional | Split orientation (split forms) |
1909+
| **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. |
19101910
| **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. |
19111911
| **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. |
1912-
| **drawerSide** | `Enum<'top' \| 'bottom' \| 'left' \| 'right'>` | optional | Drawer side (drawer forms) |
1913-
| **drawerWidth** | `string` | optional | [DEPRECATED → size buckets] Drawer width, e.g. "480px". A pixel width cannot be chosen without knowing the client viewport — the renderer derives it. |
1914-
| **modalSize** | `Enum<'sm' \| 'default' \| 'lg' \| 'xl' \| 'full'>` | optional | Modal size (modal forms) |
1912+
| **drawerSide** | `Enum<'top' \| 'bottom' \| 'left' \| 'right'>` | optional | Edge the drawer container opens from, when the React `ObjectForm` block opens this form with formType 'drawer' |
1913+
| **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. |
1914+
| **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') |
19151915
| **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) |
19161916
| **sections** | `{ name?: string; label?: string \| Record<string, string>; description?: string; collapsible?: boolean; … }[]` | optional | |
19171917
| **groups** | `{ name?: string; label?: string \| Record<string, string>; description?: string; collapsible?: boolean; … }[]` | optional | [LEGACY ALIAS → `sections`] Accepted for back-compat and folded onto `sections` at parse; `sections` wins when both are present. Prefer `sections`. |
@@ -1985,12 +1985,12 @@ The published metadata item body, opaque by ruling (1C). Shape is the item's own
19851985
| **tabPosition** | `Enum<'top' \| 'bottom' \| 'left' \| 'right'>` | optional | Tab strip position (tabbed forms) |
19861986
| **allowSkip** | `boolean` | optional | Wizard step-gate opt-out: allow entering a later step without submitting the one before it. Navigation freedom, NOT a validation exemption — the final submit still re-validates every step and returns to the first failing one. Default (absent/false): steps unlock in array order as each prior step submits validly. UI admission only, never authorization. |
19871987
| **showStepIndicator** | `boolean` | optional | Show the wizard step indicator (renderer default: shown). Step progress (completed/current/upcoming/invalid) is derived from the step gate — this boolean is the only authorable progress surface. |
1988-
| **splitDirection** | `Enum<'horizontal' \| 'vertical'>` | optional | Split orientation (split forms) |
1988+
| **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. |
19891989
| **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. |
19901990
| **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. |
1991-
| **drawerSide** | `Enum<'top' \| 'bottom' \| 'left' \| 'right'>` | optional | Drawer side (drawer forms) |
1992-
| **drawerWidth** | `string` | optional | [DEPRECATED → size buckets] Drawer width, e.g. "480px". A pixel width cannot be chosen without knowing the client viewport — the renderer derives it. |
1993-
| **modalSize** | `Enum<'sm' \| 'default' \| 'lg' \| 'xl' \| 'full'>` | optional | Modal size (modal forms) |
1991+
| **drawerSide** | `Enum<'top' \| 'bottom' \| 'left' \| 'right'>` | optional | Edge the drawer container opens from, when the React `ObjectForm` block opens this form with formType 'drawer' |
1992+
| **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. |
1993+
| **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') |
19941994
| **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) |
19951995
| **sections** | `{ name?: string; label?: string \| Record<string, string>; description?: string; collapsible?: boolean; … }[]` | optional | |
19961996
| **groups** | `{ name?: string; label?: string \| Record<string, string>; description?: string; collapsible?: boolean; … }[]` | optional | [LEGACY ALIAS → `sections`] Accepted for back-compat and folded onto `sections` at parse; `sections` wins when both are present. Prefer `sections`. |

0 commit comments

Comments
 (0)