@firestitch/report 18.21.1 → 18.21.2

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.
@@ -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-cys9XusN.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-D2dPznfE.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-D1UDj4L9.mjs.map
66
+ //# sourceMappingURL=firestitch-report-echarts-BLr6SmeK.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"firestitch-report-echarts-D1UDj4L9.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-BLr6SmeK.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"}
@@ -7955,19 +7955,23 @@ class ReportFilterStateService {
7955
7955
  this._stateChanged$.next();
7956
7956
  }
7957
7957
  // Notifications relevant to ONE component: any change to a group one of its
7958
- // filters belongs to (or a full re-init).
7958
+ // filters belongs to (or a full re-init). The component is read on each
7959
+ // event, never captured at subscribe: a tile keeps its subscription across
7960
+ // report loads, so a filter added to it while the report is open (the MCP,
7961
+ // a chat edit, the settings dialog) reaches it on the first change of its
7962
+ // group.
7959
7963
  changesFor(component) {
7960
- const groupIds = new Set((component.filters ?? []).map((filter) => filter.filterGroupId));
7961
7964
  return this._changed$.asObservable()
7962
- .pipe(filter((groupId) => groupId === null || groupIds.has(groupId)));
7965
+ .pipe(filter((groupId) => groupId === null
7966
+ || (component().filters ?? []).some((filter) => filter.filterGroupId === groupId)));
7963
7967
  }
7964
7968
  // Notifications relevant to ANY of a set of components that comes and goes
7965
7969
  // (a page's values): a change to a group one of their filters belongs to.
