@object-ui/core 17.6.0 → 18.0.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 (147) hide show
  1. package/CHANGELOG.md +7260 -0
  2. package/README.md +228 -14
  3. package/dist/actions/ActionEngine.d.ts +4 -2
  4. package/dist/actions/ActionEngine.js +13 -8
  5. package/dist/actions/ActionRunner.d.ts +473 -69
  6. package/dist/actions/ActionRunner.js +792 -125
  7. package/dist/actions/TransactionManager.d.ts +7 -2
  8. package/dist/actions/UndoManager.d.ts +8 -13
  9. package/dist/actions/actionKeys.d.ts +9 -7
  10. package/dist/actions/actionKeys.js +67 -14
  11. package/dist/actions/actionResponse.js +2 -2
  12. package/dist/actions/index.d.ts +2 -0
  13. package/dist/actions/index.js +2 -0
  14. package/dist/actions/navigationTarget.d.ts +41 -0
  15. package/dist/actions/navigationTarget.js +20 -0
  16. package/dist/actions/recordDelete.d.ts +154 -0
  17. package/dist/actions/recordDelete.js +110 -0
  18. package/dist/adapters/ApiDataSource.d.ts +8 -4
  19. package/dist/adapters/ApiDataSource.js +19 -7
  20. package/dist/adapters/ValueDataSource.d.ts +6 -1
  21. package/dist/adapters/ValueDataSource.js +1090 -98
  22. package/dist/adapters/batchTransaction.d.ts +1 -1
  23. package/dist/adapters/batchTransaction.js +1 -1
  24. package/dist/adapters/resolveDataSource.d.ts +9 -6
  25. package/dist/adapters/resolveDataSource.js +9 -12
  26. package/dist/builder/schema-builder.d.ts +38 -81
  27. package/dist/builder/schema-builder.js +33 -152
  28. package/dist/data-scope/ViewDataProvider.d.ts +8 -25
  29. package/dist/data-scope/ViewDataProvider.js +27 -54
  30. package/dist/data-scope/element-data-source.d.ts +261 -7
  31. package/dist/data-scope/element-data-source.js +342 -52
  32. package/dist/data-scope/index.d.ts +9 -4
  33. package/dist/data-scope/index.js +9 -4
  34. package/dist/evaluator/ExpressionEvaluator.d.ts +86 -0
  35. package/dist/evaluator/ExpressionEvaluator.js +184 -12
  36. package/dist/evaluator/FormulaFunctions.d.ts +0 -10
  37. package/dist/evaluator/FormulaFunctions.js +166 -27
  38. package/dist/evaluator/deadlineSettled.d.ts +40 -0
  39. package/dist/evaluator/deadlineSettled.js +45 -0
  40. package/dist/evaluator/declaredPredicate.d.ts +93 -9
  41. package/dist/evaluator/declaredPredicate.js +117 -16
  42. package/dist/evaluator/fieldRules.d.ts +88 -4
  43. package/dist/evaluator/fieldRules.js +208 -31
  44. package/dist/evaluator/index.d.ts +2 -0
  45. package/dist/evaluator/index.js +2 -0
  46. package/dist/evaluator/listConditional.d.ts +103 -34
  47. package/dist/evaluator/listConditional.js +127 -50
  48. package/dist/evaluator/optionRules.d.ts +77 -6
  49. package/dist/evaluator/optionRules.js +87 -10
  50. package/dist/evaluator/predicateInput.d.ts +15 -4
  51. package/dist/evaluator/predicateInput.js +35 -2
  52. package/dist/evaluator/rowPredicateCanon.d.ts +7 -18
  53. package/dist/evaluator/rowPredicateCanon.js +65 -115
  54. package/dist/evaluator/subjectPermissions.d.ts +105 -0
  55. package/dist/evaluator/subjectPermissions.js +86 -0
  56. package/dist/evaluator/unevaluablePredicate.d.ts +57 -0
  57. package/dist/evaluator/unevaluablePredicate.js +70 -0
  58. package/dist/index.d.ts +15 -0
  59. package/dist/index.js +83 -2
  60. package/dist/protocols/index.d.ts +0 -1
  61. package/dist/protocols/index.js +9 -1
  62. package/dist/registry/Registry.d.ts +382 -34
  63. package/dist/registry/Registry.js +247 -12
  64. package/dist/registry/WidgetRegistry.js +7 -3
  65. package/dist/registry/html-tier-intrinsics.d.ts +90 -0
  66. package/dist/registry/html-tier-intrinsics.js +110 -0
  67. package/dist/registry/public-blocks.d.ts +8 -0
  68. package/dist/registry/public-blocks.js +57 -0
  69. package/dist/theme/ThemeEngine.js +1 -1
  70. package/dist/utils/affordanceGrants.d.ts +371 -0
  71. package/dist/utils/affordanceGrants.js +252 -0
  72. package/dist/utils/chart-category-key.d.ts +82 -0
  73. package/dist/utils/chart-category-key.js +84 -0
  74. package/dist/utils/chart-measure-key.d.ts +64 -0
  75. package/dist/utils/chart-measure-key.js +65 -0
  76. package/dist/utils/chart-presentation.d.ts +95 -112
  77. package/dist/utils/chart-presentation.js +169 -104
  78. package/dist/utils/chart-series.d.ts +165 -5
  79. package/dist/utils/chart-series.js +123 -18
  80. package/dist/utils/column-sortability.d.ts +157 -0
  81. package/dist/utils/column-sortability.js +217 -0
  82. package/dist/utils/dashboard-filters.d.ts +38 -6
  83. package/dist/utils/dashboard-filters.js +107 -61
  84. package/dist/utils/dataset-format.d.ts +211 -30
  85. package/dist/utils/dataset-format.js +389 -46
  86. package/dist/utils/date-display.d.ts +346 -0
  87. package/dist/utils/date-display.js +644 -0
  88. package/dist/utils/date-macros.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 +81 -9
  94. package/dist/utils/expand-fields.js +81 -9
  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 +158 -6
  98. package/dist/utils/filter-converter.js +1098 -24
  99. package/dist/utils/filter-tokens.d.ts +49 -5
  100. package/dist/utils/filter-tokens.js +105 -33
  101. package/dist/utils/grouping-fields.d.ts +61 -0
  102. package/dist/utils/grouping-fields.js +84 -0
  103. package/dist/utils/managedBy.d.ts +3 -3
  104. package/dist/utils/managedBy.js +5 -5
  105. package/dist/utils/native-date-value.d.ts +48 -0
  106. package/dist/utils/native-date-value.js +167 -0
  107. package/dist/utils/non-grid-row-ceiling.d.ts +143 -0
  108. package/dist/utils/non-grid-row-ceiling.js +141 -0
  109. package/dist/utils/normalize-list-view.d.ts +135 -11
  110. package/dist/utils/normalize-list-view.js +243 -64
  111. package/dist/utils/number-display.d.ts +63 -14
  112. package/dist/utils/number-display.js +34 -12
  113. package/dist/utils/object-aggregate-query.d.ts +113 -0
  114. package/dist/utils/object-aggregate-query.js +50 -0
  115. package/dist/utils/parent-scope.d.ts +123 -0
  116. package/dist/utils/parent-scope.js +140 -0
  117. package/dist/utils/predicate-fields.d.ts +45 -12
  118. package/dist/utils/predicate-fields.js +141 -12
  119. package/dist/utils/record-color.d.ts +75 -0
  120. package/dist/utils/record-color.js +65 -0
  121. package/dist/utils/record-source.d.ts +298 -0
  122. package/dist/utils/record-source.js +331 -0
  123. package/dist/utils/record-title.d.ts +148 -8
  124. package/dist/utils/record-title.js +220 -26
  125. package/dist/utils/reference-keys.d.ts +21 -22
  126. package/dist/utils/reference-keys.js +532 -29
  127. package/dist/utils/sort-query.d.ts +115 -15
  128. package/dist/utils/sort-query.js +240 -13
  129. package/dist/utils/text-comparand.d.ts +92 -0
  130. package/dist/utils/text-comparand.js +99 -0
  131. package/dist/utils/without-denied-fields.d.ts +49 -0
  132. package/dist/utils/without-denied-fields.js +52 -0
  133. package/dist/validation/index.d.ts +8 -4
  134. package/dist/validation/index.js +8 -4
  135. package/dist/validation/schema-validator.d.ts +1 -1
  136. package/dist/validation/schema-validator.js +225 -83
  137. package/dist/validation/server-owned-value.d.ts +5 -1
  138. package/dist/validation/server-owned-value.js +5 -1
  139. package/dist/validation/validators/object-validation-engine.d.ts +1 -1
  140. package/dist/validation/validators/object-validation-engine.js +14 -3
  141. package/package.json +8 -9
  142. package/dist/data-scope/DataScopeManager.d.ts +0 -127
  143. package/dist/data-scope/DataScopeManager.js +0 -229
  144. package/dist/protocols/ResponsiveProtocol.d.ts +0 -73
  145. package/dist/protocols/ResponsiveProtocol.js +0 -158
  146. package/dist/validation/validation-engine.d.ts +0 -88
  147. package/dist/validation/validation-engine.js +0 -434
