@object-ui/core 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.
Files changed (157) hide show
  1. package/CHANGELOG.md +7404 -0
  2. package/README.md +127 -26
  3. package/dist/actions/ActionEngine.d.ts +5 -3
  4. package/dist/actions/ActionEngine.js +14 -10
  5. package/dist/actions/ActionRunner.d.ts +363 -30
  6. package/dist/actions/ActionRunner.js +544 -58
  7. package/dist/actions/TransactionManager.d.ts +7 -2
  8. package/dist/actions/actionKeys.d.ts +75 -13
  9. package/dist/actions/actionKeys.js +131 -16
  10. package/dist/actions/actionResponse.js +3 -3
  11. package/dist/actions/index.d.ts +2 -0
  12. package/dist/actions/index.js +2 -0
  13. package/dist/actions/recordDelete.d.ts +118 -0
  14. package/dist/actions/recordDelete.js +112 -0
  15. package/dist/actions/recordIdParam.d.ts +77 -0
  16. package/dist/actions/recordIdParam.js +37 -0
  17. package/dist/actions/serverActionHandler.d.ts +1 -1
  18. package/dist/actions/serverActionHandler.js +1 -1
  19. package/dist/adapters/ValueDataSource.d.ts +6 -1
  20. package/dist/adapters/ValueDataSource.js +1090 -98
  21. package/dist/adapters/batchTransaction.d.ts +1 -1
  22. package/dist/adapters/batchTransaction.js +1 -1
  23. package/dist/builder/schema-builder.d.ts +38 -81
  24. package/dist/builder/schema-builder.js +33 -152
  25. package/dist/data-scope/ViewDataProvider.d.ts +1 -1
  26. package/dist/data-scope/ViewDataProvider.js +21 -1
  27. package/dist/data-scope/element-data-source.d.ts +261 -7
  28. package/dist/data-scope/element-data-source.js +342 -52
  29. package/dist/data-scope/index.d.ts +9 -4
  30. package/dist/data-scope/index.js +9 -4
  31. package/dist/evaluator/ExpressionEvaluator.d.ts +128 -1
  32. package/dist/evaluator/ExpressionEvaluator.js +226 -13
  33. package/dist/evaluator/FormulaFunctions.d.ts +0 -10
  34. package/dist/evaluator/FormulaFunctions.js +166 -27
  35. package/dist/evaluator/SafeExpressionParser.js +0 -4
  36. package/dist/evaluator/declaredPredicate.d.ts +93 -9
  37. package/dist/evaluator/declaredPredicate.js +118 -17
  38. package/dist/evaluator/fieldRules.d.ts +107 -4
  39. package/dist/evaluator/fieldRules.js +231 -35
  40. package/dist/evaluator/index.d.ts +2 -0
  41. package/dist/evaluator/index.js +2 -0
  42. package/dist/evaluator/listConditional.d.ts +125 -9
  43. package/dist/evaluator/listConditional.js +167 -26
  44. package/dist/evaluator/optionRules.d.ts +126 -0
  45. package/dist/evaluator/optionRules.js +141 -4
  46. package/dist/evaluator/predicateInput.d.ts +15 -4
  47. package/dist/evaluator/predicateInput.js +35 -2
  48. package/dist/evaluator/rowPredicateCanon.d.ts +56 -0
  49. package/dist/evaluator/rowPredicateCanon.js +158 -0
  50. package/dist/evaluator/subjectPermissions.d.ts +76 -0
  51. package/dist/evaluator/subjectPermissions.js +44 -0
  52. package/dist/evaluator/unevaluablePredicate.d.ts +57 -0
  53. package/dist/evaluator/unevaluablePredicate.js +70 -0
  54. package/dist/index.d.ts +18 -0
  55. package/dist/index.js +97 -2
  56. package/dist/protocols/index.d.ts +0 -1
  57. package/dist/protocols/index.js +9 -1
  58. package/dist/registry/Registry.d.ts +397 -48
  59. package/dist/registry/Registry.js +263 -11
  60. package/dist/registry/WidgetRegistry.js +7 -3
  61. package/dist/registry/html-tier-intrinsics.d.ts +90 -0
  62. package/dist/registry/html-tier-intrinsics.js +110 -0
  63. package/dist/registry/public-blocks.d.ts +8 -0
  64. package/dist/registry/public-blocks.js +57 -0
  65. package/dist/theme/ThemeEngine.js +1 -1
  66. package/dist/theme/index.d.ts +1 -1
  67. package/dist/theme/index.js +1 -1
  68. package/dist/types/index.d.ts +92 -13
  69. package/dist/utils/chart-category-key.d.ts +82 -0
  70. package/dist/utils/chart-category-key.js +84 -0
  71. package/dist/utils/chart-measure-key.d.ts +64 -0
  72. package/dist/utils/chart-measure-key.js +65 -0
  73. package/dist/utils/chart-presentation.d.ts +188 -0
  74. package/dist/utils/chart-presentation.js +345 -0
  75. package/dist/utils/chart-series.d.ts +271 -31
  76. package/dist/utils/chart-series.js +478 -55
  77. package/dist/utils/column-identity.d.ts +43 -0
  78. package/dist/utils/column-identity.js +47 -1
  79. package/dist/utils/column-sortability.d.ts +157 -0
  80. package/dist/utils/column-sortability.js +217 -0
  81. package/dist/utils/dashboard-filters.d.ts +38 -6
  82. package/dist/utils/dashboard-filters.js +107 -61
  83. package/dist/utils/dataset-format.d.ts +211 -30
  84. package/dist/utils/dataset-format.js +407 -52
  85. package/dist/utils/date-display.d.ts +354 -0
  86. package/dist/utils/date-display.js +463 -0
  87. package/dist/utils/date-macros.js +7 -0
  88. package/dist/utils/debug.js +7 -0
  89. package/dist/utils/drill-down.d.ts +78 -0
  90. package/dist/utils/drill-down.js +93 -0
  91. package/dist/utils/emptiness.d.ts +96 -0
  92. package/dist/utils/emptiness.js +101 -0
  93. package/dist/utils/expand-fields.d.ts +171 -11
  94. package/dist/utils/expand-fields.js +171 -11
  95. package/dist/utils/extract-records.d.ts +65 -5
  96. package/dist/utils/extract-records.js +65 -8
  97. package/dist/utils/filter-converter.d.ts +152 -4
  98. package/dist/utils/filter-converter.js +1092 -22
  99. package/dist/utils/filter-tokens.d.ts +49 -5
  100. package/dist/utils/filter-tokens.js +105 -34
  101. package/dist/utils/freeze-schema.d.ts +38 -1
  102. package/dist/utils/freeze-schema.js +10 -0
  103. package/dist/utils/grouping-fields.d.ts +61 -0
  104. package/dist/utils/grouping-fields.js +84 -0
  105. package/dist/utils/humanize-label.d.ts +60 -0
  106. package/dist/utils/humanize-label.js +62 -0
  107. package/dist/utils/managedBy.d.ts +30 -5
  108. package/dist/utils/managedBy.js +5 -5
  109. package/dist/utils/native-date-value.d.ts +48 -0
  110. package/dist/utils/native-date-value.js +167 -0
  111. package/dist/utils/non-grid-row-ceiling.d.ts +143 -0
  112. package/dist/utils/non-grid-row-ceiling.js +141 -0
  113. package/dist/utils/normalize-list-view.d.ts +131 -1
  114. package/dist/utils/normalize-list-view.js +248 -6
  115. package/dist/utils/number-display.d.ts +70 -17
  116. package/dist/utils/number-display.js +34 -12
  117. package/dist/utils/object-aggregate-query.d.ts +113 -0
  118. package/dist/utils/object-aggregate-query.js +50 -0
  119. package/dist/utils/parent-scope.d.ts +123 -0
  120. package/dist/utils/parent-scope.js +140 -0
  121. package/dist/utils/predicate-fields.d.ts +62 -4
  122. package/dist/utils/predicate-fields.js +169 -4
  123. package/dist/utils/record-color.d.ts +75 -0
  124. package/dist/utils/record-color.js +65 -0
  125. package/dist/utils/record-source.d.ts +298 -0
  126. package/dist/utils/record-source.js +331 -0
  127. package/dist/utils/record-title.d.ts +148 -8
  128. package/dist/utils/record-title.js +220 -26
  129. package/dist/utils/reference-keys.d.ts +21 -22
  130. package/dist/utils/reference-keys.js +532 -29
  131. package/dist/utils/retired-field-types.d.ts +90 -0
  132. package/dist/utils/retired-field-types.js +124 -0
  133. package/dist/utils/sort-query.d.ts +128 -26
  134. package/dist/utils/sort-query.js +240 -13
  135. package/dist/utils/text-comparand.d.ts +92 -0
  136. package/dist/utils/text-comparand.js +99 -0
  137. package/dist/utils/unmaterialized-fields.d.ts +52 -0
  138. package/dist/utils/unmaterialized-fields.js +57 -0
  139. package/dist/utils/without-denied-fields.d.ts +49 -0
  140. package/dist/utils/without-denied-fields.js +52 -0
  141. package/dist/validation/index.d.ts +9 -4
  142. package/dist/validation/index.js +9 -4
  143. package/dist/validation/schema-validator.d.ts +1 -1
  144. package/dist/validation/schema-validator.js +305 -82
  145. package/dist/validation/server-owned-value.d.ts +62 -0
  146. package/dist/validation/server-owned-value.js +99 -0
  147. package/dist/validation/validators/object-validation-engine.d.ts +1 -1
  148. package/dist/validation/validators/object-validation-engine.js +14 -5
  149. package/package.json +8 -9
  150. package/dist/__benchmarks__/core.bench.d.ts +0 -8
  151. package/dist/__benchmarks__/core.bench.js +0 -53
  152. package/dist/data-scope/DataScopeManager.d.ts +0 -127
  153. package/dist/data-scope/DataScopeManager.js +0 -229
  154. package/dist/protocols/ResponsiveProtocol.d.ts +0 -73
  155. package/dist/protocols/ResponsiveProtocol.js +0 -158
  156. package/dist/validation/validation-engine.d.ts +0 -88
  157. package/dist/validation/validation-engine.js +0 -434
