@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.
- package/CHANGELOG.md +6610 -0
- package/README.md +101 -14
- package/dist/actions/ActionEngine.d.ts +4 -2
- package/dist/actions/ActionEngine.js +13 -8
- package/dist/actions/ActionRunner.d.ts +288 -27
- package/dist/actions/ActionRunner.js +443 -63
- package/dist/actions/TransactionManager.d.ts +7 -2
- package/dist/actions/actionKeys.d.ts +9 -7
- package/dist/actions/actionKeys.js +57 -14
- package/dist/actions/actionResponse.js +2 -2
- package/dist/actions/index.d.ts +1 -0
- package/dist/actions/index.js +1 -0
- package/dist/actions/recordDelete.d.ts +118 -0
- package/dist/actions/recordDelete.js +112 -0
- package/dist/adapters/ValueDataSource.d.ts +6 -1
- package/dist/adapters/ValueDataSource.js +1090 -98
- package/dist/adapters/batchTransaction.d.ts +1 -1
- package/dist/adapters/batchTransaction.js +1 -1
- package/dist/builder/schema-builder.d.ts +38 -81
- package/dist/builder/schema-builder.js +33 -152
- package/dist/data-scope/ViewDataProvider.d.ts +1 -1
- package/dist/data-scope/ViewDataProvider.js +21 -1
- package/dist/data-scope/element-data-source.d.ts +261 -7
- package/dist/data-scope/element-data-source.js +342 -52
- package/dist/data-scope/index.d.ts +9 -4
- package/dist/data-scope/index.js +9 -4
- package/dist/evaluator/ExpressionEvaluator.d.ts +86 -0
- package/dist/evaluator/ExpressionEvaluator.js +184 -12
- package/dist/evaluator/FormulaFunctions.d.ts +0 -10
- package/dist/evaluator/FormulaFunctions.js +166 -27
- package/dist/evaluator/declaredPredicate.d.ts +93 -9
- package/dist/evaluator/declaredPredicate.js +117 -16
- package/dist/evaluator/fieldRules.d.ts +88 -4
- package/dist/evaluator/fieldRules.js +203 -31
- package/dist/evaluator/index.d.ts +1 -0
- package/dist/evaluator/index.js +1 -0
- package/dist/evaluator/listConditional.d.ts +103 -34
- package/dist/evaluator/listConditional.js +127 -50
- package/dist/evaluator/optionRules.d.ts +77 -6
- package/dist/evaluator/optionRules.js +87 -10
- package/dist/evaluator/predicateInput.d.ts +15 -4
- package/dist/evaluator/predicateInput.js +35 -2
- package/dist/evaluator/rowPredicateCanon.d.ts +7 -18
- package/dist/evaluator/rowPredicateCanon.js +65 -115
- package/dist/evaluator/subjectPermissions.d.ts +76 -0
- package/dist/evaluator/subjectPermissions.js +44 -0
- package/dist/evaluator/unevaluablePredicate.d.ts +57 -0
- package/dist/evaluator/unevaluablePredicate.js +70 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +80 -2
- package/dist/protocols/index.d.ts +0 -1
- package/dist/protocols/index.js +9 -1
- package/dist/registry/Registry.d.ts +358 -31
- package/dist/registry/Registry.js +263 -11
- package/dist/registry/WidgetRegistry.js +7 -3
- package/dist/registry/html-tier-intrinsics.d.ts +90 -0
- package/dist/registry/html-tier-intrinsics.js +110 -0
- package/dist/registry/public-blocks.d.ts +8 -0
- package/dist/registry/public-blocks.js +57 -0
- package/dist/theme/ThemeEngine.js +1 -1
- package/dist/utils/chart-category-key.d.ts +82 -0
- package/dist/utils/chart-category-key.js +84 -0
- package/dist/utils/chart-measure-key.d.ts +64 -0
- package/dist/utils/chart-measure-key.js +65 -0
- package/dist/utils/chart-presentation.d.ts +95 -112
- package/dist/utils/chart-presentation.js +169 -104
- package/dist/utils/chart-series.d.ts +131 -5
- package/dist/utils/chart-series.js +98 -16
- package/dist/utils/column-sortability.d.ts +157 -0
- package/dist/utils/column-sortability.js +217 -0
- package/dist/utils/dashboard-filters.d.ts +38 -6
- package/dist/utils/dashboard-filters.js +107 -61
- package/dist/utils/dataset-format.d.ts +211 -30
- package/dist/utils/dataset-format.js +389 -46
- package/dist/utils/date-display.d.ts +354 -0
- package/dist/utils/date-display.js +463 -0
- package/dist/utils/date-macros.js +7 -0
- package/dist/utils/drill-down.d.ts +78 -0
- package/dist/utils/drill-down.js +93 -0
- package/dist/utils/emptiness.d.ts +96 -0
- package/dist/utils/emptiness.js +101 -0
- package/dist/utils/expand-fields.d.ts +76 -6
- package/dist/utils/expand-fields.js +76 -6
- package/dist/utils/extract-records.d.ts +65 -5
- package/dist/utils/extract-records.js +65 -8
- package/dist/utils/filter-converter.d.ts +152 -4
- package/dist/utils/filter-converter.js +1092 -22
- package/dist/utils/filter-tokens.d.ts +49 -5
- package/dist/utils/filter-tokens.js +105 -33
- package/dist/utils/grouping-fields.d.ts +61 -0
- package/dist/utils/grouping-fields.js +84 -0
- package/dist/utils/managedBy.d.ts +3 -3
- package/dist/utils/managedBy.js +5 -5
- package/dist/utils/native-date-value.d.ts +48 -0
- package/dist/utils/native-date-value.js +167 -0
- package/dist/utils/non-grid-row-ceiling.d.ts +143 -0
- package/dist/utils/non-grid-row-ceiling.js +141 -0
- package/dist/utils/normalize-list-view.d.ts +121 -1
- package/dist/utils/normalize-list-view.js +186 -6
- package/dist/utils/number-display.d.ts +63 -14
- package/dist/utils/number-display.js +34 -12
- package/dist/utils/object-aggregate-query.d.ts +113 -0
- package/dist/utils/object-aggregate-query.js +50 -0
- package/dist/utils/parent-scope.d.ts +123 -0
- package/dist/utils/parent-scope.js +140 -0
- package/dist/utils/predicate-fields.d.ts +45 -12
- package/dist/utils/predicate-fields.js +137 -12
- package/dist/utils/record-color.d.ts +75 -0
- package/dist/utils/record-color.js +65 -0
- package/dist/utils/record-source.d.ts +298 -0
- package/dist/utils/record-source.js +331 -0
- package/dist/utils/record-title.d.ts +148 -8
- package/dist/utils/record-title.js +220 -26
- package/dist/utils/reference-keys.d.ts +21 -22
- package/dist/utils/reference-keys.js +532 -29
- package/dist/utils/sort-query.d.ts +115 -15
- package/dist/utils/sort-query.js +240 -13
- package/dist/utils/text-comparand.d.ts +92 -0
- package/dist/utils/text-comparand.js +99 -0
- package/dist/utils/without-denied-fields.d.ts +49 -0
- package/dist/utils/without-denied-fields.js +52 -0
- package/dist/validation/index.d.ts +8 -4
- package/dist/validation/index.js +8 -4
- package/dist/validation/schema-validator.d.ts +1 -1
- package/dist/validation/schema-validator.js +200 -82
- package/dist/validation/validators/object-validation-engine.d.ts +1 -1
- package/dist/validation/validators/object-validation-engine.js +14 -3
- package/package.json +8 -9
- package/dist/data-scope/DataScopeManager.d.ts +0 -127
- package/dist/data-scope/DataScopeManager.js +0 -229
- package/dist/protocols/ResponsiveProtocol.d.ts +0 -73
- package/dist/protocols/ResponsiveProtocol.js +0 -158
- package/dist/validation/validation-engine.d.ts +0 -88
- package/dist/validation/validation-engine.js +0 -434
|
@@ -21,6 +21,14 @@
|
|
|
21
21
|
*
|
|
22
22
|
* This is a single, reviewable source of truth for the public surface — prefer
|
|
23
23
|
* editing this list over scattering `tier` flags across registration sites.
|
|
24
|
+
*
|
|
25
|
+
* ⛔ The html tier's intrinsic elements (`h1`, `p`, `a`, the sectioning tags, …)
|
|
26
|
+
* do NOT belong here. They reach the published manifest through the second
|
|
27
|
+
* roster beside this one, `HTML_TIER_INTRINSICS`, stamped `tier: 'html'`, so
|
|
28
|
+
* that the manifest's other reader — the objectstack gate that whitelists a
|
|
29
|
+
* `kind:'html'` page's tags — accepts them without this curated JSON-surface
|
|
30
|
+
* vocabulary growing (objectui#10735). Listing one here would widen the
|
|
31
|
+
* vocabulary silently; `html-tier-intrinsics.test.ts` pins the two disjoint.
|
|
24
32
|
*/
|
|
25
33
|
export const PUBLIC_BLOCKS = [
|
|
26
34
|
// ── Tier A — object-aware blocks (the contract core) ──────────────────────
|
|
@@ -34,6 +42,23 @@ export const PUBLIC_BLOCKS = [
|
|
|
34
42
|
'object-gantt',
|
|
35
43
|
'object-timeline',
|
|
36
44
|
'object-map',
|
|
45
|
+
// Curated by objectui#10064, which is a NARROWING being undone rather than a
|
|
46
|
+
// widening: `@objectstack/spec` already declares `object-tree` on
|
|
47
|
+
// `ComponentPropsMap`, and @object-ui/plugin-tree has registered the renderer
|
|
48
|
+
// all along — this roster was the one face that withheld it, so the tier sat
|
|
49
|
+
// narrower than the declaration. Everything downstream reported that
|
|
50
|
+
// faithfully and could not fix it: `getPublicConfigs()` is what both manifest
|
|
51
|
+
// producers serialize, so the framework's tracked `sdui.manifest.json` could
|
|
52
|
+
// never carry a block the contract says exists, and moving the objectui pin
|
|
53
|
+
// could not help while the pinned source had nothing to carry
|
|
54
|
+
// (objectstack#18407, whose parity-gate half waits on this entry).
|
|
55
|
+
//
|
|
56
|
+
// The `tree` alias the same module registers is deliberately NOT here: it is
|
|
57
|
+
// a second spelling of this one block and @objectstack/spec declares no such
|
|
58
|
+
// key, so curating it would widen the vocabulary past the declaration — the
|
|
59
|
+
// opposite act — and leave an authoring model two names for one block, which
|
|
60
|
+
// is the ground `record:chatter` is held out on above.
|
|
61
|
+
'object-tree',
|
|
37
62
|
'object-metric',
|
|
38
63
|
'object-chart',
|
|
39
64
|
'dashboard',
|
|
@@ -102,6 +127,38 @@ export const PUBLIC_BLOCKS = [
|
|
|
102
127
|
'tabs',
|
|
103
128
|
'accordion',
|
|
104
129
|
'container',
|
|
130
|
+
// The neutral block container, minted by the 2026-08-29 ruling as the JSON
|
|
131
|
+
// surface's replacement for the deprecated `div` (objectui#3965, PR #6878).
|
|
132
|
+
// It landed on every other declaration face — interface, zod mirror,
|
|
133
|
+
// `SchemaRegistry`, registration, docs page, and 27 catalog fixtures — and
|
|
134
|
+
// this list was the one face it missed, so the vocabulary taught a type the
|
|
135
|
+
// contract did not carry (`3619792bf`).
|
|
136
|
+
//
|
|
137
|
+
// MEASURED before it was added, because "add it and see" is how a gate
|
|
138
|
+
// discovers a new population at merge time. `registry-inputs-spec-parity`
|
|
139
|
+
// (apps/console) does NOT judge it, and not by tolerance: its coverage set is
|
|
140
|
+
// SPEC-shaped — `Object.keys(ComponentPropsMap)`, filtered to what this repo
|
|
141
|
+
// registers with inputs. It never reads this list, and membership here is
|
|
142
|
+
// neither necessary nor sufficient for being judged: `element:record_picker`
|
|
143
|
+
// is judged while absent from this list, and `flex` / `grid` / `stack` /
|
|
144
|
+
// `card` / `container` are all listed here and all unjudged, because
|
|
145
|
+
// `@objectstack/spec@17` carries no entry for ANY Tier B layout primitive. So
|
|
146
|
+
// `box` joins a spec-less population five types deep rather than opening a
|
|
147
|
+
// new one; it needs no spec entry, and no gate needed loosening to accept it.
|
|
148
|
+
//
|
|
149
|
+
// ⚠️ And "not on this list" never meant "not on an authoring surface". `box`
|
|
150
|
+
// has been validated all along through the OTHER consumer of the same
|
|
151
|
+
// `inputs`: `components/src/renderers/layout/page.tsx` builds the JSX-page
|
|
152
|
+
// compiler's manifest from `getKnownTypes()`, registry-wide. What this list
|
|
153
|
+
// gates is `getPublicConfigs()` — the curated AI-authoring vocabulary, and
|
|
154
|
+
// through `sdui-parser/scripts/gen-manifest.ts` the published
|
|
155
|
+
// `sdui.manifest.json` and `sdui-intrinsics.d.ts`. THAT is the surface `box`
|
|
156
|
+
// was missing from, which is a narrower and truer statement of the gap than
|
|
157
|
+
// "the contract does not know it".
|
|
158
|
+
//
|
|
159
|
+
// The measurement is pinned next to the roster census in `apps/console`, over
|
|
160
|
+
// the DERIVED container population rather than over this list.
|
|
161
|
+
'box',
|
|
105
162
|
'page:header',
|
|
106
163
|
'text',
|
|
107
164
|
'image',
|
|
@@ -124,7 +124,7 @@ export function generateColorVars(colors) {
|
|
|
124
124
|
// (`fontSize` / `fontWeight` / `lineHeight` / `letterSpacing`, plus
|
|
125
125
|
// `fontFamily.heading` / `fontFamily.mono`) became TOMBSTONES: the schema now
|
|
126
126
|
// rejects them by name and their prescription points at `theme.customVars`, the
|
|
127
|
-
// declared — and since #5021 the only — door for a custom property. A
|
|
127
|
+
// declared — and since objectstack-ai/objectstack#5021 the only — door for a custom property. A
|
|
128
128
|
// `--z-modal` or a `--duration-fast` is authored there now, emitted verbatim as
|
|
129
129
|
// `--<key>: <value>`.
|
|
130
130
|
//
|
|
@@ -0,0 +1,82 @@
|
|
|
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
|
+
* chart-category-key — the ONE answer to "which result column carries the
|
|
10
|
+
* CATEGORY?" for an object-bound chart (objectui#8269).
|
|
11
|
+
*
|
|
12
|
+
* The mirror of `chart-measure-key` (objectui#8266) on the other axis. That
|
|
13
|
+
* card landed `chartMeasureKey` over the contract's `chartAggregateValueKey`;
|
|
14
|
+
* the contract publishes a CATEGORY sibling in the same module —
|
|
15
|
+
* `chartAggregateCategoryKey` — and nothing in this repository read it.
|
|
16
|
+
*
|
|
17
|
+
* ## The disagreement this replaces
|
|
18
|
+
*
|
|
19
|
+
* Both dashboard relays composed the category binding as a LITERAL FLOOR:
|
|
20
|
+
*
|
|
21
|
+
* const xAxisKey = options.xField || 'name';
|
|
22
|
+
*
|
|
23
|
+
* and handed it to the `object-chart` node without ever consulting the
|
|
24
|
+
* `aggregate` that decides it. An object-bound aggregate returns one row per
|
|
25
|
+
* group, keyed by the raw `groupBy` field, so a widget declaring
|
|
26
|
+
* `aggregate: { function: 'count', groupBy: 'status' }` and no `options.xField`
|
|
27
|
+
* bound `'name'` against rows keyed `'status'`.
|
|
28
|
+
*
|
|
29
|
+
* Unlike the measure half, this one is LOUD: `hasNoCategoryKey`
|
|
30
|
+
* (`plugin-charts/src/AdvancedChartImpl.tsx`, framework#4033) fires and the
|
|
31
|
+
* author reads "This chart cannot plot its category axis: no row has a `name`
|
|
32
|
+
* field." The diagnostic is wrong-CAUSE — it names a binding the author never
|
|
33
|
+
* wrote and never mentions the `groupBy` they did — so it points at the wrong
|
|
34
|
+
* layer. Being loud makes it a lesser harm than objectui#8266, not a
|
|
35
|
+
* non-defect: measured over the rows a fieldless count returns,
|
|
36
|
+
* `[{status:'open',count:2},{status:'paid',count:5}]`, an `xAxisKey` of
|
|
37
|
+
* `'name'` refuses under BOTH series bindings, i.e. objectui#8266's fix does
|
|
38
|
+
* not reach this authoring shape at all.
|
|
39
|
+
*
|
|
40
|
+
* ## Why the answer is delegated rather than restated
|
|
41
|
+
*
|
|
42
|
+
* Restating the rule here would make this file a second opinion of a question
|
|
43
|
+
* the contract already answers — the objectui#5042 / #7544 / #8193 / #8168
|
|
44
|
+
* drift shape that `chart-measure-key` exists to end. So the rule stays
|
|
45
|
+
* upstream in `@objectstack/spec/ui` and this is the seam objectui-side callers
|
|
46
|
+
* share.
|
|
47
|
+
*
|
|
48
|
+
* ## ⚠️ NOT the same function as `resolveChartCategoryField`
|
|
49
|
+
*
|
|
50
|
+
* `plugin-charts`' own `resolveChartCategoryField` (objectui#8168) reads
|
|
51
|
+
* `aggregate.groupBy` first too — which is exactly why `ObjectChart` does NOT
|
|
52
|
+
* refuse this shape at its own level, and then forwards `schema.xAxisKey`
|
|
53
|
+
* verbatim as the render binding anyway. But the two answer DIFFERENT
|
|
54
|
+
* questions and must not be collapsed:
|
|
55
|
+
*
|
|
56
|
+
* - `resolveChartCategoryField` answers "which FIELD is the category?" — its
|
|
57
|
+
* structured-`groupBy` leg returns `node.field`, because its two readers
|
|
58
|
+
* are the refusal (does the author name a category at all?) and the
|
|
59
|
+
* field-metadata probe that loads that field's option labels and colours.
|
|
60
|
+
* - this function answers "which COLUMN do the returned rows carry it
|
|
61
|
+
* under?" — `groupBy.alias ?? groupBy.field` per the contract, because an
|
|
62
|
+
* `alias` (admitted by `ChartGroupBySchema`) renames the projected column.
|
|
63
|
+
*
|
|
64
|
+
* They coincide whenever no alias is written, which is why the distinction is
|
|
65
|
+
* easy to miss; conflating them would either bind an axis to a column the rows
|
|
66
|
+
* do not carry, or probe field metadata for a field that does not exist.
|
|
67
|
+
*/
|
|
68
|
+
import { type ChartAggregateLike } from '@objectstack/spec/ui';
|
|
69
|
+
/**
|
|
70
|
+
* The result column a chart's category axis / x-axis binding must name.
|
|
71
|
+
*
|
|
72
|
+
* `fallback` is the caller's own floor, used ONLY when the contract has no
|
|
73
|
+
* answer — a chart that declares no `aggregate` at all (its rows are raw
|
|
74
|
+
* records or authored literals, where the author's `xField` is the right key),
|
|
75
|
+
* an UNGROUPED aggregate (one row, no category column), or a `groupBy` shape
|
|
76
|
+
* `ChartGroupBySchema` already rejects. It is never a second opinion about an
|
|
77
|
+
* aggregate the contract CAN answer for.
|
|
78
|
+
*
|
|
79
|
+
* @param aggregate the chart's inline aggregate, or `undefined`
|
|
80
|
+
* @param fallback the key to bind when the contract has no answer
|
|
81
|
+
*/
|
|
82
|
+
export declare function chartCategoryKey(aggregate: ChartAggregateLike | undefined, fallback: string): string;
|
|
@@ -0,0 +1,84 @@
|
|
|
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
|
+
* chart-category-key — the ONE answer to "which result column carries the
|
|
10
|
+
* CATEGORY?" for an object-bound chart (objectui#8269).
|
|
11
|
+
*
|
|
12
|
+
* The mirror of `chart-measure-key` (objectui#8266) on the other axis. That
|
|
13
|
+
* card landed `chartMeasureKey` over the contract's `chartAggregateValueKey`;
|
|
14
|
+
* the contract publishes a CATEGORY sibling in the same module —
|
|
15
|
+
* `chartAggregateCategoryKey` — and nothing in this repository read it.
|
|
16
|
+
*
|
|
17
|
+
* ## The disagreement this replaces
|
|
18
|
+
*
|
|
19
|
+
* Both dashboard relays composed the category binding as a LITERAL FLOOR:
|
|
20
|
+
*
|
|
21
|
+
* const xAxisKey = options.xField || 'name';
|
|
22
|
+
*
|
|
23
|
+
* and handed it to the `object-chart` node without ever consulting the
|
|
24
|
+
* `aggregate` that decides it. An object-bound aggregate returns one row per
|
|
25
|
+
* group, keyed by the raw `groupBy` field, so a widget declaring
|
|
26
|
+
* `aggregate: { function: 'count', groupBy: 'status' }` and no `options.xField`
|
|
27
|
+
* bound `'name'` against rows keyed `'status'`.
|
|
28
|
+
*
|
|
29
|
+
* Unlike the measure half, this one is LOUD: `hasNoCategoryKey`
|
|
30
|
+
* (`plugin-charts/src/AdvancedChartImpl.tsx`, framework#4033) fires and the
|
|
31
|
+
* author reads "This chart cannot plot its category axis: no row has a `name`
|
|
32
|
+
* field." The diagnostic is wrong-CAUSE — it names a binding the author never
|
|
33
|
+
* wrote and never mentions the `groupBy` they did — so it points at the wrong
|
|
34
|
+
* layer. Being loud makes it a lesser harm than objectui#8266, not a
|
|
35
|
+
* non-defect: measured over the rows a fieldless count returns,
|
|
36
|
+
* `[{status:'open',count:2},{status:'paid',count:5}]`, an `xAxisKey` of
|
|
37
|
+
* `'name'` refuses under BOTH series bindings, i.e. objectui#8266's fix does
|
|
38
|
+
* not reach this authoring shape at all.
|
|
39
|
+
*
|
|
40
|
+
* ## Why the answer is delegated rather than restated
|
|
41
|
+
*
|
|
42
|
+
* Restating the rule here would make this file a second opinion of a question
|
|
43
|
+
* the contract already answers — the objectui#5042 / #7544 / #8193 / #8168
|
|
44
|
+
* drift shape that `chart-measure-key` exists to end. So the rule stays
|
|
45
|
+
* upstream in `@objectstack/spec/ui` and this is the seam objectui-side callers
|
|
46
|
+
* share.
|
|
47
|
+
*
|
|
48
|
+
* ## ⚠️ NOT the same function as `resolveChartCategoryField`
|
|
49
|
+
*
|
|
50
|
+
* `plugin-charts`' own `resolveChartCategoryField` (objectui#8168) reads
|
|
51
|
+
* `aggregate.groupBy` first too — which is exactly why `ObjectChart` does NOT
|
|
52
|
+
* refuse this shape at its own level, and then forwards `schema.xAxisKey`
|
|
53
|
+
* verbatim as the render binding anyway. But the two answer DIFFERENT
|
|
54
|
+
* questions and must not be collapsed:
|
|
55
|
+
*
|
|
56
|
+
* - `resolveChartCategoryField` answers "which FIELD is the category?" — its
|
|
57
|
+
* structured-`groupBy` leg returns `node.field`, because its two readers
|
|
58
|
+
* are the refusal (does the author name a category at all?) and the
|
|
59
|
+
* field-metadata probe that loads that field's option labels and colours.
|
|
60
|
+
* - this function answers "which COLUMN do the returned rows carry it
|
|
61
|
+
* under?" — `groupBy.alias ?? groupBy.field` per the contract, because an
|
|
62
|
+
* `alias` (admitted by `ChartGroupBySchema`) renames the projected column.
|
|
63
|
+
*
|
|
64
|
+
* They coincide whenever no alias is written, which is why the distinction is
|
|
65
|
+
* easy to miss; conflating them would either bind an axis to a column the rows
|
|
66
|
+
* do not carry, or probe field metadata for a field that does not exist.
|
|
67
|
+
*/
|
|
68
|
+
import { chartAggregateCategoryKey } from '@objectstack/spec/ui';
|
|
69
|
+
/**
|
|
70
|
+
* The result column a chart's category axis / x-axis binding must name.
|
|
71
|
+
*
|
|
72
|
+
* `fallback` is the caller's own floor, used ONLY when the contract has no
|
|
73
|
+
* answer — a chart that declares no `aggregate` at all (its rows are raw
|
|
74
|
+
* records or authored literals, where the author's `xField` is the right key),
|
|
75
|
+
* an UNGROUPED aggregate (one row, no category column), or a `groupBy` shape
|
|
76
|
+
* `ChartGroupBySchema` already rejects. It is never a second opinion about an
|
|
77
|
+
* aggregate the contract CAN answer for.
|
|
78
|
+
*
|
|
79
|
+
* @param aggregate the chart's inline aggregate, or `undefined`
|
|
80
|
+
* @param fallback the key to bind when the contract has no answer
|
|
81
|
+
*/
|
|
82
|
+
export function chartCategoryKey(aggregate, fallback) {
|
|
83
|
+
return chartAggregateCategoryKey(aggregate) ?? fallback;
|
|
84
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
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
|
+
* chart-measure-key — the ONE answer to "which result column carries the
|
|
10
|
+
* measure?" for an object-bound chart (objectui#8266).
|
|
11
|
+
*
|
|
12
|
+
* ## The disagreement this replaces
|
|
13
|
+
*
|
|
14
|
+
* The question was answered independently in three places, and for a FIELDLESS
|
|
15
|
+
* `count` — the normal way to author "how many records per status", and the
|
|
16
|
+
* most common dashboard chart there is — two of them answered differently:
|
|
17
|
+
*
|
|
18
|
+
* - the ROW PROJECTION (`aggregateValueKey` / `aggregateRecords` /
|
|
19
|
+
* `runAggregate`'s alias, all in `plugin-charts/src/ObjectChart.tsx`) keys
|
|
20
|
+
* the value column `'count'`, the alias the engine projects `COUNT(*)`
|
|
21
|
+
* under;
|
|
22
|
+
* - the SERIES BINDING, spelled twice in `plugin-dashboard`
|
|
23
|
+
* (`DashboardGridLayout.tsx` and `DashboardRenderer.tsx`), read
|
|
24
|
+
* `aggregate.field || (options.yField || 'value')` and so bound `'value'`.
|
|
25
|
+
*
|
|
26
|
+
* A `dataKey` naming a column no row carries plots nothing, and nothing says
|
|
27
|
+
* so: measured on `origin/main` `0fa7a9c83`, rows `[{status:'open',count:2},
|
|
28
|
+
* {status:'paid',count:5}]` with `series:[{dataKey:'value'}]` rendered a
|
|
29
|
+
* `.recharts-surface` with the category ticks "open"/"paid", **0 bars, 0
|
|
30
|
+
* rectangles**, no refusal and no empty state — the same rows under
|
|
31
|
+
* `dataKey:'count'` drew 2 rectangles. An empty chart reads as "no data yet",
|
|
32
|
+
* which is exactly what an author with a genuinely empty object also sees.
|
|
33
|
+
*
|
|
34
|
+
* ## Why the answer is delegated rather than restated
|
|
35
|
+
*
|
|
36
|
+
* `chartAggregateValueKey` in `@objectstack/spec/ui` is the CONTRACT's own
|
|
37
|
+
* derivation — "the VALUE column an object-bound aggregate produces … what a
|
|
38
|
+
* chart's series / y-axis binding must name". Producers and checkers already
|
|
39
|
+
* read it. Restating the rule here would make this file a fourth opinion of the
|
|
40
|
+
* same question, which is the shape (objectui#5042 / #7544 / #8193 / #8168)
|
|
41
|
+
* this module exists to end. So the rule lives upstream in the spec and this is
|
|
42
|
+
* the seam objectui-side callers share, exactly as `humanizeLabel` (objectui#5444)
|
|
43
|
+
* and `buildChartSeries` (ADR-0021) already are.
|
|
44
|
+
*
|
|
45
|
+
* ⛔ The inverse fix — making the row projection key a fieldless count
|
|
46
|
+
* `'value'` — is not available: it contradicts a pin the tree already carries
|
|
47
|
+
* (`ObjectChart.aggregateResultColumns.test.ts`) and renames the column every
|
|
48
|
+
* other consumer reads, including the engine's own `COUNT(*)` alias.
|
|
49
|
+
*/
|
|
50
|
+
import { type ChartAggregateLike } from '@objectstack/spec/ui';
|
|
51
|
+
export type { ChartAggregateLike };
|
|
52
|
+
/**
|
|
53
|
+
* The result column a chart's series must bind to.
|
|
54
|
+
*
|
|
55
|
+
* `fallback` is the caller's own floor, used ONLY when the contract has no
|
|
56
|
+
* answer — a chart that declares no `aggregate` at all (its rows are raw
|
|
57
|
+
* records or authored literals, where the author's `yField` is the right key),
|
|
58
|
+
* or an aggregate shape `ChartAggregateSchema` already rejects. It is never a
|
|
59
|
+
* second opinion about an aggregate the contract CAN answer for.
|
|
60
|
+
*
|
|
61
|
+
* @param aggregate the chart's inline aggregate, or `undefined`
|
|
62
|
+
* @param fallback the key to bind when the contract has no answer
|
|
63
|
+
*/
|
|
64
|
+
export declare function chartMeasureKey(aggregate: ChartAggregateLike | undefined, fallback: string): string;
|
|
@@ -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
|
+
* chart-measure-key — the ONE answer to "which result column carries the
|
|
10
|
+
* measure?" for an object-bound chart (objectui#8266).
|
|
11
|
+
*
|
|
12
|
+
* ## The disagreement this replaces
|
|
13
|
+
*
|
|
14
|
+
* The question was answered independently in three places, and for a FIELDLESS
|
|
15
|
+
* `count` — the normal way to author "how many records per status", and the
|
|
16
|
+
* most common dashboard chart there is — two of them answered differently:
|
|
17
|
+
*
|
|
18
|
+
* - the ROW PROJECTION (`aggregateValueKey` / `aggregateRecords` /
|
|
19
|
+
* `runAggregate`'s alias, all in `plugin-charts/src/ObjectChart.tsx`) keys
|
|
20
|
+
* the value column `'count'`, the alias the engine projects `COUNT(*)`
|
|
21
|
+
* under;
|
|
22
|
+
* - the SERIES BINDING, spelled twice in `plugin-dashboard`
|
|
23
|
+
* (`DashboardGridLayout.tsx` and `DashboardRenderer.tsx`), read
|
|
24
|
+
* `aggregate.field || (options.yField || 'value')` and so bound `'value'`.
|
|
25
|
+
*
|
|
26
|
+
* A `dataKey` naming a column no row carries plots nothing, and nothing says
|
|
27
|
+
* so: measured on `origin/main` `0fa7a9c83`, rows `[{status:'open',count:2},
|
|
28
|
+
* {status:'paid',count:5}]` with `series:[{dataKey:'value'}]` rendered a
|
|
29
|
+
* `.recharts-surface` with the category ticks "open"/"paid", **0 bars, 0
|
|
30
|
+
* rectangles**, no refusal and no empty state — the same rows under
|
|
31
|
+
* `dataKey:'count'` drew 2 rectangles. An empty chart reads as "no data yet",
|
|
32
|
+
* which is exactly what an author with a genuinely empty object also sees.
|
|
33
|
+
*
|
|
34
|
+
* ## Why the answer is delegated rather than restated
|
|
35
|
+
*
|
|
36
|
+
* `chartAggregateValueKey` in `@objectstack/spec/ui` is the CONTRACT's own
|
|
37
|
+
* derivation — "the VALUE column an object-bound aggregate produces … what a
|
|
38
|
+
* chart's series / y-axis binding must name". Producers and checkers already
|
|
39
|
+
* read it. Restating the rule here would make this file a fourth opinion of the
|
|
40
|
+
* same question, which is the shape (objectui#5042 / #7544 / #8193 / #8168)
|
|
41
|
+
* this module exists to end. So the rule lives upstream in the spec and this is
|
|
42
|
+
* the seam objectui-side callers share, exactly as `humanizeLabel` (objectui#5444)
|
|
43
|
+
* and `buildChartSeries` (ADR-0021) already are.
|
|
44
|
+
*
|
|
45
|
+
* ⛔ The inverse fix — making the row projection key a fieldless count
|
|
46
|
+
* `'value'` — is not available: it contradicts a pin the tree already carries
|
|
47
|
+
* (`ObjectChart.aggregateResultColumns.test.ts`) and renames the column every
|
|
48
|
+
* other consumer reads, including the engine's own `COUNT(*)` alias.
|
|
49
|
+
*/
|
|
50
|
+
import { chartAggregateValueKey } from '@objectstack/spec/ui';
|
|
51
|
+
/**
|
|
52
|
+
* The result column a chart's series must bind to.
|
|
53
|
+
*
|
|
54
|
+
* `fallback` is the caller's own floor, used ONLY when the contract has no
|
|
55
|
+
* answer — a chart that declares no `aggregate` at all (its rows are raw
|
|
56
|
+
* records or authored literals, where the author's `yField` is the right key),
|
|
57
|
+
* or an aggregate shape `ChartAggregateSchema` already rejects. It is never a
|
|
58
|
+
* second opinion about an aggregate the contract CAN answer for.
|
|
59
|
+
*
|
|
60
|
+
* @param aggregate the chart's inline aggregate, or `undefined`
|
|
61
|
+
* @param fallback the key to bind when the contract has no answer
|
|
62
|
+
*/
|
|
63
|
+
export function chartMeasureKey(aggregate, fallback) {
|
|
64
|
+
return chartAggregateValueKey(aggregate) ?? fallback;
|
|
65
|
+
}
|
|
@@ -5,58 +5,6 @@
|
|
|
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
|
-
* chart-presentation — the AUTHORED half of a dataset-bound chart, lowered onto
|
|
10
|
-
* the bindings {@link buildChartSeries} derived from the dataset selection.
|
|
11
|
-
*
|
|
12
|
-
* `chart-series.ts` beside this file owns the DATA half: which columns become
|
|
13
|
-
* series, which rows, which buckets. This file owns everything the author gets
|
|
14
|
-
* to say about how that data LOOKS — the ruled data/presentation split of
|
|
15
|
-
* objectui#4229, stated once:
|
|
16
|
-
*
|
|
17
|
-
* - **Data (derived, never forwarded)** — series MEMBERSHIP and the column each
|
|
18
|
-
* binding reads. Concretely `buildChartSeries`' `dataKey`s, `xAxisKey`, and
|
|
19
|
-
* the spec's two binding keys `ChartSeries.name` and `ChartAxis.field`.
|
|
20
|
-
* - **Presentation (authored, merged forward)** — everything else on those same
|
|
21
|
-
* objects: `series[].type` (the per-series mark), `series[].yAxis` (which
|
|
22
|
-
* axis it binds to), `label`/`color`/`stack`/`variant`/`dashArray`/`opacity`,
|
|
23
|
-
* the axis definitions' `title`/`format`/`min`/`max`/`stepSize`/
|
|
24
|
-
* `showGridLines`/`position`/`logarithmic`, and the chart chrome
|
|
25
|
-
* (`showLegend`, `showDataLabels`, `colors`, `annotations`, …).
|
|
26
|
-
*
|
|
27
|
-
* ## Why it lives in `@object-ui/core` rather than in one plugin
|
|
28
|
-
*
|
|
29
|
-
* It was written for `plugin-dashboard`'s `DatasetWidget` (#3135 → objectstack#7016
|
|
30
|
-
* → #4229) and lifted here by objectui#4877, when `plugin-report`'s embedded
|
|
31
|
-
* report chart turned out to need the SAME merge over the same spec shapes: the
|
|
32
|
-
* report was forwarding six keys and dropping every authored chrome key the
|
|
33
|
-
* schema declares, and re-deriving this beside the dashboard's copy is exactly
|
|
34
|
-
* the duplication objectui#4389 filed as a defect (two longhand copies of the
|
|
35
|
-
* analytics label net, one per plugin, drifting apart).
|
|
36
|
-
*
|
|
37
|
-
* Everything here is a pure data transform over plain records, so it sits below
|
|
38
|
-
* both plugins with no React and no i18n — the same layering `chart-series.ts`
|
|
39
|
-
* already has (see {@link OptionLabelTranslator} there for why an i18n-resolved
|
|
40
|
-
* string always arrives as an ARGUMENT rather than being read here).
|
|
41
|
-
*
|
|
42
|
-
* ## Two entry points, because the two surfaces declare axes differently
|
|
43
|
-
*
|
|
44
|
-
* A dashboard widget's `chartConfig` spells its axes as spec `ChartAxis`
|
|
45
|
-
* OBJECTS. A report's `chart.xAxis` / `chart.yAxis` are bare dimension/measure
|
|
46
|
-
* NAME strings — on that surface the axes are pure DATA (they ARE the selection)
|
|
47
|
-
* and carry no presentation at all. So:
|
|
48
|
-
*
|
|
49
|
-
* - {@link mergeAuthoredPresentation} is the object-axis entry point: series
|
|
50
|
-
* merge + axis presentation, for a caller whose axes are `ChartAxis` objects.
|
|
51
|
-
* - {@link mergeAuthoredSeries} is the series merge ALONE, for a caller whose
|
|
52
|
-
* axes are names. That split is structural, not a guard: handing a bare
|
|
53
|
-
* string to {@link mergeAuthoredPresentation} would run it through
|
|
54
|
-
* `axisPresentation`, which reads nothing off a string and would synthesise a
|
|
55
|
-
* `yAxis: [{}]` entry — a y-axis declaring nothing but its own existence,
|
|
56
|
-
* which is precisely how the COUNT of entries turns on a secondary axis. A
|
|
57
|
-
* surface that cannot author axis presentation should not be able to reach
|
|
58
|
-
* the code that reads it.
|
|
59
|
-
*/
|
|
60
8
|
import type { ChartSeriesBinding } from './chart-series.js';
|
|
61
9
|
/** Authored spec `ChartSeries` presentation, in the renderer's internal spelling. */
|
|
62
10
|
export interface AuthoredSeriesPresentation {
|
|
@@ -76,39 +24,25 @@ export type MergedChartSeries = ChartSeriesBinding & AuthoredSeriesPresentation;
|
|
|
76
24
|
* One authored `ChartSeries`, minus its `name` — i.e. everything about it that
|
|
77
25
|
* is presentation rather than membership.
|
|
78
26
|
*
|
|
79
|
-
* `type` is narrowed to the three families that COMPOSE on one cartesian plot
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
27
|
+
* `type` is narrowed to the three families that COMPOSE on one cartesian plot.
|
|
28
|
+
* Without the narrowing a `type: 'pie'` would not merely be inert — it would
|
|
29
|
+
* count as a family disagreement in `effectiveChartFamily`, flip the whole
|
|
30
|
+
* chart into a combo, and then draw that series as a bar anyway.
|
|
31
|
+
*
|
|
32
|
+
* `ChartRenderer` now narrows the same way for every series it receives,
|
|
33
|
+
* `dataKey`-shaped or not (`01c27c431` fixed the fast path that used to
|
|
34
|
+
* forward a `dataKey`-shaped array straight through, so `normalizeChartSchema`'s
|
|
35
|
+
* own identical narrowing never saw it) — so this module is no longer that
|
|
36
|
+
* narrowing's only line of defense. It stays anyway:
|
|
37
|
+
* `AuthoredSeriesPresentation.chartType` is a typed, narrower field
|
|
38
|
+
* (`'bar' | 'line' | 'area'`) this module's own callers read directly, and the
|
|
39
|
+
* double narrowing downstream is idempotent.
|
|
86
40
|
*/
|
|
87
41
|
export declare function seriesPresentation(raw: Record<string, unknown>): AuthoredSeriesPresentation;
|
|
88
|
-
/**
|
|
89
|
-
* One authored `ChartAxis`, minus its `field` — the axis's presentation.
|
|
90
|
-
*
|
|
91
|
-
* `field` is the one DATA key on an axis (it names the plotted column), and
|
|
92
|
-
* dropping it here is what keeps membership with the dataset **structurally**
|
|
93
|
-
* rather than by a guard: `normalizeChartSchema` synthesises series out of
|
|
94
|
-
* `yAxis[].field` when a chart declares no series, so a forwarded `field`
|
|
95
|
-
* would be a live membership channel on an empty selection. With it gone the
|
|
96
|
-
* axis carries scale and chrome only, and the count of entries — which is what
|
|
97
|
-
* turns on the secondary axis (`yAxes.length > 1`) — survives, including for
|
|
98
|
-
* an entry that declares nothing but its own existence.
|
|
99
|
-
*
|
|
100
|
-
* Keys the renderer does not read on a given axis are dropped by
|
|
101
|
-
* `normalizeChartSchema`, the ONE normalization layer (#2880 S1): today it
|
|
102
|
-
* keeps `format`/`title`/`showGridLines` on the x-axis and the full set on the
|
|
103
|
-
* y-axes. That narrowing is deliberately NOT mirrored here — a second copy
|
|
104
|
-
* would drift from the renderer's real capability the moment it grew.
|
|
105
|
-
*/
|
|
106
|
-
export declare function axisPresentation(raw: unknown): Record<string, unknown>;
|
|
107
42
|
/**
|
|
108
43
|
* Merge an authored `series[]` array's PRESENTATION onto the bindings the
|
|
109
|
-
* dataset selection derived — the series half of #4229's split, and the
|
|
110
|
-
*
|
|
111
|
-
* header).
|
|
44
|
+
* dataset selection derived — the series half of #4229's split, and the only
|
|
45
|
+
* half this module lowers (see the file header).
|
|
112
46
|
*
|
|
113
47
|
* The match rule is **by name/key**: an authored `series[].name` is paired with
|
|
114
48
|
* the derived binding whose `dataKey` it equals, and the pairing decides
|
|
@@ -136,28 +70,10 @@ export declare function axisPresentation(raw: unknown): Record<string, unknown>;
|
|
|
136
70
|
*/
|
|
137
71
|
export declare function mergeAuthoredSeries(derived: ChartSeriesBinding[], authoredSeries: unknown): MergedChartSeries[];
|
|
138
72
|
/**
|
|
139
|
-
*
|
|
140
|
-
*
|
|
141
|
-
*
|
|
142
|
-
*
|
|
143
|
-
* The series half is {@link mergeAuthoredSeries}; see it for the match rule and
|
|
144
|
-
* for why membership is safe. The axes half reads `xAxis` / `yAxis` through
|
|
145
|
-
* {@link axisPresentation}, which is why a surface spelling those as bare NAME
|
|
146
|
-
* strings must call `mergeAuthoredSeries` directly instead (file header).
|
|
147
|
-
*
|
|
148
|
-
* @param derived the bindings {@link buildChartSeries} produced from the selection
|
|
149
|
-
* @param raw the authored chart config (anything, incl. absent)
|
|
150
|
-
* @returns the merged series, plus the presentation-only axes to spread onto
|
|
151
|
-
* the chart schema (absent when the author declared none)
|
|
152
|
-
*/
|
|
153
|
-
export declare function mergeAuthoredPresentation(derived: ChartSeriesBinding[], raw: unknown): {
|
|
154
|
-
series: MergedChartSeries[];
|
|
155
|
-
axes: Record<string, unknown>;
|
|
156
|
-
};
|
|
157
|
-
/**
|
|
158
|
-
* Lower an authored chart config's CHROME (spec `ChartConfigSchema` /
|
|
159
|
-
* `ReportChartSchema` — the same keys on both) onto the chart schema a
|
|
160
|
-
* dataset-bound surface hands the renderer.
|
|
73
|
+
* Lower an authored chart config's CHROME (spec
|
|
74
|
+
* `DashboardWidgetChartConfigSchema` / `ReportChartSchema`, both extensions of
|
|
75
|
+
* `ChartConfigSchema` that keep its chrome keys unchanged) onto the chart
|
|
76
|
+
* schema a dataset-bound surface hands the renderer.
|
|
161
77
|
*
|
|
162
78
|
* ## Why this is a whitelist and not a spread
|
|
163
79
|
*
|
|
@@ -181,20 +97,48 @@ export declare function mergeAuthoredPresentation(derived: ChartSeriesBinding[],
|
|
|
181
97
|
* exists to remove.
|
|
182
98
|
* 2. **It does not fight the dataset derivation.** `type` stays out: the
|
|
183
99
|
* calling surface's own type already picks the chart family, which is the
|
|
184
|
-
* dataset path's chart-family channel.
|
|
185
|
-
*
|
|
186
|
-
*
|
|
187
|
-
*
|
|
188
|
-
*
|
|
189
|
-
*
|
|
190
|
-
*
|
|
191
|
-
*
|
|
192
|
-
*
|
|
100
|
+
* dataset path's chart-family channel. The spec agrees on the dashboard
|
|
101
|
+
* carrier: since 17.5.0 `DashboardWidgetChartConfigSchema` refuses
|
|
102
|
+
* `chartConfig.type` at parse, with `xAxis` / `yAxis` / `series`, none of
|
|
103
|
+
* which this whitelist ever lowered (objectui#11315).
|
|
104
|
+
*
|
|
105
|
+
* `aria` is not lowered either. No renderer reads it: `AdvancedChartImpl` has
|
|
106
|
+
* no `aria` prop, and `SchemaRenderer`'s ARIA injection reads the FLAT
|
|
107
|
+
* `ariaLabel`/`ariaDescribedBy`/`role`, never a nested `aria` object (criterion
|
|
108
|
+
* 1). And it is no longer declared: spec 17.5.0 retired `ChartConfig.aria` as
|
|
109
|
+
* a `retiredKey` tombstone (objectstack#17751, objectui#4044), so an authored
|
|
110
|
+
* one is refused at parse. The accessible name a chart applies is
|
|
111
|
+
* `description`, above.
|
|
193
112
|
*
|
|
194
113
|
* `title` IS emitted here. A caller that paints the title itself (the report
|
|
195
114
|
* renderer's own `h3` above the chart) must drop it from the result, or the
|
|
196
115
|
* chart draws a second one.
|
|
197
116
|
*
|
|
117
|
+
* ## `title` / `subtitle` / `description` are `I18nLabel`, and travel as such
|
|
118
|
+
*
|
|
119
|
+
* `ChartConfigSchema` types all three as the spec's `I18nLabel` union — a plain
|
|
120
|
+
* string OR an inline locale map — so all three are lowered by
|
|
121
|
+
* {@link forwardedI18nLabel}, which hands the authored value on untouched for
|
|
122
|
+
* the renderer to resolve against the viewer's language. Read that helper for
|
|
123
|
+
* why resolving cannot happen in this package.
|
|
124
|
+
*
|
|
125
|
+
* ⚠️ LEDGERED, by name, as still unresolved after objectui#9038 — not in
|
|
126
|
+
* that card's scope and not reached by the change above:
|
|
127
|
+
*
|
|
128
|
+
* - **A series `label`** still goes through {@link labelText}'s
|
|
129
|
+
* first-string-wins pick, the design objectui#4020 ledgered and a caller
|
|
130
|
+
* can override. Not reopened here.
|
|
131
|
+
*
|
|
132
|
+
* ✓ CLEARED, objectui#9150 — **the report renderer's own heading.**
|
|
133
|
+
* `DatasetReportChart` (`@object-ui/plugin-report`) still drops `title` from
|
|
134
|
+
* this result and still paints its own `h3`, but that read site no longer
|
|
135
|
+
* narrows `chart.title` to a plain string: it resolves the union through
|
|
136
|
+
* `pickLocalized` against the viewer's language, like every other `I18nLabel`
|
|
137
|
+
* on that surface. Kept here rather than deleted because the ledger entry is
|
|
138
|
+
* what the fixing card was dispatched from, and because the FIRST half of it —
|
|
139
|
+
* that a caller painting the title itself must drop `title` from this result —
|
|
140
|
+
* is a live constraint on this whitelist, stated above.
|
|
141
|
+
*
|
|
198
142
|
* @param raw the authored chart config (anything, incl. absent)
|
|
199
143
|
* @param fieldCategoryColors per-category colours resolved from the category
|
|
200
144
|
* dimension's own select/lookup option colours, merged UNDER an explicit
|
|
@@ -203,3 +147,42 @@ export declare function mergeAuthoredPresentation(derived: ChartSeriesBinding[],
|
|
|
203
147
|
* derived chart schema and every undeclared key keeps the renderer's default
|
|
204
148
|
*/
|
|
205
149
|
export declare function chartConfigPresentation(raw: unknown, fieldCategoryColors?: Record<string, string> | null): Record<string, unknown>;
|
|
150
|
+
/**
|
|
151
|
+
* Whether a chart of this family IGNORES `compareTo` — the one declaration of
|
|
152
|
+
* that rule (objectui#7495).
|
|
153
|
+
*
|
|
154
|
+
* Every surface that turns a `compareTo` into a comparison reads this; none
|
|
155
|
+
* keeps a list of its own. The inline chart path (`@object-ui/plugin-charts`'
|
|
156
|
+
* ObjectChart) skips the comparison fetch and synthesises no overlay series for
|
|
157
|
+
* these families, and the dataset widget path (`@object-ui/plugin-dashboard`'s
|
|
158
|
+
* DatasetWidget) forwards no `compareTo` to the executor for a chart of one of
|
|
159
|
+
* them, so the comparison pass never runs and no overlay series is appended.
|
|
160
|
+
*
|
|
161
|
+
* - `pie` / `donut` / `funnel` — single-distribution charts: a comparison
|
|
162
|
+
* overlay has no meaning on them, and the renderer's pie and funnel arms
|
|
163
|
+
* draw only `series[0]`.
|
|
164
|
+
* - `scatter` (objectui#7402) — a scatter binds ONE measure: the renderer reads
|
|
165
|
+
* y through the single `YAxis dataKey={series[0].dataKey}`, so an overlay was
|
|
166
|
+
* painted on the PRIMARY's y and "previous period" landed exactly on top of
|
|
167
|
+
* "current". Drawing it honestly needs the multi-measure projection declined
|
|
168
|
+
* as option A of objectui#7194; `compareTo` on a scatter returns WITH that
|
|
169
|
+
* projection.
|
|
170
|
+
*
|
|
171
|
+
* It reads the RENDERER's chart family (`bar`, `pie`, `scatter`, …), not a
|
|
172
|
+
* dashboard widget type: a caller whose widget types alias a family (the
|
|
173
|
+
* dashboard maps `bubble` to `scatter` and `pyramid` to `funnel`) maps first and
|
|
174
|
+
* asks about the family. An absent or unrecognised family does NOT ignore
|
|
175
|
+
* `compareTo` — the comparison runs.
|
|
176
|
+
*
|
|
177
|
+
* Why it lives here: the dashboard reaches `@object-ui/plugin-charts` only as a
|
|
178
|
+
* devDependency, so this package — a runtime dependency of both — is the one
|
|
179
|
+
* place both paths can read. Two copies were how the lists drifted apart: the
|
|
180
|
+
* dashboard's said "scatter only" while the charts package said all four, so a
|
|
181
|
+
* compare-to pie widget ran a comparison query whose overlay the renderer then
|
|
182
|
+
* dropped (objectui#7495; objectui#4389 is the precedent that a second copy of
|
|
183
|
+
* chart-presentation logic is a defect).
|
|
184
|
+
*
|
|
185
|
+
* @param chartType the chart family, or `undefined` when none is declared
|
|
186
|
+
* @returns `true` for `pie`, `donut`, `funnel` and `scatter`; `false` otherwise
|
|
187
|
+
*/
|
|
188
|
+
export declare function chartTypeIgnoresCompareTo(chartType: string | undefined): boolean;
|