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
feat(spec,lint): ListView react-tier vocabulary converges on the metadata-tier spelling, deprecate-first (#11695)
* feat(spec,lint): converge ListView react-tier vocabulary on the metadata-tier spelling, deprecate-first
Canonical: data={{ provider: 'object', object }} and type (ListViewSchema's
own props, surfaced via dataProps). objectName / viewType stay published as
deprecated aliases for the deprecation window; the lint warns on each use
(react-prop-deprecated), accepts either spelling for the required binding,
and resolves field props against the object bound by whichever is present.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Rxnd8cyFnoU8V5y21PaTsy
* fix(lint): export REACT_PROP_DEPRECATED from the barrel (rule-id-barrel-exports gate)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Rxnd8cyFnoU8V5y21PaTsy
---------
Co-authored-by: Claude <noreply@anthropic.com>
React-tier vocabulary converges on the metadata-tier spelling, deprecate-first (#11284, maintainer ruling 2026-08-23). `<ListView>`'s canonical bindings are now the spec ListView schema's own props: `data={{ provider: 'object', object: '…' }}` for the object binding (objectui#2890 A6) and `type` for the visualization kind. `objectName` and `viewType` remain published and accepted as deprecated aliases for the whole deprecation window — nothing is removed in this release — with the deprecation visible at authoring time: `[DEPRECATED → …]` markers in the generated react-blocks contract, and a new `react-prop-deprecated` lint warning (never an error) on every use of a deprecated spelling. The lint accepts either spelling as satisfying `<ListView>`'s required binding and resolves field-name props (`columns`, `searchableFields`, filter positions, …) against the object bound by whichever spelling is present, canonical winning when both are. `<ObjectForm>` / `<ObjectChart>` `objectName` are unchanged: the form's spec counterpart is explicitly not 1:1 (objectui#2890 Scope B), and the chart has no metadata-tier object binding to converge on (charts bind through a dashboard `dataset` there — see chart.zod.ts guidance). Removal of the deprecated aliases is a later card after the deprecation window.
@@ -1078,18 +1127,37 @@ export function validateReactPageProps(stack: AnyRec): ReactPropFinding[] {
1078
1127
}
1079
1128
if(!hasSpread){
1080
1129
for(constreqofblock.requiredBindings){
1081
-
if(!used.has(req)){
1082
-
findings.push({
1083
-
severity: 'error',
1084
-
rule: 'react-prop-missing-required',
1085
-
where, path,
1086
-
message: `<${tag}> is missing the required prop "${req}".`,
1087
-
hint: `Pass ${req}={…}. See the react-tier component contract.`,
1088
-
});
1089
-
}
1130
+
if(used.has(req))continue;
1131
+
// [#11284] A required prop that is DEPRECATED requires the
1132
+
// binding, not the spelling: the canonical replacement satisfies
1133
+
// it, so the new vocabulary is accepted without the old one.
1134
+
constdep=block.deprecated.get(req);
1135
+
if(dep&&used.has(dep.replacedBy))continue;
1136
+
findings.push({
1137
+
severity: 'error',
1138
+
rule: 'react-prop-missing-required',
1139
+
where, path,
1140
+
message: dep
1141
+
? `<${tag}> is missing its "${req}" binding — pass ${dep.replacedBy}={…} (canonical) or ${req}={…} (deprecated).`
1142
+
: `<${tag}> is missing the required prop "${req}".`,
1143
+
hint: dep ? dep.note : `Pass ${req}={…}. See the react-tier component contract.`,
1144
+
});
1090
1145
}
1091
1146
}
1092
1147
for(constuofused){
1148
+
// [#11284] Deprecate-first: the old spelling keeps working, and
1149
+
// every use says so — the contract's note names the canonical
1150
+
// metadata-tier spelling to write instead.
1151
+
constdep=block.deprecated.get(u);
1152
+
if(dep){
1153
+
findings.push({
1154
+
severity: 'warning',
1155
+
rule: REACT_PROP_DEPRECATED,
1156
+
where, path,
1157
+
message: `<${tag}> prop "${u}" is the deprecated spelling of the metadata-tier "${dep.replacedBy}" and is removed after the deprecation window (#11284).`,
1158
+
hint: dep.note,
1159
+
});
1160
+
}
1093
1161
constnear=nearestKnown(u,block.knownProps);
1094
1162
if(near){
1095
1163
findings.push({
@@ -1119,7 +1187,9 @@ export function validateReactPageProps(stack: AnyRec): ReactPropFinding[] {
summary: "Server-connected object table with toolbar and switchable visualizations (grid/kanban/calendar/gantt/…). Config props come from the spec ListView schema.",
253
+
summary: "Server-connected object table with toolbar and switchable visualizations (grid/kanban/calendar/gantt/…). Config props come from the spec ListView schema. Bind the object with the metadata-tier data source — data={{ provider: 'object', object: '…' }} — and pick the visualization with `type`; `objectName` / `viewType` are the deprecated spellings of the same two bindings.",
{name: 'viewType',type: "'grid' | 'kanban' | 'gallery' | 'calendar' | 'timeline' | 'gantt' | 'map'",kind: 'binding',description: 'Which visualization to render (default grid). How you get a kanban/calendar/gantt of the object.'},
265
+
// #11284 deprecate-first: NOT the shared OBJECT_NAME — ListView's object
266
+
// binding converges on the schema's `data` data source; this alias stays
267
+
// required so the contract keeps saying "bind something" (the lint lets
268
+
// the canonical `data` prop satisfy it).
269
+
{
270
+
name: 'objectName',
271
+
type: 'string',
272
+
kind: 'binding',
273
+
required: true,
274
+
deprecated: {
275
+
replacedBy: 'data',
276
+
note: "Write the metadata-tier data source instead: data={{ provider: 'object', object: '…' }} — the same spelling a metadata list view authors. objectName keeps working during the deprecation window.",
277
+
},
278
+
description: "[DEPRECATED → `data={{ provider: 'object', object }}`] The object this block binds to (server-connected). Converging on the metadata-tier spelling (#11284); this alias is removed after the deprecation window.",
note: 'Write type="kanban" (ListViewSchema\'s own `type`, the metadata-tier view kind) instead. viewType keeps working during the deprecation window.',
287
+
},
288
+
description: '[DEPRECATED → `type`] Which visualization to render (default grid). Converging on the metadata-tier spelling (#11284): write `type`, the same key a metadata list view authors.',
289
+
},
244
290
{name: 'filters',type: "FilterArray e.g. ['status','=','active']",kind: 'controlled',description: 'ObjectQL base filter; drive from React state for tabbed/searched lists. ([field, op, value]; ops =, !=, >, <, contains, in; compound: [\"and\", […], […]]).'},
245
291
{name: 'navigation',type: "{ mode: 'page' | 'drawer' | 'modal' | 'split' | 'none' }",kind: 'binding',description: 'What a row click does. Use { mode: \"none\" } when you handle clicks via onRowClick.'},
246
292
{name: 'onRowClick',type: '(record) => void',kind: 'callback',description: "Called with the clicked row's record — the hook for master/detail."},
0 commit comments