@@ -5,26 +5,150 @@
5
5
  * This source code is licensed under the MIT license found in the
6
6
  * LICENSE file in the root directory of this source tree.
7
7
  */
8
- import type { SchemaNode } from '../types/index.js';
8
+ import type { ComponentMeta as CanonicalComponentMeta } from '@object-ui/types';
9
+ import type { ComponentConfig } from '@object-ui/types';
10
+ /**
11
+ * The renderer a registration carries — the IDENTITY alias, deliberately.
12
+ *
13
+ * ⚠️ Load-bearing for objectui#6298, which is why it is documented rather than
14
+ * left as a bare line. `ComponentRenderer<T>` resolves to `T` and contributes
15
+ * NO type information: that is the entire reason `@object-ui/types` can declare
16
+ * the one `ComponentConfig` with `component: T` and mean exactly what this
17
+ * package used to mean by `component: ComponentRenderer<T>`, WITHOUT
18
+ * `@object-ui/types` needing to reach this declaration. It could not have
19
+ * reached it: `@object-ui/types` is the bottom layer (`packages/types/package.json`
20
+ * depends on `@objectstack/spec` and `zod` only) and this package depends on it,
21
+ * so an edge in that direction would be a cycle.
22
+ *
23
+ * The alias survives as the NAME this package's own renderer-shaped positions
24
+ * are spelled with ({@link withElementDataSourceInput}, {@link PublicComponentConfig}).
25
+ * If it is ever given real content, `component: T` over in `@object-ui/types`
26
+ * stops being the same slot — `__tests__/component-config-single-declaration.test.ts`
27
+ * asserts the identity so that change cannot pass unnoticed.
28
+ */
9
29
  export type ComponentRenderer<T = any> = T;
