Repository navigation
Commit a33fce2
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
- .changeset
- content/docs
- frontend/plugins
- references
- api
- ui
- ui/components
- docs/qa/platform-checklist/areas
- packages/spec
- authorable-surface
- liveness
- state-counts
- src
- conversions
- migrations/entries
- retired-keys
- semantic
- ui
- scripts
- skills/objectstack-ui/references
- ui
- apps/console/src
- __tests__
- components
- packages
- app-shell/src/views
- metadata-admin/previews
- i18n/src/namespaces/studio
- plugin-form
- src
- __tests__
- types/src
- __tests__
- zod
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
74 | 74 | | |
75 | 75 | | |
76 | 76 | | |
77 | | - | |
78 | | - | |
| 77 | + | |
79 | 78 | | |
80 | 79 | | |
81 | 80 | | |
82 | 81 | | |
83 | 82 | | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
84 | 96 | | |
85 | 97 | | |
86 | 98 | | |
| |||
103 | 115 | | |
104 | 116 | | |
105 | 117 | | |
106 | | - | |
| 118 | + | |
107 | 119 | | |
108 | 120 | | |
109 | 121 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1906 | 1906 | | |
1907 | 1907 | | |
1908 | 1908 | | |
1909 | | - | |
| 1909 | + | |
1910 | 1910 | | |
1911 | 1911 | | |
1912 | | - | |
1913 | | - | |
1914 | | - | |
| 1912 | + | |
| 1913 | + | |
| 1914 | + | |
1915 | 1915 | | |
1916 | 1916 | | |
1917 | 1917 | | |
| |||
1985 | 1985 | | |
1986 | 1986 | | |
1987 | 1987 | | |
1988 | | - | |
| 1988 | + | |
1989 | 1989 | | |
1990 | 1990 | | |
1991 | | - | |
1992 | | - | |
1993 | | - | |
| 1991 | + | |
| 1992 | + | |
| 1993 | + | |
1994 | 1994 | | |
1995 | 1995 | | |
1996 | 1996 | | |
| |||
0 commit comments