@object-ui/core 17.6.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 (134) hide show
  1. package/CHANGELOG.md +6610 -0
  2. package/README.md +101 -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 +288 -27
  6. package/dist/actions/ActionRunner.js +443 -63
  7. package/dist/actions/TransactionManager.d.ts +7 -2
  8. package/dist/actions/actionKeys.d.ts +9 -7
  9. package/dist/actions/actionKeys.js +57 -14
  10. package/dist/actions/actionResponse.js +2 -2
  11. package/dist/actions/index.d.ts +1 -0
  12. package/dist/actions/index.js +1 -0
  13. package/dist/actions/recordDelete.d.ts +118 -0
  14. package/dist/actions/recordDelete.js +112 -0
  15. package/dist/adapters/ValueDataSource.d.ts +6 -1
  16. package/dist/adapters/ValueDataSource.js +1090 -98
  17. package/dist/adapters/batchTransaction.d.ts +1 -1
  18. package/dist/adapters/batchTransaction.js +1 -1
  19. package/dist/builder/schema-builder.d.ts +38 -81
  20. package/dist/builder/schema-builder.js +33 -152
  21. package/dist/data-scope/ViewDataProvider.d.ts +1 -1
  22. package/dist/data-scope/ViewDataProvider.js +21 -1
  23. package/dist/data-scope/element-data-source.d.ts +261 -7
  24. package/dist/data-scope/element-data-source.js +342 -52
  25. package/dist/data-scope/index.d.ts +9 -4
  26. package/dist/data-scope/index.js +9 -4
  27. package/dist/evaluator/ExpressionEvaluator.d.ts +86 -0
  28. package/dist/evaluator/ExpressionEvaluator.js +184 -12
  29. package/dist/evaluator/FormulaFunctions.d.ts +0 -10
  30. package/dist/evaluator/FormulaFunctions.js +166 -27
  31. package/dist/evaluator/declaredPredicate.d.ts +93 -9
  32. package/dist/evaluator/declaredPredicate.js +117 -16
  33. package/dist/evaluator/fieldRules.d.ts +88 -4
  34. package/dist/evaluator/fieldRules.js +203 -31
  35. package/dist/evaluator/index.d.ts +1 -0
  36. package/dist/evaluator/index.js +1 -0
  37. package/dist/evaluator/listConditional.d.ts +103 -34
  38. package/dist/evaluator/listConditional.js +127 -50
  39. package/dist/evaluator/optionRules.d.ts +77 -6
  40. package/dist/evaluator/optionRules.js +87 -10
  41. package/dist/evaluator/predicateInput.d.ts +15 -4
  42. package/dist/evaluator/predicateInput.js +35 -2
  43. package/dist/evaluator/rowPredicateCanon.d.ts +7 -18
  44. package/dist/evaluator/rowPredicateCanon.js +65 -115
  45. package/dist/evaluator/subjectPermissions.d.ts +76 -0
  46. package/dist/evaluator/subjectPermissions.js +44 -0
  47. package/dist/evaluator/unevaluablePredicate.d.ts +57 -0
  48. package/dist/evaluator/unevaluablePredicate.js +70 -0
  49. package/dist/index.d.ts +14 -0
  50. package/dist/index.js +80 -2
  51. package/dist/protocols/index.d.ts +0 -1
  52. package/dist/protocols/index.js +9 -1
  53. package/dist/registry/Registry.d.ts +358 -31
  54. package/dist/registry/Registry.js +263 -11
  55. package/dist/registry/WidgetRegistry.js +7 -3
  56. package/dist/registry/html-tier-intrinsics.d.ts +90 -0
  57. package/dist/registry/html-tier-intrinsics.js +110 -0
  58. package/dist/registry/public-blocks.d.ts +8 -0
  59. package/dist/registry/public-blocks.js +57 -0
  60. package/dist/theme/ThemeEngine.js +1 -1
  61. package/dist/utils/chart-category-key.d.ts +82 -0
  62. package/dist/utils/chart-category-key.js +84 -0
  63. package/dist/utils/chart-measure-key.d.ts +64 -0
  64. package/dist/utils/chart-measure-key.js +65 -0
  65. package/dist/utils/chart-presentation.d.ts +95 -112
  66. package/dist/utils/chart-presentation.js +169 -104
  67. package/dist/utils/chart-series.d.ts +131 -5
  68. package/dist/utils/chart-series.js +98 -16
  69. package/dist/utils/column-sortability.d.ts +157 -0
  70. package/dist/utils/column-sortability.js +217 -0
  71. package/dist/utils/dashboard-filters.d.ts +38 -6
  72. package/dist/utils/dashboard-filters.js +107 -61
  73. package/dist/utils/dataset-format.d.ts +211 -30
  74. package/dist/utils/dataset-format.js +389 -46
  75. package/dist/utils/date-display.d.ts +354 -0
  76. package/dist/utils/date-display.js +463 -0
  77. package/dist/utils/date-macros.js +7 -0
  78. package/dist/utils/drill-down.d.ts +78 -0
  79. package/dist/utils/drill-down.js +93 -0
  80. package/dist/utils/emptiness.d.ts +96 -0
  81. package/dist/utils/emptiness.js +101 -0
  82. package/dist/utils/expand-fields.d.ts +76 -6
  83. package/dist/utils/expand-fields.js +76 -6
  84. package/dist/utils/extract-records.d.ts +65 -5
  85. package/dist/utils/extract-records.js +65 -8
  86. package/dist/utils/filter-converter.d.ts +152 -4
  87. package/dist/utils/filter-converter.js +1092 -22
  88. package/dist/utils/filter-tokens.d.ts +49 -5
  89. package/dist/utils/filter-tokens.js +105 -33
  90. package/dist/utils/grouping-fields.d.ts +61 -0
  91. package/dist/utils/grouping-fields.js +84 -0
  92. package/dist/utils/managedBy.d.ts +3 -3
  93. package/dist/utils/managedBy.js +5 -5
  94. package/dist/utils/native-date-value.d.ts +48 -0
  95. package/dist/utils/native-date-value.js +167 -0
  96. package/dist/utils/non-grid-row-ceiling.d.ts +143 -0
  97. package/dist/utils/non-grid-row-ceiling.js +141 -0
  98. package/dist/utils/normalize-list-view.d.ts +121 -1
  99. package/dist/utils/normalize-list-view.js +186 -6
  100. package/dist/utils/number-display.d.ts +63 -14
  101. package/dist/utils/number-display.js +34 -12
  102. package/dist/utils/object-aggregate-query.d.ts +113 -0
  103. package/dist/utils/object-aggregate-query.js +50 -0
  104. package/dist/utils/parent-scope.d.ts +123 -0
  105. package/dist/utils/parent-scope.js +140 -0
  106. package/dist/utils/predicate-fields.d.ts +45 -12
  107. package/dist/utils/predicate-fields.js +137 -12
  108. package/dist/utils/record-color.d.ts +75 -0
  109. package/dist/utils/record-color.js +65 -0
  110. package/dist/utils/record-source.d.ts +298 -0
  111. package/dist/utils/record-source.js +331 -0
  112. package/dist/utils/record-title.d.ts +148 -8
  113. package/dist/utils/record-title.js +220 -26
  114. package/dist/utils/reference-keys.d.ts +21 -22
  115. package/dist/utils/reference-keys.js +532 -29
  116. package/dist/utils/sort-query.d.ts +115 -15
  117. package/dist/utils/sort-query.js +240 -13
  118. package/dist/utils/text-comparand.d.ts +92 -0
  119. package/dist/utils/text-comparand.js +99 -0
  120. package/dist/utils/without-denied-fields.d.ts +49 -0
  121. package/dist/utils/without-denied-fields.js +52 -0
  122. package/dist/validation/index.d.ts +8 -4
  123. package/dist/validation/index.js +8 -4
  124. package/dist/validation/schema-validator.d.ts +1 -1
  125. package/dist/validation/schema-validator.js +200 -82
  126. package/dist/validation/validators/object-validation-engine.d.ts +1 -1
  127. package/dist/validation/validators/object-validation-engine.js +14 -3
  128. package/package.json +8 -9
  129. package/dist/data-scope/DataScopeManager.d.ts +0 -127
  130. package/dist/data-scope/DataScopeManager.js +0 -229
  131. package/dist/protocols/ResponsiveProtocol.d.ts +0 -73
  132. package/dist/protocols/ResponsiveProtocol.js +0 -158
  133. package/dist/validation/validation-engine.d.ts +0 -88
  134. package/dist/validation/validation-engine.js +0 -434
