@firestitch/report 18.21.4 → 18.21.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (25) hide show
  1. package/app/reports/components/component-list/component-list.component.d.ts +3 -0
  2. package/app/reports/export/report-export-collector.service.d.ts +1 -1
  3. package/app/reports/export/report-pptx.service.d.ts +0 -1
  4. package/app/reports/interfaces/report-value-label.interface.d.ts +4 -0
  5. package/app/reports/interfaces/report.interface.d.ts +2 -0
  6. package/app/reports/option-builder.d.ts +1 -0
  7. package/app/reports/value-labels.d.ts +2 -0
  8. package/esm2022/app/reports/components/component-list/component-list.component.mjs +11 -3
  9. package/esm2022/app/reports/export/report-export-collector.service.mjs +13 -8
  10. package/esm2022/app/reports/export/report-pdf.service.mjs +2 -2
  11. package/esm2022/app/reports/export/report-pptx.service.mjs +9 -17
  12. package/esm2022/app/reports/interfaces/report-value-label.interface.mjs +2 -0
  13. package/esm2022/app/reports/interfaces/report.interface.mjs +1 -1
  14. package/esm2022/app/reports/mark-click.mjs +9 -6
  15. package/esm2022/app/reports/option-builder.mjs +60 -10
  16. package/esm2022/app/reports/value-labels.mjs +26 -0
  17. package/esm2022/public_api.mjs +2 -1
  18. package/fesm2022/{firestitch-report-echarts-CBBTk1Ql.mjs → firestitch-report-echarts-D7WNr0Z4.mjs} +2 -2
  19. package/fesm2022/{firestitch-report-echarts-CBBTk1Ql.mjs.map → firestitch-report-echarts-D7WNr0Z4.mjs.map} +1 -1
  20. package/fesm2022/{firestitch-report-firestitch-report-Cl_JOBli.mjs → firestitch-report-firestitch-report-DWP3aywv.mjs} +123 -42
  21. package/fesm2022/firestitch-report-firestitch-report-DWP3aywv.mjs.map +1 -0
  22. package/fesm2022/firestitch-report.mjs +1 -1
  23. package/package.json +1 -1
  24. package/public_api.d.ts +1 -0
  25. package/fesm2022/firestitch-report-firestitch-report-Cl_JOBli.mjs.map +0 -1
@@ -0,0 +1,26 @@
1
+ // The words a chart's or a list's row value is shown in, when the server
2
+ // labels its column (ComponentData.valueLabels): an enum column's
3
+ // "consumerGoods" reads "Consumer Goods" on the axis, the legend, the
4
+ // tooltip, the list cell, the cross-tab heading and in both exports. Rows
5
+ // keep the stored value, which filters, sorts and clicks still use. Pure, so
6
+ // the screen and the exports word a value alike.
7
+ // Each column's entries as a lookup by value text, built once per entries
8
+ // array the data carries: a list asks once per cell, a chart once per
9
+ // category.
10
+ const LOOKUPS = new WeakMap();
11
+ // What `value`, a row value of `column`, reads as: the label of the entry
12
+ // whose value matches String(value). null when the column has no labels, the
13
+ // value has no entry or is blank, so it shows as it always has.
14
+ export function valueLabel(labels, column, value) {
15
+ const entries = column ? labels?.[column] : undefined;
16
+ if (!entries?.length || value === null || value === undefined) {
17
+ return null;
18
+ }
19
+ let lookup = LOOKUPS.get(entries);
20
+ if (!lookup) {
21
+ lookup = new Map(entries.map((entry) => [String(entry.value), entry.label]));
22
+ LOOKUPS.set(entries, lookup);
23
+ }
24
+ return lookup.get(String(value)) ?? null;
25
+ }
26
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmFsdWUtbGFiZWxzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2FwcC9yZXBvcnRzL3ZhbHVlLWxhYmVscy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFJQSx5RUFBeUU7QUFDekUsa0VBQWtFO0FBQ2xFLHNFQUFzRTtBQUN0RSwwRUFBMEU7QUFDMUUsNkVBQTZFO0FBQzdFLGlEQUFpRDtBQUVqRCwwRUFBMEU7QUFDMUUsc0VBQXNFO0FBQ3RFLFlBQVk7QUFDWixNQUFNLE9BQU8sR0FBRyxJQUFJLE9BQU8sRUFBb0QsQ0FBQztBQUVoRiwwRUFBMEU7QUFDMUUsNkVBQTZFO0FBQzdFLGdFQUFnRTtBQUNoRSxNQUFNLFVBQVUsVUFBVSxDQUN4QixNQUF1RCxFQUN2RCxNQUFpQyxFQUNqQyxLQUFjO0lBRWQsTUFBTSxPQUFPLEdBQUcsTUFBTSxDQUFDLENBQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDO0lBRXRELElBQUksQ0FBQyxPQUFPLEVBQUUsTUFBTSxJQUFJLEtBQUssS0FBSyxJQUFJLElBQUksS0FBSyxLQUFLLFNBQVMsRUFBRSxDQUFDO1FBQzlELE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUVELElBQUksTUFBTSxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDbEMsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO1FBQ1osTUFBTSxHQUFHLElBQUksR0FBRyxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsRUFBRSxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQzdFLE9BQU8sQ0FBQyxHQUFHLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxDQUFDO0lBQy9CLENBQUM7SUFFRCxPQUFPLE1BQU0sQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksSUFBSSxDQUFDO0FBQzNDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnREYXRhIH0gZnJvbSAnLi9pbnRlcmZhY2VzL3JlcG9ydC5pbnRlcmZhY2UnO1xuaW1wb3J0IHsgUmVwb3J0VmFsdWVMYWJlbCB9IGZyb20gJy4vaW50ZXJmYWNlcy9yZXBvcnQtdmFsdWUtbGFiZWwuaW50ZXJmYWNlJztcblxuXG4vLyBUaGUgd29yZHMgYSBjaGFydCdzIG9yIGEgbGlzdCdzIHJvdyB2YWx1ZSBpcyBzaG93biBpbiwgd2hlbiB0aGUgc2VydmVyXG4vLyBsYWJlbHMgaXRzIGNvbHVtbiAoQ29tcG9uZW50RGF0YS52YWx1ZUxhYmVscyk6IGFuIGVudW0gY29sdW1uJ3Ncbi8vIFwiY29uc3VtZXJHb29kc1wiIHJlYWRzIFwiQ29uc3VtZXIgR29vZHNcIiBvbiB0aGUgYXhpcywgdGhlIGxlZ2VuZCwgdGhlXG4vLyB0b29sdGlwLCB0aGUgbGlzdCBjZWxsLCB0aGUgY3Jvc3MtdGFiIGhlYWRpbmcgYW5kIGluIGJvdGggZXhwb3J0cy4gUm93c1xuLy8ga2VlcCB0aGUgc3RvcmVkIHZhbHVlLCB3aGljaCBmaWx0ZXJzLCBzb3J0cyBhbmQgY2xpY2tzIHN0aWxsIHVzZS4gUHVyZSwgc29cbi8vIHRoZSBzY3JlZW4gYW5kIHRoZSBleHBvcnRzIHdvcmQgYSB2YWx1ZSBhbGlrZS5cblxuLy8gRWFjaCBjb2x1bW4ncyBlbnRyaWVzIGFzIGEgbG9va3VwIGJ5IHZhbHVlIHRleHQsIGJ1aWx0IG9uY2UgcGVyIGVudHJpZXNcbi8vIGFycmF5IHRoZSBkYXRhIGNhcnJpZXM6IGEgbGlzdCBhc2tzIG9uY2UgcGVyIGNlbGwsIGEgY2hhcnQgb25jZSBwZXJcbi8vIGNhdGVnb3J5LlxuY29uc3QgTE9PS1VQUyA9IG5ldyBXZWFrTWFwPHJlYWRvbmx5IFJlcG9ydFZhbHVlTGFiZWxbXSwgTWFwPHN0cmluZywgc3RyaW5nPj4oKTtcblxuLy8gV2hhdCBgdmFsdWVgLCBhIHJvdyB2YWx1ZSBvZiBgY29sdW1uYCwgcmVhZHMgYXM6IHRoZSBsYWJlbCBvZiB0aGUgZW50cnlcbi8vIHdob3NlIHZhbHVlIG1hdGNoZXMgU3RyaW5nKHZhbHVlKS4gbnVsbCB3aGVuIHRoZSBjb2x1bW4gaGFzIG5vIGxhYmVscywgdGhlXG4vLyB2YWx1ZSBoYXMgbm8gZW50cnkgb3IgaXMgYmxhbmssIHNvIGl0IHNob3dzIGFzIGl0IGFsd2F5cyBoYXMuXG5leHBvcnQgZnVuY3Rpb24gdmFsdWVMYWJlbChcbiAgbGFiZWxzOiBDb21wb25lbnREYXRhWyd2YWx1ZUxhYmVscyddIHwgbnVsbCB8IHVuZGVmaW5lZCxcbiAgY29sdW1uOiBzdHJpbmcgfCBudWxsIHwgdW5kZWZpbmVkLFxuICB2YWx1ZTogdW5rbm93bixcbik6IHN0cmluZyB8IG51bGwge1xuICBjb25zdCBlbnRyaWVzID0gY29sdW1uID8gbGFiZWxzPy5bY29sdW1uXSA6IHVuZGVmaW5lZDtcblxuICBpZiAoIWVudHJpZXM/Lmxlbmd0aCB8fCB2YWx1ZSA9PT0gbnVsbCB8fCB2YWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBsZXQgbG9va3VwID0gTE9PS1VQUy5nZXQoZW50cmllcyk7XG4gIGlmICghbG9va3VwKSB7XG4gICAgbG9va3VwID0gbmV3IE1hcChlbnRyaWVzLm1hcCgoZW50cnkpID0+IFtTdHJpbmcoZW50cnkudmFsdWUpLCBlbnRyeS5sYWJlbF0pKTtcbiAgICBMT09LVVBTLnNldChlbnRyaWVzLCBsb29rdXApO1xuICB9XG5cbiAgcmV0dXJuIGxvb2t1cC5nZXQoU3RyaW5nKHZhbHVlKSkgPz8gbnVsbDtcbn1cbiJdfQ==
@@ -26,6 +26,7 @@ export * from './app/reports/interfaces/report-viewer-feature.type';
26
26
  export * from './app/reports/interfaces/report-export-format.type';
27
27
  export * from './app/reports/interfaces/component-data-applied.interface';
28
28
  export * from './app/reports/interfaces/component-data-drill.interface';
29
+ export * from './app/reports/interfaces/report-value-label.interface';
29
30
  export * from './app/reports/interfaces/report-filter-options.interface';
30
31
  export * from './app/reports/interfaces/report-filter-options-request.interface';
31
32
  export * from './app/reports/interfaces/report-saved-filter.interface';
@@ -50,4 +51,4 @@ export * from './app/reports/enums/report-chart-mark-stat.enum';
50
51
  export * from './app/reports/enums/report-chart-date-label.enum';
51
52
  export * from './app/reports/enums/report-chart-span-through.enum';
52
53
  export * from './app/reports/enums/report-change-polarity.enum';
