Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .changeset/12085-element-binding-inputs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
'@object-ui/components': minor
---

`element:repeater` and `element:number` publish the node-level `dataSource` binding as their only query input (objectui#12085). `@objectstack/spec` retires the element layer's flat binding keys as tombstones (objectstack#11509, objectstack PR #22421), and the repeater's registration still required a flat `object`, so the html-page validator refused a repeater bound through `dataSource` alone and accepted the spelling the spec retires.

**Narrowing, no widening.** The `element:repeater` registration drops its `object` (which was `required: true`), `filter`, `sort` and `limit` inputs. The `element:number` registration drops its `object` and `filter` inputs, which the metric has not read since objectui#11880. The injected `dataSource` input is unchanged on both. In the manifest these registrations feed, a repeater bound only through `dataSource` now draws no diagnostic (it drew `missing-required-prop`), and each of those six flat keys now draws `unknown-prop`. No export is added or removed, and no input is added.

**Rendering is unchanged.** The repeater still reads its flat `properties.object` / `filter` / `sort` / `limit` as the binding's fallback, for metadata written before the retirement. That read is not published as an authoring surface. The metric reads its query from `dataSource` only, as before.

objectstack's `sdui.manifest.json` is regenerated from these registrations at objectstack's next console pin bump; this release does not change that file.
4 changes: 4 additions & 0 deletions .changeset/12093-spec-main-compile.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
---

No release. objectui#12093 makes objectui compile against `@objectstack/spec` built from objectstack `main` (the Spec Main Shape Gate) while it keeps compiling, unchanged, against the installed release. The edits are tests, plus two type-only source edits with no runtime effect: `@object-ui/plugin-view`'s `ObjectView` reads the deprecated `table.defaultFilters` through a typed legacy read (the same value, read the same way, now typed by the rule-array shape legacy metadata carries rather than by the row's declaration, a retired-key tombstone on objectstack `main`), and `@object-ui/app-shell`'s zh-CN overlay-scope label table keys `org` beside the spec's union (objectstack `main` narrows that union to `env`).
Original file line number Diff line number Diff line change
Expand Up @@ -119,14 +119,18 @@ const DOC_ROWS = bindingDocRows();
/**
* The key the binding's `object` lands on. The doc: "it lands on the block's
* own object key, which is `objectName` everywhere except `record:line_items`"
* (its row spells that key in the `object` column), and "The two `element:*`
* rows keep their configuration in the node's `properties` bag ...
* `dataSource.object` wins over `properties.object`".
* (its row spells that key in the `object` column).
*
* `undefined` for the `element:*` blocks: each reads `dataSource.object`
* itself, so the binding lands on no key of theirs (objectui#11880), and since
* objectui#12085 neither `element:number` nor `element:repeater` publishes a
* flat `object` for it to land on. Row 3 asserts that exception is exactly the
* `element:*` tags, so it cannot quietly cover an `object-*` block.
*/
function objectKeyOf(tag: string): string {
function objectKeyOf(tag: string): string | undefined {
const named = /\(`([^`]+)`\)/.exec(DOC_ROWS.get(tag)?.object ?? '');
if (named) return named[1];
if (tag.startsWith('element:')) return 'object';
if (tag.startsWith('element:')) return undefined;
return 'objectName';
}

Expand All @@ -137,7 +141,8 @@ function objectKeyOf(tag: string): string {
* are supplied too, but no registration requires one, so they are not read.
*/
function bindingSupplies(tag: string): Set<string> {
const supplied = new Set([objectKeyOf(tag)]);
const key = objectKeyOf(tag);
const supplied = new Set<string>(key === undefined ? [] : [key]);
const view = DOC_ROWS.get(tag)?.view ?? '';
if (view === '✅' || view.includes('columns')) supplied.add('columns');
return supplied;
Expand Down Expand Up @@ -234,11 +239,21 @@ describe('objectui#11605 — a bound registration requires no input its binding
expect(undocumented, `${BINDING_DOC} must say what the binding supplies on each bound block`).toEqual([]);
for (const tag of BOUND) {
const key = objectKeyOf(tag);
if (key === undefined) continue;
expect(
inputsOf(tag).map((input) => input.name),
`<${tag}>: the binding's object lands on "${key}", which the entry does not declare`,
).toContain(key);
}
// The exception is the `element:*` tags and nothing else, and it is not
// vacuous: the two whose flat `object` objectui#12085 stopped publishing
// are bound entries of the shipped manifest that declare no `object`.
const landsNowhere = BOUND.filter((tag) => objectKeyOf(tag) === undefined);
expect(landsNowhere.every((tag) => tag.startsWith('element:'))).toBe(true);
for (const tag of ['element:number', 'element:repeater']) {
expect(landsNowhere, tag).toContain(tag);
expect(inputsOf(tag).map((input) => input.name), tag).not.toContain('object');
}
// Controls on the doc reading: the exception it names, and a full-view row.
expect(objectKeyOf('record:line_items')).toBe('childObject');
expect(bindingSupplies('object-grid').has('columns')).toBe(true);
Expand Down
Loading
Loading