@@ -5,6 +5,63 @@
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
+ /**
9
+ * `@object-ui/core` — ElementDataSource resolution (objectstack#5576).
10
+ *
11
+ * `PageComponentSchema.dataSource` (the spec's `ElementDataSourceSchema`) is the
12
+ * per-element data binding a page component uses to query a different object
13
+ * than the page's own context:
14
+ *
15
+ * ```json
16
+ * { "object": "account", "view": "hot", "filter": [ … ], "sort": [ … ], "limit": 20 }
17
+ * ```
18
+ *
19
+ * This module owns the two pure halves of consuming it — telling the METADATA
20
+ * apart from a runtime data-source adapter, and composing a named saved view
21
+ * with the binding's own keys. Both are needed in two places (the render path in
22
+ * `@object-ui/plugin-list`, and `ViewDataProvider.resolveElementDataSource`), so
23
+ * they live here rather than being written twice.
24
+ *
25
+ * ## Composition semantics
26
+ *
27
+ * The spec's own `describe()` text settles the one case that could go either
28
+ * way. `filter` is documented as "**Additional** filter criteria" — additional
29
+ * to what the named view already restricts — so a view filter and a binding
30
+ * filter COMBINE under `and`; the binding can only narrow the view, never widen
31
+ * it. That is also the safe direction for AI-authored metadata: a typo in a
32
+ * per-element filter cannot silently expose rows the saved view excluded.
33
+ *
34
+ * Nothing else in the binding is described as additional, and the remaining keys
35
+ * are single-valued (one ordering, one cap), so for those the rule is **the view
36
+ * provides the baseline and an explicit key overrides it**:
37
+ *
38
+ * | key | source | rule |
39
+ * |------------|-----------------------------------------|-----------------------------|
40
+ * | `object` | binding (required) | binding wins |
41
+ * | `columns` | view only — the binding has no such key | view |
42
+ * | `filter` | view + binding | AND-combined ("additional") |
43
+ * | `sort` | view or binding | binding overrides view |
44
+ * | `limit` | view (`pagination.pageSize`) or binding | usable binding overrides view |
45
+ * | `viewType` | view only | view |
46
+ *
47
+ * Both operands of `limit` carry one extra condition the other keys do not: the
48
+ * destination is declared a POSITIVE INTEGER, so a cap the contract refuses is
49
+ * NOT AUTHORED, whichever operand carried it. One chain, one rule for both: a
50
+ * usable binding cap, else a usable view cap, else none (the consumer's own
51
+ * default). See `savedViewLimit` for why the view's refused cap is dropped
52
+ * rather than clamped or thrown, `bindingLimit` for why a refused binding cap
53
+ * yields to the view's (objectui#10016), and `elementDataSourceRefusedLimitMessage`
54
+ * for the half that tells the author, about either operand.
55
+ *
56
+ * A lone `filter` — only the view has one, or only the binding does — is passed
57
+ * through in the shape it was stored in; only the two-source case is lowered to
58
+ * an ObjectQL AST, because that is what combining requires.
59
+ *
60
+ * `viewType` rides along because `list-view` IS the multi-kind view container
61
+ * (its registry `inputs` enumerate grid/kanban/gallery/…): naming a saved kanban
62
+ * view and rendering a grid would be a silently wrong answer.
63
+ */
64
+ import type { InjectedComponentInput } from '@object-ui/types';
8
65
  /** Sort entry, as both the spec's `SortItem` and objectui's view configs spell it. */