53
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHVibGljX2FwaS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9wdWJsaWNfYXBpLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7R0FNRztBQUNILDZFQUE2RTtBQUM3RSxzRUFBc0U7QUFDdEUsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0scURBQXFELENBQUM7QUFDM0YsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sbURBQW1ELENBQUM7QUFDeEYsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBQzVELE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSx1Q0FBdUMsQ0FBQztBQUN0RSxPQUFPLEVBQUUsd0JBQXdCLEVBQUUsTUFBTSxvREFBb0QsQ0FBQztBQUM5RixjQUFjLDJDQUEyQyxDQUFDO0FBQzFELGNBQWMsMERBQTBELENBQUM7QUFDekUsY0FBYyxzREFBc0QsQ0FBQztBQUNyRSxjQUFjLHNEQUFzRCxDQUFDO0FBQ3JFLGNBQWMsc0RBQXNELENBQUM7QUFDckUsY0FBYywrREFBK0QsQ0FBQztBQUM5RSxjQUFjLHVEQUF1RCxDQUFDO0FBQ3RFLGNBQWMsb0RBQW9ELENBQUM7QUFDbkUsY0FBYyxtREFBbUQsQ0FBQztBQUNsRSxjQUFjLGtEQUFrRCxDQUFDO0FBQ2pFLGNBQWMscURBQXFELENBQUM7QUFDcEUsY0FBYyxvREFBb0QsQ0FBQztBQUNuRSxjQUFjLDJEQUEyRCxDQUFDO0FBQzFFLGNBQWMseURBQXlELENBQUM7QUFDeEUsY0FBYywwREFBMEQsQ0FBQztBQUN6RSxjQUFjLGtFQUFrRSxDQUFDO0FBQ2pGLGNBQWMsd0RBQXdELENBQUM7QUFDdkUsY0FBYyxnRUFBZ0UsQ0FBQztBQUMvRSxjQUFjLHNEQUFzRCxDQUFDO0FBQ3JFLGNBQWMsc0RBQXNELENBQUM7QUFDckUsY0FBYyx1REFBdUQsQ0FBQztBQUN0RSxjQUFjLHVEQUF1RCxDQUFDO0FBQ3RFLGNBQWMseURBQXlELENBQUM7QUFDeEUsY0FBYywyREFBMkQsQ0FBQztBQUMxRSxjQUFjLCtEQUErRCxDQUFDO0FBQzlFLGNBQWMsbUVBQW1FLENBQUM7QUFDbEYsY0FBYyxtRUFBbUUsQ0FBQztBQUNsRixjQUFjLDhDQUE4QyxDQUFDO0FBQzdELGNBQWMsK0NBQStDLENBQUM7QUFDOUQsY0FBYyxvREFBb0QsQ0FBQztBQUNuRSxjQUFjLDhDQUE4QyxDQUFDO0FBQzdELGNBQWMsbURBQW1ELENBQUM7QUFDbEUsY0FBYyw2Q0FBNkMsQ0FBQztBQUM1RCxjQUFjLGtEQUFrRCxDQUFDO0FBQ2pFLGNBQWMsaURBQWlELENBQUM7QUFDaEUsY0FBYyxrREFBa0QsQ0FBQztBQUNqRSxjQUFjLG9EQUFvRCxDQUFDO0FBQ25FLGNBQWMsaURBQWlELENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuICogUHVibGljIEFQSSBTdXJmYWNlIG9mIEBmaXJlc3RpdGNoL3JlcG9ydHNcbiAqXG4gKiBUaGUgQUktYnVpbHQgcmVwb3J0IHZpZXdlci9lZGl0b3IsIGl0cyBkYXRhIGdhdGV3YXksIHNlc3Npb24gZmlsdGVyIHN0YXRlIGFuZFxuICogcmVuZGVyZXIgY29tcG9uZW50cy4gVGhlIEFJIGNoYXQgaXMgcHJvdmlkZWQgYnkgQGZpcmVzdGl0Y2gvYWksIHJlYWNoZWRcbiAqIHRocm91Z2ggdGhlIHJlcG9ydCdzIHBhZ2Ugb24gc2NyZWVuLlxuICovXG4vLyBSb3V0aW5nLWZyZWUgc3VyZmFjZTogYSByZXBvcnRzIGxpc3RpbmcgYW5kIGEgc2luZ2xlLXJlcG9ydCB2aWV3LiBUaGUgaG9zdFxuLy8gcm91dGVzIGJldHdlZW4gdGhlbSBhbmQgcGFzc2VzIFtyZXBvcnRJZF0gaW50byBGc0FpUmVwb3J0Q29tcG9uZW50LlxuZXhwb3J0IHsgRnNBaVJlcG9ydHNDb21wb25lbnQgfSBmcm9tICcuL2FwcC9yZXBvcnRzL3ZpZXdzL3JlcG9ydHMvZnMtYWktcmVwb3J0cy5jb21wb25lbnQnO1xuZXhwb3J0IHsgRnNBaVJlcG9ydENvbXBvbmVudCB9IGZyb20gJy4vYXBwL3JlcG9ydHMvdmlld3MvcmVwb3J0L2ZzLWFpLXJlcG9ydC5jb21wb25lbnQnO1xuZXhwb3J0IHsgUmVwb3J0RGF0YSB9IGZyb20gJy4vYXBwL3JlcG9ydHMvZGF0YS9yZXBvcnQuZGF0YSc7XG5leHBvcnQgeyBSZXBvcnRTZXJ2aWNlIH0gZnJvbSAnLi9hcHAvcmVwb3J0cy9zZXJ2aWNlcy9yZXBvcnQuc2VydmljZSc7XG5leHBvcnQgeyBSZXBvcnRGaWx0ZXJTdGF0ZVNlcnZpY2UgfSBmcm9tICcuL2FwcC9yZXBvcnRzL3NlcnZpY2VzL3JlcG9ydC1maWx0ZXItc3RhdGUuc2VydmljZSc7XG5leHBvcnQgKiBmcm9tICcuL2FwcC9yZXBvcnRzL2ludGVyZmFjZXMvcmVwb3J0LmludGVyZmFjZSc7XG5leHBvcnQgKiBmcm9tICcuL2FwcC9yZXBvcnRzL2ludGVyZmFjZXMvcmVwb3J0LXN0YXRlLXNuYXBzaG90LmludGVyZmFjZSc7XG5leHBvcnQgKiBmcm9tICcuL2FwcC9yZXBvcnRzL2ludGVyZmFjZXMvcmVwb3J0LXRpbGUtc3RhdGUuaW50ZXJmYWNlJztcbmV4cG9ydCAqIGZyb20gJy4vYXBwL3JlcG9ydHMvaW50ZXJmYWNlcy9yZXBvcnQtZHJpbGwtc3RlcC5pbnRlcmZhY2UnO1xuZXhwb3J0ICogZnJvbSAnLi9hcHAvcmVwb3J0cy9pbnRlcmZhY2VzL3JlcG9ydC1jaGFydC1zcGFuLmludGVyZmFjZSc7XG5leHBvcnQgKiBmcm9tICcuL2FwcC9yZXBvcnRzL2ludGVyZmFjZXMvcmVwb3J0LWNoYXJ0LWF4aXMtc2V0dGluZ3MuaW50ZXJmYWNlJztcbmV4cG9ydCAqIGZyb20gJy4vYXBwL3JlcG9ydHMvaW50ZXJmYWNlcy9yZXBvcnQtZHJpbGwtY3J1bWIuaW50ZXJmYWNlJztcbmV4cG9ydCAqIGZyb20gJy4vYXBwL3JlcG9ydHMvaW50ZXJmYWNlcy9yZXBvcnQtZHJpbGwtcmVmdXNhbC50eXBlJztcbmV4cG9ydCAqIGZyb20gJy4vYXBwL3JlcG9ydHMvaW50ZXJmYWNlcy9yZXBvcnQtZmlsdGVyLW1hdGNoLnR5cGUnO1xuZXhwb3J0ICogZnJvbSAnLi9hcHAvcmVwb3J0cy9pbnRlcmZhY2VzL3JlcG9ydC1maWx0ZXItc2tpcC50eXBlJztcbmV4cG9ydCAqIGZyb20gJy4vYXBwL3JlcG9ydHMvaW50ZXJmYWNlcy9yZXBvcnQtdmlld2VyLWZlYXR1cmUudHlwZSc7XG5leHBvcnQgKiBmcm9tICcuL2FwcC9yZXBvcnRzL2ludGVyZmFjZXMvcmVwb3J0LWV4cG9ydC1mb3JtYXQudHlwZSc7XG5leHBvcnQgKiBmcm9tICcuL2FwcC9yZXBvcnRzL2ludGVyZmFjZXMvY29tcG9uZW50LWRhdGEtYXBwbGllZC5pbnRlcmZhY2UnO1xuZXhwb3J0ICogZnJvbSAnLi9hcHAvcmVwb3J0cy9pbnRlcmZhY2VzL2NvbXBvbmVudC1kYXRhLWRyaWxsLmludGVyZmFjZSc7XG5leHBvcnQgKiBmcm9tICcuL2FwcC9yZXBvcnRzL2ludGVyZmFjZXMvcmVwb3J0LWZpbHRlci1vcHRpb25zLmludGVyZmFjZSc7XG5leHBvcnQgKiBmcm9tICcuL2FwcC9yZXBvcnRzL2ludGVyZmFjZXMvcmVwb3J0LWZpbHRlci1vcHRpb25zLXJlcXVlc3QuaW50ZXJmYWNlJztcbmV4cG9ydCAqIGZyb20gJy4vYXBwL3JlcG9ydHMvaW50ZXJmYWNlcy9yZXBvcnQtc2F2ZWQtZmlsdGVyLmludGVyZmFjZSc7XG5leHBvcnQgKiBmcm9tICcuL2FwcC9yZXBvcnRzL2ludGVyZmFjZXMvcmVwb3J0LXNhdmVkLWZpbHRlci1jaGFuZ2VzLmludGVyZmFjZSc7XG5leHBvcnQgKiBmcm9tICcuL2FwcC9yZXBvcnRzL2ludGVyZmFjZXMvcmVwb3J0LW1hcmstcG9pbnQuaW50ZXJmYWNlJztcbmV4cG9ydCAqIGZyb20gJy4vYXBwL3JlcG9ydHMvaW50ZXJmYWNlcy9yZXBvcnQtbWFyay1jbGljay5pbnRlcmZhY2UnO1xuZXhwb3J0ICogZnJvbSAnLi9hcHAvcmVwb3J0cy9pbnRlcmZhY2VzL3JlcG9ydC1leHBvcnQtbGluZS5pbnRlcmZhY2UnO1xuZXhwb3J0ICogZnJvbSAnLi9hcHAvcmVwb3J0cy9pbnRlcmZhY2VzL3JlcG9ydC1leHBvcnQtbGluZS1raW5kLnR5cGUnO1xuZXhwb3J0ICogZnJvbSAnLi9hcHAvcmVwb3J0cy9pbnRlcmZhY2VzL3JlcG9ydC1wYWNrYWdlLWNoZWNrLmludGVyZmFjZSc7XG5leHBvcnQgKiBmcm9tICcuL2FwcC9yZXBvcnRzL2ludGVyZmFjZXMvcmVwb3J0LXBhY2thZ2UtZmluZGluZy5pbnRlcmZhY2UnO1xuZXhwb3J0ICogZnJvbSAnLi9hcHAvcmVwb3J0cy9pbnRlcmZhY2VzL3JlcG9ydC1wYWNrYWdlLWZpbmRpbmctc2V2ZXJpdHkudHlwZSc7XG5leHBvcnQgKiBmcm9tICcuL2FwcC9yZXBvcnRzL2ludGVyZmFjZXMvcmVwb3J0LXBhY2thZ2UtaW1wb3J0LXJlc3BvbnNlLmludGVyZmFjZSc7XG5leHBvcnQgKiBmcm9tICcuL2FwcC9yZXBvcnRzL2ludGVyZmFjZXMvcmVwb3J0LXBhY2thZ2UtaW1wb3J0ZWQtcmVwb3J0LmludGVyZmFjZSc7XG5leHBvcnQgKiBmcm9tICcuL2FwcC9yZXBvcnRzL2VudW1zL3JlcG9ydC12YWx1ZS1mb3JtYXQuZW51bSc7XG5leHBvcnQgKiBmcm9tICcuL2FwcC9yZXBvcnRzL2VudW1zL3JlcG9ydC12YWx1ZS1mb3JtdWxhLmVudW0nO1xuZXhwb3J0ICogZnJvbSAnLi9hcHAvcmVwb3J0cy9lbnVtcy9yZXBvcnQtbGlzdC1jb2x1bW4tZm9ybWF0LmVudW0nO1xuZXhwb3J0ICogZnJvbSAnLi9hcHAvcmVwb3J0cy9lbnVtcy9yZXBvcnQtbnVtYmVyLXVuaXRzLmVudW0nO1xuZXhwb3J0ICogZnJvbSAnLi9hcHAvcmVwb3J0cy9lbnVtcy9yZXBvcnQtY2hhcnQtZGF0YS1sYWJlbHMuZW51bSc7XG5leHBvcnQgKiBmcm9tICcuL2FwcC9yZXBvcnRzL2VudW1zL3JlcG9ydC1jaGFydC1jb2xvci5lbnVtJztcbmV4cG9ydCAqIGZyb20gJy4vYXBwL3JlcG9ydHMvZW51bXMvcmVwb3J0LWNoYXJ0LWxpbmUtc3R5bGUuZW51bSc7XG5leHBvcnQgKiBmcm9tICcuL2FwcC9yZXBvcnRzL2VudW1zL3JlcG9ydC1jaGFydC1tYXJrLXN0YXQuZW51bSc7XG5leHBvcnQgKiBmcm9tICcuL2FwcC9yZXBvcnRzL2VudW1zL3JlcG9ydC1jaGFydC1kYXRlLWxhYmVsLmVudW0nO1xuZXhwb3J0ICogZnJvbSAnLi9hcHAvcmVwb3J0cy9lbnVtcy9yZXBvcnQtY2hhcnQtc3Bhbi10aHJvdWdoLmVudW0nO1xuZXhwb3J0ICogZnJvbSAnLi9hcHAvcmVwb3J0cy9lbnVtcy9yZXBvcnQtY2hhbmdlLXBvbGFyaXR5LmVudW0nO1xuIl19
54
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHVibGljX2FwaS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9wdWJsaWNfYXBpLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7R0FNRztBQUNILDZFQUE2RTtBQUM3RSxzRUFBc0U7QUFDdEUsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0scURBQXFELENBQUM7QUFDM0YsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sbURBQW1ELENBQUM7QUFDeEYsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBQzVELE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSx1Q0FBdUMsQ0FBQztBQUN0RSxPQUFPLEVBQUUsd0JBQXdCLEVBQUUsTUFBTSxvREFBb0QsQ0FBQztBQUM5RixjQUFjLDJDQUEyQyxDQUFDO0FBQzFELGNBQWMsMERBQTBELENBQUM7QUFDekUsY0FBYyxzREFBc0QsQ0FBQztBQUNyRSxjQUFjLHNEQUFzRCxDQUFDO0FBQ3JFLGNBQWMsc0RBQXNELENBQUM7QUFDckUsY0FBYywrREFBK0QsQ0FBQztBQUM5RSxjQUFjLHVEQUF1RCxDQUFDO0FBQ3RFLGNBQWMsb0RBQW9ELENBQUM7QUFDbkUsY0FBYyxtREFBbUQsQ0FBQztBQUNsRSxjQUFjLGtEQUFrRCxDQUFDO0FBQ2pFLGNBQWMscURBQXFELENBQUM7QUFDcEUsY0FBYyxvREFBb0QsQ0FBQztBQUNuRSxjQUFjLDJEQUEyRCxDQUFDO0FBQzFFLGNBQWMseURBQXlELENBQUM7QUFDeEUsY0FBYyx1REFBdUQsQ0FBQztBQUN0RSxjQUFjLDBEQUEwRCxDQUFDO0FBQ3pFLGNBQWMsa0VBQWtFLENBQUM7QUFDakYsY0FBYyx3REFBd0QsQ0FBQztBQUN2RSxjQUFjLGdFQUFnRSxDQUFDO0FBQy9FLGNBQWMsc0RBQXNELENBQUM7QUFDckUsY0FBYyxzREFBc0QsQ0FBQztBQUNyRSxjQUFjLHVEQUF1RCxDQUFDO0FBQ3RFLGNBQWMsdURBQXVELENBQUM7QUFDdEUsY0FBYyx5REFBeUQsQ0FBQztBQUN4RSxjQUFjLDJEQUEyRCxDQUFDO0FBQzFFLGNBQWMsK0RBQStELENBQUM7QUFDOUUsY0FBYyxtRUFBbUUsQ0FBQztBQUNsRixjQUFjLG1FQUFtRSxDQUFDO0FBQ2xGLGNBQWMsOENBQThDLENBQUM7QUFDN0QsY0FBYywrQ0FBK0MsQ0FBQztBQUM5RCxjQUFjLG9EQUFvRCxDQUFDO0FBQ25FLGNBQWMsOENBQThDLENBQUM7QUFDN0QsY0FBYyxtREFBbUQsQ0FBQztBQUNsRSxjQUFjLDZDQUE2QyxDQUFDO0FBQzVELGNBQWMsa0RBQWtELENBQUM7QUFDakUsY0FBYyxpREFBaUQsQ0FBQztBQUNoRSxjQUFjLGtEQUFrRCxDQUFDO0FBQ2pFLGNBQWMsb0RBQW9ELENBQUM7QUFDbkUsY0FBYyxpREFBaUQsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG4gKiBQdWJsaWMgQVBJIFN1cmZhY2Ugb2YgQGZpcmVzdGl0Y2gvcmVwb3J0c1xuICpcbiAqIFRoZSBBSS1idWlsdCByZXBvcnQgdmlld2VyL2VkaXRvciwgaXRzIGRhdGEgZ2F0ZXdheSwgc2Vzc2lvbiBmaWx0ZXIgc3RhdGUgYW5kXG4gKiByZW5kZXJlciBjb21wb25lbnRzLiBUaGUgQUkgY2hhdCBpcyBwcm92aWRlZCBieSBAZmlyZXN0aXRjaC9haSwgcmVhY2hlZFxuICogdGhyb3VnaCB0aGUgcmVwb3J0J3MgcGFnZSBvbiBzY3JlZW4uXG4gKi9cbi8vIFJvdXRpbmctZnJlZSBzdXJmYWNlOiBhIHJlcG9ydHMgbGlzdGluZyBhbmQgYSBzaW5nbGUtcmVwb3J0IHZpZXcuIFRoZSBob3N0XG4vLyByb3V0ZXMgYmV0d2VlbiB0aGVtIGFuZCBwYXNzZXMgW3JlcG9ydElkXSBpbnRvIEZzQWlSZXBvcnRDb21wb25lbnQuXG5leHBvcnQgeyBGc0FpUmVwb3J0c0NvbXBvbmVudCB9IGZyb20gJy4vYXBwL3JlcG9ydHMvdmlld3MvcmVwb3J0cy9mcy1haS1yZXBvcnRzLmNvbXBvbmVudCc7XG5leHBvcnQgeyBGc0FpUmVwb3J0Q29tcG9uZW50IH0gZnJvbSAnLi9hcHAvcmVwb3J0cy92aWV3cy9yZXBvcnQvZnMtYWktcmVwb3J0LmNvbXBvbmVudCc7XG5leHBvcnQgeyBSZXBvcnREYXRhIH0gZnJvbSAnLi9hcHAvcmVwb3J0cy9kYXRhL3JlcG9ydC5kYXRhJztcbmV4cG9ydCB7IFJlcG9ydFNlcnZpY2UgfSBmcm9tICcuL2FwcC9yZXBvcnRzL3NlcnZpY2VzL3JlcG9ydC5zZXJ2aWNlJztcbmV4cG9ydCB7IFJlcG9ydEZpbHRlclN0YXRlU2VydmljZSB9IGZyb20gJy4vYXBwL3JlcG9ydHMvc2VydmljZXMvcmVwb3J0LWZpbHRlci1zdGF0ZS5zZXJ2aWNlJztcbmV4cG9ydCAqIGZyb20gJy4vYXBwL3JlcG9ydHMvaW50ZXJmYWNlcy9yZXBvcnQuaW50ZXJmYWNlJztcbmV4cG9ydCAqIGZyb20gJy4vYXBwL3JlcG9ydHMvaW50ZXJmYWNlcy9yZXBvcnQtc3RhdGUtc25hcHNob3QuaW50ZXJmYWNlJztcbmV4cG9ydCAqIGZyb20gJy4vYXBwL3JlcG9ydHMvaW50ZXJmYWNlcy9yZXBvcnQtdGlsZS1zdGF0ZS5pbnRlcmZhY2UnO1xuZXhwb3J0ICogZnJvbSAnLi9hcHAvcmVwb3J0cy9pbnRlcmZhY2VzL3JlcG9ydC1kcmlsbC1zdGVwLmludGVyZmFjZSc7XG5leHBvcnQgKiBmcm9tICcuL2FwcC9yZXBvcnRzL2ludGVyZmFjZXMvcmVwb3J0LWNoYXJ0LXNwYW4uaW50ZXJmYWNlJztcbmV4cG9ydCAqIGZyb20gJy4vYXBwL3JlcG9ydHMvaW50ZXJmYWNlcy9yZXBvcnQtY2hhcnQtYXhpcy1zZXR0aW5ncy5pbnRlcmZhY2UnO1xuZXhwb3J0ICogZnJvbSAnLi9hcHAvcmVwb3J0cy9pbnRlcmZhY2VzL3JlcG9ydC1kcmlsbC1jcnVtYi5pbnRlcmZhY2UnO1xuZXhwb3J0ICogZnJvbSAnLi9hcHAvcmVwb3J0cy9pbnRlcmZhY2VzL3JlcG9ydC1kcmlsbC1yZWZ1c2FsLnR5cGUnO1xuZXhwb3J0ICogZnJvbSAnLi9hcHAvcmVwb3J0cy9pbnRlcmZhY2VzL3JlcG9ydC1maWx0ZXItbWF0Y2gudHlwZSc7XG5leHBvcnQgKiBmcm9tICcuL2FwcC9yZXBvcnRzL2ludGVyZmFjZXMvcmVwb3J0LWZpbHRlci1za2lwLnR5cGUnO1xuZXhwb3J0ICogZnJvbSAnLi9hcHAvcmVwb3J0cy9pbnRlcmZhY2VzL3JlcG9ydC12aWV3ZXItZmVhdHVyZS50eXBlJztcbmV4cG9ydCAqIGZyb20gJy4vYXBwL3JlcG9ydHMvaW50ZXJmYWNlcy9yZXBvcnQtZXhwb3J0LWZvcm1hdC50eXBlJztcbmV4cG9ydCAqIGZyb20gJy4vYXBwL3JlcG9ydHMvaW50ZXJmYWNlcy9jb21wb25lbnQtZGF0YS1hcHBsaWVkLmludGVyZmFjZSc7XG5leHBvcnQgKiBmcm9tICcuL2FwcC9yZXBvcnRzL2ludGVyZmFjZXMvY29tcG9uZW50LWRhdGEtZHJpbGwuaW50ZXJmYWNlJztcbmV4cG9ydCAqIGZyb20gJy4vYXBwL3JlcG9ydHMvaW50ZXJmYWNlcy9yZXBvcnQtdmFsdWUtbGFiZWwuaW50ZXJmYWNlJztcbmV4cG9ydCAqIGZyb20gJy4vYXBwL3JlcG9ydHMvaW50ZXJmYWNlcy9yZXBvcnQtZmlsdGVyLW9wdGlvbnMuaW50ZXJmYWNlJztcbmV4cG9ydCAqIGZyb20gJy4vYXBwL3JlcG9ydHMvaW50ZXJmYWNlcy9yZXBvcnQtZmlsdGVyLW9wdGlvbnMtcmVxdWVzdC5pbnRlcmZhY2UnO1xuZXhwb3J0ICogZnJvbSAnLi9hcHAvcmVwb3J0cy9pbnRlcmZhY2VzL3JlcG9ydC1zYXZlZC1maWx0ZXIuaW50ZXJmYWNlJztcbmV4cG9ydCAqIGZyb20gJy4vYXBwL3JlcG9ydHMvaW50ZXJmYWNlcy9yZXBvcnQtc2F2ZWQtZmlsdGVyLWNoYW5nZXMuaW50ZXJmYWNlJztcbmV4cG9ydCAqIGZyb20gJy4vYXBwL3JlcG9ydHMvaW50ZXJmYWNlcy9yZXBvcnQtbWFyay1wb2ludC5pbnRlcmZhY2UnO1xuZXhwb3J0ICogZnJvbSAnLi9hcHAvcmVwb3J0cy9pbnRlcmZhY2VzL3JlcG9ydC1tYXJrLWNsaWNrLmludGVyZmFjZSc7XG5leHBvcnQgKiBmcm9tICcuL2FwcC9yZXBvcnRzL2ludGVyZmFjZXMvcmVwb3J0LWV4cG9ydC1saW5lLmludGVyZmFjZSc7XG5leHBvcnQgKiBmcm9tICcuL2FwcC9yZXBvcnRzL2ludGVyZmFjZXMvcmVwb3J0LWV4cG9ydC1saW5lLWtpbmQudHlwZSc7XG5leHBvcnQgKiBmcm9tICcuL2FwcC9yZXBvcnRzL2ludGVyZmFjZXMvcmVwb3J0LXBhY2thZ2UtY2hlY2suaW50ZXJmYWNlJztcbmV4cG9ydCAqIGZyb20gJy4vYXBwL3JlcG9ydHMvaW50ZXJmYWNlcy9yZXBvcnQtcGFja2FnZS1maW5kaW5nLmludGVyZmFjZSc7XG5leHBvcnQgKiBmcm9tICcuL2FwcC9yZXBvcnRzL2ludGVyZmFjZXMvcmVwb3J0LXBhY2thZ2UtZmluZGluZy1zZXZlcml0eS50eXBlJztcbmV4cG9ydCAqIGZyb20gJy4vYXBwL3JlcG9ydHMvaW50ZXJmYWNlcy9yZXBvcnQtcGFja2FnZS1pbXBvcnQtcmVzcG9uc2UuaW50ZXJmYWNlJztcbmV4cG9ydCAqIGZyb20gJy4vYXBwL3JlcG9ydHMvaW50ZXJmYWNlcy9yZXBvcnQtcGFja2FnZS1pbXBvcnRlZC1yZXBvcnQuaW50ZXJmYWNlJztcbmV4cG9ydCAqIGZyb20gJy4vYXBwL3JlcG9ydHMvZW51bXMvcmVwb3J0LXZhbHVlLWZvcm1hdC5lbnVtJztcbmV4cG9ydCAqIGZyb20gJy4vYXBwL3JlcG9ydHMvZW51bXMvcmVwb3J0LXZhbHVlLWZvcm11bGEuZW51bSc7XG5leHBvcnQgKiBmcm9tICcuL2FwcC9yZXBvcnRzL2VudW1zL3JlcG9ydC1saXN0LWNvbHVtbi1mb3JtYXQuZW51bSc7XG5leHBvcnQgKiBmcm9tICcuL2FwcC9yZXBvcnRzL2VudW1zL3JlcG9ydC1udW1iZXItdW5pdHMuZW51bSc7XG5leHBvcnQgKiBmcm9tICcuL2FwcC9yZXBvcnRzL2VudW1zL3JlcG9ydC1jaGFydC1kYXRhLWxhYmVscy5lbnVtJztcbmV4cG9ydCAqIGZyb20gJy4vYXBwL3JlcG9ydHMvZW51bXMvcmVwb3J0LWNoYXJ0LWNvbG9yLmVudW0nO1xuZXhwb3J0ICogZnJvbSAnLi9hcHAvcmVwb3J0cy9lbnVtcy9yZXBvcnQtY2hhcnQtbGluZS1zdHlsZS5lbnVtJztcbmV4cG9ydCAqIGZyb20gJy4vYXBwL3JlcG9ydHMvZW51bXMvcmVwb3J0LWNoYXJ0LW1hcmstc3RhdC5lbnVtJztcbmV4cG9ydCAqIGZyb20gJy4vYXBwL3JlcG9ydHMvZW51bXMvcmVwb3J0LWNoYXJ0LWRhdGUtbGFiZWwuZW51bSc7XG5leHBvcnQgKiBmcm9tICcuL2FwcC9yZXBvcnRzL2VudW1zL3JlcG9ydC1jaGFydC1zcGFuLXRocm91Z2guZW51bSc7XG5leHBvcnQgKiBmcm9tICcuL2FwcC9yZXBvcnRzL2VudW1zL3JlcG9ydC1jaGFuZ2UtcG9sYXJpdHkuZW51bSc7XG4iXX0=
@@ -4,7 +4,7 @@ import * as echarts from 'echarts/core';
4
4
  export { echarts as default };
