You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit e2899f6
Browse filesBrowse the repository at this point in the historyBrowse files
feat(spec): declare 14 registry-published ObjectForm props on the react-blocks tier (#9392) (#9728)
Catch-up with the registry inputs objectui#4648/#4901 published on the
object-form registration: 14 keys are declared on the react-blocks
ObjectForm overlay (descriptions adapted from objectui's registration),
and 3 are baselined with recorded reasons per the maintainer's 2026-08-18
mixed-disposition ruling — initialData (alias of initialValues), mobile
(internal override), navigateOnSuccess (parked pending the action-success-
navigation family; revisit tracked on #9392).
The parity baseline is regenerated via --update, which also snapshots the
six SDUI object-* blocks (#7751) as additive coverage; the clean-baseline
test now derives that tail from the committed file.
Claude-Session: https://claude.ai/code/session_016D9wdJR14KKCxz1WgdAzcw
Co-authored-by: Claude <noreply@anthropic.com>
Declare 14 registry-published props on the react-tier `ObjectForm` block (ADR-0082 D4 declaration parity, #9392): `modalCloseButton`, `contentLayout`, `confirmOnDiscard`, `customFields`, `readOnly`, `submitText`, `cancelText`, `nextText`, `prevText`, `showSubmit`, `showCancel`, `showReset`, `successMessage`, `resetOnSuccess` — the inputs objectui#4648/objectui#4901 published on the `object-form` registration that the react-blocks channel of the spec never declared. Descriptions are adapted from objectui's own registration; the generated react-blocks contract (`skills/objectstack-ui`) picks them up.
6
+
7
+
Three registry inputs are deliberately NOT declared and are instead baselined with recorded reasons (maintainer ruling 2026-08-18 on #9392): `initialData` (alias spelling of `initialValues` — aliases are not promoted into spec), `mobile` (internal presentation override, not an authoring surface), and `navigateOnSuccess` (parked pending the action-success-navigation family ruling; revisit tracked on #9392).
Copy file name to clipboardExpand all lines: packages/spec/react-declaration-parity.baseline.json
+35-1Lines changed: 35 additions & 1 deletion
Original file line number
Diff line number
Diff line change
@@ -1,8 +1,18 @@
1
1
{
2
2
"_comment": "Accepted spec↔registry DECLARATION-PARITY baseline (react blocks). Per block: the registry-only input set (the registry config declares it, the spec does not) and whether the block is missing. Regenerate with: MANIFEST=… check:react-declaration-parity --baseline <this> --update. The ratchet flags only NEW registry-only inputs or newly-missing blocks. It compares two declarations and inspects no renderer, so a prop both sides declare and nothing reads records as agreement here (#4413/#4472).",
3
+
"_acceptedReasons": {
4
+
"_note": "Hand-maintained record of WHY each accepted registry-only input is deliberately not declared in spec (maintainer ruling 2026-08-18 on #9392). `--update` rewrites this file and drops this block — re-add it (updated) whenever the accepted set changes; an entry with no reason here is an accept nobody ruled.",
5
+
"ObjectForm.initialData": "Alias spelling of `initialValues` (the drawer/modal presentations read it first). Aliases are not promoted into spec, per the alias-convergence direction.",
6
+
"ObjectForm.mobile": "Internal presentation override, not an authoring surface.",
7
+
"ObjectForm.navigateOnSuccess": "Explicitly parked pending the 'action success navigation' family ruling (#9474/#9566, objectui#5034) — declaring it now risks freezing a spelling that family is shaping; revisit when `onSuccess` lands. The family landed on 2026-08-18 (PR #9601); the revisit is tracked on #9392."
{name: 'recordId',type: 'string | number',kind: 'controlled',description: 'Which record to load (edit/view). The hook for master/detail.'},
200
200
{name: 'fields',type: 'string[]',kind: 'binding',description: 'Limit/order the fields shown (defaults to the object form fields).'},
201
201
{name: 'initialValues',type: 'Record<string, any>',kind: 'binding',description: 'Prefill values in create mode.'},
202
+
// #9392 — catch-up with the registry inputs objectui#4648/#4901 published
203
+
// for keys ObjectFormRenderer already read (descriptions adapted from the
204
+
// `object-form` registration in objectui `plugin-form/src/index.tsx`, the
205
+
// one registration both parity channels enumerate). Published from the
206
+
// OVERLAY, not FormViewSchema `dataProps`, for the same reason as
207
+
// `<ObjectChart drillDown>` above: FormViewSchema is also what a
208
+
// declarative form VIEW parses, and only the react/registry tier
209
+
// measurably reads these. Three registry inputs are deliberately NOT
210
+
// declared (baselined in react-declaration-parity.baseline.json):
211
+
// `initialData` (alias spelling of `initialValues` — aliases are not
212
+
// promoted into spec), `mobile` (internal override, not an authoring
213
+
// surface), `navigateOnSuccess` (parked pending the action-success-
214
+
// navigation family ruling — see the baseline note on #9392).
215
+
{name: 'customFields',type: 'any[]',kind: 'binding',description: 'Field definitions merged over the set generated from object metadata. With inline definitions and no data source, this becomes the only field source.'},
216
+
{name: 'readOnly',type: 'boolean',kind: 'binding',description: 'Render every field read-only, whatever `mode` says.'},
217
+
{name: 'modalCloseButton',type: 'boolean',kind: 'binding',description: "Show the modal presentation's close button (formType 'modal'; honoured by the modal form)."},
218
+
{name: 'contentLayout',type: "'simple' | 'tabbed'",kind: 'binding',description: "How the modal presentation lays out sections; 'tabbed' needs more than one section to differ from 'simple'."},
219
+
{name: 'confirmOnDiscard',type: 'boolean',kind: 'binding',description: 'Ask before discarding unsaved edits when a drawer/modal form is dismissed. Set false to close immediately.'},
220
+
{name: 'submitText',type: 'string',kind: 'binding',description: 'Label of the submit button.'},
221
+
{name: 'cancelText',type: 'string',kind: 'binding',description: 'Label of the cancel button.'},
222
+
{name: 'nextText',type: 'string',kind: 'binding',description: 'Label of the next-step button (wizard).'},
223
+
{name: 'prevText',type: 'string',kind: 'binding',description: 'Label of the previous-step button (wizard).'},
224
+
{name: 'showSubmit',type: 'boolean',kind: 'binding',description: 'Show the submit button.'},
225
+
{name: 'showCancel',type: 'boolean',kind: 'binding',description: 'Show the cancel button.'},
226
+
{name: 'showReset',type: 'boolean',kind: 'binding',description: 'Show the reset button.'},
227
+
{name: 'successMessage',type: 'string',kind: 'binding',description: 'Toast shown after a successful submit. Ignored when `submitBehavior` is set.'},
228
+
{name: 'resetOnSuccess',type: 'boolean',kind: 'binding',description: 'Clear the form after a successful submit instead of keeping the saved values.'},
202
229
{name: 'onSuccess',type: '(record) => void',kind: 'callback',description: 'Called after a successful save with the saved record (e.g. close a panel + reload).'},
203
230
{name: 'onError',type: '(error: Error) => void',kind: 'callback',description: 'Called when the save fails.'},
204
231
{name: 'onCancel',type: '() => void',kind: 'callback',description: 'Called when the user cancels.'},
Copy file name to clipboardExpand all lines: skills/objectstack-ui/contracts/react-blocks.contract.json
+98Lines changed: 98 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -38,6 +38,104 @@
38
38
"required": false,
39
39
"description": "Prefill values in create mode."
40
40
},
41
+
{
42
+
"name": "customFields",
43
+
"type": "any[]",
44
+
"kind": "binding",
45
+
"required": false,
46
+
"description": "Field definitions merged over the set generated from object metadata. With inline definitions and no data source, this becomes the only field source."
47
+
},
48
+
{
49
+
"name": "readOnly",
50
+
"type": "boolean",
51
+
"kind": "binding",
52
+
"required": false,
53
+
"description": "Render every field read-only, whatever `mode` says."
54
+
},
55
+
{
56
+
"name": "modalCloseButton",
57
+
"type": "boolean",
58
+
"kind": "binding",
59
+
"required": false,
60
+
"description": "Show the modal presentation's close button (formType 'modal'; honoured by the modal form)."
61
+
},
62
+
{
63
+
"name": "contentLayout",
64
+
"type": "'simple' | 'tabbed'",
65
+
"kind": "binding",
66
+
"required": false,
67
+
"description": "How the modal presentation lays out sections; 'tabbed' needs more than one section to differ from 'simple'."
68
+
},
69
+
{
70
+
"name": "confirmOnDiscard",
71
+
"type": "boolean",
72
+
"kind": "binding",
73
+
"required": false,
74
+
"description": "Ask before discarding unsaved edits when a drawer/modal form is dismissed. Set false to close immediately."
75
+
},
76
+
{
77
+
"name": "submitText",
78
+
"type": "string",
79
+
"kind": "binding",
80
+
"required": false,
81
+
"description": "Label of the submit button."
82
+
},
83
+
{
84
+
"name": "cancelText",
85
+
"type": "string",
86
+
"kind": "binding",
87
+
"required": false,
88
+
"description": "Label of the cancel button."
89
+
},
90
+
{
91
+
"name": "nextText",
92
+
"type": "string",
93
+
"kind": "binding",
94
+
"required": false,
95
+
"description": "Label of the next-step button (wizard)."
96
+
},
97
+
{
98
+
"name": "prevText",
99
+
"type": "string",
100
+
"kind": "binding",
101
+
"required": false,
102
+
"description": "Label of the previous-step button (wizard)."
103
+
},
104
+
{
105
+
"name": "showSubmit",
106
+
"type": "boolean",
107
+
"kind": "binding",
108
+
"required": false,
109
+
"description": "Show the submit button."
110
+
},
111
+
{
112
+
"name": "showCancel",
113
+
"type": "boolean",
114
+
"kind": "binding",
115
+
"required": false,
116
+
"description": "Show the cancel button."
117
+
},
118
+
{
119
+
"name": "showReset",
120
+
"type": "boolean",
121
+
"kind": "binding",
122
+
"required": false,
123
+
"description": "Show the reset button."
124
+
},
125
+
{
126
+
"name": "successMessage",
127
+
"type": "string",
128
+
"kind": "binding",
129
+
"required": false,
130
+
"description": "Toast shown after a successful submit. Ignored when `submitBehavior` is set."
131
+
},
132
+
{
133
+
"name": "resetOnSuccess",
134
+
"type": "boolean",
135
+
"kind": "binding",
136
+
"required": false,
137
+
"description": "Clear the form after a successful submit instead of keeping the saved values."
Copy file name to clipboardExpand all lines: skills/objectstack-ui/references/react-blocks.md
+14Lines changed: 14 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -21,6 +21,20 @@ Server-connected create/edit/view form for one object. Config props come from th
21
21
|`formType`|`'simple' \| 'tabbed' \| 'wizard' \| 'split' \| 'drawer' \| 'modal'`| binding || Form presentation; drawer/modal render the form in a built-in overlay (use drawerSide/drawerWidth/modalSize). |
22
22
|`fields`|`string[]`| binding || Limit/order the fields shown (defaults to the object form fields). |
23
23
|`initialValues`|`Record<string, any>`| binding || Prefill values in create mode. |
24
+
|`customFields`|`any[]`| binding || Field definitions merged over the set generated from object metadata. With inline definitions and no data source, this becomes the only field source. |
25
+
|`readOnly`|`boolean`| binding || Render every field read-only, whatever `mode` says. |
26
+
|`modalCloseButton`|`boolean`| binding || Show the modal presentation's close button (formType 'modal'; honoured by the modal form). |
27
+
|`contentLayout`|`'simple' \| 'tabbed'`| binding || How the modal presentation lays out sections; 'tabbed' needs more than one section to differ from 'simple'. |
28
+
|`confirmOnDiscard`|`boolean`| binding || Ask before discarding unsaved edits when a drawer/modal form is dismissed. Set false to close immediately. |
29
+
|`submitText`|`string`| binding || Label of the submit button. |
30
+
|`cancelText`|`string`| binding || Label of the cancel button. |
31
+
|`nextText`|`string`| binding || Label of the next-step button (wizard). |
32
+
|`prevText`|`string`| binding || Label of the previous-step button (wizard). |
33
+
|`showSubmit`|`boolean`| binding || Show the submit button. |
34
+
|`showCancel`|`boolean`| binding || Show the cancel button. |
35
+
|`showReset`|`boolean`| binding || Show the reset button. |
36
+
|`successMessage`|`string`| binding || Toast shown after a successful submit. Ignored when `submitBehavior` is set. |
37
+
|`resetOnSuccess`|`boolean`| binding || Clear the form after a successful submit instead of keeping the saved values. |
24
38
|`mode`|`'create' \| 'edit' \| 'view'`| controlled || Create a new record, or edit/view an existing one — drive from React state. |
25
39
|`recordId`|`string \| number`| controlled || Which record to load (edit/view). The hook for master/detail. |
26
40
|`onSuccess`|`(record) => void`| callback || Called after a successful save with the saved record (e.g. close a panel + reload). |
0 commit comments