@object-ui/sdui-parser 17.5.0 → 17.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/body-dialect.d.ts +52 -0
- package/dist/body-dialect.js +85 -0
- package/dist/codegen.d.ts +5 -0
- package/dist/codegen.js +123 -32
- package/dist/dashboard-widget-options.d.ts +129 -0
- package/dist/dashboard-widget-options.js +73 -0
- package/dist/index.d.ts +62 -5
- package/dist/index.js +24 -15
- package/dist/input-type.d.ts +46 -0
- package/dist/input-type.js +69 -0
- package/dist/parse.d.ts +12 -3
- package/dist/parse.js +357 -9
- package/dist/provenance.d.ts +68 -0
- package/dist/provenance.js +77 -0
- package/dist/types.d.ts +117 -6
- package/dist/types.js +1 -1
- package/dist/validate.d.ts +111 -4
- package/dist/validate.js +337 -46
- package/package.json +6 -6
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ObjectUI — html-tier provenance (ADR-0080, objectui#4000)
|
|
3
|
+
*
|
|
4
|
+
* Records the one fact a renderer cannot otherwise recover: whether the node it
|
|
5
|
+
* is about to render was EMITTED BY THIS PARSER (an author's `kind:'html'`
|
|
6
|
+
* source, compiled tag-name-straight-through) or AUTHORED AS JSON metadata.
|
|
7
|
+
*
|
|
8
|
+
* Why a renderer needs it: the two surfaces have different vocabularies. A type
|
|
9
|
+
* the JSON surface is steering authors away from can still be a supported tag
|
|
10
|
+
* in the html tier — the plain inline element (`span`) is exactly that. (The
|
|
11
|
+
* plain box element was too, until objectui#10757 deprecated `div` on the html
|
|
12
|
+
* surface as well; the console's html compile now refuses it outright, so no
|
|
13
|
+
* notice is involved there.) Advice aimed at the JSON surface, delivered to an
|
|
14
|
+
* html-tier author, is advice they cannot act on: in that tier there is no
|
|
15
|
+
* other spelling. The
|
|
16
|
+
* deprecation notice fired at them anyway (objectui#4000), which is also why the
|
|
17
|
+
* type could never be retired — the engine's own compiler keeps emitting it.
|
|
18
|
+
*
|
|
19
|
+
* The judgement therefore has to be PROVENANCE, established by the producer,
|
|
20
|
+
* not a guess made at the consumer from the node's shape.
|
|
21
|
+
*
|
|
22
|
+
* ## Why a symbol, and why `Symbol.for`
|
|
23
|
+
*
|
|
24
|
+
* The marker is deliberately NOT a JSON-visible key:
|
|
25
|
+
*
|
|
26
|
+
* - `JSON.stringify` skips symbol keys, so provenance never lands in a
|
|
27
|
+
* persisted tree. That is the point, not a limitation: "our parser produced
|
|
28
|
+
* this node in this process" is not a fact about the saved document, and a
|
|
29
|
+
* saved document must not be able to REPLAY it. A string key like
|
|
30
|
+
* `_provenance: 'html'` would be copyable — an authored (or AI-generated)
|
|
31
|
+
* JSON page could paste it in and buy itself silence from a notice that is
|
|
32
|
+
* meant for it. Provenance that authored metadata can forge is not
|
|
33
|
+
* provenance.
|
|
34
|
+
* - `Object.keys` / `for...in` skip symbol keys, so the marker cannot leak out
|
|
35
|
+
* of a renderer onto a host element as a stray DOM attribute.
|
|
36
|
+
*
|
|
37
|
+
* It IS enumerable, which matters more than it looks: `SchemaRenderer` hands
|
|
38
|
+
* renderers a shallow copy of the node (`{ ...schema }`), and object spread
|
|
39
|
+
* copies own ENUMERABLE symbol keys while dropping non-enumerable ones. A
|
|
40
|
+
* non-enumerable marker would be lost in that copy and the misfire would come
|
|
41
|
+
* back — silently, and only in the render path. `render.test.tsx` and the
|
|
42
|
+
* components-side pin both go through the real `SchemaRenderer` for this reason.
|
|
43
|
+
*
|
|
44
|
+
* `Symbol.for` (the cross-realm registry) rather than a module-local `Symbol()`:
|
|
45
|
+
* this package ships as both ESM and CJS and is consumed from several packages,
|
|
46
|
+
* so two module instances are possible. Two local symbols would not compare
|
|
47
|
+
* equal, and the failure mode of that mismatch is the ORIGINAL BUG returning
|
|
48
|
+
* with no error anywhere. A registry key cannot drift.
|
|
49
|
+
*/
|
|
50
|
+
/**
|
|
51
|
+
* The provenance marker itself. Exported for tests and for any consumer that
|
|
52
|
+
* needs to reason about the key; prefer {@link isHtmlTierNode} for reading.
|
|
53
|
+
*/
|
|
54
|
+
export declare const HTML_TIER_NODE: symbol;
|
|
55
|
+
/**
|
|
56
|
+
* Stamp a node as html-tier output. Called by the parser as it builds each
|
|
57
|
+
* element — the producer is the only place that knows this for certain.
|
|
58
|
+
*/
|
|
59
|
+
export declare function markHtmlTierNode<T extends object>(node: T): T;
|
|
60
|
+
/**
|
|
61
|
+
* True when this node came out of the html tier's parser.
|
|
62
|
+
*
|
|
63
|
+
* Deliberately a plain boolean read of the marker — no fallback to a
|
|
64
|
+
* string-keyed spelling, no shape heuristic ("looks like a raw tag"). Either
|
|
65
|
+
* the producer marked it or it did not; a consumer-side guess is precisely what
|
|
66
|
+
* this replaces.
|
|
67
|
+
*/
|
|
68
|
+
export declare function isHtmlTierNode(node: unknown): boolean;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ObjectUI — html-tier provenance (ADR-0080, objectui#4000)
|
|
3
|
+
*
|
|
4
|
+
* Records the one fact a renderer cannot otherwise recover: whether the node it
|
|
5
|
+
* is about to render was EMITTED BY THIS PARSER (an author's `kind:'html'`
|
|
6
|
+
* source, compiled tag-name-straight-through) or AUTHORED AS JSON metadata.
|
|
7
|
+
*
|
|
8
|
+
* Why a renderer needs it: the two surfaces have different vocabularies. A type
|
|
9
|
+
* the JSON surface is steering authors away from can still be a supported tag
|
|
10
|
+
* in the html tier — the plain inline element (`span`) is exactly that. (The
|
|
11
|
+
* plain box element was too, until objectui#10757 deprecated `div` on the html
|
|
12
|
+
* surface as well; the console's html compile now refuses it outright, so no
|
|
13
|
+
* notice is involved there.) Advice aimed at the JSON surface, delivered to an
|
|
14
|
+
* html-tier author, is advice they cannot act on: in that tier there is no
|
|
15
|
+
* other spelling. The
|
|
16
|
+
* deprecation notice fired at them anyway (objectui#4000), which is also why the
|
|
17
|
+
* type could never be retired — the engine's own compiler keeps emitting it.
|
|
18
|
+
*
|
|
19
|
+
* The judgement therefore has to be PROVENANCE, established by the producer,
|
|
20
|
+
* not a guess made at the consumer from the node's shape.
|
|
21
|
+
*
|
|
22
|
+
* ## Why a symbol, and why `Symbol.for`
|
|
23
|
+
*
|
|
24
|
+
* The marker is deliberately NOT a JSON-visible key:
|
|
25
|
+
*
|
|
26
|
+
* - `JSON.stringify` skips symbol keys, so provenance never lands in a
|
|
27
|
+
* persisted tree. That is the point, not a limitation: "our parser produced
|
|
28
|
+
* this node in this process" is not a fact about the saved document, and a
|
|
29
|
+
* saved document must not be able to REPLAY it. A string key like
|
|
30
|
+
* `_provenance: 'html'` would be copyable — an authored (or AI-generated)
|
|
31
|
+
* JSON page could paste it in and buy itself silence from a notice that is
|
|
32
|
+
* meant for it. Provenance that authored metadata can forge is not
|
|
33
|
+
* provenance.
|
|
34
|
+
* - `Object.keys` / `for...in` skip symbol keys, so the marker cannot leak out
|
|
35
|
+
* of a renderer onto a host element as a stray DOM attribute.
|
|
36
|
+
*
|
|
37
|
+
* It IS enumerable, which matters more than it looks: `SchemaRenderer` hands
|
|
38
|
+
* renderers a shallow copy of the node (`{ ...schema }`), and object spread
|
|
39
|
+
* copies own ENUMERABLE symbol keys while dropping non-enumerable ones. A
|
|
40
|
+
* non-enumerable marker would be lost in that copy and the misfire would come
|
|
41
|
+
* back — silently, and only in the render path. `render.test.tsx` and the
|
|
42
|
+
* components-side pin both go through the real `SchemaRenderer` for this reason.
|
|
43
|
+
*
|
|
44
|
+
* `Symbol.for` (the cross-realm registry) rather than a module-local `Symbol()`:
|
|
45
|
+
* this package ships as both ESM and CJS and is consumed from several packages,
|
|
46
|
+
* so two module instances are possible. Two local symbols would not compare
|
|
47
|
+
* equal, and the failure mode of that mismatch is the ORIGINAL BUG returning
|
|
48
|
+
* with no error anywhere. A registry key cannot drift.
|
|
49
|
+
*/
|
|
50
|
+
/** Registry key for the marker. Stable — it is a cross-instance contract. */
|
|
51
|
+
const HTML_TIER_NODE_KEY = '@object-ui/sdui-parser.html-tier-node';
|
|
52
|
+
/**
|
|
53
|
+
* The provenance marker itself. Exported for tests and for any consumer that
|
|
54
|
+
* needs to reason about the key; prefer {@link isHtmlTierNode} for reading.
|
|
55
|
+
*/
|
|
56
|
+
export const HTML_TIER_NODE = Symbol.for(HTML_TIER_NODE_KEY);
|
|
57
|
+
/**
|
|
58
|
+
* Stamp a node as html-tier output. Called by the parser as it builds each
|
|
59
|
+
* element — the producer is the only place that knows this for certain.
|
|
60
|
+
*/
|
|
61
|
+
export function markHtmlTierNode(node) {
|
|
62
|
+
node[HTML_TIER_NODE] = true;
|
|
63
|
+
return node;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* True when this node came out of the html tier's parser.
|
|
67
|
+
*
|
|
68
|
+
* Deliberately a plain boolean read of the marker — no fallback to a
|
|
69
|
+
* string-keyed spelling, no shape heuristic ("looks like a raw tag"). Either
|
|
70
|
+
* the producer marked it or it did not; a consumer-side guess is precisely what
|
|
71
|
+
* this replaces.
|
|
72
|
+
*/
|
|
73
|
+
export function isHtmlTierNode(node) {
|
|
74
|
+
return (typeof node === 'object' &&
|
|
75
|
+
node !== null &&
|
|
76
|
+
node[HTML_TIER_NODE] === true);
|
|
77
|
+
}
|
package/dist/types.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* ObjectUI — SDUI JSX-source parser (ADR-0080)
|
|
3
3
|
*
|
|
4
4
|
* Types shared by the constrained JSX-source compiler. The parser turns a
|
|
5
|
-
* constrained JSX
|
|
5
|
+
* constrained JSX *text* into the existing SDUI `SchemaNode`
|
|
6
6
|
* tree. It PARSES — it never executes. No `import`, no `eval`, no JS.
|
|
7
7
|
*/
|
|
8
8
|
/** A node in the compiled SDUI tree. Mirrors `@object-ui/types` BaseSchema. */
|
|
@@ -39,23 +39,123 @@ export interface ParseResult {
|
|
|
39
39
|
export type ManifestInputType = 'string' | 'number' | 'boolean' | 'enum' | 'array' | 'object' | 'color' | 'date' | 'code' | 'file' | 'slot';
|
|
40
40
|
export interface ManifestInput {
|
|
41
41
|
name: string;
|
|
42
|
-
|
|
42
|
+
/**
|
|
43
|
+
* The input's coarse type: ONE kind, or an ARRAY of kinds when the key's
|
|
44
|
+
* contract is a union (objectui#3832).
|
|
45
|
+
*
|
|
46
|
+
* A value passes {@link validateTree}'s coarse check when ANY arm accepts it,
|
|
47
|
+
* and is reported when none does — the array widens what is legal, it does
|
|
48
|
+
* not switch the check off.
|
|
49
|
+
*
|
|
50
|
+
* The single-kind form is unchanged and stays the canonical spelling for a
|
|
51
|
+
* one-arm key: `manifestFromConfigs` collapses a one-element array back to
|
|
52
|
+
* the bare string, so a manifest gains arrays only where a union was really
|
|
53
|
+
* declared and every already-published entry serializes byte-identically.
|
|
54
|
+
*/
|
|
55
|
+
type: ManifestInputType | ManifestInputType[];
|
|
56
|
+
/**
|
|
57
|
+
* The coarse kind of the input's MEMBERS — array elements, or the values of
|
|
58
|
+
* an object used as a map — as ONE kind or an ARRAY of kinds for a member
|
|
59
|
+
* contract that is a union (objectui#8067).
|
|
60
|
+
*
|
|
61
|
+
* Absent means "not declared", which is what every input published before
|
|
62
|
+
* this key existed says: {@link validateTree} checks no member and the
|
|
63
|
+
* codegen emits the unnarrowed element type, exactly as before. So a
|
|
64
|
+
* manifest gains this key only where a member kind was really declared, and
|
|
65
|
+
* every already-published entry serializes byte-identically.
|
|
66
|
+
*
|
|
67
|
+
* Read the arms through `inputTypeArms(input.of)` — the same accessor
|
|
68
|
+
* `type`'s arms go through, since the two fields carry the same shape and a
|
|
69
|
+
* reader that forgets the array form is silently inert on it.
|
|
70
|
+
*/
|
|
71
|
+
of?: ManifestInputType | ManifestInputType[];
|
|
43
72
|
required?: boolean;
|
|
44
73
|
/** allowed values for `enum` inputs */
|
|
45
74
|
enum?: Array<string | {
|
|
46
75
|
value: unknown;
|
|
47
76
|
label?: string;
|
|
48
77
|
}>;
|
|
49
|
-
/**
|
|
50
|
-
|
|
78
|
+
/**
|
|
79
|
+
* Marks a data-binding input the server must resolve (ADR-0080 §6.3):
|
|
80
|
+
* `binding: 'object'` says the input NAMES an object, so the server-side
|
|
81
|
+
* binding check knows what to resolve it against. Unrelated to
|
|
82
|
+
* `type: 'object'`, the coarse control kind — a record-shaped value and an
|
|
83
|
+
* object-naming input are two different facts.
|
|
84
|
+
*
|
|
85
|
+
* ## The vocabulary is exactly `'object'` — `'field'` is retired on this face too
|
|
86
|
+
*
|
|
87
|
+
* `'field'` stood beside it from the first draft of ADR-0080 and was never
|
|
88
|
+
* written. It was retired on the serializer's INPUT boundary
|
|
89
|
+
* (`RegistryConfigLike` in `index.ts`) under ADR-0049 enforce-or-remove by
|
|
90
|
+
* the maintainer ruling of 2026-09-07 (decision batch #69), and on THIS
|
|
91
|
+
* face by objectui#8315 — the residue that ruling did not name, which left
|
|
92
|
+
* one published package narrow on one face and wide on the other.
|
|
93
|
+
*
|
|
94
|
+
* ⚠️ The argument for leaving this face wide was ANSWERED, not overlooked.
|
|
95
|
+
* It runs: producer → reader is a subset relation, so a reader accepting a
|
|
96
|
+
* value no producer emits is permissive rather than wrong. Three measured
|
|
97
|
+
* facts decided against it (objectui#8315):
|
|
98
|
+
*
|
|
99
|
+
* 1. **This is not a pure reader face.** `manifestFromConfigs` RETURNS a
|
|
100
|
+
* `Manifest`, so `ManifestInput` is also this package's OUTPUT type,
|
|
101
|
+
* and this key is fed straight from the already-narrowed boundary. A
|
|
102
|
+
* union wider than the producer's is imprecision on the way out, not
|
|
103
|
+
* permissiveness on the way in.
|
|
104
|
+
* 2. **Its sibling is a pure producer face.**
|
|
105
|
+
* `ManifestValidationResult.bindings[].kind` is written by
|
|
106
|
+
* `validateTree` by copying this key, so the subset relation runs the
|
|
107
|
+
* other way there — see that declaration. The two are COUPLED by that
|
|
108
|
+
* assignment: narrowing one alone needs a cast at the only conversion
|
|
109
|
+
* site, which is the lenient fallback AGENTS.md #0.1 bans. So "both
|
|
110
|
+
* narrow" and "both wide" were the only self-consistent states, and
|
|
111
|
+
* only one of them can be justified on the producer face.
|
|
112
|
+
* 3. **The permissiveness protected nothing.** `binding: 'field'` has
|
|
113
|
+
* zero writers here and zero in the objectstack copy of this package
|
|
114
|
+
* (measured 2026-09-09 on both heads, each with a firing
|
|
115
|
+
* `binding: 'object'` control), and the only manifest producer in
|
|
116
|
+
* either tree is `manifestFromConfigs`, whose input face is narrow.
|
|
117
|
+
*
|
|
118
|
+
* The reopen route is the ruling's own: a MEASURED need for field bindings
|
|
119
|
+
* is filed as a widening with the vocabulary decided then — not
|
|
120
|
+
* pre-declared here for a producer that does not exist.
|
|
121
|
+
*/
|
|
122
|
+
binding?: 'object';
|
|
51
123
|
description?: string;
|
|
52
124
|
}
|
|
53
125
|
export interface ManifestComponent {
|
|
54
126
|
type: string;
|
|
55
127
|
/** plugin namespace — provenance that drives `requires` */
|
|
56
128
|
namespace?: string;
|
|
129
|
+
/**
|
|
130
|
+
* The declared authoring surface. An input named `children` (type `slot`)
|
|
131
|
+
* is ALSO the containment declaration: `validateTree` draws
|
|
132
|
+
* `not-a-container` on a child list under any component whose `inputs`
|
|
133
|
+
* carry no such entry (objectui#9910; `acceptsChildren` in `validate.ts`).
|
|
134
|
+
*/
|
|
57
135
|
inputs: ManifestInput[];
|
|
136
|
+
/**
|
|
137
|
+
* LAYOUT containment (objectui#6804, objectui#9910 Q2-A): the flag the
|
|
138
|
+
* react-page JSX scope builder skips and the public layout ledger lists.
|
|
139
|
+
* ⛔ Not "accepts children" — this tier's containment check does not read it.
|
|
140
|
+
*/
|
|
58
141
|
isContainer?: boolean;
|
|
142
|
+
/**
|
|
143
|
+
* The authoring tier this entry belongs to (objectui#10735).
|
|
144
|
+
*
|
|
145
|
+
* Absent = the curated PUBLIC tier (ADR-0080 §4), the JSON-surface
|
|
146
|
+
* AI-authoring vocabulary. `'html'` = one of the intrinsic HTML elements a
|
|
147
|
+
* `kind:'html'` page may author (ADR-0081 §2), declared by the registry's
|
|
148
|
+
* `HTML_TIER_INTRINSICS` roster and carried here so the ONE flat `components`
|
|
149
|
+
* map can serve both of its readers: a whitelist reader (`compile`, the
|
|
150
|
+
* objectstack gate) takes every key and needs no change; a reader that means
|
|
151
|
+
* the curated vocabulary — the `kind:'react'` scope, the block list, a census
|
|
152
|
+
* of curated blocks — filters this key out.
|
|
153
|
+
*
|
|
154
|
+
* ⛔ Not the registration's `tier` copied through. `manifestFromConfigs`
|
|
155
|
+
* writes exactly `'html'` or nothing, so every entry published before this
|
|
156
|
+
* key existed serialises byte-identically.
|
|
157
|
+
*/
|
|
158
|
+
tier?: 'html';
|
|
59
159
|
}
|
|
60
160
|
export interface Manifest {
|
|
61
161
|
/** keyed by component `type` */
|
|
@@ -81,11 +181,22 @@ export interface ManifestValidationResult {
|
|
|
81
181
|
diagnostics: Diagnostic[];
|
|
82
182
|
/** unique plugin namespaces referenced — the page's `requires` */
|
|
83
183
|
requires: string[];
|
|
84
|
-
/**
|
|
184
|
+
/**
|
|
185
|
+
* Binding sites the server must resolve against object schema.
|
|
186
|
+
*
|
|
187
|
+
* `kind` is a PRODUCER face, not a reader face: `validateTree` writes it,
|
|
188
|
+
* copying {@link ManifestInput.binding} at the one site that builds this
|
|
189
|
+
* array. So the subset relation that licenses a permissive READER runs the
|
|
190
|
+
* other way here — a wider union accepts nothing extra, it obliges every
|
|
191
|
+
* consumer to handle an arm this package cannot emit. That is why the
|
|
192
|
+
* retired `'field'` arm (`9e37d9b39` on the input boundary, objectui#8315
|
|
193
|
+
* here) is gone from this end as well; the measurements are on
|
|
194
|
+
* {@link ManifestInput.binding}.
|
|
195
|
+
*/
|
|
85
196
|
bindings: Array<{
|
|
86
197
|
tag: string;
|
|
87
198
|
input: string;
|
|
88
|
-
kind: 'object'
|
|
199
|
+
kind: 'object';
|
|
89
200
|
value: unknown;
|
|
90
201
|
}>;
|
|
91
202
|
}
|
package/dist/types.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* ObjectUI — SDUI JSX-source parser (ADR-0080)
|
|
3
3
|
*
|
|
4
4
|
* Types shared by the constrained JSX-source compiler. The parser turns a
|
|
5
|
-
* constrained JSX
|
|
5
|
+
* constrained JSX *text* into the existing SDUI `SchemaNode`
|
|
6
6
|
* tree. It PARSES — it never executes. No `import`, no `eval`, no JS.
|
|
7
7
|
*/
|
|
8
8
|
export {};
|
package/dist/validate.d.ts
CHANGED
|
@@ -2,9 +2,116 @@
|
|
|
2
2
|
* ObjectUI — SDUI tree validation against the registry manifest (ADR-0080 §3/§6)
|
|
3
3
|
*
|
|
4
4
|
* Shallow, author-time validation: unknown component, unknown/missing prop,
|
|
5
|
-
* wrong coarse type, illegal enum value
|
|
6
|
-
*
|
|
7
|
-
*
|
|
5
|
+
* wrong coarse type, illegal enum value, and containment — a child list under
|
|
6
|
+
* a component whose registration declares no `children` input draws
|
|
7
|
+
* `not-a-container` (objectui#9910; see `acceptsChildren`). Collects
|
|
8
|
+
* `requires` (plugin provenance) and binding sites the SERVER must resolve
|
|
9
|
+
* against object schema (we cannot resolve objects/fields here — that check is
|
|
10
|
+
* framework-side by design).
|
|
8
11
|
*/
|
|
9
|
-
import type { Manifest, SchemaElement, ManifestValidationResult } from './types.js';
|
|
12
|
+
import type { Manifest, ManifestComponent, SchemaElement, ManifestValidationResult } from './types.js';
|
|
13
|
+
/**
|
|
14
|
+
* The protocol's ONE child-list key — `BaseSchema.children` — and therefore the
|
|
15
|
+
* name of the `inputs` entry a registration declares when its renderer puts
|
|
16
|
+
* that list on the page: `{ name: 'children', type: 'slot' }` (objectui#9910).
|
|
17
|
+
*/
|
|
18
|
+
export declare const CHILD_LIST_KEY = "children";
|
|
19
|
+
/**
|
|
20
|
+
* Does this component ACCEPT an authored child list? (objectui#9910)
|
|
21
|
+
*
|
|
22
|
+
* Read from exactly ONE declaration: an input named {@link CHILD_LIST_KEY} in
|
|
23
|
+
* the component's `inputs`. That is the shape ten registrations already
|
|
24
|
+
* carried when the maintainer ruled it the containment contract
|
|
25
|
+
* (2026-09-24, objectui#9910 Q1-A "declare-and-pin"), and it is held in both
|
|
26
|
+
* directions by the runtime census in
|
|
27
|
+
* `packages/components/src/renderers/__tests__/container-declaration-ratchet.test.tsx`:
|
|
28
|
+
* a renderer that puts `schema.children` on the page without declaring the
|
|
29
|
+
* input is red, and a declaration whose renderer never renders the list is
|
|
30
|
+
* red too.
|
|
31
|
+
*
|
|
32
|
+
* ⛔ `isContainer` is NOT consulted and is NOT a fallback. It used to decide
|
|
33
|
+
* this branch and it lied both ways: a hand-kept flag drifted from the code
|
|
34
|
+
* (objectui#3900 / `7c9b044f4` / #6764 / #6779 found the same drift four times),
|
|
35
|
+
* and after objectui#6771 converged a dozen registrations onto `children`
|
|
36
|
+
* the flag put a FALSE `not-a-container` on the one key they read
|
|
37
|
+
* (objectui#9910). The flag now means LAYOUT containment only — the
|
|
38
|
+
* react-page JSX scope and the public layout ledger read it; this tier does
|
|
39
|
+
* not (objectui#6804, objectui#9910 Q2-A).
|
|
40
|
+
*/
|
|
41
|
+
export declare function acceptsChildren(comp: Pick<ManifestComponent, 'inputs'>): boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Where a base prop is legal without a declaration (objectui#11044).
|
|
44
|
+
*
|
|
45
|
+
* - `'every-node'` — on every node, and a registration's own input of the
|
|
46
|
+
* same name is not consulted: {@link validateTree} skips the key before the
|
|
47
|
+
* declared-input lookup.
|
|
48
|
+
* - `'where-undeclared'` — on a type whose registration declares NO input of
|
|
49
|
+
* that name. Where one does, the declared input wins, its `type-mismatch`
|
|
50
|
+
* check included, and the generated JSX types take the declared type too.
|
|
51
|
+
*/
|
|
52
|
+
export type SduiBasePropScope = 'every-node' | 'where-undeclared';
|
|
53
|
+
/** One entry of {@link SDUI_BASE_PROPS}. */
|
|
54
|
+
export interface SduiBaseProp {
|
|
55
|
+
/** The `BaseSchema` member (`@object-ui/types`). */
|
|
56
|
+
readonly name: string;
|
|
57
|
+
readonly scope: SduiBasePropScope;
|
|
58
|
+
/**
|
|
59
|
+
* The attribute's type in the generated JSX surface (`SduiBaseProps` in
|
|
60
|
+
* `sdui-intrinsics.d.ts`), or `null` for the one key that is no attribute:
|
|
61
|
+
* `type`, which the tag name carries (`parse.ts` refuses a `type` attribute).
|
|
62
|
+
*/
|
|
63
|
+
readonly tsType: string | null;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* The base props: the `BaseSchema` members this tier accepts on a node without
|
|
67
|
+
* a registration declaring them. ONE list, read by BOTH of its consumers —
|
|
68
|
+
* {@link validateTree}'s `unknown-prop` branch and `generateDts`'s
|
|
69
|
+
* `SduiBaseProps` (objectui#11044). Before this list the two were separate
|
|
70
|
+
* hand-kept copies and had drifted: the validator accepted `bind` and `hidden`
|
|
71
|
+
* (objectui#11008) while the generated types still refused both.
|
|
72
|
+
*
|
|
73
|
+
* `bind` and `hidden` are `'every-node'` (objectui#11008). `BaseSchema` declares
|
|
74
|
+
* both for every node and no registration declares either as an input, so
|
|
75
|
+
* before they joined, the undeclared-key branch below answered every authored
|
|
76
|
+
* one with `unknown-prop` — "has no prop" about a key the protocol declares,
|
|
77
|
+
* on the nodes that honour it: `hidden` is read for every node by
|
|
78
|
+
* `SchemaRenderer`'s hide chain, and `bind` by every renderer that calls
|
|
79
|
+
* `useDataScope` (`list`, `tree-view`, the `object-*` widgets). The
|
|
80
|
+
* declaration outranks the implementation, so the parser's view is the
|
|
81
|
+
* declared type's, not a per-registration subset. The cost is accepted and
|
|
82
|
+
* named: a `bind` on a node that does not read it — `data-table`
|
|
83
|
+
* (objectui#6575) — draws nothing here either, and its render-time console
|
|
84
|
+
* warning is the one signal left.
|
|
85
|
+
*
|
|
86
|
+
* `visibleWhen`, `hiddenOn` and `testId` are `'every-node'` for the same reason
|
|
87
|
+
* (objectui#11044): no registration declares any of them, `SchemaRenderer`'s
|
|
88
|
+
* hide chain reads the first two for every node, and it strips `testId` and
|
|
89
|
+
* re-emits it as `data-testid`. `visibleWhen` is the canonical ADR-0089
|
|
90
|
+
* predicate; before it joined, the deprecated `visibleOn` was silent while it
|
|
91
|
+
* drew `unknown-prop`.
|
|
92
|
+
*
|
|
93
|
+
* The `'where-undeclared'` members (objectui#11044, triage ruling) are the
|
|
94
|
+
* `BaseSchema` members some registrations DECLARE as typed inputs — the input
|
|
95
|
+
* family's `placeholder`, `label`, `name`, … . Skipping them the way the
|
|
96
|
+
* `'every-node'` members are skipped would silence those registrations'
|
|
97
|
+
* `type-mismatch`, so they are base props only where the type declares no
|
|
98
|
+
* input of that name. ⛔ Never move one to `'every-node'` to accept a key: that
|
|
99
|
+
* silences a declared type check.
|
|
100
|
+
*
|
|
101
|
+
* Held over the live registry by `base-props-one-list-11044.test.tsx` in
|
|
102
|
+
* `@object-ui/components` — every member a `BaseSchema` member, and `body` the
|
|
103
|
+
* one member left out.
|
|
104
|
+
*
|
|
105
|
+
* ⛔ `body` is NOT here and must not be added. It was `BaseSchema`'s second
|
|
106
|
+
* child-list spelling until objectui#6771 retired it; teaching this list the
|
|
107
|
+
* key was the option that ruling refused, because it would have blessed a
|
|
108
|
+
* second permanent spelling of one concept. `./body-dialect.ts` answers it by
|
|
109
|
+
* name instead.
|
|
110
|
+
*
|
|
111
|
+
* `children` IS here: the key is legal on every node, so it never draws
|
|
112
|
+
* `unknown-prop` and its declared `slot` input is never type-checked. Whether
|
|
113
|
+
* a given component RENDERS it is the containment question below, answered by
|
|
114
|
+
* {@link acceptsChildren} from the declared input.
|
|
115
|
+
*/
|
|
116
|
+
export declare const SDUI_BASE_PROPS: readonly SduiBaseProp[];
|
|
10
117
|
export declare function validateTree(tree: SchemaElement | null, manifest: Manifest): ManifestValidationResult;
|