5
5
  import { LabelLayout } from 'echarts/features';
6
6
  import { CanvasRenderer } from 'echarts/renderers';
7
- import { R as REPORT_CHART_COLORS_CSS, a as REPORT_CHART_FONT_FAMILY, b as REPORT_AXIS_LABEL_FONT_SIZE } from './firestitch-report-firestitch-report-Cl_JOBli.mjs';
7
+ import { R as REPORT_CHART_COLORS_CSS, a as REPORT_CHART_FONT_FAMILY, b as REPORT_AXIS_LABEL_FONT_SIZE } from './firestitch-report-firestitch-report-DWP3aywv.mjs';
8
8
 
9
9
  // Tree-shaken ECharts build for the reports renderer: only the chart types and
10
10
  // components the option-builder emits are registered, keeping the lazy chunk
@@ -63,4 +63,4 @@ echarts.registerTheme('report', {
63
63
  axisLabel: { color: '#52606d', fontSize: REPORT_AXIS_LABEL_FONT_SIZE },
64
64
  },
65
65
  });
66
- //# sourceMappingURL=firestitch-report-echarts-CBBTk1Ql.mjs.map
66
+ //# sourceMappingURL=firestitch-report-echarts-D7WNr0Z4.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"firestitch-report-echarts-CBBTk1Ql.mjs","sources":["../../src/app/reports/theme/echarts.ts"],"sourcesContent":["// Tree-shaken ECharts build for the reports renderer: only the chart types and\n// components the option-builder emits are registered, keeping the lazy chunk\n// lean. Loaded on demand by ngx-echarts via provideEchartsCore — see\n// REPORT_ECHARTS_PROVIDERS in reports-echarts.provider.ts.\n//\n// The canvas renderer (not SVG) is deliberate: chart.getDataURL() needs it for\n// the high-res images the PPT/PDF exports will use.\n\nimport { BarChart, LineChart, PieChart } from 'echarts/charts';\nimport {\n DatasetComponent,\n GridComponent,\n LegendComponent,\n MarkAreaComponent,\n MarkLineComponent,\n TooltipComponent,\n} from 'echarts/components';\nimport * as echarts from 'echarts/core';\nimport { LabelLayout } from 'echarts/features';\nimport { CanvasRenderer } from 'echarts/renderers';\n\nimport { REPORT_CHART_COLORS_CSS } from './palette';\nimport { REPORT_AXIS_LABEL_FONT_SIZE, REPORT_CHART_FONT_FAMILY } from './typography';\n\necharts.use([\n BarChart,\n LineChart,\n PieChart,\n GridComponent,\n TooltipComponent,\n LegendComponent,\n DatasetComponent,\n // Reference lines and statistic lines (markLine), reference bands\n // (markArea), and the overlap hiding of 'auto' data labels (LabelLayout).\n MarkLineComponent,\n MarkAreaComponent,\n LabelLayout,\n CanvasRenderer,\n]);\n\n// The house theme — the single place report chart \"standards\" live (palette,\n// typography, tooltip styling). Polished defaults now; refined in the polish\n// phase.\necharts.registerTheme('report', {\n color: REPORT_CHART_COLORS_CSS,\n textStyle: {\n fontFamily: REPORT_CHART_FONT_FAMILY,\n },\n title: {\n textStyle: { color: '#1f2933', fontSize: 14, fontWeight: 600 },\n },\n legend: {\n textStyle: { color: '#52606d', fontSize: 11 },\n },\n tooltip: {\n backgroundColor: 'rgba(31, 41, 51, 0.92)',\n borderWidth: 0,\n textStyle: { color: '#fff', fontSize: 12 },\n },\n categoryAxis: {\n axisLine: { lineStyle: { color: '#cbd2d9' } },\n axisTick: { show: false },\n axisLabel: { color: '#52606d', fontSize: REPORT_AXIS_LABEL_FONT_SIZE },\n splitLine: { show: false },\n },\n valueAxis: {\n axisLine: { show: false },\n axisLabel: { color: '#52606d', fontSize: REPORT_AXIS_LABEL_FONT_SIZE },\n splitLine: { lineStyle: { color: '#e4e7eb' } },\n },\n timeAxis: {\n axisLine: { lineStyle: { color: '#cbd2d9' } },\n axisLabel: { color: '#52606d', fontSize: REPORT_AXIS_LABEL_FONT_SIZE },\n },\n});\n\nexport default echarts;\n"],"names":[],"mappings":";;;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AAkBA,OAAO,CAAC,GAAG,CAAC;IACV,QAAQ;IACR,SAAS;IACT,QAAQ;IACR,aAAa;IACb,gBAAgB;IAChB,eAAe;IACf,gBAAgB;;;IAGhB,iBAAiB;IACjB,iBAAiB;IACjB,WAAW;IACX,cAAc;AACf,CAAA,CAAC,CAAC;AAEH;AACA;AACA;AACA,OAAO,CAAC,aAAa,CAAC,QAAQ,EAAE;AAC9B,IAAA,KAAK,EAAE,uBAAuB;AAC9B,IAAA,SAAS,EAAE;AACT,QAAA,UAAU,EAAE,wBAAwB;AACrC,KAAA;AACD,IAAA,KAAK,EAAE;AACL,QAAA,SAAS,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,EAAE,UAAU,EAAE,GAAG,EAAE;AAC/D,KAAA;AACD,IAAA,MAAM,EAAE;QACN,SAAS,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,EAAE;AAC9C,KAAA;AACD,IAAA,OAAO,EAAE;AACP,QAAA,eAAe,EAAE,wBAAwB;AACzC,QAAA,WAAW,EAAE,CAAC;QACd,SAAS,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,EAAE;AAC3C,KAAA;AACD,IAAA,YAAY,EAAE;QACZ,QAAQ,EAAE,EAAE,SAAS,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE;AAC7C,QAAA,QAAQ,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE;QACzB,SAAS,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,2BAA2B,EAAE;AACtE,QAAA,SAAS,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE;AAC3B,KAAA;AACD,IAAA,SAAS,EAAE;AACT,QAAA,QAAQ,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE;QACzB,SAAS,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,2BAA2B,EAAE;QACtE,SAAS,EAAE,EAAE,SAAS,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE;AAC/C,KAAA;AACD,IAAA,QAAQ,EAAE;QACR,QAAQ,EAAE,EAAE,SAAS,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE;QAC7C,SAAS,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,2BAA2B,EAAE;AACvE,KAAA;AACF,CAAA,CAAC"}
1
+ {"version":3,"file":"firestitch-report-echarts-D7WNr0Z4.mjs","sources":["../../src/app/reports/theme/echarts.ts"],"sourcesContent":["// Tree-shaken ECharts build for the reports renderer: only the chart types and\n// components the option-builder emits are registered, keeping the lazy chunk\n// lean. Loaded on demand by ngx-echarts via provideEchartsCore — see\n// REPORT_ECHARTS_PROVIDERS in reports-echarts.provider.ts.\n//\n// The canvas renderer (not SVG) is deliberate: chart.getDataURL() needs it for\n// the high-res images the PPT/PDF exports will use.\n\nimport { BarChart, LineChart, PieChart } from 'echarts/charts';\nimport {\n DatasetComponent,\n GridComponent,\n LegendComponent,\n MarkAreaComponent,\n MarkLineComponent,\n TooltipComponent,\n} from 'echarts/components';\nimport * as echarts from 'echarts/core';\nimport { LabelLayout } from 'echarts/features';\nimport { CanvasRenderer } from 'echarts/renderers';\n\nimport { REPORT_CHART_COLORS_CSS } from './palette';\nimport { REPORT_AXIS_LABEL_FONT_SIZE, REPORT_CHART_FONT_FAMILY } from './typography';\n\necharts.use([\n BarChart,\n LineChart,\n PieChart,\n GridComponent,\n TooltipComponent,\n LegendComponent,\n DatasetComponent,\n // Reference lines and statistic lines (markLine), reference bands\n // (markArea), and the overlap hiding of 'auto' data labels (LabelLayout).\n MarkLineComponent,\n MarkAreaComponent,\n LabelLayout,\n CanvasRenderer,\n]);\n\n// The house theme — the single place report chart \"standards\" live (palette,\n// typography, tooltip styling). Polished defaults now; refined in the polish\n// phase.\necharts.registerTheme('report', {\n color: REPORT_CHART_COLORS_CSS,\n textStyle: {\n fontFamily: REPORT_CHART_FONT_FAMILY,\n },\n title: {\n textStyle: { color: '#1f2933', fontSize: 14, fontWeight: 600 },\n },\n legend: {\n textStyle: { color: '#52606d', fontSize: 11 },\n },\n tooltip: {\n backgroundColor: 'rgba(31, 41, 51, 0.92)',\n borderWidth: 0,\n textStyle: { color: '#fff', fontSize: 12 },\n },\n categoryAxis: {\n axisLine: { lineStyle: { color: '#cbd2d9' } },\n axisTick: { show: false },\n axisLabel: { color: '#52606d', fontSize: REPORT_AXIS_LABEL_FONT_SIZE },\n splitLine: { show: false },\n },\n valueAxis: {\n axisLine: { show: false },\n axisLabel: { color: '#52606d', fontSize: REPORT_AXIS_LABEL_FONT_SIZE },\n splitLine: { lineStyle: { color: '#e4e7eb' } },\n },\n timeAxis: {\n axisLine: { lineStyle: { color: '#cbd2d9' } },\n axisLabel: { color: '#52606d', fontSize: REPORT_AXIS_LABEL_FONT_SIZE },\n },\n});\n\nexport default echarts;\n"],"names":[],"mappings":";;;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AAkBA,OAAO,CAAC,GAAG,CAAC;IACV,QAAQ;IACR,SAAS;IACT,QAAQ;IACR,aAAa;IACb,gBAAgB;IAChB,eAAe;IACf,gBAAgB;;;IAGhB,iBAAiB;IACjB,iBAAiB;IACjB,WAAW;IACX,cAAc;AACf,CAAA,CAAC,CAAC;AAEH;AACA;AACA;AACA,OAAO,CAAC,aAAa,CAAC,QAAQ,EAAE;AAC9B,IAAA,KAAK,EAAE,uBAAuB;AAC9B,IAAA,SAAS,EAAE;AACT,QAAA,UAAU,EAAE,wBAAwB;AACrC,KAAA;AACD,IAAA,KAAK,EAAE;AACL,QAAA,SAAS,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,EAAE,UAAU,EAAE,GAAG,EAAE;AAC/D,KAAA;AACD,IAAA,MAAM,EAAE;QACN,SAAS,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,EAAE;AAC9C,KAAA;AACD,IAAA,OAAO,EAAE;AACP,QAAA,eAAe,EAAE,wBAAwB;AACzC,QAAA,WAAW,EAAE,CAAC;QACd,SAAS,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,EAAE;AAC3C,KAAA;AACD,IAAA,YAAY,EAAE;QACZ,QAAQ,EAAE,EAAE,SAAS,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE;AAC7C,QAAA,QAAQ,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE;QACzB,SAAS,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,2BAA2B,EAAE;AACtE,QAAA,SAAS,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE;AAC3B,KAAA;AACD,IAAA,SAAS,EAAE;AACT,QAAA,QAAQ,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE;QACzB,SAAS,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,2BAA2B,EAAE;QACtE,SAAS,EAAE,EAAE,SAAS,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE;AAC/C,KAAA;AACD,IAAA,QAAQ,EAAE;QACR,QAAQ,EAAE,EAAE,SAAS,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE;QAC7C,SAAS,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,2BAA2B,EAAE;AACvE,KAAA;AACF,CAAA,CAAC"}
@@ -3687,6 +3687,32 @@ const REPORT_DATA_LABEL_FONT_SIZE = 10;
3687
3687
  // .small text or the body size.