7966
- // Unlike changesFor, the set is read on each event rather than captured at
7967
- // subscribe, so one subscription follows the set as the report reloads. A
7968
- // full re-init (null) is not passed on: init() runs on a report
7969
- // (re)load, and a caller of this checks on that reload itself whether the
7970
- // filter values its components are read with moved.
7970
+ // Like changesFor, the set is read on each event, so one subscription
7971
+ // follows the set as the report reloads. Unlike it, a full re-init (null)
7972
+ // is not passed on: init() runs on a report (re)load, and a caller of this
7973
+ // checks on that reload itself whether the filter values its components
7974
+ // are read with moved.
7971
7975
  changesForAny(components) {
7972
7976
  return this._changed$.asObservable()
7973
7977
  .pipe(filter((groupId) => groupId !== null
@@ -10065,9 +10069,14 @@ function decimalMark(locale) {
10065
10069
  // re-init the filter state) reads the table again at once, even when its
10066
10070
  // filters did not move: the rows behind it, or its own query, may have.
10067
10071
  // The load is counted into the params (reportLoads), since fs-grid reads
10068
- // only when they move. The new params land in the same tick as the
10069
- // reloaded tile, so a load that also moves the authored layout costs one
10070
- // read.
10072
+ // only when they move. The params are derived from the tile as it is
10073
+ // drawn (params), so the read of a load carries the filters the load
10074
+ // brought, a filter added since the report opened included, and lands in
10075
+ // the same tick as the reloaded tile: a load that also moves the authored
10076
+ // layout costs one read.
10077
+ // - Which filter groups and whether the group-by reach the tile is read
10078
+ // from the tile as it stands at each change, never as it was drawn: a
10079
+ // filter added while the report is open reads on its first pick.
10071
10080
  // - The layout on screen is the state service's (gridLayout): the viewer's
10072
10081
  // own while they changed it from the layout authored now, else the
10073
10082
  // authored one. It outlives a page switch, and the chat reads it. So do
@@ -10091,7 +10100,16 @@ function decimalMark(locale) {
10091
10100
  class ComponentGridComponent {
10092
10101
  reportId = input.required();
10093
10102
  component = input.required();
10094
- params = signal(null);
10103
+ // What fs-grid reads with: the tile's params (_readParams) for the
10104
+ // component drawn now, read again at each settled change (_paramsRead).
10105
+ // A load re-inits the filter state a tick before the tile gets the
10106
+ // component it brought, so deriving them here is what puts a filter added
10107
+ // by that load into its read.
10108
+ params = computed(() => {
10109
+ const component = this.component();
10110
+ this._paramsRead();
10111
+ return untracked(() => this._readParams(component));
10112
+ });
10095
10113
  controls = computed(() => this.component().config?.controls ?? {});
10096
10114
  source = computed(() => new ReportGridSource(this._reportData, this.reportId(), this._componentId(), {
10097
10115
  locale: () => this._filterState.formatContext().locale,
@@ -10118,6 +10136,8 @@ class ComponentGridComponent {
10118
10136
  _paramsVersion = 0;
10119
10137
  // The report loads seen since the tile was drawn (ReportGridParams).
10120
10138
  _reportLoads = 0;
10139
+ // Moves each time a settled change has the params read again.
10140
+ _paramsRead = signal(0);
10121
10141
  ngOnInit() {
10122
10142
  this.expansion.set(this._filterState.gridExpansion(this.component()));
10123
10143
  this._init();
@@ -10131,16 +10151,14 @@ class ComponentGridComponent {
10131
10151
  }
10132
10152
  _init() {
10133
10153
  this._paramsVersion = this._filterState.stateVersion();
10134
- this.params.set(this._readParams());
10135
10154
  // A null group is a full re-init: a report load, or a reset.
10136
- this._filterState.changesFor(this.component())
10155
+ this._filterState.changesFor(this.component)
10137
10156
  .pipe(switchMap$1((groupId) => this._settled$(groupId === null)), tap$1((isLoad) => this._applyParams(isLoad)), takeUntilDestroyed(this._destroyRef))
10138
10157
  .subscribe();
10139
- if (followsGroupBy(this.component())) {
10140
- this._filterState.frequencyChanges()
10141
- .pipe(takeUntilDestroyed(this._destroyRef))
10142
- .subscribe(() => this._applyParams());
10143
- }
10158
+ // A load can make the table follow the group-by, or stop.
10159
+ this._filterState.frequencyChanges()
10160
+ .pipe(filter$1(() => followsGroupBy(this.component())), tap$1(() => this._applyParams()), takeUntilDestroyed(this._destroyRef))
10161
+ .subscribe();
10144
10162
  }
10145
10163
  // Once the tile's first read is in, its notes prune the viewer's layout
10146
10164
  // (prunedGridLayout). A tile showing its authored layout has nothing to
@@ -10181,12 +10199,11 @@ class ComponentGridComponent {
10181
10199
  this._reportLoads++;
10182
10200
  }
10183
10201
  this._paramsVersion = this._filterState.stateVersion();
10184
- this.params.set(this._readParams());
10202
+ this._paramsRead.update((count) => count + 1);
10185
10203
  }
10186
10204
  // The tile's report filters, 'any' groups and group-by grain as they stand
10187
10205
  // (tileState()), and the report loads it has seen.
10188
- _readParams() {
10189
- const component = this.component();
10206
+ _readParams(component) {
10190
10207
  const { matchAnyGroupIds, frequency } = this._filterState.tileState(component);
10191
10208
  return {
10192
10209
  filters: this._filterState.resolveForComponent(component),
@@ -10196,7 +10213,7 @@ class ComponentGridComponent {
10196
10213
  };
10197
10214
  }
10198
10215
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ComponentGridComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
10199
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: ComponentGridComponent, isStandalone: true, selector: "app-report-component-grid", inputs: { reportId: { classPropertyName: "reportId", publicName: "reportId", isSignal: true, isRequired: true, transformFunction: null }, component: { classPropertyName: "component", publicName: "component", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<!-- The comparison and window note strip above the table, from the report\n line of the latest read; the windows' descriptions and notes go in each\n column's \"About this column\" instead. -->\n<div class=\"fs-column grid-pane\">\n <app-report-component-note\n [data]=\"noteData()\"\n [windowNotes]=\"false\">\n </app-report-component-note>\n <!-- The params are seeded before the first render, so the grid's first read\n carries the tile's report filters. -->\n @if (params(); as params) {\n <fs-grid\n class=\"fs-flex\"\n [source]=\"source()\"\n [layout]=\"layout()\"\n [expansion]=\"expansion()\"\n [clearedFilter]=\"clearedFilter()\"\n (expansionChange)=\"setExpansion($event)\"\n [params]=\"params\"\n [controls]=\"controls()\"\n [formatter]=\"formatter()\"\n (layoutChange)=\"setLayout($event)\">\n <ng-template fsGridCell let-value let-field=\"field\" let-record=\"record\" let-text=\"text\">\n @if (value | fsReportGridCell: field : record : text : noteData() : formatContext(); as shown) {\n <!-- A cell that says why (a missing or zero prior) opens it on a\n click; no cell carries a native tooltip. -->\n @if (shown.title) {\n <span\n class=\"explained\"\n fsPopover\n trigger=\"click\"\n [template]=\"explanation\"\n [indication]=\"false\"\n [maxWidth]=\"320\">\n {{ shown.text }}\n </span>\n <ng-template #explanation>{{ shown.title }}</ng-template>\n } @else {\n <span>{{ shown.text }}</span>\n }\n }\n </ng-template>\n </fs-grid>\n }\n</div>\n", styles: [":host{display:block;height:100%}.grid-pane{height:100%;min-height:0}fs-grid{min-height:0}.explained{cursor:pointer;text-decoration:underline dotted;text-underline-offset:2px}\n"], dependencies: [{ kind: "component", type: FsGridComponent, selector: "fs-grid", inputs: ["source", "layout", "controls", "params", "expansion", "panel", "editorOpen", "formatter", "clearedFilter"], outputs: ["layoutChange", "expansionChange", "panelChange", "editorOpenChange"] }, { kind: "directive", type: FsGridCellDirective, selector: "[fsGridCell]" }, { kind: "directive", type: FsPopoverDirective, selector: "[fsPopover]", inputs: ["text", "template", "data", "leaveDelay", "showDelay", "maxWidth", "maxHeight", "wrapperClass", "autoShow", "autoClose", "loadingDiameter", "loading", "indication", "position", "theme", "size", "trigger", "enabled", "panel"], outputs: ["closed"], exportAs: ["fsPopover"] }, { kind: "component", type: ComponentNoteComponent, selector: "app-report-component-note", inputs: ["data", "windows", "windowDescriptions", "windowNotes"] }, { kind: "pipe", type: ReportGridCellPipe, name: "fsReportGridCell" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
10216
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: ComponentGridComponent, isStandalone: true, selector: "app-report-component-grid", inputs: { reportId: { classPropertyName: "reportId", publicName: "reportId", isSignal: true, isRequired: true, transformFunction: null }, component: { classPropertyName: "component", publicName: "component", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<!-- The comparison and window note strip above the table, from the report\n line of the latest read; the windows' descriptions and notes go in each\n column's \"About this column\" instead. -->\n<div class=\"fs-column grid-pane\">\n <app-report-component-note\n [data]=\"noteData()\"\n [windowNotes]=\"false\">\n </app-report-component-note>\n <!-- The params are read from the tile drawn (params), from its first\n render on, so every read carries the tile's report filters. -->\n <fs-grid\n class=\"fs-flex\"\n [source]=\"source()\"\n [layout]=\"layout()\"\n [expansion]=\"expansion()\"\n [clearedFilter]=\"clearedFilter()\"\n (expansionChange)=\"setExpansion($event)\"\n [params]=\"params()\"\n [controls]=\"controls()\"\n [formatter]=\"formatter()\"\n (layoutChange)=\"setLayout($event)\">\n <ng-template fsGridCell let-value let-field=\"field\" let-record=\"record\" let-text=\"text\">\n @if (value | fsReportGridCell: field : record : text : noteData() : formatContext(); as shown) {\n <!-- A cell that says why (a missing or zero prior) opens it on a\n click; no cell carries a native tooltip. -->\n @if (shown.title) {\n <span\n class=\"explained\"\n fsPopover\n trigger=\"click\"\n [template]=\"explanation\"\n [indication]=\"false\"\n [maxWidth]=\"320\">\n {{ shown.text }}\n </span>\n <ng-template #explanation>{{ shown.title }}</ng-template>\n } @else {\n <span>{{ shown.text }}</span>\n }\n }\n </ng-template>\n </fs-grid>\n</div>\n", styles: [":host{display:block;height:100%}.grid-pane{height:100%;min-height:0}fs-grid{min-height:0}.explained{cursor:pointer;text-decoration:underline dotted;text-underline-offset:2px}\n"], dependencies: [{ kind: "component", type: FsGridComponent, selector: "fs-grid", inputs: ["source", "layout", "controls", "params", "expansion", "panel", "editorOpen", "formatter", "clearedFilter"], outputs: ["layoutChange", "expansionChange", "panelChange", "editorOpenChange"] }, { kind: "directive", type: FsGridCellDirective, selector: "[fsGridCell]" }, { kind: "directive", type: FsPopoverDirective, selector: "[fsPopover]", inputs: ["text", "template", "data", "leaveDelay", "showDelay", "maxWidth", "maxHeight", "wrapperClass", "autoShow", "autoClose", "loadingDiameter", "loading", "indication", "position", "theme", "size", "trigger", "enabled", "panel"], outputs: ["closed"], exportAs: ["fsPopover"] }, { kind: "component", type: ComponentNoteComponent, selector: "app-report-component-note", inputs: ["data", "windows", "windowDescriptions", "windowNotes"] }, { kind: "pipe", type: ReportGridCellPipe, name: "fsReportGridCell" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
10200
10217
  }
10201
10218
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ComponentGridComponent, decorators: [{
10202
10219
  type: Component,
@@ -10206,7 +10223,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
10206
10223
  FsPopoverDirective,
10207
10224
  ComponentNoteComponent,
10208
10225
  ReportGridCellPipe,
10209
- ], template: "<!-- The comparison and window note strip above the table, from the report\n line of the latest read; the windows' descriptions and notes go in each\n column's \"About this column\" instead. -->\n<div class=\"fs-column grid-pane\">\n <app-report-component-note\n [data]=\"noteData()\"\n [windowNotes]=\"false\">\n </app-report-component-note>\n <!-- The params are seeded before the first render, so the grid's first read\n carries the tile's report filters. -->\n @if (params(); as params) {\n <fs-grid\n class=\"fs-flex\"\n [source]=\"source()\"\n [layout]=\"layout()\"\n [expansion]=\"expansion()\"\n [clearedFilter]=\"clearedFilter()\"\n (expansionChange)=\"setExpansion($event)\"\n [params]=\"params\"\n [controls]=\"controls()\"\n [formatter]=\"formatter()\"\n (layoutChange)=\"setLayout($event)\">\n <ng-template fsGridCell let-value let-field=\"field\" let-record=\"record\" let-text=\"text\">\n @if (value | fsReportGridCell: field : record : text : noteData() : formatContext(); as shown) {\n <!-- A cell that says why (a missing or zero prior) opens it on a\n click; no cell carries a native tooltip. -->\n @if (shown.title) {\n <span\n class=\"explained\"\n fsPopover\n trigger=\"click\"\n [template]=\"explanation\"\n [indication]=\"false\"\n [maxWidth]=\"320\">\n {{ shown.text }}\n </span>\n <ng-template #explanation>{{ shown.title }}</ng-template>\n } @else {\n <span>{{ shown.text }}</span>\n }\n }\n </ng-template>\n </fs-grid>\n }\n</div>\n", styles: [":host{display:block;height:100%}.grid-pane{height:100%;min-height:0}fs-grid{min-height:0}.explained{cursor:pointer;text-decoration:underline dotted;text-underline-offset:2px}\n"] }]
10226
+ ], template: "<!-- The comparison and window note strip above the table, from the report\n line of the latest read; the windows' descriptions and notes go in each\n column's \"About this column\" instead. -->\n<div class=\"fs-column grid-pane\">\n <app-report-component-note\n [data]=\"noteData()\"\n [windowNotes]=\"false\">\n </app-report-component-note>\n <!-- The params are read from the tile drawn (params), from its first\n render on, so every read carries the tile's report filters. -->\n <fs-grid\n class=\"fs-flex\"\n [source]=\"source()\"\n [layout]=\"layout()\"\n [expansion]=\"expansion()\"\n [clearedFilter]=\"clearedFilter()\"\n (expansionChange)=\"setExpansion($event)\"\n [params]=\"params()\"\n [controls]=\"controls()\"\n [formatter]=\"formatter()\"\n (layoutChange)=\"setLayout($event)\">\n <ng-template fsGridCell let-value let-field=\"field\" let-record=\"record\" let-text=\"text\">\n @if (value | fsReportGridCell: field : record : text : noteData() : formatContext(); as shown) {\n <!-- A cell that says why (a missing or zero prior) opens it on a\n click; no cell carries a native tooltip. -->\n @if (shown.title) {\n <span\n class=\"explained\"\n fsPopover\n trigger=\"click\"\n [template]=\"explanation\"\n [indication]=\"false\"\n [maxWidth]=\"320\">\n {{ shown.text }}\n </span>\n <ng-template #explanation>{{ shown.title }}</ng-template>\n } @else {\n <span>{{ shown.text }}</span>\n }\n }\n </ng-template>\n </fs-grid>\n</div>\n", styles: [":host{display:block;height:100%}.grid-pane{height:100%;min-height:0}fs-grid{min-height:0}.explained{cursor:pointer;text-decoration:underline dotted;text-underline-offset:2px}\n"] }]
10210
10227
  }] });
10211
10228
 
10212
10229
  // A KPI's trend over its last periods: a line that stretches to the card's
@@ -10469,9 +10486,10 @@ class ComponentListComponent {
10469
10486
  this._initListConfig(config);
10470
10487
  this._observePinOffsets();
10471
10488
  // A change to any group this list's filters belong to (from the report bar
10472
- // or the component header strip) re-runs the list.
10473
- // So does a change of the text in its search box (in the component header).
10474
- merge(this._filterState.changesFor(component), this._filterState.listSearchChanges(component.id))
10489
+ // or the component header strip) re-runs the list, a filter added since
10490
+ // the list was drawn included. So does a change of the text in its search
10491
+ // box (in the component header).
10492
+ merge(this._filterState.changesFor(this.component), this._filterState.listSearchChanges(component.id))
10475
10493
  .pipe(tap$1(() => this.listComponent()?.reload()), takeUntilDestroyed(this._destroyRef))
10476
10494
  .subscribe();
10477
10495
  }
@@ -11922,19 +11940,21 @@ class ReportComponentComponent {
11922
11940
  tileLoads(this._refresh$, () => this._load(), () => this._filterState.stateVersion())
11923
11941
  .pipe(tap$1((result) => this._loaded(result)), takeUntilDestroyed(this._destroyRef))
11924
11942
  .subscribe();
11925
- this._filterState.changesFor(this.component)
11926
- .pipe(takeUntilDestroyed(this._destroyRef))
11927
- .subscribe(() => this._refresh$.next());
11943
+ // A change to one of the tile's filter groups, read from the tile as
11944
+ // it stands, so a filter a report load added reads on its first pick.
11945
+ this._filterState.changesFor(() => this.component)
11946
+ .pipe(tap$1(() => this._refresh$.next()), takeUntilDestroyed(this._destroyRef))
11947
+ .subscribe();
11928
11948
  // A group-by change re-buckets every tile that follows it; it isn't
11929
- // scoped to a filter group, so it rides its own stream.
11930
- if (followsGroupBy(this.component)) {
11931
- this._filterState.frequencyChanges()
11932
- .pipe(takeUntilDestroyed(this._destroyRef))
11933
- .subscribe(() => {
11934
- this._grainMoved = true;
11935
- this._refresh$.next();
11936
- });
11937
- }
11949
+ // scoped to a filter group, so it rides its own stream. Whether the
11950
+ // tile follows it is read at each change: a load can make it follow
11951
+ // (a chart moved onto a time axis) or stop.
11952
+ this._filterState.frequencyChanges()
11953
+ .pipe(filter$1(() => followsGroupBy(this.component)), tap$1(() => {
11954
+ this._grainMoved = true;
11955
+ this._refresh$.next();
11956
+ }), takeUntilDestroyed(this._destroyRef))
11957
+ .subscribe();
11938
11958
  // A drill moves this chart alone.
11939
11959
  this._filterState.drillChanges(this.component.id)
11940
11960
  .pipe(takeUntilDestroyed(this._destroyRef))
@@ -12351,7 +12371,7 @@ class ReportComponentComponent {
12351
12371
  // A change to one group the header shows with another value (another bar
12352
12372
  // set it) builds it again too.
12353
12373
  _rebuildHeaderOnNewState() {
12354
- this._filterState.changesFor(this.component)
12374
+ this._filterState.changesFor(() => this.component)
12355
12375
  .pipe(filter$1((groupId) => (groupId === null
12356
12376
  ? this._filterState.stateVersion() !== this._headerVersion()
12357
12377
  : this._showsOtherValue(groupId))), tap$1(() => this._buildFilterConfig()), takeUntilDestroyed(this._destroyRef))
@@ -15819,7 +15839,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
15819
15839
  // in the report's format context, as on screen.
15820
15840
  async function renderChartImage(component, data, width, height, context, pixelRatio = 3) {
15821
15841
  // The same tree-shaken echarts build + 'report' theme the live canvas uses.
15822
- const echarts = (await import('./firestitch-report-echarts-D1UDj4L9.mjs')).default;
15842
+ const echarts = (await import('./firestitch-report-echarts-BLr6SmeK.mjs')).default;
15823
15843
  const host = document.createElement('div');
15824
15844
  host.style.width = `${width}px`;
15825
15845
  host.style.height = `${height}px`;
@@ -19512,7 +19532,7 @@ class FsAiReportComponent {
19512
19532
  ReportAiChatData,
19513
19533
  { provide: FsAiChatData, useExisting: ReportAiChatData },
19514
19534
  // Tree-shaken ECharts core + the 'report' house theme, loaded lazily.
19515
- provideEchartsCore({ echarts: () => import('./firestitch-report-echarts-D1UDj4L9.mjs').then((module) => module.default) }),
19535
+ provideEchartsCore({ echarts: () => import('./firestitch-report-echarts-BLr6SmeK.mjs').then((module) => module.default) }),
19516
19536
  // The bar's date pickers start their weeks on Monday and list the built-in
19517
19537
  // presets; a preset only sets the days.
19518
19538
  provideReportDatePicker(),
@@ -19536,7 +19556,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
19536
19556
  ReportAiChatData,
19537
19557
  { provide: FsAiChatData, useExisting: ReportAiChatData },
19538
19558
  // Tree-shaken ECharts core + the 'report' house theme, loaded lazily.
19539
- provideEchartsCore({ echarts: () => import('./firestitch-report-echarts-D1UDj4L9.mjs').then((module) => module.default) }),
19559
+ provideEchartsCore({ echarts: () => import('./firestitch-report-echarts-BLr6SmeK.mjs').then((module) => module.default) }),
19540
19560
  // The bar's date pickers start their weeks on Monday and list the built-in
19541
19561
  // presets; a preset only sets the days.
19542
19562
  provideReportDatePicker(),
@@ -19629,4 +19649,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
19629
19649
  */
19630
19650
 
19631
19651
  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 };
19632
- //# sourceMappingURL=firestitch-report-firestitch-report-cys9XusN.mjs.map
19652
+ //# sourceMappingURL=firestitch-report-firestitch-report-D2dPznfE.mjs.map