10
- export type ComponentInput = {
11
- name: string;
12
- type: 'string' | 'number' | 'boolean' | 'enum' | 'array' | 'object' | 'color' | 'date' | 'code' | 'file' | 'slot';
13
- label?: string;
14
- defaultValue?: any;
15
- required?: boolean;
16
- enum?: string[] | {
17
- label: string;
18
- value: any;
19
- }[];
20
- description?: string;
21
- advanced?: boolean;
22
- inputType?: string;
30
+ /**
31
+ * What a registration DECLARES about one authorable prop.
32
+ *
33
+ * This is the declaration the component registrations themselves import, so it
34
+ * is the one an author's manifest is ultimately built from — and it is now
35
+ * RE-EXPORTED from `@object-ui/types` rather than restated here
36
+ * (objectui#4972), the disposition objectui#4580 ruled for the identical
37
+ * shape: *a structural copy would reproduce the defect the moment either side
38
+ * moved.* This package already depends on `@object-ui/types`, so the edge
39
+ * exists and adds no cycle, and `src/types/index.ts` re-exports `SchemaNode`
40
+ * from there the same way.
41
+ *
42
+ * The copy this replaces had ALREADY moved, which is why the card is not
43
+ * hypothetical: it carried nine keys while `base.ts` carried thirteen, so
44
+ * `min` / `max` / `step` / `placeholder` were missing from *the copy every
45
+ * registration actually imports*. Those four keys were therefore unwritable at
46
+ * any real registration — a plain TS error — while `ComponentInputSchema` (the
47
+ * zod schema) and `ComponentMeta.inputs` both accepted them. The publication
48
+ * face advertised four keys the authoring face rejected; the divergence was
49
+ * dormant only because no registration had tried to write one yet.
50
+ */
51
+ export type { ComponentInput } from '@object-ui/types';
52
+ /**
53
+ * An AUTHORING SURFACE a component type can be reached from — the two this
54
+ * engine has, named as its own code already names them.
55
+ *
56
+ * - `'json'` — the JSON/SDUI authoring surface. A node an author (or an AI)
57
+ * writes as `{ "type": "…" }` in metadata.
58
+ * - `'html'` — a `kind:'html'` page, written as constrained JSX text that
59
+ * `@object-ui/sdui-parser` COMPILES (never executes) into SDUI nodes, tag
60
+ * name straight through. `isHtmlTierNode` marks what that parser emitted.
61
+ *
62
+ * The distinction is not decorative here: it is the whole reason
63
+ * {@link ComponentDeprecation} carries a surface list rather than a boolean.
64
+ */
65
+ export type AuthoringSurface = 'json' | 'html';
66
+ /**
67
+ * That a component type is DEPRECATED for authoring — the machine-readable
68
+ * statement of it (objectui#6674).
69
+ *
70
+ * ## Why this exists at all
71
+ *
72
+ * Before this type, a deprecation was stated in exactly two places, neither of
73
+ * which any gate, test or type can consult: a `console.warn` STRING LITERAL
74
+ * inside the renderer, and the word "(Deprecated)" inside a human-readable
75
+ * `label`. So the question "is this type deprecated?" had no asker. The two
76
+ * gates that touch component types — `examples/schema-catalog/test/
77
+ * catalog-gallery-render.test.tsx` and `scripts/check-doc-component-types.mjs`
78
+ * — both ask only whether a type RESOLVES, and a deprecated type resolves
79
+ * perfectly well. The measurement objectui#6674 filed is what that costs: the
80
+ * catalog suite passes 583/583 with 85 authored `div` nodes in the corpus. The
81
+ * green was the finding.
82
+ *
83
+ * This is a layer BELOW the usual "declared but enforced nowhere" defect: there
84
+ * was nothing declared to enforce.
85
+ *
86
+ * ## Why `surfaces` is required, and why a boolean would have been wrong
87
+ *
88
+ * `deprecated: true` would restate, as a contract, the exact falsehood the
89
+ * maintainer ruled against on 2026-08-10 (objectui#4000): the `span` notice is
90
+ * scoped BY PROVENANCE because that tag is deprecated on the JSON surface and
91
+ * simultaneously vocabulary of the `kind:'html'` tier — an author there writes
92
+ * the plain tag, our own parser maps it straight through, and no other
93
+ * spelling exists for them to migrate to. "A notice that says the type is
94
+ * deprecated FULL STOP is therefore false for one of its two readers"
95
+ * (`span.tsx`), and the reader it was false for was the one who could do
96
+ * nothing about it. (`div` carried the same scope until ruling A on
97
+ * objectstack#20112 deprecated it on the html surface too, with `box` as its
98
+ * replacement; it now declares both surfaces — objectui#10757. The list is
99
+ * what let that be one edit.) A declaration that dropped the scope
100
+ * would hand every future gate the same false premise, in a form that is harder
101
+ * to see than a console string. So the scope travels WITH the declaration, and
102
+ * {@link Registry.deprecationFor} makes callers name the surface they are
103
+ * asking about instead of re-deriving the exemption locally.
104
+ *
105
+ * ## What it deliberately does not do
106
+ *
107
+ * Nothing here fails a build, and nothing here deprecates anything: this is the
108
+ * vocabulary plus the reader. Which types get marked, and when, is
109
+ * objectui#3965's to decide — the ordering matters, because marking a type
110
+ * while the corpus still authors it 85 times produces a red with nowhere to go.
111
+ */
112
+ export type ComponentDeprecation = {
113
+ /**
114
+ * The surfaces on which authoring this type is deprecated. A surface NOT
115
+ * listed keeps the type as first-class vocabulary there — that is the whole
116
+ * content of the objectui#4000 ruling, said once, in the declaration.
117
+ *
118
+ * Required and expected non-empty: an empty list declares a deprecation that
119
+ * applies to no reader, which is indistinguishable from not declaring one.
120
+ */
121
+ surfaces: AuthoringSurface[];
122
+ /**
123
+ * One line of migration guidance for the surfaces above — what to author
124
+ * instead. Optional, but it is what makes a gate's failure ACTIONABLE: a gate
125
+ * that can only say "deprecated" sends its reader back to the console string
126
+ * this declaration exists to replace.
127
+ */
128
+ replacement?: string;
23
129
  };
24
- export type ComponentMeta = {
25
- label?: string;
26
- icon?: string;
27
- category?: string;
130
+ /**
131
+ * The keys the REGISTRY adds on top of the one `ComponentMeta` declaration:
132
+ * registration mechanics (`tier` / `namespace` / `skipFallback`), the
133
+ * host-labelling contract (`labelling`), and the authoring-time
134
+ * `deprecated` declaration. None of the five has a counterpart on
135
+ * the general type in `@object-ui/types`, and none is being moved there —
136
+ * publishing registry mechanics on the general type was the alternative
137
+ * objectui#6067 weighed and rejected.
138
+ *
139
+ * They live in their OWN named type so that `ComponentMeta` below can be
140
+ * DERIVED from the canonical declaration instead of restating it. Until
141
+ * objectui#6067 this file carried a second, thirteen-key structural copy of
142
+ * the name: the nine shared members restated from `@object-ui/types`' `base.ts`,
143
+ * these four added here, and `tags` / `description` — declared on the canonical
144
+ * type and on the `ComponentMetaSchema` zod mirror — simply absent. That is
145
+ * objectui#4580's ruling coming true for the third type in a row: *a
146
+ * structural copy would reproduce the defect the moment either side moved.*
147
+ * objectui#5671 executed the same convergence for `ComponentInput` in this very
148
+ * file, and objectui#5893 closed the identical two-key delta inside
149
+ * `@object-ui/types`.
150
+ */
151
+ export type RegistryComponentMetaExtras = {
28
152
  /**
29
153
  * Public contract tier (ADR-0080). `'public'` = part of the curated,
30
154
  * type-checked, AI-facing block set (gets a strengthened contract, the
@@ -38,6 +162,12 @@ export type ComponentMeta = {
38
162
  * Use this when a component should only be accessible via its full namespaced key.
39
163
  * This avoids conflicts with other components that share the same base name.
40
164
  *
165
+ * ⚠️ That promise covers BOTH registry tables since objectui#9839, and it did
166
+ * not before. Declining the bare key used to leave `register` deleting a bare
167
+ * lazy stub anyway, so a registration that opted out still took the bare key
168
+ * off its owner — and then refused to replace it, leaving it claimed by
169
+ * nobody. An opt-out now leaves the bare key exactly where it was.
170
+ *
41
171
  * @example
42
172
  * // Register as 'view:form' only, don't overwrite 'form'
43
173
  * registry.register('form', FormView, { namespace: 'view', skipFallback: true });
@@ -45,7 +175,11 @@ export type ComponentMeta = {
45
175
  skipFallback?: boolean;
46
176
  /**
47
177
  * How a HOST must associate its own visible label with what this component
48
- * renders (objectui#3961). Read by the form renderer; absent ⇒ `'control'`.
178
+ * renders (objectui#3961, extended by objectui#4857). Read by the form
179
+ * renderer; absent ⇒ `'control'`. This closed three-value vocabulary is the
180
+ * single repo-wide answer to "how does a host learn what a widget will
181
+ * render" (maintainer ruling of 2026-08-17, joint with objectui#4871) — no
182
+ * host may keep a local variant of it.
49
183
  *
50
184
  * - `'control'` — the component's outermost rendered element is a LABELABLE
51
185
  * HTML element (`input` / `textarea` / `select` / `button` / …), so the host
@@ -58,7 +192,18 @@ export type ComponentMeta = {
58
192
  * nothing and contributes no accessible name (`HTMLLabelElement.control` is
59
193
  * `null`) — so the host must instead give its label an `id` and hand the
60
194
  * component `aria-labelledby`, which associates by IDREF and works on any
61
- * element.
195
+ * element. The COMPONENT consumes those keys on its own surface.
196
+ * - `'display'` — the rendered surface is a pure display in EVERY state:
197
+ * there is no focusable control and the component itself spreads nothing
198
+ * (computed / system-generated values such as `formula` / `summary` /
199
+ * `auto_number` / `vector`). The host must not emit a `<label for>` at all
200
+ * — no labelable element will ever exist for it to reach, in the editable
201
+ * state as much as the readonly one — and instead wraps the component's
202
+ * output in the host's own container carrying the field id,
203
+ * `aria-labelledby`, `aria-describedby` and `role="group"` (the
204
+ * objectui#4788 channel, driven by this declaration rather than by
205
+ * `readonly` alone). Unlike `'group'`, the WIDGET is not expected to
206
+ * consume anything: the host's wrapper is the named surface.
62
207
  *
63
208
  * This is a DECLARATION, not a guess: the host cannot infer it from the DOM a
64
209
  * widget happens to render, and a widget that fails to declare it falls back
@@ -66,38 +211,126 @@ export type ComponentMeta = {
66
211
  * label-association tests (objectui#3952) instead of silently producing an
67
212
  * unlabelled group.
68
213
  */
69
- labelling?: 'control' | 'group';
70
- inputs?: ComponentInput[];
71
- defaultProps?: Record<string, any>;
72
- defaultChildren?: SchemaNode[];
73
- examples?: Record<string, any>;
74
- isContainer?: boolean;
75
- resizable?: boolean;
76
- resizeConstraints?: {
77
- width?: boolean;
78
- height?: boolean;
79
- minWidth?: number;
80
- maxWidth?: number;
81
- minHeight?: number;
82
- maxHeight?: number;
83
- };
84
- };
85
- export type ComponentConfig<T = any> = ComponentMeta & {
86
- type: string;
87
- component: ComponentRenderer<T>;
214
+ labelling?: 'control' | 'group' | 'display';
215
+ /**
216
+ * That authoring this type is DEPRECATED, and on which surfaces
217
+ * (objectui#6674). Absent ⇒ not deprecated anywhere; see
218
+ * {@link ComponentDeprecation} for why the surfaces are part of the
219
+ * declaration rather than a boolean, and {@link Registry.deprecationFor} for
220
+ * the reader a gate asks.
221
+ *
222
+ * This is a DECLARATION about the TYPE, which is why it sits on the
223
+ * registration rather than on a node: every node of a deprecated type is
224
+ * deprecated, and the one place that fact can be stated once is where the
225
+ * type is registered.
226
+ */
227
+ deprecated?: ComponentDeprecation;
88
228
  };
229
+ /**
230
+ * What a registration DECLARES about one component — the type every
231
+ * `ComponentRegistry.register` / `registerLazy` call is checked against.
232
+ *
233
+ * ONE declaration of the shared members: this is `@object-ui/types`'
234
+ * `ComponentMeta` (the declaration `ComponentMetaSchema` mirrors and the
235
+ * plugin-facing surface publishes) intersected with the registry-only keys
236
+ * above. The nine shared members are no longer restated here, so they cannot
237
+ * drift again, and `tags` / `description` now reach the registration surface —
238
+ * the two keys the divergence had made unwritable at the very declaration most
239
+ * component registrations import.
240
+ *
241
+ * NOTE for anyone pinning this: every member of both halves is OPTIONAL, so
242
+ * `extends` is mutually TRUE between the two shapes even when their key sets
243
+ * differ. Measured on the EMITTED `.d.ts` of both packages immediately before
244
+ * this convergence: `Core extends Canonical` and `Canonical extends Core` were
245
+ * BOTH `true` while `tags` / `description` were missing and four keys were
246
+ * extra. An assignability assertion is therefore a ghost here — it was green on
247
+ * the diverged tree. `__tests__/component-meta-derives-from-canonical.test.ts`
248
+ * compares `keyof` sets instead and keeps the assignability check beside it as
249
+ * the labelled control that shows why.
250
+ */
251
+ export type ComponentMeta = CanonicalComponentMeta & RegistryComponentMetaExtras;
252
+ /**
253
+ * ONE authority for `ComponentConfig` (objectui#6298) — this package RE-EXPORTS
254
+ * `@object-ui/types`' declaration instead of declaring a second one, the same
255
+ * disposition objectui#5671 gave `ComponentInput` a few lines above and
256
+ * objectui#4580 ruled for the whole family: *a structural copy would reproduce
257
+ * the defect the moment either side moved.*
258
+ *
259
+ * ## What was wrong
260
+ *
261
+ * Both spellings were PUBLISHED — `@object-ui/types`' `src/index.ts` exports its
262
+ * one, and this file reaches `@object-ui/core`'s public entry through
263
+ * `src/index.ts`'s `export * from './registry/Registry.js'`. An IDE auto-import
264
+ * therefore picked between two different types by alphabetical order. After
265
+ * objectui#6067 / PR #6297 single-sourced the `ComponentMeta` half, what still
266
+ * differed was GENERICITY AND THE `component` SLOT: `@object-ui/types`' was
267
+ * non-generic with `component: any`, this one was `<T = any>` with
268
+ * `component: ComponentRenderer<T>`.
269
+ *
270
+ * ⚠️ Measured on the EMITTED `.d.ts` of both packages immediately before this
271
+ * convergence, `Exact<TypesConfig, CoreConfig>` — mutual assignability — read
272
+ * `true` on the DIVERGED pair, because `component: any` absorbs everything and
273
+ * every other member is optional. An assignability assertion is a GHOST here,
274
+ * exactly as `__tests__/component-meta-derives-from-canonical.test.ts` records
275
+ * for the sibling type. The readings that actually moved were "is
276
+ * `@object-ui/types`' declaration generic" (`TS2315: Type 'ComponentConfig' is
277
+ * not generic` before, no error after) and the symmetric key-set difference.
278
+ *
279
+ * A re-export is not a second authority — `scripts/__tests__/one-authority-per-exported-name-6273.test.ts`
280
+ * counts declarations and ALIASING re-exports, never `export type { X } from …`
281
+ * — which is why this convergence takes `ComponentConfig` off that gate's
282
+ * `KNOWN_COLLISIONS` baseline. Deriving a new declaration here instead would
283
+ * NOT have: `ComponentMeta` was converged that way by PR #6297 and is still a
284
+ * row on that baseline today.
285
+ */
286
+ export type { ComponentConfig } from '@object-ui/types';
287
+ /**
288
+ * What the registry actually STORES and hands back — `ComponentConfig` plus the
289
+ * registry-only keys, as a NAMED extension (objectui#6298).
290
+ *
291
+ * This is type-identical to the `ComponentConfig` this file used to declare:
292
+ * `CanonicalComponentMeta & RegistryComponentMetaExtras & { type; component }`,
293
+ * reached from the other side. The two halves are named rather than restated —
294
+ * one declaration for the shared members ({@link ComponentConfig}, in
295
+ * `@object-ui/types`), a named extension for the rest
296
+ * ({@link RegistryComponentMetaExtras}) — which is the shape PR #6297 gave
297
+ * {@link ComponentMeta}.
298
+ *
299
+ * It exists because the extras are NOT optional decoration on a registry entry:
300
+ * {@link Registry.getNamespaceComponents} filters on `config.namespace`, and
301
+ * `tier` / `labelling` / `deprecated` are read off registrations elsewhere. A
302
+ * bare re-export as the entry type would have silently dropped them.
303
+ *
304
+ * ⚠️ `ComponentConfig` remains the AUTHORING vocabulary and the general name;
305
+ * registrations are checked against {@link ComponentMeta}, never against this.
306
+ * Nothing writes a `RegistryComponentConfig` literal — the registry builds them.
307
+ */
308
+ export type RegistryComponentConfig<T = any> = ComponentConfig<T> & RegistryComponentMetaExtras;
89
309
  /**
90
310
  * A CONTRACT-surface entry (ADR-0080), as returned by
91
311
  * {@link Registry.getPublicConfigs}.
92
312
  *
93
- * Same shape as {@link ComponentConfig} except `component` is absent while the
313
+ * Same shape as {@link RegistryComponentConfig} except `component` is absent while the
94
314
  * entry is still a pending `registerLazy` stub: the plugin module has not been
95
315
  * imported yet, so there is no renderer to hand out. Consumers render such an
96
316
  * entry through `SchemaRenderer`, which triggers the loader and shows a
97
317
  * placeholder in the meantime (objectui#2953).
318
+ *
319
+ * `tier` is widened by one PROJECTION-ONLY value, `'html'`: an entry the html
320
+ * tier's intrinsic roster contributed (objectui#10735). No registration
321
+ * declares it — `RegistryComponentMetaExtras.tier` stays `'public' | 'internal'`
322
+ * — the read stamps it, and `manifestFromConfigs` carries it into the manifest
323
+ * so a consumer that means the CURATED vocabulary can filter it out.
98
324
  */
99
- export type PublicComponentConfig<T = any> = ComponentMeta & {
325
+ export type PublicComponentConfig<T = any> = Omit<ComponentMeta, 'tier'> & {
100
326
  type: string;
327
+ /**
328
+ * The registration's declared tier, or `'html'` for an entry that reaches the
329
+ * contract through {@link HTML_TIER_INTRINSICS} rather than through the
330
+ * curated roster or a `tier: 'public'` opt-in. Absent or `'public'` = the
331
+ * curated JSON-surface vocabulary.
332
+ */
333
+ tier?: ComponentMeta['tier'] | 'html';
101
334
  component?: ComponentRenderer<T>;
102
335
  /** True while this entry is a `registerLazy` stub whose loader has not run. */
103
336
  lazy?: boolean;
@@ -110,6 +343,58 @@ export type PublicComponentConfig<T = any> = ComponentMeta & {
110
343
  * `register()` for that type.
111
344
  */
112
345
  export type LazyComponentLoader = () => Promise<unknown>;
346
+ /**
347
+ * Emit the spec's `dataSource` input for a registration whose renderer wraps
348
+ * `ElementDataSourceGate` (objectui#6678).
349
+ *
350
+ * ## The one place, and why it is this one
351
+ *
352
+ * The maintainer ruling of 2026-08-29 adopted option B **in the injection
353
+ * form**: the declaration is emitted mechanically at the wrapping seam so every
354
+ * gate-wrapping registration declares the key from the same place that reads it
355
+ * — one mechanism rather than nine hand-kept copies across nine packages, which
356
+ * drift and which a tenth block would simply forget. `register()` is where every
357
+ * one of those registrations passes through, so it is where the emission lands;
358
+ * the DECLARATION itself is `ELEMENT_DATA_SOURCE_INPUT`, which lives beside the
359
+ * binding's own semantics in `data-scope/element-data-source.ts`.
360
+ *
361
+ * ## What it must NOT do, which is half the ruling
362
+ *
363
+ * Widening this to every registration is option A wearing a different hat: it
364
+ * would silence `dataSource` on `flex` and `card`, which do not read it, and the
365
+ * diagnostic would lie in the other direction instead of the one it lied in
366
+ * before. So the condition is the marker and nothing else — no heuristic over
367
+ * `objectName`, no "looks object-bound".
368
+ *
369
+ * ## Idempotent, and it never overwrites
370
+ *
371
+ * A registration that declares `dataSource` ITSELF keeps its own entry: the
372
+ * emission fills a gap, it does not own the key. (Nothing declares it today —
373
+ * that is the defect — but a block whose binding needs a narrower description
374
+ * later must be able to say so without fighting this function.) Re-registering
375
+ * the same component, which the registry allows and tests do constantly, is
376
+ * likewise a no-op rather than a growing `inputs` array.
377
+ *
378
+ * ## Typed end to end — the cast is gone (`9e37d9b39`)
379
+ *
380
+ * The spliced element is an `InjectedComponentInput` (`@object-ui/types`): a
381
+ * `ComponentInput` plus the framework-set `binding` marker, so it is a plain
382
+ * subtype of the array's element type and the return value type-checks as a
383
+ * `ComponentMeta` with no assertion. This used to read `as ComponentMeta`,
384
+ * because `ELEMENT_DATA_SOURCE_INPUT` carried a hand-written inline type and
385
+ * `binding` had no declared home — and a cast at the one place the key is
386
+ * written is exactly what would have hidden any later drift between the
387
+ * constant and the type. The absence is held by `eslint.config.js`, which
388
+ * scopes `@typescript-eslint/consistent-type-assertions` with
389
+ * `assertionStyle: 'never'` to THIS FILE (objectui#8316) — an AST rule,
390
+ * because `tsc --noEmit` stays at exit 0 with the cast re-added and the
391
+ * source-text pin that used to stand here was green for `<ComponentMeta>{…}`,
392
+ * the same assertion in the other spelling.
393
+ * `packages/types/src/__tests__/injected-component-input-6950.test.ts` still
394
+ * pins the positive half, that the local below is ANNOTATED. Keep it typed: if
395
+ * the shape ever stops fitting, that line is where the compiler should say so.
396
+ */
397
+ export declare function withElementDataSourceInput<T>(component: ComponentRenderer<T>, meta?: ComponentMeta): ComponentMeta | undefined;
113
398
  export declare class Registry<T = any> {
114
399
  private components;
115
400
  private lazyEntries;
@@ -149,9 +434,28 @@ export declare class Registry<T = any> {
149
434
  /**
150
435
  * Remove a previously registered component. Mirrors {@link register} by
151
436
  * clearing both the namespaced key and the bare-name fallback (when the
152
- * fallback still points at this registration), plus any matching lazy stub.
437
+ * fallback still points at this registration), plus any matching lazy stub —
438
+ * where "matching" means the same thing on both tables: a stub that still
439
+ * belongs to THIS registration (objectui#9839).
153
440
  * Notifies subscribers only when something was actually removed.
154
441
  *
442
+ * ⭐ Why "matching" cannot mean "a stub under either key". This function
443
+ * already answers that question for the bare `components` key and answers it
444
+ * "ownership" — it will not drop bare `dashboard` when it resolves to
445
+ * `plugin-dashboard:dashboard`. Reading the next line as an unconditional
446
+ * delete makes the SAME call, on the SAME bare key, with the SAME owner,
447
+ * take the opposite decision purely because the owner happens to be sitting
448
+ * in the other table at that instant — and which table it is sitting in is
449
+ * exactly the "has the chunk loaded yet" race that objectui#9533 and
450
+ * objectui#9821 are about. A policy that flips on chunk-load timing is not a
451
+ * policy, so the stub gets the ownership test too.
452
+ *
453
+ * ⚠️ The BARE form (`unregister(type)` with no namespace) is unchanged and
454
+ * is still the unconditional one, on both tables: `fullType === type` there,
455
+ * so the deletes below address the bare key directly. That is the "force"
456
+ * form teardown sites pair with the namespaced call, and taking it away
457
+ * would break them.
458
+ *
155
459
  * Mainly used by tests that install a stub renderer and need to restore the
156
460
  * prior registry state on teardown, since the registry is a process-level
157
461
  * singleton shared across test files.
@@ -228,7 +532,7 @@ export declare class Registry<T = any> {
228
532
  * @param namespace - Optional namespace for lookup priority
229
533
  * @returns Component configuration or undefined
230
534
  */
231
- getConfig(type: string, namespace?: string): ComponentConfig<T> | undefined;
535
+ getConfig(type: string, namespace?: string): RegistryComponentConfig<T> | undefined;
232
536
  /**
233
537
  * Check if a component type is registered.
234
538
  *
@@ -272,12 +576,48 @@ export declare class Registry<T = any> {
272
576
  * known", not as "declares no props".
273
577
  */
274
578
  getMeta(type: string, namespace?: string): ComponentMeta | undefined;
579
+ /**
580
+ * The deprecation `type` declares FOR `surface` — or `undefined` when it
581
+ * declares none there (objectui#6674).
582
+ *
583
+ * ## The question this makes askable
584
+ *
585
+ * "Is this type deprecated?" — which, before the {@link ComponentDeprecation}
586
+ * declaration existed, nothing could ask. The only two statements of a
587
+ * deprecation were a `console.warn` string literal in a renderer and the word
588
+ * "(Deprecated)" inside a human `label`; no gate, test or type can consult
589
+ * either. Both gates that touch component types ask whether a type RESOLVES,
590
+ * and a deprecated type resolves.
591
+ *
592
+ * ## Why the caller must name a surface
593
+ *
594
+ * Because the honest answer differs by surface, and a reader that dropped the
595
+ * distinction would let every caller re-derive it — which is how the same
596
+ * exemption ends up written N times and wrong in N-1 of them. `span` is
597
+ * deprecated for JSON-authored pages and is vocabulary of the `kind:'html'`
598
+ * tier (objectui#4000). Asking `deprecationFor('span', 'html')` therefore
599
+ * correctly answers `undefined` even when the type declares a `'json'`
600
+ * deprecation, while `deprecationFor('div', 'html')` answers the declaration,
601
+ * because `div` names both surfaces (objectui#10757). A gate over html-tier
602
+ * sources gets the right answer for either without knowing the rulings: the
603
+ * console's html compile reads exactly this to decide what it refuses.
604
+ *
605
+ * Returning the DECLARATION rather than a boolean is deliberate: the caller
606
+ * that has to report the finding also needs `replacement` to say what to
607
+ * author instead, and a boolean would send it back to the console string.
608
+ *
609
+ * Resolution is {@link getMeta}'s, so both spellings of a namespaced
610
+ * registration answer alike (`div` and `ui:div`), a `skipFallback` type
611
+ * answers only under its namespaced key, and a pending `registerLazy` stub
612
+ * answers from the meta it was registered with.
613
+ */
614
+ deprecationFor(type: string, surface: AuthoringSurface, namespace?: string): ComponentDeprecation | undefined;
275
615
  /**
276
616
  * Get all registered component configurations.
277
617
  *
278
618
  * @returns Array of all component configurations
279
619
  */
280
- getAllConfigs(): ComponentConfig<T>[];
620
+ getAllConfigs(): RegistryComponentConfig<T>[];
281
621
  /**
282
622
  * Resolve `tag` for the CONTRACT surface: the loaded registration when the
283
623
  * component is already in the registry, otherwise the metadata of a pending
@@ -290,9 +630,18 @@ export declare class Registry<T = any> {
290
630
  */
291
631
  private getContractConfig;
292
632
  /**
293
- * Get the curated PUBLIC-tier component configs (ADR-0080) — those registered
294
- * with `tier: 'public'`. This is the contract/AI-vocabulary surface, a subset
295
- * of the full rendering capability returned by {@link getAllConfigs}.
633
+ * Get the CONTRACT-surface component configs (ADR-0080) — what the published
634
+ * `sdui.manifest.json` serialises. A subset of the full rendering capability
635
+ * returned by {@link getAllConfigs}, made of two tiers:
636
+ *
637
+ * - the curated PUBLIC tier — `PUBLIC_BLOCKS` plus registrations that opted
638
+ * in with `tier: 'public'` — the JSON-surface AI-authoring vocabulary;
639
+ * - the html tier's registered intrinsic elements — `HTML_TIER_INTRINSICS`,
640
+ * each entry stamped `tier: 'html'` (objectui#10735). A `kind:'html'` page
641
+ * may author these tags and the gate that reads the manifest must accept
642
+ * them; they are NOT part of the curated vocabulary, so a consumer that
643
+ * means that vocabulary alone — the `kind:'react'` JSX scope, the block
644
+ * list, a census of curated blocks — filters on the stamp.
296
645
  *
297
646
  * Includes blocks that are only lazily registered so far; those come back
298
647
  * with `lazy: true` and no `component` (see {@link PublicComponentConfig}).
@@ -304,6 +653,6 @@ export declare class Registry<T = any> {
304
653
  * @param namespace - Namespace to filter by
305
654
  * @returns Array of component configurations in the namespace
306
655
  */
307
- getNamespaceComponents(namespace: string): ComponentConfig<T>[];
656
+ getNamespaceComponents(namespace: string): RegistryComponentConfig<T>[];
308
657
  }
309
658
  export declare const ComponentRegistry: Registry<any>;