3688
3688
  const REPORT_KPI_VALUE_FONT_SIZE = 34;
3689
3689
 
3690
+ // The words a chart's or a list's row value is shown in, when the server
3691
+ // labels its column (ComponentData.valueLabels): an enum column's
3692
+ // "consumerGoods" reads "Consumer Goods" on the axis, the legend, the
3693
+ // tooltip, the list cell, the cross-tab heading and in both exports. Rows
3694
+ // keep the stored value, which filters, sorts and clicks still use. Pure, so
3695
+ // the screen and the exports word a value alike.
3696
+ // Each column's entries as a lookup by value text, built once per entries
3697
+ // array the data carries: a list asks once per cell, a chart once per
3698
+ // category.
3699
+ const LOOKUPS = new WeakMap();
3700
+ // What `value`, a row value of `column`, reads as: the label of the entry
3701
+ // whose value matches String(value). null when the column has no labels, the
3702
+ // value has no entry or is blank, so it shows as it always has.
3703
+ function valueLabel(labels, column, value) {
3704
+ const entries = column ? labels?.[column] : undefined;
3705
+ if (!entries?.length || value === null || value === undefined) {
3706
+ return null;
3707
+ }
3708
+ let lookup = LOOKUPS.get(entries);
3709
+ if (!lookup) {
3710
+ lookup = new Map(entries.map((entry) => [String(entry.value), entry.label]));
3711
+ LOOKUPS.set(entries, lookup);
3712
+ }
3713
+ return lookup.get(String(value)) ?? null;
3714
+ }
3715
+
3690
3716
  // Room for an axis title. ECharts 5's containLabel keeps the TICK labels inside
