@object-ui/plugin-report 16.1.0 → 17.2.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 CHANGED
@@ -1,5 +1,405 @@
1
1
  # @object-ui/plugin-report
2
2
 
3
+ ## 17.2.0
4
+
5
+ ### Patch Changes
6
+
7
+ - d9668a7: Honor the server's declared percent scale, so a ratio of exactly 1 renders as 100.0% (#3136)
8
+
9
+ A dataset measure declared `format: '0.0%'` rendered every ratio below 1
10
+ correctly and got the single most consequential one wrong: a rate of exactly
11
+ `1` printed as **`1.0%`**. On an SLA / pass-rate dashboard that turns
12
+ "everything met the SLA" into "1% met the SLA", on both surfaces the issue
13
+ names — the KPI card and the dataset-bound table (they share `formatMeasure`).
14
+
15
+ The cause was never a bad multiplier; it was a missing fact. `formatMeasure`
16
+ scaled by magnitude — `percentDisplayValue` multiplies by 100 only strictly
17
+ inside `(-1, 1)` — because the column arrived with a `%` format string and
18
+ nothing saying what scale its numbers were on. That guess is undecidable at
19
+ exactly 1, which is both a full-compliance ratio ("100%") and one percentage
20
+ point ("1%"), and it resolved to the reading almost nobody means.
21
+
22
+ The server now answers the question instead (framework: `percentScaleOf` +
23
+ `AnalyticsResult.fields[].percentScale`, the sibling of the ADR-0053 currency
24
+ chain): a `derived: { op: 'ratio' }` measure is a `fraction` by definition, and
25
+ a measure over a `percent` field inherits that field's scale. `formatMeasure`
26
+ takes the declared scale as a fourth argument and, when present, scales by it —
27
+ `fraction` ×100, `whole` verbatim — instead of inspecting the value. Every
28
+ dataset-bound call site passes the column's `percentScale`: the dashboard
29
+ metric/table/pivot cells, the report renderer's cells, totals and KPI, and the
30
+ dataset preview.
31
+
32
+ `percentDisplayValue` is untouched and still the fallback for a column that
33
+ arrives without the annotation (an older server, or a non-dataset percent cell
34
+ in a list view), so nothing that renders correctly today changes.
35
+
36
+ - 022e4c3: Upgrade to `@objectstack/spec@17.0.0-rc.1`, stop offering the retired `wait` timeout fields (#3101), and route the newly-adopted `combo` chart type.
37
+
38
+ **Breaking for authoring, and the reason to do it now**: the `wait` panel no longer offers
39
+ `waitEventConfig.timeoutMs` or `.onTimeout`. Both are `retiredKey()` tombstones as of spec
40
+ 17.0.0-rc.1 (framework#4158), which means a value written there is **rejected at load** —
41
+ so until this lands, Studio can produce flow metadata the author's own runtime refuses.
42
+ That hazard opened the moment rc.1 published, independent of when this repo bumps.
43
+
44
+ `wait` never had a timeout: `onTimeout` had zero readers, so neither `'fail'` nor
45
+ `'continue'` ever happened, and `timeoutMs`'s only reader used it as the timer **duration**
46
+ when `timerDuration` was absent. Use **Duration** — it accepts a bare number as
47
+ milliseconds, making the old `timeoutMs: 60000` and `timerDuration: '60000'` the same wait.
48
+ Stored flows are converted by framework's D2 conversion; the designer simply stops offering
49
+ the entry. The two `zh` label overrides go with the fields.
50
+
51
+ #3101 asked for this to ride along with the bump rather than land alone, and that is
52
+ load-bearing: the sibling-block assertion is **bidirectional**, so deleting the fields
53
+ against a spec that still declares them fails in the other direction.
54
+
55
+ **`combo` is now a spec chart type** — the sole addition to `ChartTypeSchema` in rc.1 (19
56
+ members → 20). It had been a renderer-local family the chart renderer derived from the
57
+ series, so nothing classified it on the two surfaces that route a _spec_ chart type: a
58
+ spec-valid `combo` fell through to the red "Unknown component type" panel on a dashboard
59
+ and to the out-of-spec notice on a report. Both now route it
60
+ (`widgetDispatch.SERIES_CHART_TYPES`, `planReportChart`). The renderer-local derivation
61
+ stays — it is what makes an authored `type: 'combo'` render rather than merely validate.
62
+
63
+ **Retired spec exports this repo bound to**, all removed upstream in spec 17.0.0:
64
+
65
+ - `JoinStrategy` / `WindowFunction` (framework#4286 tombstoned `query.joins` and
66
+ `query.windowFunctions`: no engine or driver ever read either on the query path). They
67
+ were derived off the spec enums under objectstack#4115's "come off the spec enum, not a
68
+ restatement" rule; with no enum left, `data-protocol.ts` now restates the members locally
69
+ — verbatim from the last spec that published them — as the objectui query-AST vocabulary
70
+ they have become. The AST itself is unchanged.
71
+ - `PerformanceConfig`, retired with `dashboard.performance` (framework#3896). Nothing bound
72
+ to it — `@object-ui/react`'s `usePerformance` declares its own interface and is untouched.
73
+ The dashboard form is derived from the spec's own `dashboardForm`, so the field
74
+ disappears from the inspector for free; its test now pins the absence.
75
+
76
+ **Three inverted pins fired, and are recorded rather than resolved.** objectstack#4171's
77
+ tripwires asserted that `NavigationItem`, `FormField` and `ConditionalValidation`'s branches
78
+ still erased to `any`/`unknown` upstream — the premise that justified objectui keeping local
79
+ declarations. rc.1 types them properly, so the assertions are inverted to state the new
80
+ fact. The burn-down each one asks for — deriving those types from the spec — touches
81
+ widely-used public types and is deliberately **not** bundled into a version bump; it is
82
+ tracked in #3177. `JoinNode`'s pin is gone outright: the symbol no longer exists.
83
+
84
+ **What the bump arms.** The reconciliation ledger's `subflow` and `decision` panels
85
+ feature-detect their spec exports and had never actually run — rc.0 predates the exports
86
+ (framework#4278). They now execute and pass. The `script` panel's full bidirectional check
87
+ stays deliberately skipped: rc.1 predates framework#4343, so the retired dispatch branches
88
+ are still contract keys there, and only the "offers nothing the executor ignores" direction
89
+ is meaningful. It arms itself on the next rc.
90
+
91
+ - Updated dependencies [4ae0ac4]
92
+ - Updated dependencies [696e3c1]
93
+ - Updated dependencies [bca45cc]
94
+ - Updated dependencies [a889e31]
95
+ - Updated dependencies [09d30a4]
96
+ - Updated dependencies [4bf612c]
97
+ - Updated dependencies [335041c]
98
+ - Updated dependencies [b414983]
99
+ - Updated dependencies [256f8cc]
100
+ - Updated dependencies [d9668a7]
101
+ - Updated dependencies [4b470b9]
102
+ - Updated dependencies [785b8a5]
103
+ - Updated dependencies [cb82705]
104
+ - Updated dependencies [f572849]
105
+ - Updated dependencies [4a51e77]
106
+ - Updated dependencies [f6e8d78]
107
+ - Updated dependencies [ea96284]
108
+ - Updated dependencies [d3584c6]
109
+ - Updated dependencies [a8ad6c0]
110
+ - Updated dependencies [444457c]
111
+ - Updated dependencies [850033c]
112
+ - Updated dependencies [022e4c3]
113
+ - Updated dependencies [009e25d]
114
+ - Updated dependencies [726b89c]
115
+ - @object-ui/types@17.2.0
116
+ - @object-ui/components@17.2.0
117
+ - @object-ui/core@17.2.0
118
+ - @object-ui/react@17.2.0
119
+ - @object-ui/i18n@17.2.0
120
+ - @object-ui/plugin-grid@17.2.0
121
+ - @object-ui/fields@17.2.0
122
+
123
+ ## 17.1.0
124
+
125
+ ### Minor Changes
126
+
127
+ - 8529444: feat(report): carry a report's `order` into the dataset selection (framework#3916)
128
+
129
+ `@objectstack/spec` 17 gave reports an ordering declaration — `ReportSchema.order`
130
+ (and `blocks[].order` for a joined report): a list of `{ by, direction }` keys,
131
+ most significant first. The framework executor applies it. `DatasetReportRenderer`
132
+ built the selection it posts and never carried the declaration into it, so an
133
+ authored `order` reached no query and did nothing.
134
+
135
+ `useDatasetRows` — the single fetch choke point behind every report path — now
136
+ takes the lowered ordering, and all four call sites supply it: the grouped table,
137
+ the embedded chart, the matrix cross-tab, and each joined block.
138
+
139
+ - **Lowering.** `readOrder()` turns the authored list into
140
+ `DatasetSelection.order`, the array's element order becoming the object's key
141
+ insertion order (which is how sort significance is expressed on the wire). It
142
+ is permissive about its input, like the neighbouring `readNames()` — stored
143
+ report JSON crosses the repo boundary and may lag the schema, so an entry with
144
+ no usable `by` is dropped rather than thrown. An absent or entirely-unusable
145
+ list yields `undefined`, so the field is OMITTED and the server's own defaults
146
+ still apply: a selected time dimension comes back chronological with nothing
147
+ declared.
148
+
149
+ Kept local rather than importing spec's `reportSelectionOrder` — the pinned
150
+ `^17.0.0-rc.0` predates that export. Swap it for the import on the next bump.
151
+
152
+ - **Scoped per sub-selection.** A report's `order` is validated against its
153
+ WHOLE selection, but this renderer issues narrower queries from it: the chart
154
+ plots one dimension × one measure, and the flat-table path drops the matrix
155
+ across-dimensions. The server rejects an order key naming nothing the
156
+ selection projects (a deliberate 400), so forwarding the full list would turn
157
+ a valid report into a failed chart. Keys outside a sub-selection are dropped
158
+ at the choke point instead. Nothing is masked: the schema already validated
159
+ every key against `rows` ∪ `columns` ∪ `values`, so the only keys that can be
160
+ lost are ones the narrower query genuinely has no column for.
161
+
162
+ - **Part of the refetch key.** The ordering changes the ROWS the server returns,
163
+ not just their presentation, so it joins the `useDatasetRows` signature — an
164
+ ordering edited from asc to desc refetches instead of re-rendering the stale
165
+ grid.
166
+
167
+ - **Matrix across-axis.** `colHeaders` are collected in row-arrival order, so
168
+ ordering the rows by the across dimension is what makes the columns read
169
+ left-to-right in that order. Ordering rides on the primary query only; the
170
+ server drops it for the totals sub-queries by design.
171
+
172
+ Ordering stays server-side throughout — never a client-side re-sort, which would
173
+ order the page rather than the query and could not sort by a derived measure at
174
+ all.
175
+
176
+ ### Patch Changes
177
+
178
+ - Updated dependencies [62311b6]
179
+ - Updated dependencies [fc0272a]
180
+ - Updated dependencies [9e7349e]
181
+ - Updated dependencies [8864971]
182
+ - Updated dependencies [1cf0de7]
183
+ - Updated dependencies [752e18f]
184
+ - Updated dependencies [c785740]
185
+ - Updated dependencies [b41f401]
186
+ - Updated dependencies [5340879]
187
+ - Updated dependencies [19e9fa0]
188
+ - Updated dependencies [a149e90]
189
+ - Updated dependencies [d61efd1]
190
+ - Updated dependencies [95b7214]
191
+ - Updated dependencies [7d9734d]
192
+ - Updated dependencies [6ae818e]
193
+ - Updated dependencies [9eb932b]
194
+ - Updated dependencies [746dd00]
195
+ - Updated dependencies [aebfa4f]
196
+ - Updated dependencies [38ca8be]
197
+ - Updated dependencies [3cb9646]
198
+ - Updated dependencies [68ef584]
199
+ - Updated dependencies [4952edf]
200
+ - Updated dependencies [7f0252e]
201
+ - Updated dependencies [c4d7b20]
202
+ - Updated dependencies [c769d3d]
203
+ - Updated dependencies [7639a61]
204
+ - Updated dependencies [94e63ef]
205
+ - Updated dependencies [c735bf7]
206
+ - Updated dependencies [02aef0c]
207
+ - Updated dependencies [6f29aa5]
208
+ - Updated dependencies [d21794c]
209
+ - Updated dependencies [c4db402]
210
+ - Updated dependencies [5319bf1]
211
+ - Updated dependencies [49e5671]
212
+ - Updated dependencies [9a04d25]
213
+ - Updated dependencies [b5b97e2]
214
+ - Updated dependencies [f59f2c1]
215
+ - Updated dependencies [07de839]
216
+ - Updated dependencies [2a40b5e]
217
+ - Updated dependencies [df613fa]
218
+ - Updated dependencies [4874117]
219
+ - Updated dependencies [ad0183a]
220
+ - Updated dependencies [ce08d55]
221
+ - Updated dependencies [eb4b740]
222
+ - Updated dependencies [aecc934]
223
+ - Updated dependencies [5b084eb]
224
+ - Updated dependencies [aa1240a]
225
+ - Updated dependencies [2374a49]
226
+ - Updated dependencies [390c071]
227
+ - Updated dependencies [d10f526]
228
+ - Updated dependencies [2d5d594]
229
+ - Updated dependencies [ea7f477]
230
+ - Updated dependencies [379728f]
231
+ - Updated dependencies [7f23cd0]
232
+ - Updated dependencies [0ded602]
233
+ - Updated dependencies [24e0e0a]
234
+ - Updated dependencies [f8a95e5]
235
+ - Updated dependencies [3a6cf24]
236
+ - Updated dependencies [aa35561]
237
+ - Updated dependencies [03bd53b]
238
+ - Updated dependencies [3c1f321]
239
+ - Updated dependencies [a045a32]
240
+ - Updated dependencies [912496d]
241
+ - Updated dependencies [80edbd4]
242
+ - Updated dependencies [9867281]
243
+ - @object-ui/core@17.1.0
244
+ - @object-ui/components@17.1.0
245
+ - @object-ui/plugin-grid@17.1.0
246
+ - @object-ui/react@17.1.0
247
+ - @object-ui/types@17.1.0
248
+ - @object-ui/i18n@17.1.0
249
+ - @object-ui/fields@17.1.0
250
+
251
+ ## 17.0.0
252
+
253
+ ### Minor Changes
254
+
255
+ - 059a052: feat(report)!: drop `SpecReportColumn`/`SpecReportGrouping` re-exports + retire the legacy ReportViewer chart fallback (#3463)
256
+
257
+ Cross-repo close-out of the ADR-0021 report cleanup (framework #3463). Upstream
258
+ `@objectstack/spec` removed the dead `ReportColumnSchema` / `ReportGroupingSchema`
259
+ and the unread report `chart.groupBy`; this drops their objectui mirrors and the
260
+ now-orphaned legacy report chart path.
261
+
262
+ - **types**: removed the `SpecReportColumn` / `SpecReportColumnInput` /
263
+ `SpecReportGrouping` / `SpecReportGroupingInput` type re-exports and the
264
+ `SpecReportColumnSchema` / `SpecReportGroupingSchema` value re-exports from
265
+ `@object-ui/types` (they aliased the deleted upstream symbols). The live
266
+ report shape is dataset-bound — `SpecReport` with `dataset` + `values`
267
+ (measure names) + `rows` / `columns` (dimension names).
268
+ - **app-shell**: `ReportView` now renders every report through the spec
269
+ `ReportRenderer` dispatcher (dataset → `DatasetReportRenderer`, stored pre-9.0
270
+ JSON → presentation bridge, pre-spec `{ data, columns }` → `LegacyReportRenderer`).
271
+ Deleted the `ReportViewer` last-resort branch, the `mapReportForViewer`
272
+ spec→legacy chart-section adapter (the sole producer of `xAxisField` /
273
+ `yAxisFields`), and the now-dead data-fetch loading flag. No shipped report
274
+ metadata reached the removed branch — the Studio inspector only ever writes
275
+ the dataset-bound shape.
276
+ - **plugin-report**: removed the `ReportViewer` chart-section branch. It read
277
+ the invented `xAxisField` / `yAxisFields` (never the spec's `xAxis` / `yAxis`)
278
+ and was only fed by the deleted `mapReportForViewer`. `ReportViewer` itself is
279
+ retained — its table / summary / text sections still back the `report-viewer`
280
+ registered component and the pre-9.0 presentation bridge.
281
+
282
+ **Migration**: nothing an author writes changes. TypeScript consumers importing
283
+ `SpecReportColumn*` / `SpecReportGrouping*` from `@object-ui/types` have no
284
+ replacement type — model report columns as the dataset's measure names and
285
+ grouping as its dimension names.
286
+
287
+ ### Patch Changes
288
+
289
+ - 5b9cf96: fix(plugin-map): drop the `maplibre-gl@6` default import, and put type-check behind a CI gate that cannot be silently skipped (#2911)
290
+
291
+ `maplibre-gl@6.0.0` removed its default export (arrived via #2848, dependabot),
292
+ so `ObjectMap.tsx`'s `import maplibregl from 'maplibre-gl'` has been a TS1192
293
+ error on `main` for a day. The binding was never used — the map instance comes
294
+ from `react-map-gl/maplibre`, and the stylesheet from the side-effect import on
295
+ the next line — so the import is simply deleted rather than rewritten to
296
+ `import * as`.
297
+
298
+ Removing it is runtime-neutral, which the issue had explicitly left unverified.
299
+ `@vis.gl/react-maplibre` (what `react-map-gl/maplibre` re-exports) does
300
+ `Promise.resolve(mapLib || import('maplibre-gl'))` in `components/map.js`, so it
301
+ loads the library itself when no `mapLib` prop is passed. Verified in a browser
302
+ against the `store-locator-map` catalog schema: `maplibre-gl` is fetched as its
303
+ own lazy chunk, the WebGL canvas comes up 800x600, and all three markers mount —
304
+ byte-identical probe output with and without the static import. That also matches
305
+ what `apps/console/src/main.tsx` already intends, where the plugin is registered
306
+ lazily specifically to keep `maplibre-gl` out of the initial bundle.
307
+
308
+ **The reason it survived a day of green CI is the part worth fixing.** No
309
+ workflow ran `type-check` at all, and `turbo build` only checks types for
310
+ packages whose `build` script happens to invoke `tsc` — the 22 `vite build`
311
+ packages transpile without checking. A sweep of all 45 packages found ten with
312
+ broken types, `plugin-map` merely being the one that had a script to notice it.
313
+
314
+ Adding a `pnpm type-check` job alone would not have been a gate: **turbo silently
315
+ skips any package with no `type-check` script**, so 17 packages read as passing
316
+ because nothing ran. With `plugin-map` fixed, `pnpm type-check` reports 63/63
317
+ green while nine packages are still broken. So:
318
+
319
+ - `plugin-ai` and `plugin-report` gain the `paths` override their type-checked
320
+ peers already carry, which detaches workspace deps from sibling _source_ and
321
+ resolves them through built `.d.ts` — the sole cause of the 104-error TS6059
322
+ `rootDir` floods, and the same trick their own `vite.config.ts` already applies
323
+ to the dts program.
324
+ - Seven packages gain `"type-check": "tsc --noEmit"` (`plugin-ai`,
325
+ `plugin-report`, `plugin-dashboard`, `create-plugin`, `console`, and the two
326
+ console examples). Coverage goes 28 -> 35 of 45.
327
+ - New `scripts/check-type-check-coverage.mjs` makes the invisibility impossible:
328
+ a package with no `type-check` script must be declared, with a reason, and the
329
+ lists only shrink — gaining a script without deleting the entry fails the
330
+ guard. The nine known-broken packages are recorded there with error counts
331
+ (`@object-ui/runner` has no `tsconfig.json` at all), tracked as follow-ups.
332
+ - New `Type Check` CI job runs the coverage guard first (instant, no install),
333
+ then `pnpm type-check`.
334
+
335
+ Both halves were proven to fail before being trusted: the guard was exercised in
336
+ all four of its failure modes, and re-introducing the `maplibre-gl` import turns
337
+ the job red again, as does a fresh error injected into `plugin-ai` — a package
338
+ that had no type checking whatsoever before this change.
339
+
340
+ - Updated dependencies [7b21891]
341
+ - Updated dependencies [0b3be01]
342
+ - Updated dependencies [3c4d935]
343
+ - Updated dependencies [4b1ed7d]
344
+ - Updated dependencies [4b60d2d]
345
+ - Updated dependencies [952b978]
346
+ - Updated dependencies [de5e40c]
347
+ - Updated dependencies [1a03af6]
348
+ - Updated dependencies [3e886eb]
349
+ - Updated dependencies [cfc675e]
350
+ - Updated dependencies [20df08c]
351
+ - Updated dependencies [1767124]
352
+ - Updated dependencies [8ecf5a6]
353
+ - Updated dependencies [af705b9]
354
+ - Updated dependencies [0502a7c]
355
+ - Updated dependencies [7b35e4b]
356
+ - Updated dependencies [8fb1295]
357
+ - Updated dependencies [e16ed2d]
358
+ - Updated dependencies [c6fd752]
359
+ - Updated dependencies [f9bbddb]
360
+ - Updated dependencies [dfd3705]
361
+ - Updated dependencies [c77108c]
362
+ - Updated dependencies [2735de6]
363
+ - Updated dependencies [697cda4]
364
+ - Updated dependencies [c19ac11]
365
+ - Updated dependencies [6dee2cb]
366
+ - Updated dependencies [e05f052]
367
+ - Updated dependencies [0502a7c]
368
+ - Updated dependencies [faad45e]
369
+ - Updated dependencies [553443e]
370
+ - Updated dependencies [09c6a17]
371
+ - Updated dependencies [c7cff19]
372
+ - Updated dependencies [df6697f]
373
+ - Updated dependencies [ba73a02]
374
+ - Updated dependencies [ba45145]
375
+ - Updated dependencies [cd09a7b]
376
+ - Updated dependencies [f1abf0e]
377
+ - Updated dependencies [f05b84e]
378
+ - Updated dependencies [9b4b952]
379
+ - Updated dependencies [341bfb5]
380
+ - Updated dependencies [2f947e4]
381
+ - Updated dependencies [7d46648]
382
+ - Updated dependencies [9b53d72]
383
+ - Updated dependencies [bb4aa25]
384
+ - Updated dependencies [75f1cdf]
385
+ - Updated dependencies [662bdf9]
386
+ - Updated dependencies [059a052]
387
+ - Updated dependencies [53642d4]
388
+ - Updated dependencies [8aae006]
389
+ - Updated dependencies [c6cfdf1]
390
+ - Updated dependencies [dc7a798]
391
+ - Updated dependencies [d147a13]
392
+ - Updated dependencies [c6aaed8]
393
+ - Updated dependencies [263f885]
394
+ - Updated dependencies [dc334da]
395
+ - @object-ui/components@17.0.0
396
+ - @object-ui/i18n@17.0.0
397
+ - @object-ui/fields@17.0.0
398
+ - @object-ui/react@17.0.0
399
+ - @object-ui/plugin-grid@17.0.0
400
+ - @object-ui/types@17.0.0
401
+ - @object-ui/core@17.0.0
402
+
3
403
  ## 16.1.0
4
404
 
5
405
  ### Minor Changes
@@ -26,7 +426,7 @@
26
426
  and removes both bounds together. A new `drillUrlFilters` module owns the
27
427
  write/read serialization so both sides can't drift (round-trip tested).
28
428
 
29
- Companion to the framework analytics change (objectstack-ai/framework#3256).
429
+ Companion to the framework analytics change (objectstack-ai/objectstack#3256).
30
430
 
31
431
  ### Patch Changes
32
432
 
@@ -9,7 +9,10 @@
9
9
  * use, so the numbers (and the server-resolved dimension display labels)
10
10
  * match everywhere.
11
11
  *
12
- * - `summary` / `tabular` → one grouped table (`rows` + `values`).
12
+ * - `tabular` → the selection as a simple list (`rows` + `values`), no totals.
13
+ * - `summary` → the same table plus a SERVER-computed grand-total footer
14
+ * (`totals: { groupings: [[]] }`) — the declared type picks the branch
15
+ * (#2941), the data shape never does.
13
16
  * - `matrix` → a true cross-tab (ADR-0021 D2): `rows` down × `columns`
14
17
  * across, measures in the cells. One dataset query over all dimensions,
15
18
  * pivoted client-side. Totals (per-row subtotals, per-column subtotals,
@@ -30,6 +33,19 @@
30
33
  * the field's declared `currency` (`Intl` symbol) + numeral `format`, never
31
34
  * the raw field name or a misleading "$".
32
35
  *
36
+ * Ordering (framework#3916): a report's `order` — a list of `{ by, direction }`
37
+ * keys, most significant first — is lowered onto the dataset selection, so the
38
+ * SERVER orders the whole grid (after measure-scoped filters merge and derived
39
+ * measures evaluate) and this renderer only places the rows it is handed. It is
40
+ * never a client-side re-sort: sorting here would order the truncated page
41
+ * rather than the query, and could not sort by a derived measure at all.
42
+ *
43
+ * For a matrix that also decides the ACROSS axis: `colHeaders` are collected in
44
+ * row-arrival order, so ordering the rows by the across dimension is what makes
45
+ * the columns read left-to-right in that order. Declaring nothing still reads
46
+ * correctly — the server defaults a selected time dimension to ascending, which
47
+ * is what makes month/quarter columns chronological out of the box.
48
+ *
33
49
  * Drill-down (ADR-0021 D2): when the report's `drilldown` flag is not `false`
34
50
  * and the host supplies `onDrill`, every aggregated row / matrix cell is
35
51
  * clickable and emits `{ dataset, groupKey, runtimeFilter }`. The HOST owns
@@ -69,6 +85,16 @@ interface DatasetReportLike {
69
85
  values?: string[];
70
86
  runtimeFilter?: Record<string, unknown>;
71
87
  filter?: Record<string, unknown>;
88
+ /**
89
+ * Result ordering, most significant key first (framework#3916). Each `by`
90
+ * names a dimension the report groups by (`rows` / `columns`) or a measure it
91
+ * displays (`values`). A `joined` report carries this per BLOCK, never on the
92
+ * container.
93
+ */
94
+ order?: Array<{
95
+ by?: unknown;
96
+ direction?: unknown;
97
+ }>;
72
98
  /** Click-through to underlying records (default true). */
73
99
  drilldown?: boolean;
74
100
  /** Embedded chart visualization (ADR-0021): type + xAxis/yAxis over the dataset. */
@@ -91,5 +117,64 @@ export interface DatasetReportRendererProps {
91
117
  }
92
118
  /** `true` when this report should render through the dataset path. */
93
119
  export declare function isDatasetReport(value: unknown): value is DatasetReportLike;
120
+ /**
121
+ * Resolve a report's declared `type` — the spec's `ReportType`
122
+ * (`ui/report.zod.ts`: `tabular | summary | matrix | joined`) — to the
123
+ * presentation it renders. The DECLARED type picks the branch; it is never
124
+ * inferred from the data shape. Before this, `tabular` and `summary` shared
125
+ * one branch and the visual difference was read off whether `rows` happened
126
+ * to be non-empty — a `tabular` report that declared `rows` silently rendered
127
+ * exactly like a `summary` (#2941). An absent/out-of-spec value falls back to
128
+ * `tabular`, the spec's own declared default.
129
+ *
130
+ * Exported for the spec-parity test, which fails the moment `ReportType` and
131
+ * this dispatch drift in either direction.
132
+ */
133
+ export declare function resolveReportPresentation(type: unknown): 'tabular' | 'summary' | 'matrix' | 'joined';
134
+ /** How a report renders its embedded chart for one spec `ChartTypeSchema` value. */
135
+ export type ReportChartPlan =
136
+ /** A categorical series the generic chart component draws distinctly. */
137
+ {
138
+ kind: 'series';
139
+ chartType: string;
140
+ }
141
+ /** Single-value family — one dimensionless dataset query, shown as a number. */
142
+ | {
143
+ kind: 'single_value';
144
+ }
145
+ /** Tabular family — the grouped table beneath IS the rendering; no duplicate chart. */
146
+ | {
147
+ kind: 'tabular';
148
+ }
149
+ /** Out-of-spec value (stored dialect / typo) — surfaced, never a silent bar. */
150
+ | {
151
+ kind: 'unsupported';
152
+ type: string;
153
+ };
154
+ /**
155
+ * Classify a report chart type into its rendering plan — every value of the
156
+ * spec's `ChartTypeSchema` (`ui/chart.zod.ts`, 19 names), each on the branch
157
+ * its family demands. The old mapping collapsed 10 of the 19 to a BAR — a
158
+ * plausible wrong picture with no warning (#2941). Now:
159
+ *
160
+ * - the 12 series families reach the generic chart component verbatim
161
+ * (`column` is its documented vertical-bar alias; `horizontal-bar` stays
162
+ * horizontal instead of silently flipping vertical);
163
+ * - the single-value families (`gauge` / `solid-gauge` / `metric` / `kpi` /
164
+ * `bullet`) render the measure as a number — the spec's own comment calls
165
+ * them "honest single-value variants pending a real dial/target renderer";
166
+ * - `table` / `pivot` add no duplicate chart: the grouped table that always
167
+ * renders beneath the chart slot is exactly the tabular presentation;
168
+ * - anything else is out-of-spec and gets a visible notice.
169
+ *
170
+ * `combo` joined `ChartTypeSchema` in spec 17.0.0-rc.1 and routes as a series
171
+ * chart. It was renderer-local until then — the chart renderer derives the base
172
+ * family from the series — so nothing here classified it, and a spec-valid combo
173
+ * report hit the out-of-spec notice the moment the spec started accepting one.
174
+ *
175
+ * Exported for the spec-parity test, which fails the moment `ChartTypeSchema`
176
+ * and this classification drift in either direction.
177
+ */
178
+ export declare function planReportChart(t: unknown): ReportChartPlan;
94
179
  export declare const DatasetReportRenderer: React.FC<DatasetReportRendererProps>;
95
180
  export {};
@@ -1,4 +1,4 @@
1
- import { DataSource, QueryParams, ReportSchema, ReportExportFormat, ReportExportConfig, ReportSchedule } from '@object-ui/types';
1
+ import { DataSource, QueryParams, ReportComponentSchema, ReportExportFormat, ReportExportConfig, ReportScheduleConfig } from '@object-ui/types';
2
2
  /**
3
3
  * Options for live report export
4
4
  */
@@ -45,7 +45,7 @@ export interface LiveExportResult {
45
45
  /**
46
46
  * Schedule trigger callback
47
47
  */
48
- export type ScheduleTriggerCallback = (report: ReportSchema, schedule: ReportSchedule) => void;
48
+ export type ScheduleTriggerCallback = (report: ReportComponentSchema, schedule: ReportScheduleConfig) => void;
49
49
  /**
50
50
  * Export a report with live data fetched from a DataSource adapter.
51
51
  *
@@ -58,7 +58,7 @@ export type ScheduleTriggerCallback = (report: ReportSchema, schedule: ReportSch
58
58
  * });
59
59
  * ```
60
60
  */
61
- export declare function exportWithLiveData(report: ReportSchema, options: LiveExportOptions): Promise<LiveExportResult>;
61
+ export declare function exportWithLiveData(report: ReportComponentSchema, options: LiveExportOptions): Promise<LiveExportResult>;
62
62
  /**
63
63
  * Export report as Excel with formatted columns and formula support.
64
64
  *
@@ -79,7 +79,7 @@ export declare function exportWithLiveData(report: ReportSchema, options: LiveEx
79
79
  * });
80
80
  * ```
81
81
  */
82
- export declare function exportExcelWithFormulas(report: ReportSchema, data: any[], options?: {
82
+ export declare function exportExcelWithFormulas(report: ReportComponentSchema, data: any[], options?: {
83
83
  columns?: ExcelColumnConfig[];
84
84
  filename?: string;
85
85
  includeAggregationRow?: boolean;
@@ -101,4 +101,4 @@ export declare function exportExcelWithFormulas(report: ReportSchema, data: any[
101
101
  * await trigger();
102
102
  * ```
103
103
  */
104
- export declare function createScheduleTrigger(report: ReportSchema, dataSource: DataSource, resource: string, onComplete: ScheduleTriggerCallback): () => Promise<LiveExportResult[]>;
104
+ export declare function createScheduleTrigger(report: ReportComponentSchema, dataSource: DataSource, resource: string, onComplete: ScheduleTriggerCallback): () => Promise<LiveExportResult[]>;
@@ -1,4 +1,4 @@
1
- import { ReportSchema, ReportExportConfig, ReportExportFormat } from '@object-ui/types';
1
+ import { ReportComponentSchema, ReportExportConfig, ReportExportFormat } from '@object-ui/types';
2
2
  /**
3
3
  * Report Export Engine
4
4
  * Handles exporting report data to various formats using browser-native APIs.
@@ -6,24 +6,24 @@ import { ReportSchema, ReportExportConfig, ReportExportFormat } from '@object-ui
6
6
  /**
7
7
  * Export report data as CSV
8
8
  */
9
- export declare function exportAsCSV(report: ReportSchema, data: any[], config?: ReportExportConfig): void;
9
+ export declare function exportAsCSV(report: ReportComponentSchema, data: any[], config?: ReportExportConfig): void;
10
10
  /**
11
11
  * Export report data as JSON
12
12
  */
13
- export declare function exportAsJSON(report: ReportSchema, data: any[], config?: ReportExportConfig): void;
13
+ export declare function exportAsJSON(report: ReportComponentSchema, data: any[], config?: ReportExportConfig): void;
14
14
  /**
15
15
  * Export report as HTML (printable format)
16
16
  */
17
- export declare function exportAsHTML(report: ReportSchema, data: any[], config?: ReportExportConfig): void;
17
+ export declare function exportAsHTML(report: ReportComponentSchema, data: any[], config?: ReportExportConfig): void;
18
18
  /**
19
19
  * Export report as PDF using browser print
20
20
  */
21
- export declare function exportAsPDF(report: ReportSchema, data: any[], config?: ReportExportConfig): void;
21
+ export declare function exportAsPDF(report: ReportComponentSchema, data: any[], config?: ReportExportConfig): void;
22
22
  /**
23
23
  * Export report as Excel-compatible CSV (with BOM for proper UTF-8 in Excel)
24
24
  */
25
- export declare function exportAsExcel(report: ReportSchema, data: any[], config?: ReportExportConfig): void;
25
+ export declare function exportAsExcel(report: ReportComponentSchema, data: any[], config?: ReportExportConfig): void;
26
26
  /**
27
27
  * Main export function - routes to correct format handler
28
28
  */
29
- export declare function exportReport(format: ReportExportFormat, report: ReportSchema, data: any[], config?: ReportExportConfig): void;
29
+ export declare function exportReport(format: ReportExportFormat, report: ReportComponentSchema, data: any[], config?: ReportExportConfig): void;
@@ -1,5 +1,14 @@
1
1
  import { default as React } from 'react';
2
2
  import { ReportViewerSchema } from '@object-ui/types';
3
+ /**
4
+ * Compute one summary value for a report column. Covers every
5
+ * `ReportAggregationType` member (`@object-ui/types/reports.ts`) — `distinct`
6
+ * used to fall into `default: return ''` and render a blank cell while the
7
+ * type accepted it (#2942). Exported for the coverage guard, whose sample
8
+ * table is `Record<ReportAggregationType, …>` so a new member fails
9
+ * type-check until it computes here.
10
+ */
11
+ export declare function computeReportAggregation(data: Record<string, any>[] | undefined, fieldName: string, aggregation?: string): string | number;
3
12
  export interface ReportViewerProps {
4
13
  schema: ReportViewerSchema;
5
14
  /** Callback to refresh data */