@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
@@ -0,0 +1,65 @@
1
+ /**
2
+ * ObjectUI
3
+ * Copyright (c) 2024-present ObjectStack Inc.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
8
+ /**
9
+ * Colour literals the renderers accept as-is.
10
+ *
11
+ * Hex accepts 3, 6 and 8 digits. The timeline's private regex accepted 3 and 6;
12
+ * `plugin-calendar`'s accepted 3, 6 and 8 — two in-repo spellings of the same
13
+ * question, and the narrow one is the only one under which a VALID CSS colour
14
+ * (`#rrggbbaa`) could fall past this rung and be replaced by a derived colour.
15
+ * Widening can only turn "not recognised" into "the author's colour"; it can
16
+ * never turn a colour into something else. So the wider spelling wins.
17
+ */
18
+ const HEX_COLOR_RE = /^#([0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$/i;
19
+ /** Does this string already name a colour the DOM can paint? */
20
+ export function isColorLiteral(value) {
21
+ return HEX_COLOR_RE.test(value) || value.startsWith('rgb') || value.startsWith('hsl');
22
+ }
23
+ /**
24
+ * Build a `value -> option colour` lookup from a field definition's `options`.
25
+ * Returns an empty map for a field with no options, so callers need no guard.
26
+ */
27
+ export function buildFieldColorMap(fieldDef) {
28
+ const options = fieldDef?.options;
29
+ if (!Array.isArray(options))
30
+ return {};
31
+ const map = {};
32
+ for (const opt of options) {
33
+ if (!opt || typeof opt !== 'object')
34
+ continue;
35
+ if (opt.value == null)
36
+ continue;
37
+ if (typeof opt.color === 'string' && opt.color)
38
+ map[String(opt.value)] = opt.color;
39
+ }
40
+ return map;
41
+ }
42
+ /**
43
+ * Build the per-field colour resolver: rung 1 (option colour) then rung 2 (the
44
+ * value is already a colour literal), else `undefined` so the caller runs its
45
+ * own last rung.
46
+ *
47
+ * A factory rather than a plain function because callers resolve one field
48
+ * across every row of a view — the option map is built once, not per record.
49
+ *
50
+ * @param fieldDef `objectSchema.fields[colorField]`, or `undefined` when the
51
+ * view has no schema in hand (an inline-data or `api`-provider view). With no
52
+ * options, rung 1 is a no-op and rung 2 still answers for literal colours.
53
+ */
54
+ export function createFieldColorResolver(fieldDef) {
55
+ const colorByValue = buildFieldColorMap(fieldDef);
56
+ return (value) => {
57
+ if (value == null || value === '')
58
+ return undefined;
59
+ const key = String(value);
60
+ const optionColor = colorByValue[key];
61
+ if (optionColor)
62
+ return optionColor;
63
+ return isColorLiteral(key) ? key : undefined;
64
+ };
65
+ }
@@ -0,0 +1,298 @@
1
+ /**
2
+ * ObjectUI — the shared record-source readers: the ruled three-rung ladder
3
+ * (`resolveRecordSourceConfig`) and the object-name it resolves to
4
+ * (`resolveRecordSourceObjectName`)
5
+ * Copyright (c) 2024-present ObjectStack Inc.
6
+ *
7
+ * This source code is licensed under the MIT license found in the
8
+ * LICENSE file in the root directory of this source tree.
9
+ */
10
+ import type { ViewData } from '@object-ui/types';
11
+ /**
12
+ * The object a view block is bound to, resolved ONCE for the whole renderer
13
+ * (`b041b9c0c`).
14
+ *
15
+ * ## The question this answers, and the one it does not
16
+ *
17
+ * There are TWO separately-ruled precedence questions about `objectName`, and
18
+ * they only look like one question when a single reader is asked to answer
19
+ * both:
20
+ *
21
+ * 1. **Which object does this block RESOLVE, at render time, when it carries
22
+ * more than one binding?** — the published three-rung record-source ladder
23
+ * (`data`, then `staticData`, then `objectName`), declared on both faces of
24
+ * the contract (`ObjectMapSchema.objectName` / `ObjectGanttSchema.objectName`
25
+ * in `@object-ui/types`, and the `.describe` on their zod twins — the map
26
+ * twin's reads *"objectName — the THIRD record source `getDataConfig`
27
+ * resolves, after `data` and `staticData`"*, naming `ObjectMap.tsx`'s local
28
+ * wrapper; the gantt twin names `resolveRecordSourceConfig` itself), ruled
29
+ * 2026-09-02 (landed as `77cb489b4`) and pinned by
30
+ * `objectql-record-source-refinement-6939.test.ts`. **That is this
31
+ * function.**
32
+ * 2. **How does `objectName` get POPULATED when it is absent?** — the
33
+ * authoring-time gap-fill in `normalizeListViewSchema` (objectui#7477,
34
+ * ruling B, landed as `00d2fa682`), where an `objectName` already on the schema WINS
35
+ * and the `data` block only fills a gap: *"it can never re-point a binding
36
+ * that already resolves."*
37
+ *
38
+ * The two are NOT merged and neither is re-pointed at the other. Merging them
39
+ * would override a standing maintainer ruling in whichever direction the merged
40
+ * reader happened to pick: at the sites below the binding that already resolves
41
+ * IS `data.object`, so ruling B's own words argue for keeping rung 1 as it is.
42
+ *
43
+ * ## Why `staticData` does not appear here
44
+ *
45
+ * The ladder's second rung wraps inline rows as `{ provider: 'value', items }`,
46
+ * which names no object at all. So for the object-NAME question the three-rung
47
+ * ladder reduces to two rungs — the resolved config's object when it names one,
48
+ * else the schema's own `objectName`, which is what a `value`/`api`-backed block
49
+ * still needs for metadata reads, i18n field labels and permission verdicts.
50
+ * Callers pass the ALREADY-RESOLVED config (their
51
+ * {@link resolveRecordSourceConfig} output, direct or through a local wrapper),
52
+ * so rung ordering is settled before this function is reached.
53
+ *
54
+ * ## No lenient rung was added (AGENTS.md #0.1)
55
+ *
56
+ * `ViewDataSchema`'s `object` provider is a `strictObject` carrying exactly
57
+ * `{ provider, object }` with `object` REQUIRED, so `{ provider: 'object' }`
58
+ * without an `object` is off-contract. This reader does not coerce that shape
59
+ * back to `objectName`; the two call sites that used to (`ObjectGrid`'s
60
+ * `'object' in dataConfig` test and `ObjectTree`'s header `?? schema.objectName`
61
+ * tail) keep their own tail at the site, so the collapse changes nothing they
62
+ * resolve today while the shared rung stays contract-strict.
63
+ *
64
+ * @param schema - The block's schema; only `objectName` is read.
65
+ * @param dataConfig - The RESOLVED data config — the caller's own
66
+ * {@link resolveRecordSourceConfig} output, `null` when nothing is bound.
67
+ * @returns The bound object's name, or `undefined` when neither the resolved
68
+ * config nor the schema names one.
69
+ *
70
+ * @example
71
+ * ```ts
72
+ * const dataConfig = useMemo(() => resolveRecordSourceConfig(schema, 'view-data'), [schema]);
73
+ * const objectName = resolveRecordSourceObjectName(schema, dataConfig);
74
+ * ```
75
+ */
76
+ export declare function resolveRecordSourceObjectName(schema: {
77
+ objectName?: string;
78
+ } | null | undefined, dataConfig: {
79
+ provider?: string;
80
+ object?: string;
81
+ } | null | undefined): string | undefined;
82
+ /**
83
+ * Which arm of `data` a block's PUBLISHED row declares — the only shape rung 1
84
+ * of the ladder honours for that block (objectui#8348).
85
+ *
86
+ * Maintainer ruling, decision batch #83 (2026-09-08), verbatim: 「8348 以协议为准」
87
+ * — the contract decides. A renderer honours the `data` spelling its block's
88
+ * published row declares and no other: what `os validate` and the save gate
89
+ * refuse, the renderer refuses too.
90
+ *
91
+ * - `'view-data'` — the row is the spec's `ViewData` discriminated union, four
92
+ * strict OBJECT arms on `provider`. A bare array under `data` is NOT a record
93
+ * source for such a block.
94
+ * - `'array'` — the row is `z.array(...)`: an array of PRE-FETCHED RECORDS. The
95
+ * `{ provider, items }` config object is NOT a record source for such a
96
+ * block.
97
+ * - `'undeclared'` — no published face declares a `data` row for the block at
98
+ * all, so neither arm of the ruling reaches it and rung 1 keeps its pre-8348
99
+ * verbatim behaviour. ⛔ NOT a tolerance to copy: it is the honest answer for
100
+ * a block the ruling does not decide, and it is reported rather than guessed.
101
+ * No ladder block passes it any more: `object-tree`, the last one that did,
102
+ * gained a published row and moved to `'view-data'` (objectui#8348, ruling
103
+ * batch #136 item 3, Q1-C). It stays the answer
104
+ * {@link recordSourceDataArmForType} gives a type it does not list.
105
+ *
106
+ * The arm is passed BY THE CALL SITE rather than looked up from `schema.type`
107
+ * on purpose. Most of these renderers are registered twice — `object-grid`
108
+ * and the `view:grid` alias `grid`, `object-calendar` and `calendar`, and so on
109
+ * (the bare `gantt` and `map` keys are retired, objectui#8008 / objectui#10393)
110
+ * — so a node reaches the same component under either spelling, and a table
111
+ * keyed by `type` would answer for one tag and silently miss the other. A
112
+ * REQUIRED parameter makes the arm a compile-time obligation at each of the
113
+ * five sites instead.
114
+ */
115
+ export type RecordSourceDataArm = 'view-data' | 'array' | 'undeclared';
116
+ /**
117
+ * The authored `data` shape a block ON THAT ARM may declare — the DECLARATION
118
+ * half of the same per-block ruling {@link authoredDataIsOnTheDeclaredArm}
119
+ * decides at RUNTIME (`ab856ed30`).
120
+ *
121
+ * ## The contradiction this closes
122
+ *
123
+ * {@link resolveRecordSourceConfig} used to declare its `data` parameter as a
124
+ * flat `ViewData`, while its own docblock, its REQUIRED `dataArm` parameter and
125
+ * its rung-1 predicate all say the honoured shape DIFFERS PER BLOCK — and
126
+ * `ViewData` is a discriminated union over four strict OBJECT arms with no
127
+ * array member. So the signature refused the one block whose published row IS
128
+ * the array arm, and the arm parameter that exists to make the row a
129
+ * compile-time obligation was the one thing the compiler ignored. The
130
+ * contradiction was held shut at `ObjectCalendar.tsx`'s call site by an
131
+ * `as ViewData | undefined` cast whose own comment reported it as an upstream
132
+ * defect rather than a licence.
133
+ *
134
+ * ⛔ The repair is NOT a union of the arms. `ViewData | unknown[]` would let a
135
+ * `'view-data'` site declare a bare array and a `'array'` site declare a
136
+ * provider block — each of them the shape that block's row REFUSES, each of
137
+ * them compiling — which is the repo-wide default {@link RecordSourceDataArm}'s
138
+ * docblock refuses by name: *"a default is how the second de-facto contract got
139
+ * in"* (AGENTS.md #0.1).
140
+ *
141
+ * - `'view-data'` — the spec's `ViewData`. UNCHANGED, and that matters: this
142
+ * is exactly what the flat declaration said, and it was right for the three
143
+ * blocks on this arm, so nothing moves for `object-grid`, `object-map` or
144
+ * `object-gantt`.
145
+ * - `'array'` — `unknown[]`, the shape `object-calendar`'s published row
146
+ * declares (`ComponentPropsMap['object-calendar'].data` is
147
+ * `z.array(z.unknown()).optional()`, *"Pre-fetched records"*).
148
+ * - `'undeclared'` — `unknown`. No published face declares a `data` row for
149
+ * such a block, so rung 1 keeps its pre-8348 verbatim behaviour and honours
150
+ * ANY truthy value. Anything narrower here would be a rule nobody has ruled.
151
+ *
152
+ * ⚠️ RUNTIME IS UNMOVED. This type is erased; {@link authoredDataIsOnTheDeclaredArm}
153
+ * still takes `unknown` and still decides rung 1 on the value's KIND, so every
154
+ * runtime verdict — including the off-arm ones — is byte-for-byte what it was.
155
+ * `record-source-config.behaviourNeutrality-7632.test.ts` passes its fixtures
156
+ * through `as any` precisely so it keeps measuring that, whatever the
157
+ * declaration says.
158
+ *
159
+ * ⚠️ DISTRIBUTIVE on purpose, and that is why this is a conditional type rather
160
+ * than a set of overloads. A caller holding a `RecordSourceDataArm`-typed
161
+ * VARIABLE instead of a literal gets `ViewData | unknown[] | unknown`, i.e.
162
+ * `unknown` — the honest answer when the arm is not decided at compile time.
163
+ * The same caller would match NONE of three literal-armed overloads, which
164
+ * would turn a working call into an error for no contract reason.
165
+ */
166
+ export type AuthoredRecordSourceData<Arm extends RecordSourceDataArm> = Arm extends 'view-data' ? ViewData : Arm extends 'array' ? unknown[] : unknown;
167
+ /**
168
+ * The block's record source, resolved from the ruled three-rung ladder
169
+ * (`ce2aaefe1`), with rung 1 judged against the block's own published `data`
170
+ * row (objectui#8348).
171
+ *
172
+ * ## The ruled contract this is the ONE implementation of
173
+ *
174
+ * `data`, then `staticData`, then `objectName` — declared on both faces of the
175
+ * published contract and pinned by
176
+ * `objectql-record-source-refinement-6939.test.ts`. Quoted here from the
177
+ * `ObjectMapSchema` faces, whose `getDataConfig` is `ObjectMap.tsx`'s local
178
+ * wrapper around this function; the gantt and calendar faces name
179
+ * `resolveRecordSourceConfig` instead (objectui#9618):
180
+ *
181
+ * 1. **`data`** — *"Data source configuration. Read FIRST by `getDataConfig`"*,
182
+ * honoured ONLY on the arm `dataArm` names. Returned verbatim, so a config
183
+ * on the declared arm reaches the caller exactly as the author wrote it.
184
+ * 2. **`staticData`** — *"Inline records — read SECOND by `getDataConfig`,
185
+ * wrapped into a `{ provider: value }` config"*.
186
+ * 3. **`objectName`** — *"the THIRD record source `getDataConfig` resolves,
187
+ * after `data` and `staticData`"*, folded to `{ provider: 'object' }`.
188
+ *
189
+ * `null` when none of the three is present — the same "nothing is drawn" signal
190
+ * the zod `requireRecordSource` refinement is written against.
191
+ *
192
+ * This is the PRODUCER whose output {@link resolveRecordSourceObjectName} (the
193
+ * reader `b041b9c0c` published) consumes; that function's docblock describes the same
194
+ * ladder from the consuming end. Five plugins — calendar, gantt, grid, map and
195
+ * tree — each carried a hand-copy of this ladder with no gate holding them
196
+ * together, which is the AGENTS.md #0.1 drift class: a change to the ruled
197
+ * order had five edit sites and nothing noticed a missed one.
198
+ *
199
+ * ## Rung 1 is judged against the block's own row (objectui#8348)
200
+ *
201
+ * ⛔ This docblock used to state, as a fact about the whole ladder, that *"an
202
+ * array under `data` cannot be published"*. That is true of the blocks whose row
203
+ * is `ViewData` and FALSE of `object-calendar`, whose published row
204
+ * (`ComponentPropsMap['object-calendar'].data` on `@objectstack/spec` 17.4.0) is
205
+ * `z.array(z.unknown()).optional()` — *"Pre-fetched records — skips the internal
206
+ * fetch"*. Both directions of that disagreement were live at once: the renderers
207
+ * honoured the `{ provider, items }` object on a block whose row refuses it by
208
+ * kind, and `ObjectGrid` / `ObjectMap` lifted a bare array on blocks whose row
209
+ * refuses THAT by kind. Decision batch #83 settled it — the row decides — and
210
+ * `dataArm` is where each block says which row it has.
211
+ *
212
+ * JUDGED, per block, against that block's `ComponentPropsMap` row in the
213
+ * INSTALLED `@objectstack/spec` — and ⛔ the verdicts are not written down here
214
+ * as facts, because a spec release can move a row (AGENTS.md #9). Each pin
215
+ * below derives the arm from the row at test time and compares it with what the
216
+ * block passes, so a moved row turns it red:
217
+ *
218
+ * - `object-grid` — `'view-data'`; `gridBareArrayDataRefused-8348.test.tsx`,
219
+ * its "the spec row is what all of the above is judged against" test. The
220
+ * row's own description names the refusal: *"the bare-array shortcut is
221
+ * refused — see migration `object-grid-data-view-data-converged`"*.
222
+ * - `object-calendar` — `'array'`; the test of the same name in
223
+ * `ObjectCalendar.dataObjectArmRefused-8348.test.tsx`. The registration
224
+ * publishes the same arm (`{ name: 'data', type: 'array' }`).
225
+ * - `object-map`, `object-gantt`, `object-tree` — `'view-data'`; one
226
+ * `dataArmSpecRow-8348` pin per block, in each plugin's own tests. These
227
+ * three rows are what ruling batch #136 item 3 (Q1-C) had the protocol
228
+ * gain; until they were installable, map and gantt were judged through this
229
+ * repo's own `ObjectMapSchema.data` / `ObjectGanttSchema.data` and tree
230
+ * passed `'undeclared'`. The tree's row declares `data`, so the ruling's
231
+ * 「协议没有的能力删」 clause did not fire for it: it keeps the object arm and
232
+ * loses only the bare-array spelling. Its `staticData` rung is declared by
233
+ * the same row and is unchanged.
234
+ *
235
+ * ## The DECLARATION follows the arm too (`ab856ed30`)
236
+ *
237
+ * The `data` member below is {@link AuthoredRecordSourceData}`<Arm>`, not a flat
238
+ * `ViewData`: the arm decides what a site may DECLARE exactly as it decides
239
+ * what rung 1 HONOURS. Read that type's docblock for why it is arm-indexed
240
+ * rather than a union of the arms, and for the reading that says nothing at
241
+ * runtime moved.
242
+ *
243
+ * ## No lenient rung was added (AGENTS.md #0.1)
244
+ *
245
+ * **Null tolerance** stays out: all five copies dereference `schema` unguarded
246
+ * and would throw on `null`; no site passes one, so no `?.` was added.
247
+ *
248
+ * `ObjectCalendar`'s copy guarded with `'data' in schema && schema.data`. That
249
+ * `in` test was a TYPESCRIPT narrowing device, not a behavioural one: when the
250
+ * property is absent the read yields `undefined`, which is falsy either way, so
251
+ * the guard could never change which rung is taken. The optional-property
252
+ * parameter below admits a schema that declares neither key directly, which is
253
+ * why the guard is gone rather than flattened away. The equivalence itself is
254
+ * pinned, not argued, by `CALENDAR_IN_GUARD` in
255
+ * `record-source-config.behaviourNeutrality-7632.test.ts`.
256
+ *
257
+ * ⛔ This passage used to explain that guard by the PROPS UNION the calendar
258
+ * plugin once carried — `ObjectGridSchema | CalendarSchema`, whose second
259
+ * member declared neither `data` nor `staticData`. objectui#8651 RETIRED that
260
+ * union (`ObjectCalendarComponentProps.schema` is the published
261
+ * `ObjectCalendarSchema` today), so the sentence explained the guard by a type
262
+ * no reader could look up. Rewritten rather than deleted: the guard's history
263
+ * is still why this parameter's members are optional.
264
+ *
265
+ * @param schema - The block's schema; only `data`, `staticData` and
266
+ * `objectName` are read. Its `data` member is typed by the arm — see
267
+ * {@link AuthoredRecordSourceData}.
268
+ * @param dataArm - The arm the CALLING BLOCK's published `data` row declares.
269
+ * Required: there is no repo-wide default, because the answer differs per
270
+ * block and a default is how the second de-facto contract got in.
271
+ * @returns The resolved data config, or `null` when nothing is bound.
272
+ *
273
+ * @example
274
+ * ```ts
275
+ * const dataConfig = useMemo(() => resolveRecordSourceConfig(schema, 'view-data'), [schema]);
276
+ * const objectName = resolveRecordSourceObjectName(schema, dataConfig);
277
+ * ```
278
+ */
279
+ export declare function resolveRecordSourceConfig<Arm extends RecordSourceDataArm>(schema: {
280
+ objectName?: string;
281
+ data?: AuthoredRecordSourceData<Arm>;
282
+ staticData?: any[];
283
+ }, dataArm: Arm): ViewData | null;
284
+ /**
285
+ * Which `data` arm the block registered under `type` declares.
286
+ *
287
+ * `'undeclared'` for every type not listed above — the same verdict the ladder
288
+ * gives a block no published face declares a `data` row for, and the same
289
+ * behaviour those types have today. That default is deliberately the
290
+ * NO-CHANGE direction: a caller acting on this reading (today:
291
+ * `SchemaRenderer`'s props spread) leaves an unlisted type exactly as it was,
292
+ * so a block that has never been measured is never silently re-decided by this
293
+ * table's mere existence.
294
+ *
295
+ * @param type - The node's registry key, either spelling.
296
+ * @returns The arm that type's published `data` row declares.
297
+ */
298
+ export declare function recordSourceDataArmForType(type: string | null | undefined): RecordSourceDataArm;