9
66
  export interface ElementDataSourceSort {
10
67
  field: string;
@@ -13,11 +70,38 @@ export interface ElementDataSourceSort {
13
70
  /**
14
71
  * Element-level data source — matches `@objectstack/spec` `ElementDataSourceSchema`.
15
72
  *
16
- * `filter` is typed `unknown` rather than the spec's `FilterCondition` because
17
- * three shapes legitimately reach a renderer here (a MongoDB-style condition
18
- * object, an ObjectQL AST node array, a spec `ViewFilterRule[]`) and
19
- * {@link mergeFilterNodes} is the single sink that lowers all three. Narrowing
20
- * the type here would only move the cast, not remove it.
73
+ * `filter` has two populations, and since the upstream convergence they differ:
74
+ *
75
+ * - **What an author may write** is the spec's `ViewFilterRule` array alone —
76
+ * `[{ field, operator, value }, …]`. The spec's `filter` doors converged on it
77
+ * (objectui#6206; migration `element-data-source-and-object-block-filter-rule-array`),
78
+ * and `ElementDataSourceSchema` refuses the other two shapes at the door: the
79
+ * MongoDB-style record form (`{ status: 'open' }`) by kind, and an ObjectQL
80
+ * AST tuple array (`[['status', '=', 'open']]`) because each member must be a
81
+ * rule object.
82
+ * - **What a renderer may still receive** is all three. The D2 conversion that
83
+ * migration entry records, `page-component-filter-record-to-rule-array`,
84
+ * rewrites a stored `filter` only where the rule array spells it losslessly —
85
+ * a flat record, an operator object whose operators the rule vocabulary
86
+ * spells, several such keys, or a single-level AST tuple array — on every
87
+ * ObjectStack stored-row read and under `os migrate meta --stored`. It leaves
88
+ * exactly as stored a filter carrying `$and` / `$or` / `$not`; any filter with
89
+ * a part that has no lossless rule spelling (a `null` value, an operator such
90
+ * as `$null` / `$exists` or an AST `like`, an array or object comparand in
91
+ * equality position, an AST `and` / `or` group); and every filter, the
92
+ * binding's included, of a component whose rows are inline
93
+ * (`data: { provider: 'value' }`, a `data` array, or `staticData`). And this
94
+ * renderer is backend-agnostic: it replays no conversion itself, and only
95
+ * ObjectStack's own data-at-rest seams do, so a page that reaches it any other
96
+ * way arrives as it was written. Any of the three shapes may therefore still
97
+ * arrive here, beside the rule array.
98
+ *
99
+ * `filter` is typed `unknown` rather than the spec's `ViewFilterRule[]` because
100
+ * this interface carries the second population, not the first, and
101
+ * {@link mergeFilterNodes} is the single sink that lowers all three shapes.
102
+ * Narrowing the type here would only move the cast, not remove it, and it would
103
+ * not stop a stored record-form filter from arriving. Refusing the retired
104
+ * shapes is the spec schema's job at the authoring door, not this type's.
21
105
  */
22
106
  export interface ElementDataSourceConfig {
23
107
  object: string;
@@ -43,7 +127,12 @@ export interface ComposedElementDataSource {
43
127
  filter?: unknown;
44
128
  /** Binding sort if given, else the view's. */
45
129
  sort?: unknown;
46
- /** Binding limit if given, else the view's page size. */
130
+ /**
131
+ * The binding's limit if it is one the contract admits, else the view's page
132
+ * size under the same condition. A refused cap from either operand is not
133
+ * authored (`bindingLimit` and `savedViewLimit` apply the one rule), and
134
+ * `elementDataSourceRefusedLimitMessage` is what says so.
135
+ */
47
136
  limit?: number;
48
137
  /** The view's render kind (grid / kanban / …), when the view declares one. */
49
138
  viewType?: string;
@@ -91,12 +180,65 @@ export declare function collectSavedViews(...sources: unknown[]): Record<string,
91
180
  * binding exists to remove.
92
181
  */
93
182
  export declare function resolveSavedView(views: Record<string, ElementSavedView>, requested: string | undefined | null, object: string): ElementSavedView | undefined;
183
+ /**
184
+ * The diagnostic half of {@link savedViewLimit} and {@link bindingLimit}.
185
+ * `null` means "nothing to say".
186
+ *
187
+ * ## Which operand
188
+ *
189
+ * `operand` picks the refusal to describe; it defaults to `'view'`, the one
190
+ * this builder described before objectui#10016. Each operand gets its own
191
+ * sentence, and each names its operand, so the two refusals stay
192
+ * distinguishable when both fire. They do fire together when the binding AND
193
+ * the view each carry a refused cap: two declarations, one message each.
194
+ *
195
+ * `binding` is the binding as authored. The view's sentence needs it too: it
196
+ * says the consumer falls back to its own default, and that is only true when
197
+ * the binding supplied no usable cap. A usable binding cap is used whatever the
198
+ * view carries, so a refused view cap under one changed nothing and is not
199
+ * reported. That condition lives HERE, once, rather than at each caller,
200
+ * because every caller needs it and two copies could drift.
201
+ *
202
+ * ## Why a BUILDER here, and not a warning from the composer
203
+ *
204
+ * This is the shape {@link elementDataSourceViewNotFoundMessage} already
205
+ * established in this module, for the reason its doc gives: built here so every
206
+ * caller reports the same defect the same way. It is followed rather than
207
+ * re-decided because the alternative is ruled out mechanically —
208
+ * {@link composeElementDataSource} is PURE and the render path calls it from a
209
+ * `useMemo`, so a warning emitted inside it would fire during render and fire
210
+ * again on every re-render. The repaired relay one layer up emits from an
211
+ * effect for exactly that reason; a pure function has no effect to emit from,
212
+ * so it hands the caller the words instead.
213
+ *
214
+ * ## Why the message has to exist at all
215
+ *
216
+ * Dropping alone would be a SILENT change on the renderer path: today the
217
+ * refused value travels as far as a block whose own guard reports it once, and
218
+ * after this repair that block receives nothing and correctly says nothing —
219
+ * an absent key is not a mistake. So the repair would remove the only place the
220
+ * author was being told. The layer that makes the decision is the layer that
221
+ * reports it.
222
+ *
223
+ * ⛔ NOT a second guard: the predicate lives once, in {@link isUsableRowLimit},
224
+ * and the view's carrier is read once, by {@link savedViewRawLimit}; this reads
225
+ * both.
226
+ *
227
+ * ⚠️ It speaks only about a cap THIS layer dropped. A non-numeric
228
+ * `pagination.pageSize` never became a limit here, before or after, so there is
229
+ * nothing for this layer to report about it. A non-numeric binding `limit` is
230
+ * different: `??` used to pass it through, so this layer now drops it and says
231
+ * so.
232
+ */
233
+ export declare function elementDataSourceRefusedLimitMessage(view: ElementSavedView | null | undefined, viewName: string | undefined | null, object: string, binding?: {
234
+ limit?: unknown;
235
+ } | null, operand?: 'view' | 'binding'): string | null;
94
236
  /**
95
237
  * Compose an `ElementDataSource` binding with the saved view it names.
96
238
  *
97
239
  * Pure — the caller resolves the view (see {@link resolveSavedView}) and owns
98
240
  * the "named a view that does not exist" decision. Passing `undefined` /`null`
99
- * for `view` composes a binding with no view, which is exactly the pre-#5576
241
+ * for `view` composes a binding with no view, which is exactly the pre-objectstack-ai/objectstack#5576
100
242
  * behaviour for the other four keys.
101
243
  *
102
244
  * See the module doc for the per-key rule table; `filter` is the only key that
@@ -109,5 +251,117 @@ export declare function composeElementDataSource(config: ElementDataSourceConfig
109
251
  * have. Built here so the render path and `ViewDataProvider` report the same
110
252
  * defect the same way, and so the known-view list (the thing that actually gets
111
253
  * an author unstuck) is never omitted by one caller.
254
+ *
255
+ * ## Why the empty case may not say "this object has no saved views"
256
+ *
257
+ * An EMPTY `knownViews` reaches this function from two different worlds, and
258
+ * this function cannot tell them apart:
259
+ *
260
+ * 1. the saved views were read and there are none;
261
+ * 2. the read never successfully happened.
262
+ *
263
+ * World 2 is not hypothetical and not a bug to be fixed upstream: the shipped
264
+ * `ObjectStackAdapter.listViews` contract degrades EVERY failure — refused,
265
+ * offline, malformed — to `[]` on the RESOLVED path (deliberate, and objectui#8151
266
+ * keeps it), so a broken read arrives at `useElementDataSource` as a successful
267
+ * empty answer. The hook's own discrimination catches a REJECTION, which is a
268
+ * shape that contract never produces, so nothing separates the two worlds by the
269
+ * time the count lands here.
270
+ *
271
+ * Framework decision objectstack#13906 decision 1 option A — *a thing that could
272
+ * not be READ is not a thing that is ABSENT* — therefore binds this branch: it
273
+ * may only assert what is true in BOTH worlds. It names the possibilities and
274
+ * commits to neither, because committing is exactly the claim nobody established.
275
+ *
276
+ * ⛔ Do not "restore" the shorter sentence by inferring failure from emptiness in
277
+ * either direction — emptiness is what both worlds produce, so it can never tell
278
+ * them apart. Saying more than this needs the failure FACT plumbed in from the
279
+ * adapter (objectui#8151's surface), not a better guess here.
112
280
  */
113
281
  export declare function elementDataSourceViewNotFoundMessage(object: string, view: string, knownViews: readonly string[]): string;
282
+ /**
283
+ * The spec key this module resolves, spelled once.
284
+ *
285
+ * Every consumer that needs the NAME (the registry injection, its gates, the
286
+ * pins) reads it from here rather than repeating the literal, so "which key is
287
+ * this?" has exactly one answer in the tree.
288
+ */
289
+ export declare const ELEMENT_DATA_SOURCE_KEY = "dataSource";
290
+ /**
291
+ * The authoring-surface declaration of {@link ELEMENT_DATA_SOURCE_KEY} — the one
292
+ * copy, emitted into every registration that wraps the runtime gate.
293
+ *
294
+ * ## Why it lives here and is injected rather than written per block
295
+ *
296
+ * `PageComponentSchema.dataSource` is READ by `ElementDataSourceGate` in
297
+ * `@object-ui/react` on behalf of every object-bound block that wraps itself in
298
+ * it — nine of them at the time of writing. It was declared by NONE: `validateTree`
299
+ * skips `BASE_PROPS` and otherwise looks a prop up in the component's `inputs`,
300
+ * and `dataSource` was in neither. So the html tier reported the one spelling
301
+ * that resolves a saved view — the only one that works — with the identical
302
+ * `unknown-prop` warning it gives the spellings that do nothing, on the tier
303
+ * meant to accept AI-authored pages, where the diagnostic IS the contract
304
+ * (objectui#6678, the reporter of objectui#6598 gave up on exactly this).
305
+ *
306
+ * The maintainer ruling of 2026-08-29 took option B **in the injection form**:
307
+ * emitted mechanically at the wrapping seam, so a block declares the key from
308
+ * the same place that reads it. Nine hand-kept copies is the shape that ruling
309
+ * refused — they drift, and a tenth block would simply forget. Adding the key to
310
+ * `sdui-parser`'s `BASE_PROPS` (option A) was refused too: that set mirrors
311
+ * `BaseSchema`, and silencing `dataSource` on blocks that do NOT read it
312
+ * (`flex`, `card`) would make the diagnostic lie in the other direction.
313
+ *
314
+ * ## Why `object`, and not a bare `'object'` kind
315
+ *
316
+ * The `binding: 'object'` marker is what tells a consumer this input names an
317
+ * OBJECT — `validateTree` records it as a binding site, and the designer offers
318
+ * an object picker rather than a free-text blob. The `type` stays the coarse
319
+ * `'object'` kind because the value is a record; the two words are unrelated and
320
+ * both are correct here.
321
+ *
322
+ * ## Typed as the framework's injected input (`9e37d9b39`)
323
+ *
324
+ * `binding` is not a `ComponentInput` member. The maintainer ruling of
325
+ * 2026-09-07 answered the card's product question — may an ordinary
326
+ * registration declare a binding input? — with no, so the ONE writer of the
327
+ * key is this constant, typed by `InjectedComponentInput` from
328
+ * `@object-ui/types`: a `ComponentInput` plus the marker. The hand-written
329
+ * inline type literal that used to sit here was the tell that the key had no
330
+ * authored home, and the splice in `Registry.register` reached the `inputs`
331
+ * array through an `as ComponentMeta` cast. Both are gone: the shape is now
332
+ * checked here and at the splice, and a registration that writes `binding`
333
+ * itself is an excess-property `tsc` error.
334
+ */
335
+ export declare const ELEMENT_DATA_SOURCE_INPUT: InjectedComponentInput;
336
+ /**
337
+ * Declare that `renderer` wraps `ElementDataSourceGate`, so its registrations
338
+ * publish {@link ELEMENT_DATA_SOURCE_INPUT}.
339
+ *
340
+ * This is the SEAM, and it is deliberately the only way in: `Registry.register`
341
+ * injects the declaration for exactly the renderers marked here, so the key is
342
+ * published by whatever consumes the gate and by nothing else — which is what
343
+ * keeps the `flex` / `card` direction of the ruling true.
344
+ * `scripts/check-element-data-source-declaration.mjs` fails any source that
345
+ * consumes the gate without passing through it, so a new block cannot forget.
346
+ *
347
+ * ## Two import paths, ONE name and ONE function
348
+ *
349
+ * `@object-ui/react` re-exports this beside `ElementDataSourceGate` so the seam is
350
+ * findable next to the thing it is about. That export is for DISCOVERABILITY:
351
+ * every CALL SITE imports from here, and
352
+ * `scripts/check-element-data-source-declaration.mjs` enforces it.
353
+ *
354
+ * The rule is measured, not stylistic. A registration runs at MODULE SCOPE, and
355
+ * `element:record_picker`'s registration in `@object-ui/components` is the
356
+ * worked example. 101 suites in this repo partially
357
+ * mock `@object-ui/react` by hand-listing the exports they return, and a
358
+ * module-scope read of a name those lists do not carry throws at COLLECTION
359
+ * time — the importing test file fails before it runs a single assertion.
360
+ * Measured: 17 files, all four CI shards, zero failed assertions among them.
361
+ * Nothing mocks `@object-ui/core`, and `@object-ui/components` already imports
362
+ * `ComponentRegistry` from it at module scope, so this path adds no coupling
363
+ * that was not already there.
364
+ */
365
+ export declare function elementDataSourceBlock<C>(renderer: C): C;
366
+ /** Whether `renderer` was marked by {@link elementDataSourceBlock}. */
367
+ export declare function isElementDataSourceBlock(renderer: unknown): boolean;