@object-ui/plugin-charts 16.1.0 → 17.1.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 +376 -1
- package/dist/AdvancedChartImpl.d.ts +65 -11
- package/dist/ChartRenderer.d.ts +46 -0
- package/dist/ObjectChart.d.ts +17 -1
- package/dist/index.js +1132 -726
- package/dist/index.umd.cjs +2 -2
- package/dist/normalizeChartSchema.d.ts +207 -0
- package/package.json +9 -8
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,380 @@
|
|
|
1
1
|
# @object-ui/plugin-charts
|
|
2
2
|
|
|
3
|
+
## 17.1.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- f1c04b6: fix(charts): a spec `series[].type` override actually draws, and a spec-shape `series` plots at all (#2945)
|
|
8
|
+
|
|
9
|
+
#2945 listed `combo` (`plugin-charts`) as renderer-local dialect to "promote or
|
|
10
|
+
delete". Neither: the spec **already models a combo chart**, per-series, and its
|
|
11
|
+
own field comment says so —
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
// spec/src/ui/chart.zod.ts — ChartSeriesSchema
|
|
15
|
+
/** Series type override (combo charts) */
|
|
16
|
+
type: ChartTypeSchema.optional().describe('Override chart type for this series'),
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
— exactly as it models stacking with `ChartSeries.stack` rather than a
|
|
20
|
+
`stacked-bar` family. So `combo` is not a name an author should reach for; it is
|
|
21
|
+
what "the series disagree about their family" looks like from the renderer's
|
|
22
|
+
side. `effectiveChartFamily` now derives it, and `combo` stays a documented
|
|
23
|
+
renderer-local marker (internal callers pass it directly today).
|
|
24
|
+
|
|
25
|
+
Chasing that turned up two live bugs, both silent, on the path a spec author
|
|
26
|
+
takes.
|
|
27
|
+
|
|
28
|
+
**1. The per-series override was parsed, carried, and then dropped.** Only the
|
|
29
|
+
renderer's `chartType === 'combo'` branch read `series[].chartType`, so
|
|
30
|
+
|
|
31
|
+
```ts
|
|
32
|
+
{ type: 'bar', series: [{ name: 'revenue' }, { name: 'margin', type: 'line' }] }
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
drew `margin` as a bar. Nothing was wrong at any layer but the last — a unit test
|
|
36
|
+
even asserted the value was carried.
|
|
37
|
+
|
|
38
|
+
**2. A spec-shape `series` rendered nothing at all.** `series` is the one binding
|
|
39
|
+
both shapes spell with the same key, so `ChartRenderer`'s blanket "internal props
|
|
40
|
+
win" rule let the author's `[{ name }]` shadow the normalized `[{ dataKey }]` and
|
|
41
|
+
reach a renderer that reads `dataKey`. Blank chart. Every other spec binding has a
|
|
42
|
+
distinct name (`xAxis` vs `xAxisKey`), which is why only this one broke — and why
|
|
43
|
+
the isolated normalization tests all passed over a dead path. The raw array is now
|
|
44
|
+
preferred only when it already speaks the internal shape, so internal callers are
|
|
45
|
+
byte-for-byte unchanged and a mixed array works too.
|
|
46
|
+
|
|
47
|
+
**Also fixed in passing:** the combo branch had an `area` arm under a `BarChart`
|
|
48
|
+
container, and Recharts renders an `<Area>` child of `BarChart` as nothing — so an
|
|
49
|
+
authored combo with an `area` series drew a blank series. The container is now
|
|
50
|
+
`ComposedChart`, which is what Recharts provides for mixed marks.
|
|
51
|
+
|
|
52
|
+
Widening only. A chart whose series all resolve to one family keeps its own
|
|
53
|
+
family, an explicit `combo` is untouched, and a family with no per-series meaning
|
|
54
|
+
(`pie`, `horizontal-bar`, …) is never widened. A derived combo binds series to the
|
|
55
|
+
left axis unless one asks for `yAxis: 'right'` — the spec's own default — so
|
|
56
|
+
widening changes the series' mark and not its scale; the legacy bar→left/line→right
|
|
57
|
+
guess is kept for an authored `combo`, where it was historically the only way to
|
|
58
|
+
reach a second axis.
|
|
59
|
+
|
|
60
|
+
Guards: `effectiveChartFamily` / `comboBaseFamily` are unit-tested over the whole
|
|
61
|
+
family matrix; DOM-level tests assert the **marks** rather than the derived family,
|
|
62
|
+
since the carry was already covered and the drawing was what broke; and
|
|
63
|
+
`spec-derived-unions.test.ts` asserts `combo` is absent from the spec's
|
|
64
|
+
`ChartTypeSchema`, so the day it is adopted upstream the derivation is named as the
|
|
65
|
+
thing to retire.
|
|
66
|
+
|
|
67
|
+
### Patch Changes
|
|
68
|
+
|
|
69
|
+
- Updated dependencies [62311b6]
|
|
70
|
+
- Updated dependencies [fc0272a]
|
|
71
|
+
- Updated dependencies [9e7349e]
|
|
72
|
+
- Updated dependencies [8864971]
|
|
73
|
+
- Updated dependencies [1cf0de7]
|
|
74
|
+
- Updated dependencies [752e18f]
|
|
75
|
+
- Updated dependencies [c785740]
|
|
76
|
+
- Updated dependencies [b41f401]
|
|
77
|
+
- Updated dependencies [19e9fa0]
|
|
78
|
+
- Updated dependencies [d61efd1]
|
|
79
|
+
- Updated dependencies [95b7214]
|
|
80
|
+
- Updated dependencies [7d9734d]
|
|
81
|
+
- Updated dependencies [6ae818e]
|
|
82
|
+
- Updated dependencies [9eb932b]
|
|
83
|
+
- Updated dependencies [746dd00]
|
|
84
|
+
- Updated dependencies [aebfa4f]
|
|
85
|
+
- Updated dependencies [38ca8be]
|
|
86
|
+
- Updated dependencies [3cb9646]
|
|
87
|
+
- Updated dependencies [68ef584]
|
|
88
|
+
- Updated dependencies [4952edf]
|
|
89
|
+
- Updated dependencies [7f0252e]
|
|
90
|
+
- Updated dependencies [c4d7b20]
|
|
91
|
+
- Updated dependencies [c769d3d]
|
|
92
|
+
- Updated dependencies [7639a61]
|
|
93
|
+
- Updated dependencies [94e63ef]
|
|
94
|
+
- Updated dependencies [c735bf7]
|
|
95
|
+
- Updated dependencies [02aef0c]
|
|
96
|
+
- Updated dependencies [6f29aa5]
|
|
97
|
+
- Updated dependencies [d21794c]
|
|
98
|
+
- Updated dependencies [c4db402]
|
|
99
|
+
- Updated dependencies [5319bf1]
|
|
100
|
+
- Updated dependencies [49e5671]
|
|
101
|
+
- Updated dependencies [9a04d25]
|
|
102
|
+
- Updated dependencies [b5b97e2]
|
|
103
|
+
- Updated dependencies [f59f2c1]
|
|
104
|
+
- Updated dependencies [07de839]
|
|
105
|
+
- Updated dependencies [2a40b5e]
|
|
106
|
+
- Updated dependencies [df613fa]
|
|
107
|
+
- Updated dependencies [4874117]
|
|
108
|
+
- Updated dependencies [ad0183a]
|
|
109
|
+
- Updated dependencies [ce08d55]
|
|
110
|
+
- Updated dependencies [eb4b740]
|
|
111
|
+
- Updated dependencies [5b084eb]
|
|
112
|
+
- Updated dependencies [aa1240a]
|
|
113
|
+
- Updated dependencies [2374a49]
|
|
114
|
+
- Updated dependencies [390c071]
|
|
115
|
+
- Updated dependencies [d10f526]
|
|
116
|
+
- Updated dependencies [2d5d594]
|
|
117
|
+
- Updated dependencies [ea7f477]
|
|
118
|
+
- Updated dependencies [379728f]
|
|
119
|
+
- Updated dependencies [7f23cd0]
|
|
120
|
+
- Updated dependencies [0ded602]
|
|
121
|
+
- Updated dependencies [24e0e0a]
|
|
122
|
+
- Updated dependencies [f8a95e5]
|
|
123
|
+
- Updated dependencies [3a6cf24]
|
|
124
|
+
- Updated dependencies [aa35561]
|
|
125
|
+
- Updated dependencies [03bd53b]
|
|
126
|
+
- Updated dependencies [3c1f321]
|
|
127
|
+
- Updated dependencies [a045a32]
|
|
128
|
+
- Updated dependencies [912496d]
|
|
129
|
+
- Updated dependencies [80edbd4]
|
|
130
|
+
- Updated dependencies [9867281]
|
|
131
|
+
- @object-ui/core@17.1.0
|
|
132
|
+
- @object-ui/components@17.1.0
|
|
133
|
+
- @object-ui/react@17.1.0
|
|
134
|
+
- @object-ui/types@17.1.0
|
|
135
|
+
- @object-ui/i18n@17.1.0
|
|
136
|
+
|
|
137
|
+
## 17.0.0
|
|
138
|
+
|
|
139
|
+
### Minor Changes
|
|
140
|
+
|
|
141
|
+
- aa88056: feat(charts): honor `ChartAxis.stepSize`, `ChartConfig.description` and `ChartConfig.height` (framework#3752)
|
|
142
|
+
|
|
143
|
+
The tail of the declared-≠-delivered sweep from framework#3729 / #2880. Three
|
|
144
|
+
`ChartConfig` props reached the renderer and did nothing:
|
|
145
|
+
|
|
146
|
+
- **`ChartAxis.stepSize`** — Recharts has no "a tick every N units" prop
|
|
147
|
+
(`tickCount` is a hint it may ignore, `interval` is for categorical axes), so
|
|
148
|
+
honoring a step means handing it the tick array outright. `ticksFor` builds it
|
|
149
|
+
from the axis's own `min`/`max` where declared and from the plotted values
|
|
150
|
+
otherwise, so a step works with or without a pinned domain. A data-derived max
|
|
151
|
+
rounds UP to the next step (otherwise the topmost bar sits above the last
|
|
152
|
+
gridline and the axis reads as truncated); an explicit `max` clamps instead,
|
|
153
|
+
since a tick outside a pinned domain would be drawn outside the plot. A step
|
|
154
|
+
that would produce more than 200 ticks is refused rather than rendered — that
|
|
155
|
+
is a wrong config, and drawing it would hang the page instead of surfacing the
|
|
156
|
+
mistake.
|
|
157
|
+
- **`ChartConfig.description`** — the accessibility description. A chart is a
|
|
158
|
+
picture to a screen reader; the container now carries `role="img"` +
|
|
159
|
+
`aria-label`. Without a description it stays an ordinary div, because
|
|
160
|
+
stamping `role="img"` on an _unlabelled_ graphic is worse than leaving one a
|
|
161
|
+
screen reader can skip.
|
|
162
|
+
- **`ChartConfig.height`** — was read only by the legacy `ChartBarRenderer`, not
|
|
163
|
+
by the advanced path that draws every real chart. Now applied to the chart
|
|
164
|
+
container as an inline style, which beats its default `h-[350px]` class.
|
|
165
|
+
|
|
166
|
+
`height` and `description` ride on the shared container props, so they apply to
|
|
167
|
+
all eight chart families rather than one branch.
|
|
168
|
+
|
|
169
|
+
- 9b53d72: feat(charts): ObjectChart honors the spec `ChartConfig` author shape (objectui#2880 / framework#3729)
|
|
170
|
+
|
|
171
|
+
`ChartConfigSchema` is the chart protocol, but the renderer only ever read a
|
|
172
|
+
Recharts-flavoured internal shape — `chartType`, `xAxisKey`, `series[].dataKey`.
|
|
173
|
+
Everything an author wrote in the SPEC shape reached the renderer and was
|
|
174
|
+
silently dropped, which is exactly what ADR-0078 forbids. framework#3725
|
|
175
|
+
documented the gap by trimming the published contract down to the props that
|
|
176
|
+
actually worked; this closes it the other way round.
|
|
177
|
+
|
|
178
|
+
**S1 — one normalization boundary.** `normalizeChartSchema` translates the
|
|
179
|
+
author shape into the internal pipeline contract in a single place, rather than
|
|
180
|
+
scattering `??` fallbacks through the render tree (framework PD #12: one
|
|
181
|
+
translation is a contract mapping, N fallbacks are a second dialect):
|
|
182
|
+
|
|
183
|
+
- `type` → `chartType`, `xAxis: { field }` → `xAxisKey`, `series: [{ name }]` →
|
|
184
|
+
`series: [{ dataKey }]`
|
|
185
|
+
- the report surface's bare-string `xAxis`/`yAxis` resolve too
|
|
186
|
+
- `yAxis: [{ field }]` alone plots, with no `series` declared
|
|
187
|
+
- **internal props win**, so `DashboardRenderer`, `ObjectView` and the dataset
|
|
188
|
+
path are byte-for-byte unaffected — there is no migration
|
|
189
|
+
|
|
190
|
+
**The `type` collision.** `ChartConfig.type` is the chart family, but on any
|
|
191
|
+
surface that flattens chart config into a props bag `type` is already the SDUI
|
|
192
|
+
envelope's component discriminator. Spreading props last let an author's
|
|
193
|
+
`type="bar"` replace `object-chart` so the block stopped resolving; stamping the
|
|
194
|
+
discriminator last ate the author's value instead. The react-page wrapper now
|
|
195
|
+
keeps both: the discriminator wins the `type` slot and the author's value is
|
|
196
|
+
preserved beside it as `specType`, which the normalizer reads back.
|
|
197
|
+
|
|
198
|
+
**S2 — axis presentation.** `ChartAxis.format` drives the tick formatter (via
|
|
199
|
+
`Intl.NumberFormat`, no new dependency), `min`/`max` pin the domain,
|
|
200
|
+
`logarithmic` swaps the scale, `title` labels the axis, and `showGridLines` is
|
|
201
|
+
honored. A second `yAxis` entry (or `position: 'right'`) turns on the secondary
|
|
202
|
+
axis that `series[].yAxis` binds to — in combo charts an explicit binding now
|
|
203
|
+
beats the family-derived bar→left/line→right guess. `showLegend` is honored,
|
|
204
|
+
and `title`/`subtitle` render above the plot instead of only titling the
|
|
205
|
+
drill-down drawer.
|
|
206
|
+
|
|
207
|
+
**S3 — `series[].stack`, `annotations`, `interaction`.** Stacking passes the
|
|
208
|
+
author's group name through as Recharts' `stackId`. Annotations render as
|
|
209
|
+
`ReferenceLine` (`type: 'line'`) / `ReferenceArea` (`type: 'region'`) with the
|
|
210
|
+
declared axis, colour, style and label. `interaction.tooltips: false` suppresses
|
|
211
|
+
the hover card and `interaction.brush: true` adds the range selector;
|
|
212
|
+
`showDataLabels` prints values on the marks. `interaction.zoom` has no Recharts
|
|
213
|
+
primitive behind it and is deliberately still unimplemented rather than faked.
|
|
214
|
+
|
|
215
|
+
### Patch Changes
|
|
216
|
+
|
|
217
|
+
- 7b35e4b: fix(dashboard,charts): resolve `{current_user_id}` in widget filters (framework #3574)
|
|
218
|
+
|
|
219
|
+
A dashboard widget filtered on `{current_user_id}` rendered `0`. The token
|
|
220
|
+
reached SQL as a literal, matched no row, and nothing was logged on the client
|
|
221
|
+
or the server — a silent zero that reads as "you have no work" rather than
|
|
222
|
+
"this filter did not resolve". The same token in a list-view filter resolved
|
|
223
|
+
correctly, so a user-scoped list and a user-scoped widget over the same data
|
|
224
|
+
disagreed.
|
|
225
|
+
|
|
226
|
+
There was no shared resolver. Three ad-hoc implementations had grown up
|
|
227
|
+
independently — `ObjectView` for list views, `ObjectDataPage` for URL filter
|
|
228
|
+
triples, `NavigationRenderer` for hrefs — and each understood only the filter
|
|
229
|
+
shape its own surface used. `ObjectView`'s opened with
|
|
230
|
+
`if (!Array.isArray(filter)) return filter`, so it could not have been reused
|
|
231
|
+
by dashboard widgets even in principle: widget filters are MongoDB-style
|
|
232
|
+
objects. Widgets therefore got no resolution at all — `DatasetWidget` called
|
|
233
|
+
`resolveDateMacros` and nothing else, which is why `{today}` worked in a widget
|
|
234
|
+
and `{current_user_id}` silently did not.
|
|
235
|
+
|
|
236
|
+
- **`@object-ui/core`** — new `utils/filter-tokens.ts` with
|
|
237
|
+
`resolveContextTokens` and `resolveFilterPlaceholders`. The latter expands
|
|
238
|
+
_every_ placeholder vocabulary in one call and is what surfaces should use;
|
|
239
|
+
resolving only some of them is the whole defect. The walk handles arrays and
|
|
240
|
+
plain objects uniformly, so one resolver covers both platform filter shapes.
|
|
241
|
+
- **`@object-ui/react`** — new `FilterScopeProvider` / `useFilterScope`. The
|
|
242
|
+
renderer packages deliberately do not depend on `@object-ui/auth`, so the
|
|
243
|
+
shell supplies the session values. This is a separate context from
|
|
244
|
+
`PredicateScopeContext`, which is the expression evaluation scope and carries
|
|
245
|
+
no organization.
|
|
246
|
+
- **`@object-ui/plugin-dashboard` / `@object-ui/plugin-charts`** — all six
|
|
247
|
+
widgets that previously resolved date macros only now resolve both
|
|
248
|
+
vocabularies: `DatasetWidget`, `ObjectMetricWidget`, `ObjectDataTable`,
|
|
249
|
+
`ObjectPivotTable`, and `ObjectChart` (dataset-bound and inline paths). The
|
|
250
|
+
chart's `compareTo` comparison filter gets the session pass too — otherwise
|
|
251
|
+
the overlay series silently ignored the owner clause the primary series
|
|
252
|
+
honoured.
|
|
253
|
+
- **`@object-ui/app-shell`** — `ObjectView`'s local `substituteFilterTokens`
|
|
254
|
+
and `ObjectDataPage`'s inline `=== '{current_user_id}'` ternary now delegate
|
|
255
|
+
to the shared resolver, so both also gain `{current_org_id}` and date macros.
|
|
256
|
+
Two of the three ad-hoc implementations are gone rather than joined by a
|
|
257
|
+
fourth.
|
|
258
|
+
|
|
259
|
+
An unresolvable token is left intact rather than dropped: leaving it yields an
|
|
260
|
+
empty result, whereas dropping the clause would _widen_ the result set and show
|
|
261
|
+
a signed-out viewer everyone's data. It is no longer silent — the resolver
|
|
262
|
+
warns, naming the token, and suggests the intended spelling for known
|
|
263
|
+
near-misses (`{current_user}`, `{user_id}`, `{organization_id}`). Authoring-time
|
|
264
|
+
enforcement lands separately as `filter-token-unknown` in `@objectstack/lint`.
|
|
265
|
+
|
|
266
|
+
- e16ed2d: fix(dashboard,charts): send widget `dateGranularity`/`sortBy`/`limit` to the query, and give funnels a real stage order (framework#3588)
|
|
267
|
+
|
|
268
|
+
`DatasetWidget` never read `widget.options`. Four keys an author writes there
|
|
269
|
+
change the query the server compiles, so a widget declaring
|
|
270
|
+
`options: { dateGranularity: 'month' }` grouped by the raw timestamp and drew
|
|
271
|
+
one bar per record, and `sortBy`/`sortOrder` produced no ordering at all.
|
|
272
|
+
|
|
273
|
+
- `DatasetWidget` lowers `options.dateGranularity`, `options.sortBy` +
|
|
274
|
+
`options.sortOrder`, and `options.limit` into the `DatasetSelection` it posts.
|
|
275
|
+
A `sortBy` naming something the widget does not project is dropped rather than
|
|
276
|
+
sent, so a stale sort key left by an edit degrades to "unordered" instead of
|
|
277
|
+
failing the widget against the server's stricter validation. These keys also
|
|
278
|
+
join the refetch signature, so editing one in the designer refetches instead
|
|
279
|
+
of re-rendering the previous grid.
|
|
280
|
+
- Funnel stages follow a **declared order**. `AdvancedChartImpl` sorted funnel
|
|
281
|
+
segments by value descending, unconditionally — which overrode any server
|
|
282
|
+
ordering and rendered a sales pipeline as a tidy narrowing shape whatever the
|
|
283
|
+
stages' real sequence, hiding the very anomaly (a bulge at Proposal) the chart
|
|
284
|
+
exists to show. It now honours a `categoryOrder`, which `DatasetWidget`
|
|
285
|
+
derives from the dimension field's picklist option order — the pipeline order
|
|
286
|
+
an author already declared on the object — or from an explicit
|
|
287
|
+
`options.stageOrder`. With no declared order the value-descending default is
|
|
288
|
+
unchanged, and a category missing from the order is kept (after the declared
|
|
289
|
+
ones), never dropped.
|
|
290
|
+
- New `@object-ui/core` helpers `buildCategoryOrder` / `buildCategoryRank`,
|
|
291
|
+
keyed by both the stored value and the display label like the existing
|
|
292
|
+
`buildOptionColorMap`, so ordering works whether or not the server resolved
|
|
293
|
+
the dimension's labels.
|
|
294
|
+
|
|
295
|
+
Requires the framework-side fix in objectstack#3588 for the selection keys to
|
|
296
|
+
take effect server-side.
|
|
297
|
+
|
|
298
|
+
- 6e8fd3c: fix(charts): a fieldless `count` aggregate keyed its value column `undefined`, so the chart plotted nothing (framework#3701)
|
|
299
|
+
|
|
300
|
+
framework#3701 pinned down what an OBJECT-bound chart aggregate names its result
|
|
301
|
+
columns — the raw field names it was given (`groupBy` for the category, `field`
|
|
302
|
+
for the value; no `sum_`-style decoration, unlike a dataset measure), plus the
|
|
303
|
+
literal `count` when a `count` omits `field`, which is the alias the engine
|
|
304
|
+
projects `COUNT(*)` under. `os validate` now lints page sources against that
|
|
305
|
+
convention, so the paths that build these rows have to honour it exactly.
|
|
306
|
+
|
|
307
|
+
Three of the four did. The odd one out was `count` — the one function that may
|
|
308
|
+
legitimately omit `field` — because every row builder read `params.field`
|
|
309
|
+
directly:
|
|
310
|
+
|
|
311
|
+
- `aggregateRecords` / `ObjectDataSource.aggregateClientSide` emitted
|
|
312
|
+
`{ [groupBy]: key, [undefined]: value }`, i.e. a column literally named
|
|
313
|
+
`undefined` that no axis binding could ever name;
|
|
314
|
+
- the legacy analytics path was worse: it remapped the server's `count` measure
|
|
315
|
+
onto `params.field` and **deleted** the original key, so the value the server
|
|
316
|
+
did return was thrown away before the chart saw it.
|
|
317
|
+
|
|
318
|
+
All of them now resolve the column through one helper (`aggregateValueKey`) so a
|
|
319
|
+
fieldless count lands under `count`, matching the framework contract. The
|
|
320
|
+
comparison-overlay column is derived from the same key (`count__comparison`
|
|
321
|
+
instead of `undefined__comparison`), and `aggregate.field` is typed optional to
|
|
322
|
+
match the spec's `ChartAggregateSchema`. Charts that name a field are unchanged.
|
|
323
|
+
|
|
324
|
+
- Updated dependencies [7b21891]
|
|
325
|
+
- Updated dependencies [0b3be01]
|
|
326
|
+
- Updated dependencies [3c4d935]
|
|
327
|
+
- Updated dependencies [4b60d2d]
|
|
328
|
+
- Updated dependencies [952b978]
|
|
329
|
+
- Updated dependencies [de5e40c]
|
|
330
|
+
- Updated dependencies [1a03af6]
|
|
331
|
+
- Updated dependencies [3e886eb]
|
|
332
|
+
- Updated dependencies [cfc675e]
|
|
333
|
+
- Updated dependencies [20df08c]
|
|
334
|
+
- Updated dependencies [1767124]
|
|
335
|
+
- Updated dependencies [8ecf5a6]
|
|
336
|
+
- Updated dependencies [af705b9]
|
|
337
|
+
- Updated dependencies [0502a7c]
|
|
338
|
+
- Updated dependencies [7b35e4b]
|
|
339
|
+
- Updated dependencies [8fb1295]
|
|
340
|
+
- Updated dependencies [e16ed2d]
|
|
341
|
+
- Updated dependencies [c6fd752]
|
|
342
|
+
- Updated dependencies [f9bbddb]
|
|
343
|
+
- Updated dependencies [dfd3705]
|
|
344
|
+
- Updated dependencies [c77108c]
|
|
345
|
+
- Updated dependencies [2735de6]
|
|
346
|
+
- Updated dependencies [c19ac11]
|
|
347
|
+
- Updated dependencies [6dee2cb]
|
|
348
|
+
- Updated dependencies [e05f052]
|
|
349
|
+
- Updated dependencies [0502a7c]
|
|
350
|
+
- Updated dependencies [faad45e]
|
|
351
|
+
- Updated dependencies [09c6a17]
|
|
352
|
+
- Updated dependencies [c7cff19]
|
|
353
|
+
- Updated dependencies [ba73a02]
|
|
354
|
+
- Updated dependencies [cd09a7b]
|
|
355
|
+
- Updated dependencies [f1abf0e]
|
|
356
|
+
- Updated dependencies [f05b84e]
|
|
357
|
+
- Updated dependencies [9b4b952]
|
|
358
|
+
- Updated dependencies [2f947e4]
|
|
359
|
+
- Updated dependencies [7d46648]
|
|
360
|
+
- Updated dependencies [9b53d72]
|
|
361
|
+
- Updated dependencies [bb4aa25]
|
|
362
|
+
- Updated dependencies [75f1cdf]
|
|
363
|
+
- Updated dependencies [662bdf9]
|
|
364
|
+
- Updated dependencies [059a052]
|
|
365
|
+
- Updated dependencies [53642d4]
|
|
366
|
+
- Updated dependencies [8aae006]
|
|
367
|
+
- Updated dependencies [c6cfdf1]
|
|
368
|
+
- Updated dependencies [d147a13]
|
|
369
|
+
- Updated dependencies [c6aaed8]
|
|
370
|
+
- Updated dependencies [263f885]
|
|
371
|
+
- Updated dependencies [dc334da]
|
|
372
|
+
- @object-ui/components@17.0.0
|
|
373
|
+
- @object-ui/i18n@17.0.0
|
|
374
|
+
- @object-ui/react@17.0.0
|
|
375
|
+
- @object-ui/types@17.0.0
|
|
376
|
+
- @object-ui/core@17.0.0
|
|
377
|
+
|
|
3
378
|
## 16.1.0
|
|
4
379
|
|
|
5
380
|
### Patch Changes
|
|
@@ -429,7 +804,7 @@
|
|
|
429
804
|
`ObjectView` emit the dataset shape. The legacy inline aggregate is kept as a
|
|
430
805
|
deprecated fallback so pre-ADR-0021 metadata keeps rendering.
|
|
431
806
|
|
|
432
|
-
Refs objectstack-ai/
|
|
807
|
+
Refs objectstack-ai/objectstack#1890
|
|
433
808
|
|
|
434
809
|
- ab168e4: Dashboard charts no longer render blank on first paint. Recharts'
|
|
435
810
|
`ResponsiveContainer` was a child of a `flex … justify-center` box, so it
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ChartConfig } from './ChartContainerImpl';
|
|
2
|
+
import { NormalizedAxis, NormalizedSeries } from './normalizeChartSchema';
|
|
2
3
|
/**
|
|
3
4
|
* ObjectUI
|
|
4
5
|
* Copyright (c) 2024-present ObjectStack Inc.
|
|
@@ -8,18 +9,20 @@ import { ChartConfig } from './ChartContainerImpl';
|
|
|
8
9
|
*/
|
|
9
10
|
import * as React from "react";
|
|
10
11
|
export interface AdvancedChartImplProps {
|
|
12
|
+
/**
|
|
13
|
+
* Chart family. `combo` is renderer-local and rarely needs to be passed:
|
|
14
|
+
* series declaring different families derive it (`effectiveChartFamily`),
|
|
15
|
+
* which is how `@objectstack/spec` expresses a combo chart.
|
|
16
|
+
*/
|
|
11
17
|
chartType?: 'bar' | 'column' | 'horizontal-bar' | 'line' | 'area' | 'pie' | 'donut' | 'radar' | 'scatter' | 'funnel' | 'combo' | 'treemap' | 'sankey';
|
|
12
18
|
data?: Array<Record<string, any>>;
|
|
13
19
|
config?: ChartConfig;
|
|
14
20
|
xAxisKey?: string;
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
dashArray?: string;
|
|
21
|
-
label?: string;
|
|
22
|
-
}>;
|
|
21
|
+
/**
|
|
22
|
+
* Plotted series, in the renderer's internal shape. Authors write the spec
|
|
23
|
+
* `series: [{ name, stack, yAxis, … }]`; `normalizeChartSchema` translates.
|
|
24
|
+
*/
|
|
25
|
+
series?: NormalizedSeries[];
|
|
23
26
|
className?: string;
|
|
24
27
|
/** Categorical/series colour palette. Overrides the theme's `--chart-1..n`
|
|
25
28
|
* defaults so a page/dashboard can brand its charts (data-screens). */
|
|
@@ -33,6 +36,20 @@ export interface AdvancedChartImplProps {
|
|
|
33
36
|
* categories absent here fall back to the positional palette, then the theme.
|
|
34
37
|
*/
|
|
35
38
|
categoryColors?: Record<string, string>;
|
|
39
|
+
/**
|
|
40
|
+
* Declared category order for ordered-sequence charts (funnel / pyramid),
|
|
41
|
+
* keyed like {@link categoryColors} by the category VALUE or its display
|
|
42
|
+
* LABEL, listed in domain order.
|
|
43
|
+
*
|
|
44
|
+
* A funnel's shape asserts a sequence, so without this the renderer can only
|
|
45
|
+
* guess at one and sorts by value descending. That is right for a generic
|
|
46
|
+
* "biggest first" funnel and wrong for a sales pipeline, where the stages
|
|
47
|
+
* have a declared order (Qualification → Needs Analysis → Proposal →
|
|
48
|
+
* Negotiation) that a healthy pipeline happens to narrow along — and an
|
|
49
|
+
* unhealthy one does not. When supplied, this order wins; categories not
|
|
50
|
+
* listed keep their incoming relative order after the listed ones.
|
|
51
|
+
*/
|
|
52
|
+
categoryOrder?: string[];
|
|
36
53
|
/**
|
|
37
54
|
* Optional drill-down click handler. Fires when a chart segment is clicked
|
|
38
55
|
* with `{ category, series, value }`. Wired for bar/horizontal-bar/line/
|
|
@@ -43,6 +60,40 @@ export interface AdvancedChartImplProps {
|
|
|
43
60
|
series?: string;
|
|
44
61
|
value?: number;
|
|
45
62
|
}) => void;
|
|
63
|
+
/**
|
|
64
|
+
* Spec `ChartAxis` presentation for the category axis — `format` (tick
|
|
65
|
+
* formatter), `title`, `showGridLines`. Its `field` already arrived as
|
|
66
|
+
* {@link AdvancedChartImplProps.xAxisKey}. Resolved by
|
|
67
|
+
* `normalizeChartSchema`, so the renderer never parses the author shape.
|
|
68
|
+
*/
|
|
69
|
+
xAxis?: NormalizedAxis;
|
|
70
|
+
/**
|
|
71
|
+
* Spec `ChartConfig.yAxis` — one entry per value axis, in declaration order.
|
|
72
|
+
* Index 0 is the primary axis; a second entry (or one with
|
|
73
|
+
* `position: 'right'`) turns on the secondary axis that `series[].yAxis`
|
|
74
|
+
* binds to. Carries `min`/`max` (domain), `format` (ticks), `logarithmic`
|
|
75
|
+
* (scale) and `title`.
|
|
76
|
+
*/
|
|
77
|
+
yAxes?: NormalizedAxis[];
|
|
78
|
+
/** Spec `ChartConfig.showLegend`. Omitted → shown (the schema default). */
|
|
79
|
+
showLegend?: boolean;
|
|
80
|
+
/** Spec `ChartConfig.showDataLabels` — print each point's value on the mark. */
|
|
81
|
+
showDataLabels?: boolean;
|
|
82
|
+
/** Spec `ChartConfig.title` / `.subtitle`, rendered above the plot. */
|
|
83
|
+
title?: string;
|
|
84
|
+
subtitle?: string;
|
|
85
|
+
/**
|
|
86
|
+
* Spec `ChartConfig.description` — the accessibility description. A chart is
|
|
87
|
+
* a picture to a screen reader; without this it announces as an unlabelled
|
|
88
|
+
* graphic, so the container carries it as `role="img"` + `aria-label`.
|
|
89
|
+
*/
|
|
90
|
+
description?: string;
|
|
91
|
+
/** Spec `ChartConfig.height` — fixed plot height in pixels. */
|
|
92
|
+
height?: number;
|
|
93
|
+
/** Spec `ChartConfig.annotations` — reference lines / bands. */
|
|
94
|
+
annotations?: Array<Record<string, any>>;
|
|
95
|
+
/** Spec `ChartConfig.interaction` — `tooltips`, `brush`. */
|
|
96
|
+
interaction?: Record<string, any>;
|
|
46
97
|
/**
|
|
47
98
|
* Disable Recharts' entrance animation when `false`. Animations drive the
|
|
48
99
|
* reveal via `requestAnimationFrame`, which browsers throttle/pause in
|
|
@@ -55,7 +106,10 @@ export interface AdvancedChartImplProps {
|
|
|
55
106
|
isAnimationActive?: boolean;
|
|
56
107
|
}
|
|
57
108
|
/**
|
|
58
|
-
*
|
|
59
|
-
*
|
|
109
|
+
* Public entry point. A THIN wrapper purely so the unreadable-data guard can
|
|
110
|
+
* short-circuit without breaking the rules of hooks: the condition depends on
|
|
111
|
+
* `data`, which arrives asynchronously, so an early return inside the renderer
|
|
112
|
+
* would change its hook count between renders. The wrapper's own hook list is
|
|
113
|
+
* fixed, and the renderer below is reached with data it can actually plot.
|
|
60
114
|
*/
|
|
61
|
-
export default function AdvancedChartImpl(
|
|
115
|
+
export default function AdvancedChartImpl(props: AdvancedChartImplProps): React.JSX.Element;
|
package/dist/ChartRenderer.d.ts
CHANGED
|
@@ -23,7 +23,19 @@ export interface ChartRendererProps {
|
|
|
23
23
|
chartType?: 'bar' | 'column' | 'horizontal-bar' | 'line' | 'area' | 'pie' | 'donut' | 'radar' | 'scatter' | 'funnel' | 'combo' | 'treemap' | 'sankey';
|
|
24
24
|
data?: Array<Record<string, any>>;
|
|
25
25
|
config?: Record<string, any>;
|
|
26
|
+
/** Internal binding. Authors write the spec `xAxis: { field }` (or the
|
|
27
|
+
* report surface's bare string); `normalizeChartSchema` resolves both. */
|
|
26
28
|
xAxisKey?: string;
|
|
29
|
+
/**
|
|
30
|
+
* Plotted series — **both shapes**, unlike the bindings below.
|
|
31
|
+
*
|
|
32
|
+
* `series` is the one binding the spec and the internal contract spell with
|
|
33
|
+
* the same key, so declaring only the internal shape here made
|
|
34
|
+
* `series: [{ name: 'total' }]` a type error on an author who was writing
|
|
35
|
+
* the protocol correctly — and, until #2945, one whose chart also rendered
|
|
36
|
+
* blank. `normalizeChartSchema` translates; an array that already speaks the
|
|
37
|
+
* internal shape passes through untouched.
|
|
38
|
+
*/
|
|
27
39
|
series?: Array<{
|
|
28
40
|
dataKey: string;
|
|
29
41
|
label?: string;
|
|
@@ -31,12 +43,46 @@ export interface ChartRendererProps {
|
|
|
31
43
|
opacity?: number;
|
|
32
44
|
dashArray?: string;
|
|
33
45
|
chartType?: 'bar' | 'line' | 'area';
|
|
46
|
+
stack?: string;
|
|
47
|
+
yAxis?: 'left' | 'right';
|
|
48
|
+
color?: string;
|
|
49
|
+
} | {
|
|
50
|
+
name: string;
|
|
51
|
+
label?: unknown;
|
|
52
|
+
type?: string;
|
|
53
|
+
variant?: 'current' | 'comparison' | 'primary';
|
|
54
|
+
opacity?: number;
|
|
55
|
+
dashArray?: string;
|
|
56
|
+
stack?: string;
|
|
57
|
+
yAxis?: 'left' | 'right';
|
|
58
|
+
color?: string;
|
|
34
59
|
}>;
|
|
60
|
+
/** Spec `ChartConfig` shape — honored via `normalizeChartSchema`
|
|
61
|
+
* (objectui#2880). Listed here so the author-facing contract type-checks;
|
|
62
|
+
* the internal props above win when both are present. */
|
|
63
|
+
xAxis?: unknown;
|
|
64
|
+
yAxis?: unknown;
|
|
65
|
+
showLegend?: boolean;
|
|
66
|
+
showDataLabels?: boolean;
|
|
67
|
+
title?: unknown;
|
|
68
|
+
subtitle?: unknown;
|
|
69
|
+
description?: unknown;
|
|
70
|
+
height?: number;
|
|
71
|
+
annotations?: Array<Record<string, any>>;
|
|
72
|
+
interaction?: Record<string, any>;
|
|
73
|
+
/** An author `type` rescued from the SDUI envelope's discriminator
|
|
74
|
+
* collision by the react-page wrapper — see `normalizeChartSchema`. */
|
|
75
|
+
specType?: string;
|
|
35
76
|
colors?: string[];
|
|
36
77
|
/** Per-category colour map (value/label → colour). Wins over `colors` per
|
|
37
78
|
* category; see AdvancedChartImpl. Set by ObjectChart from select/lookup
|
|
38
79
|
* dimension option colours and/or an explicit author map. */
|
|
39
80
|
categoryColors?: Record<string, string>;
|
|
81
|
+
/** Declared category order (value/label keys, in domain order) for
|
|
82
|
+
* ordered-sequence charts — funnel/pyramid stages. Set by DatasetWidget
|
|
83
|
+
* from the dimension's picklist order or an explicit `stageOrder`; see
|
|
84
|
+
* AdvancedChartImpl. Omitted → the funnel's value-descending default. */
|
|
85
|
+
categoryOrder?: string[];
|
|
40
86
|
/** Pass `false` for a deterministic, export-safe render with no entrance
|
|
41
87
|
* animation (see AdvancedChartImpl). Omitted → animated default. */
|
|
42
88
|
isAnimationActive?: boolean;
|
package/dist/ObjectChart.d.ts
CHANGED
|
@@ -4,13 +4,29 @@ import { default as React } from 'react';
|
|
|
4
4
|
* Local implementation to avoid a dependency on @object-ui/fields.
|
|
5
5
|
*/
|
|
6
6
|
export declare function humanizeLabel(value: string): string;
|
|
7
|
+
/**
|
|
8
|
+
* The result column an object-bound `aggregate` projects its value under
|
|
9
|
+
* (framework#3701, `chartAggregateValueKey` in `@objectstack/spec/ui`).
|
|
10
|
+
*
|
|
11
|
+
* The raw `field` name — an object-bound aggregate does NOT decorate it the way
|
|
12
|
+
* a dataset measure is named (`sum_amount`). Only `count` may omit `field`, and
|
|
13
|
+
* it then lands under the literal `'count'`, which is the alias the engine
|
|
14
|
+
* projects `COUNT(*)` under. Exported so every path that builds these rows
|
|
15
|
+
* agrees on one key instead of each re-deriving it.
|
|
16
|
+
*/
|
|
17
|
+
export declare function aggregateValueKey(aggregate: {
|
|
18
|
+
field?: string;
|
|
19
|
+
function?: string;
|
|
20
|
+
}): string;
|
|
21
|
+
/** Suffix the previous-window value carries under a compareTo overlay. */
|
|
22
|
+
export declare const COMPARISON_SUFFIX = "__comparison";
|
|
7
23
|
/**
|
|
8
24
|
* Client-side aggregation for fetched records.
|
|
9
25
|
* Groups records by `groupBy` field and applies the aggregation function
|
|
10
26
|
* to the `field` values in each group.
|
|
11
27
|
*/
|
|
12
28
|
export declare function aggregateRecords(records: any[], aggregate: {
|
|
13
|
-
field
|
|
29
|
+
field?: string;
|
|
14
30
|
function: string;
|
|
15
31
|
groupBy: string;
|
|
16
32
|
}): any[];
|