3691
3717
  // the grid but not the axis name, so without this a vertical chart's category
3692
3718
  // title runs off the bottom edge or under a bottom legend, and its value title
@@ -3838,7 +3864,7 @@ function extractChartSeries(component, data) {
3838
3864
  const { xColumn, groupColumn } = chartColumns(config, data);
3839
3865
  const measures = chartMeasures(config, data);
3840
3866
  const rawCategories = uniqueValues(data.rows, xColumn);
3841
- const categories = rawCategories.map((category) => String(category ?? '—'));
3867
+ const categories = rawCategories.map((category) => dimensionText(data, xColumn, category));
3842
3868
  const series = [];
3843
3869
  const rawGroups = groupColumn ? uniqueValues(data.rows, groupColumn) : [];
3844
3870
  if (groupColumn) {
@@ -3846,7 +3872,7 @@ function extractChartSeries(component, data) {
3846
3872
  const measure = measures[0];
3847
3873
  for (const groupValue of rawGroups) {
3848
3874
  series.push({
3849
- name: String(groupValue ?? '—'),
3875
+ name: dimensionText(data, groupColumn, groupValue),
3850
3876
  values: categoryValues(data.rows, xColumn, rawCategories, measure.column, (row) => row[groupColumn] === groupValue),
3851
3877
  type: measure.type,
3852
3878
  measure,
@@ -3867,6 +3893,13 @@ function extractChartSeries(component, data) {
3867
3893
  }
3868
3894
  return { categories, series, rawCategories, rawGroups };
3869
3895
  }
3896
+ // A category or a split value as the chart writes it: its label when the
3897
+ // server labels its column, else the value as it came, a blank one as '—'. A
3898
+ // time column is never labeled, so its period starts stay raw for the axis
3899
+ // to format.
3900
+ function dimensionText(data, column, value) {
3901
+ return valueLabel(data.valueLabels, column, value) ?? String(value ?? '—');
3902
+ }
3870
3903
  // The column a chart's categories come from, and the one that splits its
3871
3904
  // first measure into a series per value, if any. colorBy emits one series per
3872
3905
  // category too (so each bar carries its own color + legend entry), but the
@@ -5535,10 +5568,14 @@ function seriesTooltip(measure, context) {
5535
5568
  valueFormatter: (value) => formatNumber(Array.isArray(value) ? value[0] : value, measure, context),
5536
5569
  };
5537
5570
  }
5571
+ // A pie's slices are named by categoryLineLabels(), so a monthly pie's legend
5572
+ // and tooltip read the month ("August"), never its period start
5573
+ // ("2026-08-01").
5538
5574
  function buildPieOption(component, data, donut, context) {
5539
5575
  const config = component.config;
5540
5576
  const extracted = extractChartSeries(component, data);
5541
5577
  const values = extracted.series[0]?.values ?? [];
5578
+ const names = categoryLineLabels(extracted.categories, config, data, context.locale);
5542
5579
  const legendPosition = resolveLegendPosition(config, extracted.series.length);
5543
5580
  return {
5544
5581
  tooltip: { trigger: 'item' },
@@ -5550,8 +5587,8 @@ function buildPieOption(component, data, donut, context) {
5550
5587
  center: pieCenter(legendPosition),
5551
5588
  tooltip: seriesTooltip(extracted.series[0]?.measure, context),
5552
5589
  label: { show: false },
5553
- data: extracted.categories.map((category, index) => ({
5554
- name: category,
5590
+ data: names.map((name, index) => ({
5591
+ name,
5555
5592
  value: values[index] ?? 0,
5556
5593
  })),
5557
5594
  },
@@ -5706,21 +5743,59 @@ function formatPeriodLabel(value, granularity, multiYear, locale, dateLabel = Re
5706
5743
  }
5707
5744
  return multiYear && periodYearApart(granularity, dateLabel) ? `${parts.primary} ${parts.year}` : parts.primary;
5708
5745
  }
5746
+ // A chart's categories as one-line labels, for what writes a category on a
5747
+ // single line: a pie's slices (legend, tooltip, click) and the PowerPoint
5748
+ // export's axis. On a bucketed time axis each period start reads as the axis
5749
+ // writes it, in the report's locale and the axis's date label style, a short
5750
+ // label taking its year inline only when the categories span years; any
5751
+ // other category as it is.
5752
+ function categoryLineLabels(categories, config, data, locale) {
5753
+ const granularity = bucketGranularity(data);
5754
+ if (!granularity) {
5755
+ return categories;
5756
+ }
5757
+ const multiYear = spansMultipleYears(categories);
5758
+ const dateLabel = chartDateLabel(config);
5759
+ return categories.map((category) => formatPeriodLabel(category, granularity, multiYear, locale, dateLabel));
5760
+ }
5761
+ // Between a cross-tab cell column's pivot value and its measure when the grid
5762
+ // has several measures ('2026-01-01 — revenue'), as the server names the
5763
+ // column (ReportListPivot::getCellColumn). With one measure the column is the
5764
+ // pivot value alone.
5765
+ const PIVOT_MEASURE_SEPARATOR = ' — ';
5709
5766
  // A cross-tab's column headings, the one rule the grid and the PDF/PowerPoint
5710
5767
  // exports share. The first is the row key and keeps its authored label; the
5711
- // rest are pivot VALUES. When the pivot axis is a time dimension the server
5712
- // sends the grain it bucketed at, so a period-start like "2026-01-01" reads
5713
- // "January 2026" ('janvier 2026' in fr-CA), as the chart's x-axis labels it.
5768
+ // rest are pivot VALUES, each read as the server labels the pivot column (an
5769
+ // enum's "consumerGoods" heads "Consumer Goods"). When the pivot axis is a
5770
+ // time dimension the server sends the grain it bucketed at, so a
5771
+ // period-start like "2026-01-01" reads "January 2026" ('janvier 2026' in
5772
+ // fr-CA), as the chart's x-axis labels it. A grid of several measures keeps
5773
+ // each column's measure after its value.
5714
5774
  function pivotHeadings(config, data, locale) {
5715
5775
  const columns = data.columns ?? [];
5716
- const multiYear = spansMultipleYears(columns);
5776
+ const severalMeasures = new Set(Object.values(data.cellMeasures ?? {})).size > 1;
5777
+ const cells = columns.slice(1)
5778
+ .map((column) => pivotCellParts(column, severalMeasures ? data.cellMeasures?.[column] : undefined));
5779
+ const multiYear = spansMultipleYears(cells.map((cell) => cell.value));
5717
5780
  return columns.map((column, index) => {
5718
5781
  if (index === 0) {
5719
5782
  return config.rowBy?.label || column;
5720
5783
  }
5721
- return data.granularity ? formatPeriodLabel(column, data.granularity, multiYear, locale) : column;
5784
+ const { value, measure } = cells[index - 1];
5785
+ const heading = valueLabel(data.valueLabels, config.pivotBy?.column, value)
5786
+ ?? (data.granularity ? formatPeriodLabel(value, data.granularity, multiYear, locale) : value);
5787
+ return `${heading}${measure}`;
5722
5788
  });
5723
5789
  }
5790
+ // A cross-tab cell column split into the pivot value it is named by and the
5791
+ // measure part after it ('' with one measure, or when `measure` does not end
5792
+ // the column).
5793
+ function pivotCellParts(column, measure) {
5794
+ const suffix = measure === undefined ? '' : `${PIVOT_MEASURE_SEPARATOR}${measure}`;
5795
+ return suffix && column.endsWith(suffix)
5796
+ ? { value: column.slice(0, -suffix.length), measure: suffix }
5797
+ : { value: column, measure: '' };
5798
+ }
5724
5799
  // A cross-tab's columns as the grid and the exports draw them: each headed by
5725
5800
  // pivotHeadings(), and every pivot-value column formatted by the one
5726
5801
  // config.cellFormat. The row key column stays as it came. `numeric` marks the
@@ -9375,9 +9450,10 @@ function chartPoints(component, data, context, extracted, dataIndex, series) {
9375
9450
  }
9376
9451
  return points;
9377
9452
  }
9378
- // The category as the rows hold it and as the axis wrote it. On a time axis
9379
- // it also gives the period's first day and the grain, and reads as the
9380
- // tooltip names it ('January 2026'); a pie writes its slices as they come.
9453
+ // The category as the rows hold it and as the axis wrote it (a labeled
9454
+ // column's label). On a time axis it also gives the period's first day and
9455
+ // the grain, and reads as the tooltip names it ('January 2026'); a pie's as
9456
+ // its legend names the slice (categoryLineLabels).
9381
9457
  function categoryPoint(config, data, context, extracted, column, dataIndex) {
9382
9458
  const raw = extracted.rawCategories[dataIndex];
9383
9459
  const label = extracted.categories[dataIndex];
@@ -9390,7 +9466,9 @@ function categoryPoint(config, data, context, extracted, column, dataIndex) {
9390
9466
  return {
9391
9467
  column,
9392
9468
  raw,
9393
- label: pie ? label : formatPeriodLabel(String(raw), grain, true, context.locale, chartDateLabel(config)),
9469
+ label: pie
9470
+ ? categoryLineLabels(extracted.categories, config, data, context.locale)[dataIndex] ?? label
9471
+ : formatPeriodLabel(String(raw), grain, true, context.locale, chartDateLabel(config)),
9394
9472
  period,
9395
9473
  grain,
9396
9474
  };
@@ -10431,6 +10509,12 @@ class ComponentListComponent {
10431
10509
  // the note above the list, the header tooltips and the output cells; null
10432
10510
  // until it arrives, and empty of every key for a list that has none.
10433
10511
  noteData = signal(null);
10512
+ // What each stored value of a labeled column reads as (an enum's, a
10513
+ // cross-tab's row key's), from the latest page 1: its cells show the label
10514
+ // (valueLabel), while the rows keep the value that sorts and filters. null
10515
+ // until it arrives, and for a list with none.
10516
+ valueLabels = signal(null);
10517
+ valueLabel = valueLabel;
10434
10518
  // How many rows the list shows (load more appends) out of how many its
10435
10519
  // filters keep. A cross-tab counts grid rows.
10436
10520
  rowCount = signal(null);
@@ -10600,6 +10684,7 @@ class ComponentListComponent {
10600
10684
  this.totals.set(data.totals ?? null);
10601
10685
  this.totalsNote.set(data.totalsNote ?? null);
10602
10686
  this.noteData.set(this._noteData(data));
10687
+ this.valueLabels.set(data.valueLabels ?? null);
10603
10688
  this._alignOutputColumns(data);
10604
10689
  }
10605
10690
  // The server's page size when it sends one (it clamps the request),
@@ -10700,7 +10785,7 @@ class ComponentListComponent {
10700
10785
  }
10701
10786
  }
10702
10787
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ComponentListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
10703
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: ComponentListComponent, isStandalone: true, selector: "app-report-component-list", inputs: { reportId: { classPropertyName: "reportId", publicName: "reportId", isSignal: true, isRequired: true, transformFunction: null }, component: { classPropertyName: "component", publicName: "component", isSignal: true, isRequired: true, transformFunction: null } }, viewQueries: [{ propertyName: "listComponent", first: true, predicate: FsListComponent, descendants: true, isSignal: true }], ngImport: i0, template: "@if (truncated()) {\n <div class=\"pivot-truncated\">\n This grid was built from a partial result, so some columns or values may be missing. Narrow it with a filter.\n </div>\n}\n\n<!-- The windows a comparison compares, and why it reads as it does. A\n windowed column's own notes are in its header's tooltip. -->\n<app-report-component-note\n [data]=\"noteData()\"\n [windowNotes]=\"false\">\n</app-report-component-note>\n\n<!-- fs-list reads a column's footer template once, as a direct child of\n fs-list-column, so a list with totals renders its columns in a branch of\n their own rather than wrapping the footer in an @if. Its header template too,\n which every column carries: an output column's tooltip says what it holds.\n Columns are tracked by alignment as well as name, since fs-list reads a\n column's alignment only when it builds the column. -->\n<fs-list\n [config]=\"listConfig\"\n [class.report-totals-empty]=\"!totals()\">\n @if (showTotals()) {\n @for (column of columns(); track column.column + ':' + column.numeric) {\n <fs-list-column\n [name]=\"column.column\"\n [title]=\"column.label || column.column\"\n [show]=\"!hidden().has(column.column)\"\n [sortable]=\"!pivoted() || $first\"\n [align]=\"column.numeric ? 'right' : 'left'\"\n [class]=\"columnClasses(column, $index, pinned())\">\n <ng-template fs-list-header>\n <ng-container\n [ngTemplateOutlet]=\"headerTpl\"\n [ngTemplateOutletContext]=\"{ column: column }\">\n </ng-container>\n </ng-template>\n <ng-template\n fs-list-cell\n let-row=\"row\">\n <ng-container\n [ngTemplateOutlet]=\"cellTpl\"\n [ngTemplateOutletContext]=\"{ $implicit: row[column.column], row: row, column: column }\">\n </ng-container>\n </ng-template>\n <ng-template fs-list-footer>\n @if (totals()?.[column.column] !== undefined) {\n <ng-container\n [ngTemplateOutlet]=\"cellTpl\"\n [ngTemplateOutletContext]=\"{ $implicit: totals()?.[column.column], row: totals(), column: column }\">\n </ng-container>\n } @else if (column.column === totalsLabelColumn()) {\n {{ totalLabel }}\n }\n </ng-template>\n </fs-list-column>\n }\n } @else {\n @for (column of columns(); track column.column + ':' + column.numeric) {\n <fs-list-column\n [name]=\"column.column\"\n [title]=\"column.label || column.column\"\n [show]=\"!hidden().has(column.column)\"\n [sortable]=\"!pivoted() || $first\"\n [align]=\"column.numeric ? 'right' : 'left'\"\n [class]=\"columnClasses(column, $index, pinned())\">\n <ng-template fs-list-header>\n <ng-container\n [ngTemplateOutlet]=\"headerTpl\"\n [ngTemplateOutletContext]=\"{ column: column }\">\n </ng-container>\n </ng-template>\n <ng-template\n fs-list-cell\n let-row=\"row\">\n <ng-container\n [ngTemplateOutlet]=\"cellTpl\"\n [ngTemplateOutletContext]=\"{ $implicit: row[column.column], row: row, column: column }\">\n </ng-container>\n </ng-template>\n </fs-list-column>\n }\n }\n</fs-list>\n\n@if (caption()) {\n <div class=\"list-caption small\">\n {{ caption() }}\n </div>\n}\n\n<!-- A column's heading, with what an output column holds as its tooltip (an\n empty one never shows). -->\n<ng-template\n #headerTpl\n let-column=\"column\">\n <span [matTooltip]=\"columnNotes()[column.column] ?? ''\">{{ column.label || column.column }}</span>\n</ng-template>\n\n<!-- One cell, in the body and the totals row alike: an output column by what\n it holds (its row gives a change its prior), a date column as a day in the\n report's zone and locale, any other through its number format. -->\n<ng-template\n #cellTpl\n let-value\n let-row=\"row\"\n let-column=\"column\">\n @if (outputColumns()[column.column]; as output) {\n @if (row | fsReportOutput: column : output : formatContext(); as cell) {\n <span [attr.title]=\"cell.title\">{{ cell.text }}</span>\n }\n } @else if (column.format === ReportListColumnFormat.Date) {\n {{ value | fsReportDate: timezone() : formatContext().locale }}\n } @else {\n {{ value | fsReportNumber: column : formatContext() }}\n }\n</ng-template>\n", styles: [":host{display:flex;flex-direction:column;width:100%;height:100%;min-height:0}:host ::ng-deep fs-list{display:flex;flex-direction:column;flex:1 1 auto;height:auto;min-height:0}:host ::ng-deep fs-list .fs-list-container{display:flex;flex-direction:column;flex:1 1 auto;min-height:0;height:100%}:host ::ng-deep fs-list .fs-list-header-container{flex:0 0 auto}:host ::ng-deep fs-list .fs-list-container .fs-list-table-container{flex:1 1 auto;min-height:0;overflow-y:auto!important}:host ::ng-deep fs-list .fs-list-table thead th{position:sticky;top:0;z-index:1;background-color:#fff}:host ::ng-deep fs-list .fs-list-table tfoot td{position:sticky;bottom:0;z-index:1;background-color:#fff;font-weight:500;box-shadow:inset 0 1px #0000001f}:host ::ng-deep fs-list.report-totals-empty tfoot{display:none}:host ::ng-deep fs-list .report-pinned{position:sticky;left:var(--report-pin-left, 0px);z-index:1;background-color:#fff}:host ::ng-deep fs-list .report-pin-0{--report-pin-left: var(--report-pin-left-0, 0px)}:host ::ng-deep fs-list .report-pin-1{--report-pin-left: var(--report-pin-left-1, 0px)}:host ::ng-deep fs-list .report-pin-2{--report-pin-left: var(--report-pin-left-2, 0px)}:host ::ng-deep fs-list .report-pin-last{box-shadow:inset -1px 0 #0000001f}:host ::ng-deep fs-list .fs-list-table thead th.report-pinned{z-index:3}:host ::ng-deep fs-list .fs-list-table tfoot td.report-pinned{z-index:2}:host ::ng-deep fs-list .fs-list-table tfoot td.report-pin-last{box-shadow:inset -1px 0 #0000001f,inset 0 1px #0000001f}:host ::ng-deep fs-list th.report-nowrap,:host ::ng-deep fs-list td.report-nowrap{white-space:nowrap}:host ::ng-deep fs-list fs-list-pagination{flex:0 0 auto}:host ::ng-deep fs-list .fs-list-load-more{position:sticky;bottom:0;background-color:#fff}:host ::ng-deep fs-list .fs-list-load-more button{margin-top:0}.list-caption{flex:0 0 auto;padding-top:4px}.pivot-truncated{flex:0 0 auto;padding:8px 12px;margin-bottom:8px;border-radius:4px;background-color:#fff4e5;color:#663c00}\n"], dependencies: [{ kind: "component", type: ComponentNoteComponent, selector: "app-report-component-note", inputs: ["data", "windows", "windowDescriptions", "windowNotes"] }, { kind: "ngmodule", type: FsListModule }, { kind: "component", type: i1$4.FsListComponent, selector: "fs-list", inputs: ["config", "loaderLines", "cellRowType"], outputs: ["filtersReady"] }, { kind: "directive", type: i1$4.FsListColumnDirective, selector: "fs-list-column", inputs: ["show", "title", "name", "customizable", "sortable", "sortableDefault", "sortableDirection", "direction", "align", "width", "class"] }, { kind: "directive", type: i1$4.FsListCellDirective, selector: "[fs-list-cell],[fsListCell]", inputs: ["colspan", "align", "class", "fsListCell", "configTyping"] }, { kind: "directive", type: i1$4.FsListHeaderDirective, selector: "[fs-list-header]", inputs: ["colspan", "align", "class"] }, { kind: "directive", type: i1$4.FsListFooterDirective, selector: "[fs-list-footer]", inputs: ["colspan", "align", "class"] }, { kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: ReportDatePipe, name: "fsReportDate" }, { kind: "pipe", type: ReportNumberPipe, name: "fsReportNumber" }, { kind: "pipe", type: ReportOutputPipe, name: "fsReportOutput" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
10788
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: ComponentListComponent, isStandalone: true, selector: "app-report-component-list", inputs: { reportId: { classPropertyName: "reportId", publicName: "reportId", isSignal: true, isRequired: true, transformFunction: null }, component: { classPropertyName: "component", publicName: "component", isSignal: true, isRequired: true, transformFunction: null } }, viewQueries: [{ propertyName: "listComponent", first: true, predicate: FsListComponent, descendants: true, isSignal: true }], ngImport: i0, template: "@if (truncated()) {\n <div class=\"pivot-truncated\">\n This grid was built from a partial result, so some columns or values may be missing. Narrow it with a filter.\n </div>\n}\n\n<!-- The windows a comparison compares, and why it reads as it does. A\n windowed column's own notes are in its header's tooltip. -->\n<app-report-component-note\n [data]=\"noteData()\"\n [windowNotes]=\"false\">\n</app-report-component-note>\n\n<!-- fs-list reads a column's footer template once, as a direct child of\n fs-list-column, so a list with totals renders its columns in a branch of\n their own rather than wrapping the footer in an @if. Its header template too,\n which every column carries: an output column's tooltip says what it holds.\n Columns are tracked by alignment as well as name, since fs-list reads a\n column's alignment only when it builds the column. -->\n<fs-list\n [config]=\"listConfig\"\n [class.report-totals-empty]=\"!totals()\">\n @if (showTotals()) {\n @for (column of columns(); track column.column + ':' + column.numeric) {\n <fs-list-column\n [name]=\"column.column\"\n [title]=\"column.label || column.column\"\n [show]=\"!hidden().has(column.column)\"\n [sortable]=\"!pivoted() || $first\"\n [align]=\"column.numeric ? 'right' : 'left'\"\n [class]=\"columnClasses(column, $index, pinned())\">\n <ng-template fs-list-header>\n <ng-container\n [ngTemplateOutlet]=\"headerTpl\"\n [ngTemplateOutletContext]=\"{ column: column }\">\n </ng-container>\n </ng-template>\n <ng-template\n fs-list-cell\n let-row=\"row\">\n <ng-container\n [ngTemplateOutlet]=\"cellTpl\"\n [ngTemplateOutletContext]=\"{ $implicit: row[column.column], row: row, column: column }\">\n </ng-container>\n </ng-template>\n <ng-template fs-list-footer>\n @if (totals()?.[column.column] !== undefined) {\n <ng-container\n [ngTemplateOutlet]=\"cellTpl\"\n [ngTemplateOutletContext]=\"{ $implicit: totals()?.[column.column], row: totals(), column: column }\">\n </ng-container>\n } @else if (column.column === totalsLabelColumn()) {\n {{ totalLabel }}\n }\n </ng-template>\n </fs-list-column>\n }\n } @else {\n @for (column of columns(); track column.column + ':' + column.numeric) {\n <fs-list-column\n [name]=\"column.column\"\n [title]=\"column.label || column.column\"\n [show]=\"!hidden().has(column.column)\"\n [sortable]=\"!pivoted() || $first\"\n [align]=\"column.numeric ? 'right' : 'left'\"\n [class]=\"columnClasses(column, $index, pinned())\">\n <ng-template fs-list-header>\n <ng-container\n [ngTemplateOutlet]=\"headerTpl\"\n [ngTemplateOutletContext]=\"{ column: column }\">\n </ng-container>\n </ng-template>\n <ng-template\n fs-list-cell\n let-row=\"row\">\n <ng-container\n [ngTemplateOutlet]=\"cellTpl\"\n [ngTemplateOutletContext]=\"{ $implicit: row[column.column], row: row, column: column }\">\n </ng-container>\n </ng-template>\n </fs-list-column>\n }\n }\n</fs-list>\n\n@if (caption()) {\n <div class=\"list-caption small\">\n {{ caption() }}\n </div>\n}\n\n<!-- A column's heading, with what an output column holds as its tooltip (an\n empty one never shows). -->\n<ng-template\n #headerTpl\n let-column=\"column\">\n <span [matTooltip]=\"columnNotes()[column.column] ?? ''\">{{ column.label || column.column }}</span>\n</ng-template>\n\n<!-- One cell, in the body and the totals row alike: an output column by what\n it holds (its row gives a change its prior), a date column as a day in the\n report's zone and locale, a labeled column's value as its label, any other\n through its number format. -->\n<ng-template\n #cellTpl\n let-value\n let-row=\"row\"\n let-column=\"column\">\n @if (outputColumns()[column.column]; as output) {\n @if (row | fsReportOutput: column : output : formatContext(); as cell) {\n <span [attr.title]=\"cell.title\">{{ cell.text }}</span>\n }\n } @else if (column.format === ReportListColumnFormat.Date) {\n {{ value | fsReportDate: timezone() : formatContext().locale }}\n } @else {\n {{ valueLabel(valueLabels(), column.column, value) ?? (value | fsReportNumber: column : formatContext()) }}\n }\n</ng-template>\n", styles: [":host{display:flex;flex-direction:column;width:100%;height:100%;min-height:0}:host ::ng-deep fs-list{display:flex;flex-direction:column;flex:1 1 auto;height:auto;min-height:0}:host ::ng-deep fs-list .fs-list-container{display:flex;flex-direction:column;flex:1 1 auto;min-height:0;height:100%}:host ::ng-deep fs-list .fs-list-header-container{flex:0 0 auto}:host ::ng-deep fs-list .fs-list-container .fs-list-table-container{flex:1 1 auto;min-height:0;overflow-y:auto!important}:host ::ng-deep fs-list .fs-list-table thead th{position:sticky;top:0;z-index:1;background-color:#fff}:host ::ng-deep fs-list .fs-list-table tfoot td{position:sticky;bottom:0;z-index:1;background-color:#fff;font-weight:500;box-shadow:inset 0 1px #0000001f}:host ::ng-deep fs-list.report-totals-empty tfoot{display:none}:host ::ng-deep fs-list .report-pinned{position:sticky;left:var(--report-pin-left, 0px);z-index:1;background-color:#fff}:host ::ng-deep fs-list .report-pin-0{--report-pin-left: var(--report-pin-left-0, 0px)}:host ::ng-deep fs-list .report-pin-1{--report-pin-left: var(--report-pin-left-1, 0px)}:host ::ng-deep fs-list .report-pin-2{--report-pin-left: var(--report-pin-left-2, 0px)}:host ::ng-deep fs-list .report-pin-last{box-shadow:inset -1px 0 #0000001f}:host ::ng-deep fs-list .fs-list-table thead th.report-pinned{z-index:3}:host ::ng-deep fs-list .fs-list-table tfoot td.report-pinned{z-index:2}:host ::ng-deep fs-list .fs-list-table tfoot td.report-pin-last{box-shadow:inset -1px 0 #0000001f,inset 0 1px #0000001f}:host ::ng-deep fs-list th.report-nowrap,:host ::ng-deep fs-list td.report-nowrap{white-space:nowrap}:host ::ng-deep fs-list fs-list-pagination{flex:0 0 auto}:host ::ng-deep fs-list .fs-list-load-more{position:sticky;bottom:0;background-color:#fff}:host ::ng-deep fs-list .fs-list-load-more button{margin-top:0}.list-caption{flex:0 0 auto;padding-top:4px}.pivot-truncated{flex:0 0 auto;padding:8px 12px;margin-bottom:8px;border-radius:4px;background-color:#fff4e5;color:#663c00}\n"], dependencies: [{ kind: "component", type: ComponentNoteComponent, selector: "app-report-component-note", inputs: ["data", "windows", "windowDescriptions", "windowNotes"] }, { kind: "ngmodule", type: FsListModule }, { kind: "component", type: i1$4.FsListComponent, selector: "fs-list", inputs: ["config", "loaderLines", "cellRowType"], outputs: ["filtersReady"] }, { kind: "directive", type: i1$4.FsListColumnDirective, selector: "fs-list-column", inputs: ["show", "title", "name", "customizable", "sortable", "sortableDefault", "sortableDirection", "direction", "align", "width", "class"] }, { kind: "directive", type: i1$4.FsListCellDirective, selector: "[fs-list-cell],[fsListCell]", inputs: ["colspan", "align", "class", "fsListCell", "configTyping"] }, { kind: "directive", type: i1$4.FsListHeaderDirective, selector: "[fs-list-header]", inputs: ["colspan", "align", "class"] }, { kind: "directive", type: i1$4.FsListFooterDirective, selector: "[fs-list-footer]", inputs: ["colspan", "align", "class"] }, { kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: ReportDatePipe, name: "fsReportDate" }, { kind: "pipe", type: ReportNumberPipe, name: "fsReportNumber" }, { kind: "pipe", type: ReportOutputPipe, name: "fsReportOutput" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
10704
10789
  }
10705
10790
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ComponentListComponent, decorators: [{
10706
10791
  type: Component,
@@ -10712,7 +10797,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
10712
10797
  ReportDatePipe,
10713
10798
  ReportNumberPipe,
10714
10799
  ReportOutputPipe,
10715
- ], template: "@if (truncated()) {\n <div class=\"pivot-truncated\">\n This grid was built from a partial result, so some columns or values may be missing. Narrow it with a filter.\n </div>\n}\n\n<!-- The windows a comparison compares, and why it reads as it does. A\n windowed column's own notes are in its header's tooltip. -->\n<app-report-component-note\n [data]=\"noteData()\"\n [windowNotes]=\"false\">\n</app-report-component-note>\n\n<!-- fs-list reads a column's footer template once, as a direct child of\n fs-list-column, so a list with totals renders its columns in a branch of\n their own rather than wrapping the footer in an @if. Its header template too,\n which every column carries: an output column's tooltip says what it holds.\n Columns are tracked by alignment as well as name, since fs-list reads a\n column's alignment only when it builds the column. -->\n<fs-list\n [config]=\"listConfig\"\n [class.report-totals-empty]=\"!totals()\">\n @if (showTotals()) {\n @for (column of columns(); track column.column + ':' + column.numeric) {\n <fs-list-column\n [name]=\"column.column\"\n [title]=\"column.label || column.column\"\n [show]=\"!hidden().has(column.column)\"\n [sortable]=\"!pivoted() || $first\"\n [align]=\"column.numeric ? 'right' : 'left'\"\n [class]=\"columnClasses(column, $index, pinned())\">\n <ng-template fs-list-header>\n <ng-container\n [ngTemplateOutlet]=\"headerTpl\"\n [ngTemplateOutletContext]=\"{ column: column }\">\n </ng-container>\n </ng-template>\n <ng-template\n fs-list-cell\n let-row=\"row\">\n <ng-container\n [ngTemplateOutlet]=\"cellTpl\"\n [ngTemplateOutletContext]=\"{ $implicit: row[column.column], row: row, column: column }\">\n </ng-container>\n </ng-template>\n <ng-template fs-list-footer>\n @if (totals()?.[column.column] !== undefined) {\n <ng-container\n [ngTemplateOutlet]=\"cellTpl\"\n [ngTemplateOutletContext]=\"{ $implicit: totals()?.[column.column], row: totals(), column: column }\">\n </ng-container>\n } @else if (column.column === totalsLabelColumn()) {\n {{ totalLabel }}\n }\n </ng-template>\n </fs-list-column>\n }\n } @else {\n @for (column of columns(); track column.column + ':' + column.numeric) {\n <fs-list-column\n [name]=\"column.column\"\n [title]=\"column.label || column.column\"\n [show]=\"!hidden().has(column.column)\"\n [sortable]=\"!pivoted() || $first\"\n [align]=\"column.numeric ? 'right' : 'left'\"\n [class]=\"columnClasses(column, $index, pinned())\">\n <ng-template fs-list-header>\n <ng-container\n [ngTemplateOutlet]=\"headerTpl\"\n [ngTemplateOutletContext]=\"{ column: column }\">\n </ng-container>\n </ng-template>\n <ng-template\n fs-list-cell\n let-row=\"row\">\n <ng-container\n [ngTemplateOutlet]=\"cellTpl\"\n [ngTemplateOutletContext]=\"{ $implicit: row[column.column], row: row, column: column }\">\n </ng-container>\n </ng-template>\n </fs-list-column>\n }\n }\n</fs-list>\n\n@if (caption()) {\n <div class=\"list-caption small\">\n {{ caption() }}\n </div>\n}\n\n<!-- A column's heading, with what an output column holds as its tooltip (an\n empty one never shows). -->\n<ng-template\n #headerTpl\n let-column=\"column\">\n <span [matTooltip]=\"columnNotes()[column.column] ?? ''\">{{ column.label || column.column }}</span>\n</ng-template>\n\n<!-- One cell, in the body and the totals row alike: an output column by what\n it holds (its row gives a change its prior), a date column as a day in the\n report's zone and locale, any other through its number format. -->\n<ng-template\n #cellTpl\n let-value\n let-row=\"row\"\n let-column=\"column\">\n @if (outputColumns()[column.column]; as output) {\n @if (row | fsReportOutput: column : output : formatContext(); as cell) {\n <span [attr.title]=\"cell.title\">{{ cell.text }}</span>\n }\n } @else if (column.format === ReportListColumnFormat.Date) {\n {{ value | fsReportDate: timezone() : formatContext().locale }}\n } @else {\n {{ value | fsReportNumber: column : formatContext() }}\n }\n</ng-template>\n", styles: [":host{display:flex;flex-direction:column;width:100%;height:100%;min-height:0}:host ::ng-deep fs-list{display:flex;flex-direction:column;flex:1 1 auto;height:auto;min-height:0}:host ::ng-deep fs-list .fs-list-container{display:flex;flex-direction:column;flex:1 1 auto;min-height:0;height:100%}:host ::ng-deep fs-list .fs-list-header-container{flex:0 0 auto}:host ::ng-deep fs-list .fs-list-container .fs-list-table-container{flex:1 1 auto;min-height:0;overflow-y:auto!important}:host ::ng-deep fs-list .fs-list-table thead th{position:sticky;top:0;z-index:1;background-color:#fff}:host ::ng-deep fs-list .fs-list-table tfoot td{position:sticky;bottom:0;z-index:1;background-color:#fff;font-weight:500;box-shadow:inset 0 1px #0000001f}:host ::ng-deep fs-list.report-totals-empty tfoot{display:none}:host ::ng-deep fs-list .report-pinned{position:sticky;left:var(--report-pin-left, 0px);z-index:1;background-color:#fff}:host ::ng-deep fs-list .report-pin-0{--report-pin-left: var(--report-pin-left-0, 0px)}:host ::ng-deep fs-list .report-pin-1{--report-pin-left: var(--report-pin-left-1, 0px)}:host ::ng-deep fs-list .report-pin-2{--report-pin-left: var(--report-pin-left-2, 0px)}:host ::ng-deep fs-list .report-pin-last{box-shadow:inset -1px 0 #0000001f}:host ::ng-deep fs-list .fs-list-table thead th.report-pinned{z-index:3}:host ::ng-deep fs-list .fs-list-table tfoot td.report-pinned{z-index:2}:host ::ng-deep fs-list .fs-list-table tfoot td.report-pin-last{box-shadow:inset -1px 0 #0000001f,inset 0 1px #0000001f}:host ::ng-deep fs-list th.report-nowrap,:host ::ng-deep fs-list td.report-nowrap{white-space:nowrap}:host ::ng-deep fs-list fs-list-pagination{flex:0 0 auto}:host ::ng-deep fs-list .fs-list-load-more{position:sticky;bottom:0;background-color:#fff}:host ::ng-deep fs-list .fs-list-load-more button{margin-top:0}.list-caption{flex:0 0 auto;padding-top:4px}.pivot-truncated{flex:0 0 auto;padding:8px 12px;margin-bottom:8px;border-radius:4px;background-color:#fff4e5;color:#663c00}\n"] }]
10800
+ ], template: "@if (truncated()) {\n <div class=\"pivot-truncated\">\n This grid was built from a partial result, so some columns or values may be missing. Narrow it with a filter.\n </div>\n}\n\n<!-- The windows a comparison compares, and why it reads as it does. A\n windowed column's own notes are in its header's tooltip. -->\n<app-report-component-note\n [data]=\"noteData()\"\n [windowNotes]=\"false\">\n</app-report-component-note>\n\n<!-- fs-list reads a column's footer template once, as a direct child of\n fs-list-column, so a list with totals renders its columns in a branch of\n their own rather than wrapping the footer in an @if. Its header template too,\n which every column carries: an output column's tooltip says what it holds.\n Columns are tracked by alignment as well as name, since fs-list reads a\n column's alignment only when it builds the column. -->\n<fs-list\n [config]=\"listConfig\"\n [class.report-totals-empty]=\"!totals()\">\n @if (showTotals()) {\n @for (column of columns(); track column.column + ':' + column.numeric) {\n <fs-list-column\n [name]=\"column.column\"\n [title]=\"column.label || column.column\"\n [show]=\"!hidden().has(column.column)\"\n [sortable]=\"!pivoted() || $first\"\n [align]=\"column.numeric ? 'right' : 'left'\"\n [class]=\"columnClasses(column, $index, pinned())\">\n <ng-template fs-list-header>\n <ng-container\n [ngTemplateOutlet]=\"headerTpl\"\n [ngTemplateOutletContext]=\"{ column: column }\">\n </ng-container>\n </ng-template>\n <ng-template\n fs-list-cell\n let-row=\"row\">\n <ng-container\n [ngTemplateOutlet]=\"cellTpl\"\n [ngTemplateOutletContext]=\"{ $implicit: row[column.column], row: row, column: column }\">\n </ng-container>\n </ng-template>\n <ng-template fs-list-footer>\n @if (totals()?.[column.column] !== undefined) {\n <ng-container\n [ngTemplateOutlet]=\"cellTpl\"\n [ngTemplateOutletContext]=\"{ $implicit: totals()?.[column.column], row: totals(), column: column }\">\n </ng-container>\n } @else if (column.column === totalsLabelColumn()) {\n {{ totalLabel }}\n }\n </ng-template>\n </fs-list-column>\n }\n } @else {\n @for (column of columns(); track column.column + ':' + column.numeric) {\n <fs-list-column\n [name]=\"column.column\"\n [title]=\"column.label || column.column\"\n [show]=\"!hidden().has(column.column)\"\n [sortable]=\"!pivoted() || $first\"\n [align]=\"column.numeric ? 'right' : 'left'\"\n [class]=\"columnClasses(column, $index, pinned())\">\n <ng-template fs-list-header>\n <ng-container\n [ngTemplateOutlet]=\"headerTpl\"\n [ngTemplateOutletContext]=\"{ column: column }\">\n </ng-container>\n </ng-template>\n <ng-template\n fs-list-cell\n let-row=\"row\">\n <ng-container\n [ngTemplateOutlet]=\"cellTpl\"\n [ngTemplateOutletContext]=\"{ $implicit: row[column.column], row: row, column: column }\">\n </ng-container>\n </ng-template>\n </fs-list-column>\n }\n }\n</fs-list>\n\n@if (caption()) {\n <div class=\"list-caption small\">\n {{ caption() }}\n </div>\n}\n\n<!-- A column's heading, with what an output column holds as its tooltip (an\n empty one never shows). -->\n<ng-template\n #headerTpl\n let-column=\"column\">\n <span [matTooltip]=\"columnNotes()[column.column] ?? ''\">{{ column.label || column.column }}</span>\n</ng-template>\n\n<!-- One cell, in the body and the totals row alike: an output column by what\n it holds (its row gives a change its prior), a date column as a day in the\n report's zone and locale, a labeled column's value as its label, any other\n through its number format. -->\n<ng-template\n #cellTpl\n let-value\n let-row=\"row\"\n let-column=\"column\">\n @if (outputColumns()[column.column]; as output) {\n @if (row | fsReportOutput: column : output : formatContext(); as cell) {\n <span [attr.title]=\"cell.title\">{{ cell.text }}</span>\n }\n } @else if (column.format === ReportListColumnFormat.Date) {\n {{ value | fsReportDate: timezone() : formatContext().locale }}\n } @else {\n {{ valueLabel(valueLabels(), column.column, value) ?? (value | fsReportNumber: column : formatContext()) }}\n }\n</ng-template>\n", styles: [":host{display:flex;flex-direction:column;width:100%;height:100%;min-height:0}:host ::ng-deep fs-list{display:flex;flex-direction:column;flex:1 1 auto;height:auto;min-height:0}:host ::ng-deep fs-list .fs-list-container{display:flex;flex-direction:column;flex:1 1 auto;min-height:0;height:100%}:host ::ng-deep fs-list .fs-list-header-container{flex:0 0 auto}:host ::ng-deep fs-list .fs-list-container .fs-list-table-container{flex:1 1 auto;min-height:0;overflow-y:auto!important}:host ::ng-deep fs-list .fs-list-table thead th{position:sticky;top:0;z-index:1;background-color:#fff}:host ::ng-deep fs-list .fs-list-table tfoot td{position:sticky;bottom:0;z-index:1;background-color:#fff;font-weight:500;box-shadow:inset 0 1px #0000001f}:host ::ng-deep fs-list.report-totals-empty tfoot{display:none}:host ::ng-deep fs-list .report-pinned{position:sticky;left:var(--report-pin-left, 0px);z-index:1;background-color:#fff}:host ::ng-deep fs-list .report-pin-0{--report-pin-left: var(--report-pin-left-0, 0px)}:host ::ng-deep fs-list .report-pin-1{--report-pin-left: var(--report-pin-left-1, 0px)}:host ::ng-deep fs-list .report-pin-2{--report-pin-left: var(--report-pin-left-2, 0px)}:host ::ng-deep fs-list .report-pin-last{box-shadow:inset -1px 0 #0000001f}:host ::ng-deep fs-list .fs-list-table thead th.report-pinned{z-index:3}:host ::ng-deep fs-list .fs-list-table tfoot td.report-pinned{z-index:2}:host ::ng-deep fs-list .fs-list-table tfoot td.report-pin-last{box-shadow:inset -1px 0 #0000001f,inset 0 1px #0000001f}:host ::ng-deep fs-list th.report-nowrap,:host ::ng-deep fs-list td.report-nowrap{white-space:nowrap}:host ::ng-deep fs-list fs-list-pagination{flex:0 0 auto}:host ::ng-deep fs-list .fs-list-load-more{position:sticky;bottom:0;background-color:#fff}:host ::ng-deep fs-list .fs-list-load-more button{margin-top:0}.list-caption{flex:0 0 auto;padding-top:4px}.pivot-truncated{flex:0 0 auto;padding:8px 12px;margin-bottom:8px;border-radius:4px;background-color:#fff4e5;color:#663c00}\n"] }]
10716
10801
  }], ctorParameters: () => [] });
10717
10802
 
10718
10803
  // How a value chip is marked in the editor. The names follow the embeds of
@@ -15258,15 +15343,17 @@ function coverLines(collected) {
15258
15343
  // An exported list cell, reading like the on-screen cell, through the same
15259
15344
  // functions as the screen: a date column renders in the report's zone and
15260
15345
  // locale, and a column with number-format keys (a cross-tab's cells through
15261
- // its cellFormat) in the report's locale and currency. Any other value goes
15262
- // out verbatim, and an empty one as ''. CSV never comes through here: its
15263
- // values stay raw.
15346
+ // its cellFormat) in the report's locale and currency. A value of a column
15347
+ // the data labels (`labels`, ComponentData.valueLabels: an enum's, a
15348
+ // cross-tab's row key's) reads as its label. Any other value goes out
15349
+ // verbatim, and an empty one as ''. CSV never comes through here: the server
15350
+ // writes it, labels included.
15264
15351
  //
15265
15352
  // An output column is written by what it holds, as the screen's cell is
15266
15353
  // (formatOutputValue): a signed change, a percent change, a change of a rate
15267
15354
  // in points, a rank, a share. Its row gives a change the prior beside it, so
15268
15355
  // a missing baseline ('—') reads apart from a zero one ('n/a').
15269
- function exportCell(value, column, timezone, context, row) {
15356
+ function exportCell(value, column, timezone, context, row, labels) {
15270
15357
  const output = column.output;
15271
15358
  if (output) {
15272
15359
  return formatOutputValue(value, output.output, column, context, {
@@ -15282,13 +15369,15 @@ function exportCell(value, column, timezone, context, row) {
15282
15369
  if (column.format === ReportListColumnFormat.Date) {
15283
15370
  return formatReportDate(value, timezone, context.locale);
15284
15371
  }
15285
- return hasNumberFormat(column) ? formatNumber(value, column, context, { empty: '' }) : String(value);
15372
+ return valueLabel(labels, column.column, value)
15373
+ ?? (hasNumberFormat(column) ? formatNumber(value, column, context, { empty: '' }) : String(value));
15286
15374
  }
15287
15375
  // The columns an exported list table draws. A cross-tab's arrive with its
15288
15376
  // rows (the row key first, then one per pivot value), since only the result
15289
15377
  // knows the pivot values, and are built by pivotColumnSpecs() as on screen:
15290
- // headed by its periods in the report's locale, each pivot value formatted by
15291
- // cellFormat. A plain list draws its configured columns but the ones the
15378
+ // headed by its pivot values as pivotHeadings() reads them (their labels, its
15379
+ // periods in the report's locale), each pivot value formatted by cellFormat.
15380
+ // A plain list draws its configured columns but the ones the
15292
15381
  // viewer hid (`hidden`, kept to listHiddenColumns, so never all of them),
15293
15382
  // else every column the query returned, as it came. Output columns (the
15294
15383
  // data's outputs, a cross-tab cell through cellMeasures) carry how they are
@@ -15850,7 +15939,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
15850
15939
  // in the report's format context, as on screen.
15851
15940
  async function renderChartImage(component, data, width, height, context, pixelRatio = 3) {
15852
15941
  // The same tree-shaken echarts build + 'report' theme the live canvas uses.
15853
- const echarts = (await import('./firestitch-report-echarts-CBBTk1Ql.mjs')).default;
15942
+ const echarts = (await import('./firestitch-report-echarts-D7WNr0Z4.mjs')).default;
15854
15943
  const host = document.createElement('div');
15855
15944
  host.style.width = `${width}px`;
15856
15945
  host.style.height = `${height}px`;
@@ -16801,7 +16890,7 @@ class ReportPdfService {
16801
16890
  // totals row (null without one). The columns the viewer hid are left out.
16802
16891
  _tableCells(context, component, data, hiddenColumns) {
16803
16892
  const columns = listColumns(component, data, context.formatContext.locale, hiddenColumns);
16804
- const cells = data.rows.map((row) => columns.map((column) => this._pdfText(exportCell(row[column.column], column, context.timezone, context.formatContext, row))));
16893
+ const cells = data.rows.map((row) => columns.map((column) => this._pdfText(exportCell(row[column.column], column, context.timezone, context.formatContext, row, data.valueLabels))));
16805
16894
  const foot = listTotalsRow(data, columns, context.timezone, context.formatContext);
16806
16895
  return {
16807
16896
  cells,
@@ -17691,7 +17780,9 @@ class ReportPptxService {
17691
17780
  };
17692
17781
  const pie = chartType === 'pie' || chartType === 'donut';
17693
17782
  const colorBy = isColorBy(config);
17694
- const labels = this._categoryLabels(extracted.categories, data.granularity, context.locale, chartDateLabel(config));
17783
+ // Compact period labels, as the screen's pie names its slices: PowerPoint
17784
+ // can't do the axis's styled second line, so the year is inline.
17785
+ const labels = categoryLineLabels(extracted.categories, config, data, context.locale);
17695
17786
  // A 100% stacked chart's primary bars and areas plot the shares the screen
17696
17787
  // draws, stacked: PowerPoint's own percentStacked grouping is dropped on an
17697
17788
  // area chart, so one rule covers both. The data sheet holds the shares;
@@ -18098,7 +18189,7 @@ class ReportPptxService {
18098
18189
  const config = component.config;
18099
18190
  const waterfall = extractWaterfall(component, data);
18100
18191
  const measure = config.measures?.[0];
18101
- const labels = this._categoryLabels(waterfall.steps.map((step) => step.category), data.granularity, context.locale, chartDateLabel(config));
18192
+ const labels = categoryLineLabels(waterfall.steps.map((step) => step.category), config, data, context.locale);
18102
18193
  const series = this._waterfallSeries(waterfall.steps);
18103
18194
  // The references are constant lines beside the stacked bars, on the one
18104
18195
  // value axis. Without any the chart is the one stacked bar chart, without
@@ -18165,17 +18256,6 @@ class ReportPptxService {
18165
18256
  }
18166
18257
  return [base, ...[...above, ...below].filter((entry) => entry.values.some((value) => value !== null))];
18167
18258
  }
18168
- // Compact period labels match the on-screen axis, in the report's locale and
18169
- // the axis's date label style (a short label takes its year only when the
18170
- // data spans years); PowerPoint can't do a styled second line, so it's
18171
- // inline.
18172
- _categoryLabels(categories, granularity, locale, dateLabel) {
18173
- if (!granularity) {
18174
- return categories;
18175
- }
18176
- const multiYear = spansMultipleYears(categories);
18177
- return categories.map((category) => formatPeriodLabel(category, granularity, multiYear, locale, dateLabel));
18178
- }
18179
18259
  // The axis label and title settings of a chart with one value axis, and that
18180
18260
  // axis's range (valueAxis). A pie has no value axis to title. Without a
18181
18261
  // valueAxis.label the value axis is titled by the first measure's label, as
@@ -18231,13 +18311,14 @@ class ReportPptxService {
18231
18311
  options: { bold: true, color: 'FFFFFF', fill: { color: '4E79A7' }, ...align(index) },
18232
18312
  }));
18233
18313
  // A date or formatted-number cell is a value written in the report's
18234
- // locale; every other cell prints the query's text as it came.
18314
+ // locale; every other cell prints the query's text as it came, or its
18315
+ // label (exportCell).
18235
18316
  const valueLocale = (index) => {
18236
18317
  const column = columns[index];
18237
18318
  return column.numeric || column.format === ReportListColumnFormat.Date ? context.locale : undefined;
18238
18319
  };
18239
18320
  const body = rows.map((row) => columns.map((column, index) => ({
18240
- text: exportCell(row[column.column], column, timezone, context, row),
18321
+ text: exportCell(row[column.column], column, timezone, context, row, data.valueLabels),
18241
18322
  options: pptxRunOptions(align(index), valueLocale(index)),
18242
18323
  })));
18243
18324
  if (remaining > 0) {
@@ -19441,7 +19522,7 @@ class FsAiReportComponent {
19441
19522
  ReportAiChatData,
19442
19523
  { provide: FsAiChatData, useExisting: ReportAiChatData },
19443
19524
  // Tree-shaken ECharts core + the 'report' house theme, loaded lazily.
19444
- provideEchartsCore({ echarts: () => import('./firestitch-report-echarts-CBBTk1Ql.mjs').then((module) => module.default) }),
19525
+ provideEchartsCore({ echarts: () => import('./firestitch-report-echarts-D7WNr0Z4.mjs').then((module) => module.default) }),
19445
19526
  // The bar's date pickers start their weeks on Monday and list the built-in
19446
19527
  // presets; a preset only sets the days.
19447
19528
  provideReportDatePicker(),
@@ -19465,7 +19546,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
19465
19546
  ReportAiChatData,
19466
19547
  { provide: FsAiChatData, useExisting: ReportAiChatData },
19467
19548
  // Tree-shaken ECharts core + the 'report' house theme, loaded lazily.
19468
- provideEchartsCore({ echarts: () => import('./firestitch-report-echarts-CBBTk1Ql.mjs').then((module) => module.default) }),
19549
+ provideEchartsCore({ echarts: () => import('./firestitch-report-echarts-D7WNr0Z4.mjs').then((module) => module.default) }),
19469
19550
  // The bar's date pickers start their weeks on Monday and list the built-in
19470
19551
  // presets; a preset only sets the days.
19471
19552
  provideReportDatePicker(),
@@ -19558,4 +19639,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
19558
19639
  */
19559
19640
 
19560
19641
  export { FsAiReportsComponent as F, GRANULARITY_OPTIONS as G, REPORT_CHART_COLORS_CSS as R, REPORT_CHART_FONT_FAMILY as a, REPORT_AXIS_LABEL_FONT_SIZE as b, FsAiReportComponent as c, ReportData as d, ReportService as e, ReportFilterStateService as f, ReportNodeType as g, ReportState as h, ReportValueFormat as i, ReportValueFormula as j, ReportListColumnFormat as k, ReportNumberUnits as l, ReportChartDataLabels as m, ReportChartColor as n, ReportChartLineStyle as o, ReportChartMarkStat as p, ReportChartDateLabel as q, ReportChartSpanThrough as r, ReportChangePolarity as s };
19561
- //# sourceMappingURL=firestitch-report-firestitch-report-Cl_JOBli.mjs.map
19642
+ //# sourceMappingURL=firestitch-report-firestitch-report-DWP3aywv.mjs.map