@@ -5,7 +5,27 @@
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 { ComponentInput } from '@object-ui/types';
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
30
  /**
11
31
  * What a registration DECLARES about one authorable prop.
@@ -29,10 +49,106 @@ export type ComponentRenderer<T = any> = T;
29
49
  * dormant only because no registration had tried to write one yet.
30
50
  */
31
51
  export type { ComponentInput } from '@object-ui/types';
32
- export type ComponentMeta = {
33
- label?: string;
34
- icon?: string;
35
- category?: string;
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;
129
+ };
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 `RegistryComponentMeta` 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 = {
36
152
  /**
37
153
  * Public contract tier (ADR-0080). `'public'` = part of the curated,
38
154
  * type-checked, AI-facing block set (gets a strengthened contract, the
@@ -46,6 +162,12 @@ export type ComponentMeta = {
46
162
  * Use this when a component should only be accessible via its full namespaced key.
47
163
  * This avoids conflicts with other components that share the same base name.
48
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
+ *
49
171
  * @example
50
172
  * // Register as 'view:form' only, don't overwrite 'form'
51
173
  * registry.register('form', FormView, { namespace: 'view', skipFallback: true });
@@ -90,36 +212,146 @@ export type ComponentMeta = {
90
212
  * unlabelled group.
91
213
  */
92
214
  labelling?: 'control' | 'group' | 'display';
93
- inputs?: ComponentInput[];
94
- defaultProps?: Record<string, any>;
95
- examples?: Record<string, any>;
96
- isContainer?: boolean;
97
- resizable?: boolean;
98
- resizeConstraints?: {
99
- width?: boolean;
100
- height?: boolean;
101
- minWidth?: number;
102
- maxWidth?: number;
103
- minHeight?: number;
104
- maxHeight?: number;
105
- };
106
- };
107
- export type ComponentConfig<T = any> = ComponentMeta & {
108
- type: string;
109
- component: ComponentRenderer<T>;
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;
110
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
+ * ## Its own NAME since objectui#6349 (batch 4)
242
+ *
243
+ * This type used to be published as `ComponentMeta` too — the same name as the
244
+ * canonical declaration it extends, with a different meaning (registration
245
+ * metadata: the canonical members PLUS the five registry-only keys). A derived
246
+ * declaration is still a second authority for the name, so the card's rename
247
+ * branch applies: the registration type is `RegistryComponentMeta` (the name
248
+ * `PluginScopeImpl.ts` already gave it locally), and `ComponentMeta` from this
249
+ * package is a plain re-export of `@object-ui/types`' one (just below). The
250
+ * registry's own doors — `register`, `registerLazy`, `getMeta` — are typed
251
+ * with this name, so a registration literal keeps accepting the registry keys.
252
+ *
253
+ * NOTE for anyone pinning this: every member of both halves is OPTIONAL, so
254
+ * `extends` is mutually TRUE between the two shapes even when their key sets
255
+ * differ. Measured on the EMITTED `.d.ts` of both packages immediately before
256
+ * this convergence: `Core extends Canonical` and `Canonical extends Core` were
257
+ * BOTH `true` while `tags` / `description` were missing and four keys were
258
+ * extra. An assignability assertion is therefore a ghost here — it was green on
259
+ * the diverged tree. `__tests__/component-meta-derives-from-canonical.test.ts`
260
+ * compares `keyof` sets instead and keeps the assignability check beside it as
261
+ * the labelled control that shows why.
262
+ */
263
+ export type RegistryComponentMeta = CanonicalComponentMeta & RegistryComponentMetaExtras;
264
+ /**
265
+ * The general component metadata — `@object-ui/types`' ONE declaration,
266
+ * re-exported so an import of `ComponentMeta` from this package resolves to
267
+ * the same type as one from `@object-ui/types` (objectui#6349, batch 4). It
268
+ * carries none of the registry-only keys; a registration is typed with
269
+ * {@link RegistryComponentMeta}.
270
+ */
271
+ export type { ComponentMeta } from '@object-ui/types';
272
+ /**
273
+ * ONE authority for `ComponentConfig` (objectui#6298) — this package RE-EXPORTS
274
+ * `@object-ui/types`' declaration instead of declaring a second one, the same
275
+ * disposition objectui#5671 gave `ComponentInput` a few lines above and
276
+ * objectui#4580 ruled for the whole family: *a structural copy would reproduce
277
+ * the defect the moment either side moved.*
278
+ *
279
+ * ## What was wrong
280
+ *
281
+ * Both spellings were PUBLISHED — `@object-ui/types`' `src/index.ts` exports its
282
+ * one, and this file reaches `@object-ui/core`'s public entry through
283
+ * `src/index.ts`'s `export * from './registry/Registry.js'`. An IDE auto-import
284
+ * therefore picked between two different types by alphabetical order. After
285
+ * objectui#6067 / PR #6297 single-sourced the `ComponentMeta` half, what still
286
+ * differed was GENERICITY AND THE `component` SLOT: `@object-ui/types`' was
287
+ * non-generic with `component: any`, this one was `<T = any>` with
288
+ * `component: ComponentRenderer<T>`.
289
+ *
290
+ * ⚠️ Measured on the EMITTED `.d.ts` of both packages immediately before this
291
+ * convergence, `Exact<TypesConfig, CoreConfig>` — mutual assignability — read
292
+ * `true` on the DIVERGED pair, because `component: any` absorbs everything and
293
+ * every other member is optional. An assignability assertion is a GHOST here,
294
+ * exactly as `__tests__/component-meta-derives-from-canonical.test.ts` records
295
+ * for the sibling type. The readings that actually moved were "is
296
+ * `@object-ui/types`' declaration generic" (`TS2315: Type 'ComponentConfig' is
297
+ * not generic` before, no error after) and the symmetric key-set difference.
298
+ *
299
+ * A re-export is not a second authority — `scripts/__tests__/one-authority-per-exported-name-6273.test.ts`
300
+ * counts declarations and ALIASING re-exports, never `export type { X } from …`
301
+ * — which is why this convergence takes `ComponentConfig` off that gate's
302
+ * `KNOWN_COLLISIONS` baseline. Deriving a new declaration here instead would
303
+ * NOT have: `ComponentMeta` was converged that way by PR #6297 and stayed a row
304
+ * on that baseline until objectui#6349 gave the registry's declaration its own
305
+ * name, `RegistryComponentMeta`.
306
+ */
307
+ export type { ComponentConfig } from '@object-ui/types';
308
+ /**
309
+ * What the registry actually STORES and hands back — `ComponentConfig` plus the
310
+ * registry-only keys, as a NAMED extension (objectui#6298).
311
+ *
312
+ * This is type-identical to the `ComponentConfig` this file used to declare:
313
+ * `CanonicalComponentMeta & RegistryComponentMetaExtras & { type; component }`,
314
+ * reached from the other side. The two halves are named rather than restated —
315
+ * one declaration for the shared members ({@link ComponentConfig}, in
316
+ * `@object-ui/types`), a named extension for the rest
317
+ * ({@link RegistryComponentMetaExtras}) — which is the shape PR #6297 gave
318
+ * {@link RegistryComponentMeta}.
319
+ *
320
+ * It exists because the extras are NOT optional decoration on a registry entry:
321
+ * {@link Registry.getNamespaceComponents} filters on `config.namespace`, and
322
+ * `tier` / `labelling` / `deprecated` are read off registrations elsewhere. A
323
+ * bare re-export as the entry type would have silently dropped them.
324
+ *
325
+ * ⚠️ `ComponentConfig` remains the AUTHORING vocabulary and the general name;
326
+ * registrations are checked against {@link RegistryComponentMeta}, never against this.
327
+ * Nothing writes a `RegistryComponentConfig` literal — the registry builds them.
328
+ */
329
+ export type RegistryComponentConfig<T = any> = ComponentConfig<T> & RegistryComponentMetaExtras;
111
330
  /**
112
331
  * A CONTRACT-surface entry (ADR-0080), as returned by
113
332
  * {@link Registry.getPublicConfigs}.
114
333
  *
115
- * Same shape as {@link ComponentConfig} except `component` is absent while the
334
+ * Same shape as {@link RegistryComponentConfig} except `component` is absent while the
116
335
  * entry is still a pending `registerLazy` stub: the plugin module has not been
117
336
  * imported yet, so there is no renderer to hand out. Consumers render such an
118
337
  * entry through `SchemaRenderer`, which triggers the loader and shows a
119
338
  * placeholder in the meantime (objectui#2953).
339
+ *
340
+ * `tier` is widened by one PROJECTION-ONLY value, `'html'`: an entry the html
341
+ * tier's intrinsic roster contributed (objectui#10735). No registration
342
+ * declares it — `RegistryComponentMetaExtras.tier` stays `'public' | 'internal'`
343
+ * — the read stamps it, and `manifestFromConfigs` carries it into the manifest
344
+ * so a consumer that means the CURATED vocabulary can filter it out.
120
345
  */
121
- export type PublicComponentConfig<T = any> = ComponentMeta & {
346
+ export type PublicComponentConfig<T = any> = Omit<RegistryComponentMeta, 'tier'> & {
122
347
  type: string;
348
+ /**
349
+ * The registration's declared tier, or `'html'` for an entry that reaches the
350
+ * contract through {@link HTML_TIER_INTRINSICS} rather than through the
351
+ * curated roster or a `tier: 'public'` opt-in. Absent or `'public'` = the
352
+ * curated JSON-surface vocabulary.
353
+ */
354
+ tier?: RegistryComponentMeta['tier'] | 'html';
123
355
  component?: ComponentRenderer<T>;
124
356
  /** True while this entry is a `registerLazy` stub whose loader has not run. */
125
357
  lazy?: boolean;
@@ -132,6 +364,58 @@ export type PublicComponentConfig<T = any> = ComponentMeta & {
132
364
  * `register()` for that type.
133
365
  */
134
366
  export type LazyComponentLoader = () => Promise<unknown>;
367
+ /**
368
+ * Emit the spec's `dataSource` input for a registration whose renderer wraps
369
+ * `ElementDataSourceGate` (objectui#6678).
370
+ *
371
+ * ## The one place, and why it is this one
372
+ *
373
+ * The maintainer ruling of 2026-08-29 adopted option B **in the injection
374
+ * form**: the declaration is emitted mechanically at the wrapping seam so every
375
+ * gate-wrapping registration declares the key from the same place that reads it
376
+ * — one mechanism rather than nine hand-kept copies across nine packages, which
377
+ * drift and which a tenth block would simply forget. `register()` is where every
378
+ * one of those registrations passes through, so it is where the emission lands;
379
+ * the DECLARATION itself is `ELEMENT_DATA_SOURCE_INPUT`, which lives beside the
380
+ * binding's own semantics in `data-scope/element-data-source.ts`.
381
+ *
382
+ * ## What it must NOT do, which is half the ruling
383
+ *
384
+ * Widening this to every registration is option A wearing a different hat: it
385
+ * would silence `dataSource` on `flex` and `card`, which do not read it, and the
386
+ * diagnostic would lie in the other direction instead of the one it lied in
387
+ * before. So the condition is the marker and nothing else — no heuristic over
388
+ * `objectName`, no "looks object-bound".
389
+ *
390
+ * ## Idempotent, and it never overwrites
391
+ *
392
+ * A registration that declares `dataSource` ITSELF keeps its own entry: the
393
+ * emission fills a gap, it does not own the key. (Nothing declares it today —
394
+ * that is the defect — but a block whose binding needs a narrower description
395
+ * later must be able to say so without fighting this function.) Re-registering
396
+ * the same component, which the registry allows and tests do constantly, is
397
+ * likewise a no-op rather than a growing `inputs` array.
398
+ *
399
+ * ## Typed end to end — the cast is gone (`9e37d9b39`)
400
+ *
401
+ * The spliced element is an `InjectedComponentInput` (`@object-ui/types`): a
402
+ * `ComponentInput` plus the framework-set `binding` marker, so it is a plain
403
+ * subtype of the array's element type and the return value type-checks as a
404
+ * `RegistryComponentMeta` with no assertion. This used to read `as ComponentMeta`,
405
+ * because `ELEMENT_DATA_SOURCE_INPUT` carried a hand-written inline type and
406
+ * `binding` had no declared home — and a cast at the one place the key is
407
+ * written is exactly what would have hidden any later drift between the
408
+ * constant and the type. The absence is held by `eslint.config.js`, which
409
+ * scopes `@typescript-eslint/consistent-type-assertions` with
410
+ * `assertionStyle: 'never'` to THIS FILE (objectui#8316) — an AST rule,
411
+ * because `tsc --noEmit` stays at exit 0 with the cast re-added and the
412
+ * source-text pin that used to stand here was green for `<ComponentMeta>{…}`,
413
+ * the same assertion in the other spelling.
414
+ * `packages/types/src/__tests__/injected-component-input-6950.test.ts` still
415
+ * pins the positive half, that the local below is ANNOTATED. Keep it typed: if
416
+ * the shape ever stops fitting, that line is where the compiler should say so.
417
+ */
418
+ export declare function withElementDataSourceInput<T>(component: ComponentRenderer<T>, meta?: RegistryComponentMeta): RegistryComponentMeta | undefined;
135
419
  export declare class Registry<T = any> {
136
420
  private components;
137
421
  private lazyEntries;
@@ -167,13 +451,32 @@ export declare class Registry<T = any> {
167
451
  * registry.register('button', ButtonComponent);
168
452
  * // Accessible as 'button'
169
453
  */
170
- register(type: string, component: ComponentRenderer<T>, meta?: ComponentMeta): void;
454
+ register(type: string, component: ComponentRenderer<T>, meta?: RegistryComponentMeta): void;
171
455
  /**
172
456
  * Remove a previously registered component. Mirrors {@link register} by
173
457
  * clearing both the namespaced key and the bare-name fallback (when the
174
- * fallback still points at this registration), plus any matching lazy stub.
458
+ * fallback still points at this registration), plus any matching lazy stub —
459
+ * where "matching" means the same thing on both tables: a stub that still
460
+ * belongs to THIS registration (objectui#9839).
175
461
  * Notifies subscribers only when something was actually removed.
176
462
  *
463
+ * ⭐ Why "matching" cannot mean "a stub under either key". This function
464
+ * already answers that question for the bare `components` key and answers it
465
+ * "ownership" — it will not drop bare `dashboard` when it resolves to
466
+ * `plugin-dashboard:dashboard`. Reading the next line as an unconditional
467
+ * delete makes the SAME call, on the SAME bare key, with the SAME owner,
468
+ * take the opposite decision purely because the owner happens to be sitting
469
+ * in the other table at that instant — and which table it is sitting in is
470
+ * exactly the "has the chunk loaded yet" race that objectui#9533 and
471
+ * objectui#9821 are about. A policy that flips on chunk-load timing is not a
472
+ * policy, so the stub gets the ownership test too.
473
+ *
474
+ * ⚠️ The BARE form (`unregister(type)` with no namespace) is unchanged and
475
+ * is still the unconditional one, on both tables: `fullType === type` there,
476
+ * so the deletes below address the bare key directly. That is the "force"
477
+ * form teardown sites pair with the namespaced call, and taking it away
478
+ * would break them.
479
+ *
177
480
  * Mainly used by tests that install a stub renderer and need to restore the
178
481
  * prior registry state on teardown, since the registry is a process-level
179
482
  * singleton shared across test files.
@@ -191,7 +494,7 @@ export declare class Registry<T = any> {
191
494
  * @example
192
495
  * ComponentRegistry.registerLazy('object-map', () => import('@object-ui/plugin-map'), { namespace: 'plugin-map' });
193
496
  */
194
- registerLazy(type: string, loader: LazyComponentLoader, meta?: ComponentMeta): void;
497
+ registerLazy(type: string, loader: LazyComponentLoader, meta?: RegistryComponentMeta): void;
195
498
  /**
196
499
  * Returns true if `type` (or its namespaced form) has a registered lazy
197
500
  * loader awaiting first use.
@@ -250,7 +553,7 @@ export declare class Registry<T = any> {
250
553
  * @param namespace - Optional namespace for lookup priority
251
554
  * @returns Component configuration or undefined
252
555
  */
253
- getConfig(type: string, namespace?: string): ComponentConfig<T> | undefined;
556
+ getConfig(type: string, namespace?: string): RegistryComponentConfig<T> | undefined;
254
557
  /**
255
558
  * Check if a component type is registered.
256
559
  *
@@ -293,13 +596,49 @@ export declare class Registry<T = any> {
293
596
  * absent until the chunk loads. Consumers should treat that as "not yet
294
597
  * known", not as "declares no props".
295
598
  */
296
- getMeta(type: string, namespace?: string): ComponentMeta | undefined;
599
+ getMeta(type: string, namespace?: string): RegistryComponentMeta | undefined;
600
+ /**
601
+ * The deprecation `type` declares FOR `surface` — or `undefined` when it
602
+ * declares none there (objectui#6674).
603
+ *
604
+ * ## The question this makes askable
605
+ *
606
+ * "Is this type deprecated?" — which, before the {@link ComponentDeprecation}
607
+ * declaration existed, nothing could ask. The only two statements of a
608
+ * deprecation were a `console.warn` string literal in a renderer and the word
609
+ * "(Deprecated)" inside a human `label`; no gate, test or type can consult
610
+ * either. Both gates that touch component types ask whether a type RESOLVES,
611
+ * and a deprecated type resolves.
612
+ *
613
+ * ## Why the caller must name a surface
614
+ *
615
+ * Because the honest answer differs by surface, and a reader that dropped the
616
+ * distinction would let every caller re-derive it — which is how the same
617
+ * exemption ends up written N times and wrong in N-1 of them. `span` is
618
+ * deprecated for JSON-authored pages and is vocabulary of the `kind:'html'`
619
+ * tier (objectui#4000). Asking `deprecationFor('span', 'html')` therefore
620
+ * correctly answers `undefined` even when the type declares a `'json'`
621
+ * deprecation, while `deprecationFor('div', 'html')` answers the declaration,
622
+ * because `div` names both surfaces (objectui#10757). A gate over html-tier
623
+ * sources gets the right answer for either without knowing the rulings: the
624
+ * console's html compile reads exactly this to decide what it refuses.
625
+ *
626
+ * Returning the DECLARATION rather than a boolean is deliberate: the caller
627
+ * that has to report the finding also needs `replacement` to say what to
628
+ * author instead, and a boolean would send it back to the console string.
629
+ *
630
+ * Resolution is {@link getMeta}'s, so both spellings of a namespaced
631
+ * registration answer alike (`div` and `ui:div`), a `skipFallback` type
632
+ * answers only under its namespaced key, and a pending `registerLazy` stub
633
+ * answers from the meta it was registered with.
634
+ */
635
+ deprecationFor(type: string, surface: AuthoringSurface, namespace?: string): ComponentDeprecation | undefined;
297
636
  /**
298
637
  * Get all registered component configurations.
299
638
  *
300
639
  * @returns Array of all component configurations
301
640
  */
302
- getAllConfigs(): ComponentConfig<T>[];
641
+ getAllConfigs(): RegistryComponentConfig<T>[];
303
642
  /**
304
643
  * Resolve `tag` for the CONTRACT surface: the loaded registration when the
305
644
  * component is already in the registry, otherwise the metadata of a pending
@@ -312,9 +651,18 @@ export declare class Registry<T = any> {
312
651
  */
313
652
  private getContractConfig;
314
653
  /**
315
- * Get the curated PUBLIC-tier component configs (ADR-0080) — those registered
316
- * with `tier: 'public'`. This is the contract/AI-vocabulary surface, a subset
317
- * of the full rendering capability returned by {@link getAllConfigs}.
654
+ * Get the CONTRACT-surface component configs (ADR-0080) — what the published
655
+ * `sdui.manifest.json` serialises. A subset of the full rendering capability
656
+ * returned by {@link getAllConfigs}, made of two tiers:
657
+ *
658
+ * - the curated PUBLIC tier — `PUBLIC_BLOCKS` plus registrations that opted
659
+ * in with `tier: 'public'` — the JSON-surface AI-authoring vocabulary;
660
+ * - the html tier's registered intrinsic elements — `HTML_TIER_INTRINSICS`,
661
+ * each entry stamped `tier: 'html'` (objectui#10735). A `kind:'html'` page
662
+ * may author these tags and the gate that reads the manifest must accept
663
+ * them; they are NOT part of the curated vocabulary, so a consumer that
664
+ * means that vocabulary alone — the `kind:'react'` JSX scope, the block
665
+ * list, a census of curated blocks — filters on the stamp.
318
666
  *
319
667
  * Includes blocks that are only lazily registered so far; those come back
320
668
  * with `lazy: true` and no `component` (see {@link PublicComponentConfig}).
@@ -326,6 +674,6 @@ export declare class Registry<T = any> {
326
674
  * @param namespace - Namespace to filter by
327
675
  * @returns Array of component configurations in the namespace
328
676
  */
329
- getNamespaceComponents(namespace: string): ComponentConfig<T>[];
677
+ getNamespaceComponents(namespace: string): RegistryComponentConfig<T>[];
330
678
  }
331
679
  export declare const ComponentRegistry: Registry<any>;