@firestitch/report 18.9.0 → 18.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (190) hide show
  1. package/app/reports/anchor-at-point.d.ts +14 -0
  2. package/app/reports/canvas-landing-page.d.ts +2 -0
  3. package/app/reports/components/component-chart/component-chart.component.d.ts +18 -2
  4. package/app/reports/components/component-kpi/component-kpi.component.d.ts +4 -1
  5. package/app/reports/components/report-canvas/report-canvas.component.d.ts +3 -0
  6. package/app/reports/components/report-component/report-component.component.d.ts +35 -1
  7. package/app/reports/components/report-view-picker/report-view-picker.component.d.ts +21 -0
  8. package/app/reports/data/report.data.d.ts +17 -2
  9. package/app/reports/dialogs/component-settings/component-settings.component.d.ts +18 -3
  10. package/app/reports/dialogs/report-settings/report-settings.component.d.ts +15 -6
  11. package/app/reports/dialogs/report-view/report-view-dialog.component.d.ts +13 -0
  12. package/app/reports/drill-crumbs.d.ts +12 -0
  13. package/app/reports/export/report-export-collector.service.d.ts +13 -4
  14. package/app/reports/export/report-filter-lines.d.ts +18 -0
  15. package/app/reports/filter-settings-rules.d.ts +33 -0
  16. package/app/reports/format.d.ts +0 -1
  17. package/app/reports/interfaces/canvas-landing-input.interface.d.ts +8 -0
  18. package/app/reports/interfaces/component-data-applied.interface.d.ts +13 -0
  19. package/app/reports/interfaces/component-data-drill.interface.d.ts +22 -0
  20. package/app/reports/interfaces/filter-bar-placement.type.d.ts +1 -0
  21. package/app/reports/interfaces/filter-component-toggle-state.interface.d.ts +4 -0
  22. package/app/reports/interfaces/filter-settings-option.interface.d.ts +4 -0
  23. package/app/reports/interfaces/filter-type-select-state.interface.d.ts +5 -0
  24. package/app/reports/interfaces/report-chart-hit.interface.d.ts +5 -0
  25. package/app/reports/interfaces/report-chat-viewer-cross-filter-field.interface.d.ts +4 -0
  26. package/app/reports/interfaces/report-chat-viewer-cross-filter.interface.d.ts +7 -0
  27. package/app/reports/interfaces/report-chat-viewer-detail.interface.d.ts +4 -0
  28. package/app/reports/interfaces/report-chat-viewer-drill-step.interface.d.ts +5 -0
  29. package/app/reports/interfaces/report-chat-viewer-drill.interface.d.ts +5 -0
  30. package/app/reports/interfaces/report-chat-viewer-filter.interface.d.ts +3 -0
  31. package/app/reports/interfaces/report-chat-viewer-selection.interface.d.ts +5 -0
  32. package/app/reports/interfaces/report-chat-viewer-state.interface.d.ts +12 -0
  33. package/app/reports/interfaces/report-drill-crumb.interface.d.ts +6 -0
  34. package/app/reports/interfaces/report-drill-refusal.type.d.ts +1 -0
  35. package/app/reports/interfaces/report-drill-step.interface.d.ts +5 -0
  36. package/app/reports/interfaces/report-export-line-kind.type.d.ts +1 -0
  37. package/app/reports/interfaces/report-export-line.interface.d.ts +8 -0
  38. package/app/reports/interfaces/report-export-lines-input.interface.d.ts +9 -0
  39. package/app/reports/interfaces/report-export-snapshot.interface.d.ts +15 -0
  40. package/app/reports/interfaces/report-filter-line-context.interface.d.ts +8 -0
  41. package/app/reports/interfaces/report-filter-line-form.type.d.ts +1 -0
  42. package/app/reports/interfaces/report-filter-match.type.d.ts +1 -0
  43. package/app/reports/interfaces/report-filter-option-pair.interface.d.ts +4 -0
  44. package/app/reports/interfaces/report-filter-options-ask.interface.d.ts +6 -0
  45. package/app/reports/interfaces/report-filter-options-list.interface.d.ts +7 -0
  46. package/app/reports/interfaces/report-filter-options-request.interface.d.ts +6 -0
  47. package/app/reports/interfaces/report-filter-options-stream.interface.d.ts +11 -0
  48. package/app/reports/interfaces/report-filter-options.interface.d.ts +7 -0
  49. package/app/reports/interfaces/report-filter-skip.type.d.ts +1 -0
  50. package/app/reports/interfaces/report-mark-action.type.d.ts +1 -0
  51. package/app/reports/interfaces/report-mark-click.interface.d.ts +13 -0
  52. package/app/reports/interfaces/report-mark-context.interface.d.ts +6 -0
  53. package/app/reports/interfaces/report-mark-decision.interface.d.ts +6 -0
  54. package/app/reports/interfaces/report-mark-event.interface.d.ts +11 -0
  55. package/app/reports/interfaces/report-mark-point.interface.d.ts +8 -0
  56. package/app/reports/interfaces/report-temporary-state.interface.d.ts +4 -0
  57. package/app/reports/interfaces/report-tile-state.interface.d.ts +8 -0
  58. package/app/reports/interfaces/report-url-link.interface.d.ts +4 -0
  59. package/app/reports/interfaces/report-url-value-name.type.d.ts +1 -0
  60. package/app/reports/interfaces/report-url-write.interface.d.ts +4 -0
  61. package/app/reports/interfaces/report-view-config.interface.d.ts +11 -0
  62. package/app/reports/interfaces/report-view-create.interface.d.ts +7 -0
  63. package/app/reports/interfaces/report-view-deleted.interface.d.ts +4 -0
  64. package/app/reports/interfaces/report-view-dialog-data.interface.d.ts +7 -0
  65. package/app/reports/interfaces/report-view-dropped.interface.d.ts +5 -0
  66. package/app/reports/interfaces/report-view-menu-item.interface.d.ts +10 -0
  67. package/app/reports/interfaces/report-view-summary.interface.d.ts +11 -0
  68. package/app/reports/interfaces/report-view.interface.d.ts +7 -0
  69. package/app/reports/interfaces/report-viewer-feature.type.d.ts +1 -0
  70. package/app/reports/interfaces/report-views.interface.d.ts +7 -0
  71. package/app/reports/interfaces/report.interface.d.ts +27 -3
  72. package/app/reports/interfaces/tile-load-result.interface.d.ts +4 -0
  73. package/app/reports/mark-click.d.ts +20 -0
  74. package/app/reports/option-builder.d.ts +12 -1
  75. package/app/reports/report-chat-viewer-state.d.ts +8 -0
  76. package/app/reports/report-date-presets.d.ts +2 -0
  77. package/app/reports/report-filter-items.d.ts +27 -22
  78. package/app/reports/report-tile.d.ts +2 -0
  79. package/app/reports/report-url-state.d.ts +27 -10
  80. package/app/reports/report-view-config.d.ts +36 -0
  81. package/app/reports/report-view-menu.d.ts +15 -0
  82. package/app/reports/report-viewer-features.d.ts +5 -0
  83. package/app/reports/services/report-filter-options.service.d.ts +26 -0
  84. package/app/reports/services/report-filter-state.service.d.ts +64 -1
  85. package/app/reports/services/report-view.service.d.ts +51 -0
  86. package/app/reports/tile-data-state.d.ts +7 -0
  87. package/app/reports/tile-loads.d.ts +4 -0
  88. package/app/reports/views/report/fs-ai-report.component.d.ts +9 -1
  89. package/app/reports/views/report/report.component.d.ts +6 -0
  90. package/esm2022/app/reports/anchor-at-point.mjs +49 -0
  91. package/esm2022/app/reports/canvas-landing-page.mjs +25 -0
  92. package/esm2022/app/reports/components/component-chart/component-chart.component.mjs +97 -5
  93. package/esm2022/app/reports/components/component-kpi/component-kpi.component.mjs +11 -4
  94. package/esm2022/app/reports/components/component-list/component-list.component.mjs +7 -1
  95. package/esm2022/app/reports/components/report-canvas/report-canvas.component.mjs +47 -32
  96. package/esm2022/app/reports/components/report-component/report-component.component.mjs +257 -61
  97. package/esm2022/app/reports/components/report-view-picker/report-view-picker.component.mjs +115 -0
  98. package/esm2022/app/reports/data/report.data.mjs +87 -10
  99. package/esm2022/app/reports/dialogs/component-settings/component-settings.component.mjs +106 -51
  100. package/esm2022/app/reports/dialogs/report-settings/report-settings.component.mjs +86 -90
  101. package/esm2022/app/reports/dialogs/report-view/report-view-dialog.component.mjs +52 -0
  102. package/esm2022/app/reports/drill-crumbs.mjs +73 -0
  103. package/esm2022/app/reports/export/report-export-collector.service.mjs +187 -117
  104. package/esm2022/app/reports/export/report-filter-lines.mjs +235 -0
  105. package/esm2022/app/reports/export/report-pdf.service.mjs +12 -7
  106. package/esm2022/app/reports/export/report-pptx.service.mjs +18 -14
  107. package/esm2022/app/reports/filter-settings-rules.mjs +283 -0
  108. package/esm2022/app/reports/format.mjs +2 -22
  109. package/esm2022/app/reports/interfaces/canvas-landing-input.interface.mjs +2 -0
  110. package/esm2022/app/reports/interfaces/component-data-applied.interface.mjs +2 -0
  111. package/esm2022/app/reports/interfaces/component-data-drill.interface.mjs +2 -0
  112. package/esm2022/app/reports/interfaces/filter-bar-placement.type.mjs +2 -0
  113. package/esm2022/app/reports/interfaces/filter-component-toggle-state.interface.mjs +2 -0
  114. package/esm2022/app/reports/interfaces/filter-settings-option.interface.mjs +2 -0
  115. package/esm2022/app/reports/interfaces/filter-type-select-state.interface.mjs +2 -0
  116. package/esm2022/app/reports/interfaces/report-chart-hit.interface.mjs +2 -0
  117. package/esm2022/app/reports/interfaces/report-chat-viewer-cross-filter-field.interface.mjs +2 -0
  118. package/esm2022/app/reports/interfaces/report-chat-viewer-cross-filter.interface.mjs +2 -0
  119. package/esm2022/app/reports/interfaces/report-chat-viewer-detail.interface.mjs +2 -0
  120. package/esm2022/app/reports/interfaces/report-chat-viewer-drill-step.interface.mjs +2 -0
  121. package/esm2022/app/reports/interfaces/report-chat-viewer-drill.interface.mjs +2 -0
  122. package/esm2022/app/reports/interfaces/report-chat-viewer-filter.interface.mjs +1 -1
  123. package/esm2022/app/reports/interfaces/report-chat-viewer-selection.interface.mjs +2 -0
  124. package/esm2022/app/reports/interfaces/report-chat-viewer-state.interface.mjs +1 -1
  125. package/esm2022/app/reports/interfaces/report-drill-crumb.interface.mjs +2 -0
  126. package/esm2022/app/reports/interfaces/report-drill-refusal.type.mjs +2 -0
  127. package/esm2022/app/reports/interfaces/report-drill-step.interface.mjs +2 -0
  128. package/esm2022/app/reports/interfaces/report-export-line-kind.type.mjs +2 -0
  129. package/esm2022/app/reports/interfaces/report-export-line.interface.mjs +2 -0
  130. package/esm2022/app/reports/interfaces/report-export-lines-input.interface.mjs +2 -0
  131. package/esm2022/app/reports/interfaces/report-export-snapshot.interface.mjs +2 -0
  132. package/esm2022/app/reports/interfaces/report-filter-line-context.interface.mjs +2 -0
  133. package/esm2022/app/reports/interfaces/report-filter-line-form.type.mjs +2 -0
  134. package/esm2022/app/reports/interfaces/report-filter-match.type.mjs +2 -0
  135. package/esm2022/app/reports/interfaces/report-filter-option-pair.interface.mjs +2 -0
  136. package/esm2022/app/reports/interfaces/report-filter-options-ask.interface.mjs +2 -0
  137. package/esm2022/app/reports/interfaces/report-filter-options-list.interface.mjs +2 -0
  138. package/esm2022/app/reports/interfaces/report-filter-options-request.interface.mjs +2 -0
  139. package/esm2022/app/reports/interfaces/report-filter-options-stream.interface.mjs +2 -0
  140. package/esm2022/app/reports/interfaces/report-filter-options.interface.mjs +2 -0
  141. package/esm2022/app/reports/interfaces/report-filter-skip.type.mjs +2 -0
  142. package/esm2022/app/reports/interfaces/report-mark-action.type.mjs +2 -0
  143. package/esm2022/app/reports/interfaces/report-mark-click.interface.mjs +2 -0
  144. package/esm2022/app/reports/interfaces/report-mark-context.interface.mjs +2 -0
  145. package/esm2022/app/reports/interfaces/report-mark-decision.interface.mjs +2 -0
  146. package/esm2022/app/reports/interfaces/report-mark-event.interface.mjs +2 -0
  147. package/esm2022/app/reports/interfaces/report-mark-point.interface.mjs +2 -0
  148. package/esm2022/app/reports/interfaces/report-temporary-state.interface.mjs +2 -0
  149. package/esm2022/app/reports/interfaces/report-tile-state.interface.mjs +2 -0
  150. package/esm2022/app/reports/interfaces/report-url-link.interface.mjs +2 -0
  151. package/esm2022/app/reports/interfaces/report-url-value-name.type.mjs +2 -0
  152. package/esm2022/app/reports/interfaces/report-url-write.interface.mjs +2 -0
  153. package/esm2022/app/reports/interfaces/report-view-config.interface.mjs +2 -0
  154. package/esm2022/app/reports/interfaces/report-view-create.interface.mjs +2 -0
  155. package/esm2022/app/reports/interfaces/report-view-deleted.interface.mjs +2 -0
  156. package/esm2022/app/reports/interfaces/report-view-dialog-data.interface.mjs +2 -0
  157. package/esm2022/app/reports/interfaces/report-view-dropped.interface.mjs +2 -0
  158. package/esm2022/app/reports/interfaces/report-view-menu-item.interface.mjs +2 -0
  159. package/esm2022/app/reports/interfaces/report-view-summary.interface.mjs +2 -0
  160. package/esm2022/app/reports/interfaces/report-view.interface.mjs +2 -0
  161. package/esm2022/app/reports/interfaces/report-viewer-feature.type.mjs +2 -0
  162. package/esm2022/app/reports/interfaces/report-views.interface.mjs +2 -0
  163. package/esm2022/app/reports/interfaces/report.interface.mjs +1 -1
  164. package/esm2022/app/reports/interfaces/tile-load-result.interface.mjs +2 -0
  165. package/esm2022/app/reports/mark-click.mjs +193 -0
  166. package/esm2022/app/reports/option-builder.mjs +159 -15
  167. package/esm2022/app/reports/report-chat-viewer-state.mjs +34 -0
  168. package/esm2022/app/reports/report-date-presets.mjs +18 -0
  169. package/esm2022/app/reports/report-filter-items.mjs +343 -72
  170. package/esm2022/app/reports/report-tile.mjs +12 -0
  171. package/esm2022/app/reports/report-url-state.mjs +596 -108
  172. package/esm2022/app/reports/report-view-config.mjs +697 -0
  173. package/esm2022/app/reports/report-view-menu.mjs +119 -0
  174. package/esm2022/app/reports/report-viewer-features.mjs +42 -0
  175. package/esm2022/app/reports/services/report-filter-options.service.mjs +238 -0
  176. package/esm2022/app/reports/services/report-filter-state.service.mjs +697 -62
  177. package/esm2022/app/reports/services/report-view.service.mjs +358 -0
  178. package/esm2022/app/reports/tile-data-state.mjs +127 -0
  179. package/esm2022/app/reports/tile-loads.mjs +38 -0
  180. package/esm2022/app/reports/views/report/fs-ai-report.component.mjs +177 -46
  181. package/esm2022/app/reports/views/report/report.component.mjs +103 -23
  182. package/esm2022/public_api.mjs +23 -1
  183. package/fesm2022/{firestitch-report-echarts-DBMOHmBF.mjs → firestitch-report-echarts-UBg8Wlhd.mjs} +2 -2
  184. package/fesm2022/{firestitch-report-echarts-DBMOHmBF.mjs.map → firestitch-report-echarts-UBg8Wlhd.mjs.map} +1 -1
  185. package/fesm2022/{firestitch-report-firestitch-report-CqbXT1gh.mjs → firestitch-report-firestitch-report-B1keNrcK.mjs} +9063 -4272
  186. package/fesm2022/firestitch-report-firestitch-report-B1keNrcK.mjs.map +1 -0
  187. package/fesm2022/firestitch-report.mjs +1 -1
  188. package/package.json +1 -1
  189. package/public_api.d.ts +22 -0
  190. package/fesm2022/firestitch-report-firestitch-report-CqbXT1gh.mjs.map +0 -1
@@ -0,0 +1,235 @@
1
+ import { forkJoin, of } from 'rxjs';
2
+ import { catchError, map } from 'rxjs/operators';
3
+ import { crumbedTitle, drillCrumbLabels } from '../drill-crumbs';
4
+ import { formatDayRange, formatPlainNumber } from '../format';
5
+ import { GRANULARITY_OPTIONS, } from '../interfaces/report.interface';
6
+ import { dateBoundLabel, dateBoundString, relativeLabel } from '../report-filter-items';
7
+ import { isTile } from '../report-tile';
8
+ import { finiteNumber } from '../report-view-config';
9
+ // The words a file uses for what the screen held: each filter's value, the
10
+ // group-by grain, a drilled tile, the match and the open view. The PDF and
11
+ // PowerPoint covers print these lines, and the zip sends them (filterLines,
12
+ // with filterSummary as their text for an older server), so every export
13
+ // words one filter one way. Pure, so the node harness checks every wording.
14
+ // The match while the report bar's filters combine with 'any': the chip's
15
+ // words, and the cover's line. The zip's notes carry the server's own
16
+ // sentence instead.
17
+ export const MATCH_ANY_CHIP = 'Match: any filter';
18
+ export const MATCH_ANY_LINE = 'Filters in the report bar: match any';
19
+ // The report bar's Match chip while the filters combine with 'all'. A file
20
+ // prints no line for it.
21
+ export const MATCH_ALL_CHIP = 'Match: all filters';
22
+ // A group's label when it has none.
23
+ const UNLABELED_GROUP = 'Filter';
24
+ // The label of the group-by line when the report names no control.
25
+ const GROUP_BY_LABEL = 'Group By';
26
+ // One filter group's value as text ('Region: West, East'), or null when the
27
+ // value holds nothing. Values left out say so before the label: 'Exclude
28
+ // Region: West, East'. 'chip' is the short form; 'line' adds what a file
29
+ // reader cannot see on screen:
30
+ // - exclude: 'Exclude Region: West, East (rows with no Region are kept)', or
31
+ // '... are left out' when the blank label (context.blankLabel) is one of
32
+ // the values left out. Without a known blank label the line says nothing
33
+ // about the blank rows;
34
+ // - range: 'Amount: 10 to 50 (both included)'; an open end reads '10 or
35
+ // more' or '50 or less' in both forms;
36
+ // - a live preset: 'Report Period: Last 30 days (Sep 3 – Oct 2, 2026)';
37
+ // - a page group: 'Cohort (page "Retention" only): 2025'.
38
+ // Numbers and dates are written in the report's locale, and 0 is a number
39
+ // like any other.
40
+ export function filterLineText(group, value, context, form) {
41
+ const label = group.label || UNLABELED_GROUP;
42
+ const text = value ? valueText(label, value, context, form) : null;
43
+ if (text === null) {
44
+ return null;
45
+ }
46
+ const pageOnly = form === 'line' && group.level === 'page' && context.pageName;
47
+ const name = pageOnly ? `${label} (page "${context.pageName}" only)` : label;
48
+ return `${excludes(value) ? 'Exclude ' : ''}${name}: ${text}`;
49
+ }
50
+ // The match as text while it is 'any', else null; the chip also words 'all'.
51
+ export function matchLineText(match, form) {
52
+ if (match !== 'any') {
53
+ return form === 'chip' && match === 'all' ? MATCH_ALL_CHIP : null;
54
+ }
55
+ return form === 'chip' ? MATCH_ANY_CHIP : MATCH_ANY_LINE;
56
+ }
57
+ // A drilled tile's line: its title and the breadcrumb of its path, in the
58
+ // report's locale ('Revenue by Period › 2026 › Q3').
59
+ export function drillLineText(component, path, formatContext) {
60
+ return crumbedTitle(component.title, drillCrumbLabels(path, formatContext));
61
+ }
62
+ // The cover's line for the open saved view: 'View: "Q3 North" (shared)',
63
+ // with ', changed since it was opened' while the screen differs from it.
64
+ // Null when no view is open.
65
+ export function viewLineText(view, changed) {
66
+ if (!view) {
67
+ return null;
68
+ }
69
+ const line = `View: "${(view.name ?? '').trim()}" (${view.shared ? 'shared' : 'personal'})`;
70
+ return changed ? `${line}, changed since it was opened` : line;
71
+ }
72
+ // The filter lines of an export, in order: one per filter group with a
73
+ // value (the report's group order), the group-by line, then one per drilled
74
+ // chart (page order). A This Page export (input.pageId) lists only the
75
+ // groups that reach a tile of that page, and only that page's drilled
76
+ // charts. A select's names are a request, so the lines arrive together once
77
+ // every name is known; a failed name read writes the picks as they are
78
+ // stored.
79
+ export function exportLines(input) {
80
+ const groups$ = exportGroups(input.report, input.pageId)
81
+ .map((group) => groupLine(group, input));
82
+ const rest = [groupByLine(input), ...drillLines(input)]
83
+ .filter((line) => line !== null);
84
+ return (groups$.length ? forkJoin(groups$) : of([]))
85
+ .pipe(map((lines) => [
86
+ ...lines.filter((line) => line !== null),
87
+ ...rest,
88
+ ]));
89
+ }
90
+ // The groups an export's lines may name: every group, or for a This Page
91
+ // export the groups with a member tile on that page. A page group reaches
92
+ // only its own page.
93
+ export function exportGroups(report, pageId) {
94
+ const groups = report.filterGroups ?? [];
95
+ if (!pageId) {
96
+ return groups;
97
+ }
98
+ const page = (report.pages ?? []).find((candidate) => candidate.id === pageId);
99
+ const tileIds = (page?.components ?? [])
100
+ .filter((component) => isTile(component))
101
+ .map((component) => component.id);
102
+ return groups.filter((group) => (group.level !== 'page' || group.pageId === pageId)
103
+ && groupMemberIds(group).some((componentId) => tileIds.includes(componentId)));
104
+ }
105
+ // The text after the label, or null when the value holds nothing.
106
+ function valueText(label, value, context, form) {
107
+ if (value.start || value.end) {
108
+ return dateText(value, context, form);
109
+ }
110
+ if (value.values?.length) {
111
+ return pickNames(value.values, context).join(', ');
112
+ }
113
+ if (value.excludeValues?.length) {
114
+ return excludeText(label, value.excludeValues, context, form);
115
+ }
116
+ const keyword = typeof value.value === 'string' ? value.value.trim() : '';
117
+ return rangeText(value, context, form) ?? (keyword ? `"${keyword}"` : null);
118
+ }
119
+ // A date range: a live preset by its name (with its days in a line), else
120
+ // its two days ('…' for an open end).
121
+ function dateText(value, context, form) {
122
+ if (context.preset) {
123
+ const name = relativeLabel(context.preset);
124
+ const days = form === 'line'
125
+ ? formatDayRange(dateBoundString(value.start), dateBoundString(value.end), context.locale)
126
+ : '';
127
+ return days ? `${name} (${days})` : name;
128
+ }
129
+ return `${dateBoundLabel(value.start, context.locale) ?? '…'} – ${dateBoundLabel(value.end, context.locale) ?? '…'}`;
130
+ }
131
+ // Whether a value is worded as values left out: the same order valueText
132
+ // reads a value in, so a value with days or kept picks is never one.
133
+ function excludes(value) {
134
+ return !value.start && !value.end && !value.values?.length && !!value.excludeValues?.length;
135
+ }
136
+ // The values a select leaves out. A line says what happens to the rows with
137
+ // no value: they stay, unless the group's blank label is one of the values
138
+ // left out. While the blank label is unknown (undefined) the line says
139
+ // nothing about them: a blank label among the picks would make 'are kept'
140
+ // false.
141
+ function excludeText(label, values, context, form) {
142
+ const text = pickNames(values, context).join(', ');
143
+ const blankLabel = context.blankLabel;
144
+ if (form === 'chip' || blankLabel === undefined) {
145
+ return text;
146
+ }
147
+ const blank = blankLabel !== null && values.some((value) => String(value) === blankLabel);
148
+ return `${text} (rows with no ${label} ${blank ? 'are left out' : 'are kept'})`;
149
+ }
150
+ // A number range's ends in the report's locale, or null with neither.
151
+ function rangeText(value, context, form) {
152
+ const min = finiteNumber(value.min);
153
+ const max = finiteNumber(value.max);
154
+ const write = (end) => formatPlainNumber(end, context.locale);
155
+ if (min !== undefined && max !== undefined) {
156
+ return `${write(min)} to ${write(max)}${form === 'line' ? ' (both included)' : ''}`;
157
+ }
158
+ if (min !== undefined) {
159
+ return `${write(min)} or more`;
160
+ }
161
+ return max !== undefined ? `${write(max)} or less` : null;
162
+ }
163
+ // The picks' names: the ones the caller resolved, else each pick as stored.
164
+ function pickNames(values, context) {
165
+ const names = context.names;
166
+ return values.map((value, index) => names?.[index] ?? String(value));
167
+ }
168
+ // One group's line, once its picks are named. An exclude line says what
169
+ // happens to the blank rows from the group's blank label, which the server
170
+ // sends on a select group (null: blank rows have none). An older server
171
+ // sends none, and the line then says nothing about them.
172
+ function groupLine(group, input) {
173
+ const snapshot = input.snapshot;
174
+ const value = snapshot.values[group.id];
175
+ if (!value) {
176
+ return of(null);
177
+ }
178
+ const picks = value.start || value.end ? [] : (value.values?.length ? value.values : value.excludeValues ?? []);
179
+ const names$ = picks.length
180
+ ? input.names(group, picks).pipe(catchError(() => of(null)))
181
+ : of(null);
182
+ return names$.pipe(map((names) => {
183
+ const text = filterLineText(group, value, {
184
+ locale: snapshot.formatContext.locale,
185
+ names,
186
+ preset: snapshot.presets[group.id] ?? null,
187
+ pageName: pageName(input.report, group.pageId),
188
+ blankLabel: group.blankLabel,
189
+ }, 'line');
190
+ return text ? { kind: 'group', text, groupId: group.id } : null;
191
+ }));
192
+ }
193
+ // The group-by grain under the report's own name for the control, or null
194
+ // while no grain is picked.
195
+ function groupByLine(input) {
196
+ const frequency = input.snapshot.frequency;
197
+ if (!frequency) {
198
+ return null;
199
+ }
200
+ const option = GRANULARITY_OPTIONS.find((item) => item.value === frequency);
201
+ const label = input.report.config?.groupBy?.label || GROUP_BY_LABEL;
202
+ return { kind: 'groupBy', text: `${label}: ${option?.name ?? frequency}` };
203
+ }
204
+ // One line per drilled chart of the export's pages, while the server drills.
205
+ function drillLines(input) {
206
+ const { report, snapshot, pageId } = input;
207
+ if (!snapshot.features.includes('drill')) {
208
+ return [];
209
+ }
210
+ return (report.pages ?? [])
211
+ .filter((page) => !pageId || page.id === pageId)
212
+ .flatMap((page) => page.components ?? [])
213
+ .filter((component) => component.type === 'chart' && !!snapshot.view.tiles?.[component.id]?.drill?.length)
214
+ .map((component) => ({
215
+ kind: 'drill',
216
+ text: drillLineText(component, snapshot.view.tiles[component.id].drill, snapshot.formatContext),
217
+ componentId: component.id,
218
+ }));
219
+ }
220
+ // The tiles a group's members sit on: the server's list, else the tiles of
221
+ // its enabled members (an older server).
222
+ function groupMemberIds(group) {
223
+ return group.componentIds
224
+ ?? (group.filters ?? []).filter((member) => member.enabled).map((member) => member.componentId);
225
+ }
226
+ // A page's name as the export names it ('Page 2' when it has none), or null
227
+ // for no page.
228
+ function pageName(report, pageId) {
229
+ const index = pageId ? (report.pages ?? []).findIndex((page) => page.id === pageId) : -1;
230
+ if (index < 0) {
231
+ return null;
232
+ }
233
+ return report.pages[index].name || `Page ${index + 1}`;
234
+ }
235
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVwb3J0LWZpbHRlci1saW5lcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9hcHAvcmVwb3J0cy9leHBvcnQvcmVwb3J0LWZpbHRlci1saW5lcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQWMsUUFBUSxFQUFFLEVBQUUsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUNoRCxPQUFPLEVBQUUsVUFBVSxFQUFFLEdBQUcsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBRWpELE9BQU8sRUFBRSxZQUFZLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUNqRSxPQUFPLEVBQUUsY0FBYyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sV0FBVyxDQUFDO0FBUTlELE9BQU8sRUFFTCxtQkFBbUIsR0FLcEIsTUFBTSxnQ0FBZ0MsQ0FBQztBQUN4QyxPQUFPLEVBQUUsY0FBYyxFQUFFLGVBQWUsRUFBRSxhQUFhLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUN4RixPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDeEMsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBR3JELDJFQUEyRTtBQUMzRSwyRUFBMkU7QUFDM0UsNEVBQTRFO0FBQzVFLHlFQUF5RTtBQUN6RSw0RUFBNEU7QUFHNUUsMEVBQTBFO0FBQzFFLHNFQUFzRTtBQUN0RSxvQkFBb0I7QUFDcEIsTUFBTSxDQUFDLE1BQU0sY0FBYyxHQUFHLG1CQUFtQixDQUFDO0FBQ2xELE1BQU0sQ0FBQyxNQUFNLGNBQWMsR0FBRyxzQ0FBc0MsQ0FBQztBQUVyRSwyRUFBMkU7QUFDM0UseUJBQXlCO0FBQ3pCLE1BQU0sQ0FBQyxNQUFNLGNBQWMsR0FBRyxvQkFBb0IsQ0FBQztBQUVuRCxvQ0FBb0M7QUFDcEMsTUFBTSxlQUFlLEdBQUcsUUFBUSxDQUFDO0FBRWpDLG1FQUFtRTtBQUNuRSxNQUFNLGNBQWMsR0FB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LElBQUksS0FBSyxHQUFHLENBQUMsRUFBRSxDQUFDO1FBQ2QsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBRUQsT0FBTyxNQUFNLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksSUFBSSxRQUFRLEtBQUssR0FBRyxDQUFDLEVBQUUsQ0FBQztBQUN6RCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgT2JzZXJ2YWJsZSwgZm9ya0pvaW4sIG9mIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBjYXRjaEVycm9yLCBtYXAgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5cbmltcG9ydCB7IGNydW1iZWRUaXRsZSwgZHJpbGxDcnVtYkxhYmVscyB9IGZyb20gJy4uL2RyaWxsLWNydW1icyc7XG5pbXBvcnQgeyBmb3JtYXREYXlSYW5nZSwgZm9ybWF0UGxhaW5OdW1iZXIgfSBmcm9tICcuLi9mb3JtYXQnO1xuaW1wb3J0IHsgUmVwb3J0RHJpbGxTdGVwIH0gZnJvbSAnLi4vaW50ZXJmYWNlcy9yZXBvcnQtZHJpbGwtc3RlcC5pbnRlcmZhY2UnO1xuaW1wb3J0IHsgUmVwb3J0RXhwb3J0TGluZSB9IGZyb20gJy4uL2ludGVyZmFjZXMvcmVwb3J0LWV4cG9ydC1saW5lLmludGVyZmFjZSc7XG5pbXBvcnQgeyBSZXBvcnRFeHBvcnRMaW5lc0lucHV0IH0gZnJvbSAnLi4vaW50ZXJmYWNlcy9yZXBvcnQtZXhwb3J0LWxpbmVzLWlucHV0LmludGVyZmFjZSc7XG5pbXBvcnQgeyBSZXBvcnRGaWx0ZXJMaW5lQ29udGV4dCB9IGZyb20gJy4uL2ludGVyZmFjZXMvcmVwb3J0LWZpbHRlci1saW5lLWNvbnRleHQuaW50ZXJmYWNlJztcbmltcG9ydCB7IFJlcG9ydEZpbHRlckxpbmVGb3JtIH0gZnJvbSAnLi4vaW50ZXJmYWNlcy9yZXBvcnQtZmlsdGVyLWxpbmUtZm9ybS50eXBlJztcbmltcG9ydCB7IFJlcG9ydEZpbHRlck1hdGNoIH0gZnJvbSAnLi4vaW50ZXJmYWNlcy9yZXBvcnQtZmlsdGVyLW1hdGNoLnR5cGUnO1xuaW1wb3J0IHsgUmVwb3J0Vmlld1N1bW1hcnkgfSBmcm9tICcuLi9pbnRlcmZhY2VzL3JlcG9ydC12aWV3LXN1bW1hcnkuaW50ZXJmYWNlJztcbmltcG9ydCB7XG4gIEZpbHRlckdyb3VwVmFsdWUsXG4gIEdSQU5VTEFSSVRZX09QVElPTlMsXG4gIFJlcG9ydCxcbiAgUmVwb3J0Q29tcG9uZW50LFxuICBSZXBvcnRGaWx0ZXJHcm91cCxcbiAgUmVwb3J0Rm9ybWF0Q29udGV4dCxcbn0gZnJvbSAnLi4vaW50ZXJmYWNlcy9yZXBvcnQuaW50ZXJmYWNlJztcbmltcG9ydCB7IGRhdGVCb3VuZExhYmVsLCBkYXRlQm91bmRTdHJpbmcsIHJlbGF0aXZlTGFiZWwgfSBmcm9tICcuLi9yZXBvcnQtZmlsdGVyLWl0ZW1zJztcbmltcG9ydCB7IGlzVGlsZSB9IGZyb20gJy4uL3JlcG9ydC10aWxlJztcbmltcG9ydCB7IGZpbml0ZU51bWJlciB9IGZyb20gJy4uL3JlcG9ydC12aWV3LWNvbmZpZyc7XG5cblxuLy8gVGhlIHdvcmRzIGEgZmlsZSB1c2VzIGZvciB3aGF0IHRoZSBzY3JlZW4gaGVsZDogZWFjaCBmaWx0ZXIncyB2YWx1ZSwgdGhlXG4vLyBncm91cC1ieSBncmFpbiwgYSBkcmlsbGVkIHRpbGUsIHRoZSBtYXRjaCBhbmQgdGhlIG9wZW4gdmlldy4gVGhlIFBERiBhbmRcbi8vIFBvd2VyUG9pbnQgY292ZXJzIHByaW50IHRoZXNlIGxpbmVzLCBhbmQgdGhlIHppcCBzZW5kcyB0aGVtIChmaWx0ZXJMaW5lcyxcbi8vIHdpdGggZmlsdGVyU3VtbWFyeSBhcyB0aGVpciB0ZXh0IGZvciBhbiBvbGRlciBzZXJ2ZXIpLCBzbyBldmVyeSBleHBvcnRcbi8vIHdvcmRzIG9uZSBmaWx0ZXIgb25lIHdheS4gUHVyZSwgc28gdGhlIG5vZGUgaGFybmVzcyBjaGVja3MgZXZlcnkgd29yZGluZy5cblxuXG4vLyBUaGUgbWF0Y2ggd2hpbGUgdGhlIHJlcG9ydCBiYXIncyBmaWx0ZXJzIGNvbWJpbmUgd2l0aCAnYW55JzogdGhlIGNoaXAnc1xuLy8gd29yZHMsIGFuZCB0aGUgY292ZXIncyBsaW5lLiBUaGUgemlwJ3Mgbm90ZXMgY2FycnkgdGhlIHNlcnZlcidzIG93blxuLy8gc2VudGVuY2UgaW5zdGVhZC5cbmV4cG9ydCBjb25zdCBNQVRDSF9BTllfQ0hJUCA9ICdNYXRjaDogYW55IGZpbHRlcic7XG5leHBvcnQgY29uc3QgTUFUQ0hfQU5ZX0xJTkUgPSAnRmlsdGVycyBpbiB0aGUgcmVwb3J0IGJhcjogbWF0Y2ggYW55JztcblxuLy8gVGhlIHJlcG9ydCBiYXIncyBNYXRjaCBjaGlwIHdoaWxlIHRoZSBmaWx0ZXJzIGNvbWJpbmUgd2l0aCAnYWxsJy4gQSBmaWxlXG4vLyBwcmludHMgbm8gbGluZSBmb3IgaXQuXG5leHBvcnQgY29uc3QgTUFUQ0hfQUxMX0NISVAgPSAnTWF0Y2g6IGFsbCBmaWx0ZXJzJztcblxuLy8gQSBncm91cCdzIGxhYmVsIHdoZW4gaXQgaGFzIG5vbmUuXG5jb25zdCBVTkxBQkVMRURfR1JPVVAgPSAnRmlsdGVyJztcblxuLy8gVGhlIGxhYmVsIG9mIHRoZSBncm91cC1ieSBsaW5lIHdoZW4gdGhlIHJlcG9ydCBuYW1lcyBubyBjb250cm9sLlxuY29uc3QgR1JPVVBfQllfTEFCRUwgPSAnR3JvdXAgQnknO1xuXG5cbi8vIE9uZSBmaWx0ZXIgZ3JvdXAncyB2YWx1ZSBhcyB0ZXh0ICgnUmVnaW9uOiBXZXN0LCBFYXN0JyksIG9yIG51bGwgd2hlbiB0aGVcbi8vIHZhbHVlIGhvbGRzIG5vdGhpbmcuIFZhbHVlcyBsZWZ0IG91dCBzYXkgc28gYmVmb3JlIHRoZSBsYWJlbDogJ0V4Y2x1ZGVcbi8vIFJlZ2lvbjogV2VzdCwgRWFzdCcuICdjaGlwJyBpcyB0aGUgc2hvcnQgZm9ybTsgJ2xpbmUnIGFkZHMgd2hhdCBhIGZpbGVcbi8vIHJlYWRlciBjYW5ub3Qgc2VlIG9uIHNjcmVlbjpcbi8vIC0gZXhjbHVkZTogJ0V4Y2x1ZGUgUmVnaW9uOiBXZXN0LCBFYXN0IChyb3dzIHdpdGggbm8gUmVnaW9uIGFyZSBrZXB0KScsIG9yXG4vLyAgICcuLi4gYXJlIGxlZnQgb3V0JyB3aGVuIHRoZSBibGFuayBsYWJlbCAoY29udGV4dC5ibGFua0xhYmVsKSBpcyBvbmUgb2Zcbi8vICAgdGhlIHZhbHVlcyBsZWZ0IG91dC4gV2l0aG91dCBhIGtub3duIGJsYW5rIGxhYmVsIHRoZSBsaW5lIHNheXMgbm90aGluZ1xuLy8gICBhYm91dCB0aGUgYmxhbmsgcm93cztcbi8vIC0gcmFuZ2U6ICdBbW91bnQ6IDEwIHRvIDUwIChib3RoIGluY2x1ZGVkKSc7IGFuIG9wZW4gZW5kIHJlYWRzICcxMCBvclxuLy8gICBtb3JlJyBvciAnNTAgb3IgbGVzcycgaW4gYm90aCBmb3Jtcztcbi8vIC0gYSBsaXZlIHByZXNldDogJ1JlcG9ydCBQZXJpb2Q6IExhc3QgMzAgZGF5cyAoU2VwIDMg4oCTIE9jdCAyLCAyMDI2KSc7XG4vLyAtIGEgcGFnZSBncm91cDogJ0NvaG9ydCAocGFnZSBcIlJldGVudGlvblwiIG9ubHkpOiAyMDI1Jy5cbi8vIE51bWJlcnMgYW5kIGRhdGVzIGFyZSB3cml0dGVuIGluIHRoZSByZXBvcnQncyBsb2NhbGUsIGFuZCAwIGlzIGEgbnVtYmVyXG4vLyBsaWtlIGFueSBvdGhlci5cbmV4cG9ydCBmdW5jdGlvbiBmaWx0ZXJMaW5lVGV4dChcbiAgZ3JvdXA6IFBpY2s8UmVwb3J0RmlsdGVyR3JvdXAsICdsYWJlbCcgfCAnbGV2ZWwnPixcbiAgdmFsdWU6IEZpbHRlckdyb3VwVmFsdWUgfCBudWxsIHwgdW5kZWZpbmVkLFxuICBjb250ZXh0OiBSZXBvcnRGaWx0ZXJMaW5lQ29udGV4dCxcbiAgZm9ybTogUmVwb3J0RmlsdGVyTGluZUZvcm0sXG4pOiBzdHJpbmcgfCBudWxsIHtcbiAgY29uc3QgbGFiZWwgPSBncm91cC5sYWJlbCB8fCBVTkxBQkVMRURfR1JPVVA7XG4gIGNvbnN0IHRleHQgPSB2YWx1ZSA/IHZhbHVlVGV4dChsYWJlbCwgdmFsdWUsIGNvbnRleHQsIGZvcm0pIDogbnVsbDtcblxuICBpZiAodGV4dCA9PT0gbnVsbCkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgY29uc3QgcGFnZU9ubHkgPSBmb3JtID09PSAnbGluZScgJiYgZ3JvdXAubGV2ZWwgPT09ICdwYWdlJyAmJiBjb250ZXh0LnBhZ2VOYW1lO1xuICBjb25zdCBuYW1lID0gcGFnZU9ubHkgPyBgJHtsYWJlbH0gKHBhZ2UgXCIke2NvbnRleHQucGFnZU5hbWV9XCIgb25seSlgIDogbGFiZWw7XG5cbiAgcmV0dXJuIGAke2V4Y2x1ZGVzKHZhbHVlKSA/ICdFeGNsdWRlICcgOiAnJ30ke25hbWV9OiAke3RleHR9YDtcbn1cblxuLy8gVGhlIG1hdGNoIGFzIHRleHQgd2hpbGUgaXQgaXMgJ2FueScsIGVsc2UgbnVsbDsgdGhlIGNoaXAgYWxzbyB3b3JkcyAnYWxsJy5cbmV4cG9ydCBmdW5jdGlvbiBtYXRjaExpbmVUZXh0KG1hdGNoOiBSZXBvcnRGaWx0ZXJNYXRjaCB8IG51bGwgfCB1bmRlZmluZWQsIGZvcm06IFJlcG9ydEZpbHRlckxpbmVGb3JtKTogc3RyaW5nIHwgbnVsbCB7XG4gIGlmIChtYXRjaCAhPT0gJ2FueScpIHtcbiAgICByZXR1cm4gZm9ybSA9PT0gJ2NoaXAnICYmIG1hdGNoID09PSAnYWxsJyA/IE1BVENIX0FMTF9DSElQIDogbnVsbDtcbiAgfVxuXG4gIHJldHVybiBmb3JtID09PSAnY2hpcCcgPyBNQVRDSF9BTllfQ0hJUCA6IE1BVENIX0FOWV9MSU5FO1xufVxuXG4vLyBBIGRyaWxsZWQgdGlsZSdzIGxpbmU6IGl0cyB0aXRsZSBhbmQgdGhlIGJyZWFkY3J1bWIgb2YgaXRzIHBhdGgsIGluIHRoZVxuLy8gcmVwb3J0J3MgbG9jYWxlICgnUmV2ZW51ZSBieSBQZXJpb2Qg4oC6IDIwMjYg4oC6IFEzJykuXG5leHBvcnQgZnVuY3Rpb24gZHJpbGxMaW5lVGV4dChcbiAgY29tcG9uZW50OiBQaWNrPFJlcG9ydENvbXBvbmVudCwgJ3RpdGxlJz4sXG4gIHBhdGg6IHJlYWRvbmx5IFJlcG9ydERyaWxsU3RlcFtdLFxuICBmb3JtYXRDb250ZXh0OiBQaWNrPFJlcG9ydEZvcm1hdENvbnRleHQsICdsb2NhbGUnPixcbik6IHN0cmluZyB7XG4gIHJldHVybiBjcnVtYmVkVGl0bGUoY29tcG9uZW50LnRpdGxlLCBkcmlsbENydW1iTGFiZWxzKHBhdGgsIGZvcm1hdENvbnRleHQpKTtcbn1cblxuLy8gVGhlIGNvdmVyJ3MgbGluZSBmb3IgdGhlIG9wZW4gc2F2ZWQgdmlldzogJ1ZpZXc6IFwiUTMgTm9ydGhcIiAoc2hhcmVkKScsXG4vLyB3aXRoICcsIGNoYW5nZWQgc2luY2UgaXQgd2FzIG9wZW5lZCcgd2hpbGUgdGhlIHNjcmVlbiBkaWZmZXJzIGZyb20gaXQuXG4vLyBOdWxsIHdoZW4gbm8gdmlldyBpcyBvcGVuLlxuZXhwb3J0IGZ1bmN0aW9uIHZpZXdMaW5lVGV4dChcbiAgdmlldzogUGljazxSZXBvcnRWaWV3U3VtbWFyeSwgJ25hbWUnIHwgJ3NoYXJlZCc+IHwgbnVsbCB8IHVuZGVmaW5lZCxcbiAgY2hhbmdlZDogYm9vbGVhbixcbik6IHN0cmluZyB8IG51bGwge1xuICBpZiAoIXZpZXcpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIGNvbnN0IGxpbmUgPSBgVmlldzogXCIkeyh2aWV3Lm5hbWUgPz8gJycpLnRyaW0oKX1cIiAoJHt2aWV3LnNoYXJlZCA/ICdzaGFyZWQnIDogJ3BlcnNvbmFsJ30pYDtcblxuICByZXR1cm4gY2hhbmdlZCA/IGAke2xpbmV9LCBjaGFuZ2VkIHNpbmNlIGl0IHdhcyBvcGVuZWRgIDogbGluZTtcbn1cblxuLy8gVGhlIGZpbHRlciBsaW5lcyBvZiBhbiBleHBvcnQsIGluIG9yZGVyOiBvbmUgcGVyIGZpbHRlciBncm91cCB3aXRoIGFcbi8vIHZhbHVlICh0aGUgcmVwb3J0J3MgZ3JvdXAgb3JkZXIpLCB0aGUgZ3JvdXAtYnkgbGluZSwgdGhlbiBvbmUgcGVyIGRyaWxsZWRcbi8vIGNoYXJ0IChwYWdlIG9yZGVyKS4gQSBUaGlzIFBhZ2UgZXhwb3J0IChpbnB1dC5wYWdlSWQpIGxpc3RzIG9ubHkgdGhlXG4vLyBncm91cHMgdGhhdCByZWFjaCBhIHRpbGUgb2YgdGhhdCBwYWdlLCBhbmQgb25seSB0aGF0IHBhZ2UncyBkcmlsbGVkXG4vLyBjaGFydHMuIEEgc2VsZWN0J3MgbmFtZXMgYXJlIGEgcmVxdWVzdCwgc28gdGhlIGxpbmVzIGFycml2ZSB0b2dldGhlciBvbmNlXG4vLyBldmVyeSBuYW1lIGlzIGtub3duOyBhIGZhaWxlZCBuYW1lIHJlYWQgd3JpdGVzIHRoZSBwaWNrcyBhcyB0aGV5IGFyZVxuLy8gc3RvcmVkLlxuZXhwb3J0IGZ1bmN0aW9uIGV4cG9ydExpbmVzKGlucHV0OiBSZXBvcnRFeHBvcnRMaW5lc0lucHV0KTogT2JzZXJ2YWJsZTxSZXBvcnRFeHBvcnRMaW5lW10+IHtcbiAgY29uc3QgZ3JvdXBzJCA9IGV4cG9ydEdyb3VwcyhpbnB1dC5yZXBvcnQsIGlucHV0LnBhZ2VJZClcbiAgICAubWFwKChncm91cCkgPT4gZ3JvdXBMaW5lKGdyb3VwLCBpbnB1dCkpO1xuICBjb25zdCByZXN0ID0gW2dyb3VwQnlMaW5lKGlucHV0KSwgLi4uZHJpbGxMaW5lcyhpbnB1dCldXG4gICAgLmZpbHRlcigobGluZSk6IGxpbmUgaXMgUmVwb3J0RXhwb3J0TGluZSA9PiBsaW5lICE9PSBudWxsKTtcblxuICByZXR1cm4gKGdyb3VwcyQubGVuZ3RoID8gZm9ya0pvaW4oZ3JvdXBzJCkgOiBvZihbXSkpXG4gICAgLnBpcGUoXG4gICAgICBtYXAoKGxpbmVzKSA9PiBbXG4gICAgICAgIC4uLmxpbmVzLmZpbHRlcigobGluZSk6IGxpbmUgaXMgUmVwb3J0RXhwb3J0TGluZSA9PiBsaW5lICE9PSBudWxsKSxcbiAgICAgICAgLi4ucmVzdCxcbiAgICAgIF0pLFxuICAgICk7XG59XG5cbi8vIFRoZSBncm91cHMgYW4gZXhwb3J0J3MgbGluZXMgbWF5IG5hbWU6IGV2ZXJ5IGdyb3VwLCBvciBmb3IgYSBUaGlzIFBhZ2Vcbi8vIGV4cG9ydCB0aGUgZ3JvdXBzIHdpdGggYSBtZW1iZXIgdGlsZSBvbiB0aGF0IHBhZ2UuIEEgcGFnZSBncm91cCByZWFjaGVzXG4vLyBvbmx5IGl0cyBvd24gcGFnZS5cbmV4cG9ydCBmdW5jdGlvbiBleHBvcnRHcm91cHMocmVwb3J0OiBSZXBvcnQsIHBhZ2VJZDogbnVtYmVyIHwgbnVsbCk6IFJlcG9ydEZpbHRlckdyb3VwW10ge1xuICBjb25zdCBncm91cHMgPSByZXBvcnQuZmlsdGVyR3JvdXBzID8/IFtdO1xuXG4gIGlmICghcGFnZUlkKSB7XG4gICAgcmV0dXJuIGdyb3VwcztcbiAgfVxuXG4gIGNvbnN0IHBhZ2UgPSAocmVwb3J0LnBhZ2VzID8/IFtdKS5maW5kKChjYW5kaWRhdGUpID0+IGNhbmRpZGF0ZS5pZCA9PT0gcGFnZUlkKTtcbiAgY29uc3QgdGlsZUlkcyA9IChwYWdlPy5jb21wb25lbnRzID8/IFtdKVxuICAgIC5maWx0ZXIoKGNvbXBvbmVudCkgPT4gaXNUaWxlKGNvbXBvbmVudCkpXG4gICAgLm1hcCgoY29tcG9uZW50KSA9PiBjb21wb25lbnQuaWQpO1xuXG4gIHJldHVybiBncm91cHMuZmlsdGVyKChncm91cCkgPT4gKGdyb3VwLmxldmVsICE9PSAncGFnZScgfHwgZ3JvdXAucGFnZUlkID09PSBwYWdlSWQpXG4gICAgJiYgZ3JvdXBNZW1iZXJJZHMoZ3JvdXApLnNvbWUoKGNvbXBvbmVudElkKSA9PiB0aWxlSWRzLmluY2x1ZGVzKGNvbXBvbmVudElkKSkpO1xufVxuXG4vLyBUaGUgdGV4dCBhZnRlciB0aGUgbGFiZWwsIG9yIG51bGwgd2hlbiB0aGUgdmFsdWUgaG9sZHMgbm90aGluZy5cbmZ1bmN0aW9uIHZhbHVlVGV4dChcbiAgbGFiZWw6IHN0cmluZyxcbiAgdmFsdWU6IEZpbHRlckdyb3VwVmFsdWUsXG4gIGNvbnRleHQ6IFJlcG9ydEZpbHRlckxpbmVDb250ZXh0LFxuICBmb3JtOiBSZXBvcnRGaWx0ZXJMaW5lRm9ybSxcbik6IHN0cmluZyB8IG51bGwge1xuICBpZiAodmFsdWUuc3RhcnQgfHwgdmFsdWUuZW5kKSB7XG4gICAgcmV0dXJuIGRhdGVUZXh0KHZhbHVlLCBjb250ZXh0LCBmb3JtKTtcbiAgfVxuXG4gIGlmICh2YWx1ZS52YWx1ZXM/Lmxlbmd0aCkge1xuICAgIHJldHVybiBwaWNrTmFtZXModmFsdWUudmFsdWVzLCBjb250ZXh0KS5qb2luKCcsICcpO1xuICB9XG5cbiAgaWYgKHZhbHVlLmV4Y2x1ZGVWYWx1ZXM/Lmxlbmd0aCkge1xuICAgIHJldHVybiBleGNsdWRlVGV4dChsYWJlbCwgdmFsdWUuZXhjbHVkZVZhbHVlcywgY29udGV4dCwgZm9ybSk7XG4gIH1cblxuICBjb25zdCBrZXl3b3JkID0gdHlwZW9mIHZhbHVlLnZhbHVlID09PSAnc3RyaW5nJyA/IHZhbHVlLnZhbHVlLnRyaW0oKSA6ICcnO1xuXG4gIHJldHVybiByYW5nZVRleHQodmFsdWUsIGNvbnRleHQsIGZvcm0pID8/IChrZXl3b3JkID8gYFwiJHtrZXl3b3JkfVwiYCA6IG51bGwpO1xufVxuXG4vLyBBIGRhdGUgcmFuZ2U6IGEgbGl2ZSBwcmVzZXQgYnkgaXRzIG5hbWUgKHdpdGggaXRzIGRheXMgaW4gYSBsaW5lKSwgZWxzZVxuLy8gaXRzIHR3byBkYXlzICgn4oCmJyBmb3IgYW4gb3BlbiBlbmQpLlxuZnVuY3Rpb24gZGF0ZVRleHQodmFsdWU6IEZpbHRlckdyb3VwVmFsdWUsIGNvbnRleHQ6IFJlcG9ydEZpbHRlckxpbmVDb250ZXh0LCBmb3JtOiBSZXBvcnRGaWx0ZXJMaW5lRm9ybSk6IHN0cmluZyB7XG4gIGlmIChjb250ZXh0LnByZXNldCkge1xuICAgIGNvbnN0IG5hbWUgPSByZWxhdGl2ZUxhYmVsKGNvbnRleHQucHJlc2V0KTtcbiAgICBjb25zdCBkYXlzID0gZm9ybSA9PT0gJ2xpbmUnXG4gICAgICA/IGZvcm1hdERheVJhbmdlKGRhdGVCb3VuZFN0cmluZyh2YWx1ZS5zdGFydCksIGRhdGVCb3VuZFN0cmluZyh2YWx1ZS5lbmQpLCBjb250ZXh0LmxvY2FsZSlcbiAgICAgIDogJyc7XG5cbiAgICByZXR1cm4gZGF5cyA/IGAke25hbWV9ICgke2RheXN9KWAgOiBuYW1lO1xuICB9XG5cbiAgcmV0dXJuIGAke2RhdGVCb3VuZExhYmVsKHZhbHVlLnN0YXJ0LCBjb250ZXh0LmxvY2FsZSkgPz8gJ+KApid9IOKAkyAke2RhdGVCb3VuZExhYmVsKHZhbHVlLmVuZCwgY29udGV4dC5sb2NhbGUpID8/ICfigKYnfWA7XG59XG5cbi8vIFdoZXRoZXIgYSB2YWx1ZSBpcyB3b3JkZWQgYXMgdmFsdWVzIGxlZnQgb3V0OiB0aGUgc2FtZSBvcmRlciB2YWx1ZVRleHRcbi8vIHJlYWRzIGEgdmFsdWUgaW4sIHNvIGEgdmFsdWUgd2l0aCBkYXlzIG9yIGtlcHQgcGlja3MgaXMgbmV2ZXIgb25lLlxuZnVuY3Rpb24gZXhjbHVkZXModmFsdWU6IEZpbHRlckdyb3VwVmFsdWUpOiBib29sZWFuIHtcbiAgcmV0dXJuICF2YWx1ZS5zdGFydCAmJiAhdmFsdWUuZW5kICYmICF2YWx1ZS52YWx1ZXM/Lmxlbmd0aCAmJiAhIXZhbHVlLmV4Y2x1ZGVWYWx1ZXM/Lmxlbmd0aDtcbn1cblxuLy8gVGhlIHZhbHVlcyBhIHNlbGVjdCBsZWF2ZXMgb3V0LiBBIGxpbmUgc2F5cyB3aGF0IGhhcHBlbnMgdG8gdGhlIHJvd3Mgd2l0aFxuLy8gbm8gdmFsdWU6IHRoZXkgc3RheSwgdW5sZXNzIHRoZSBncm91cCdzIGJsYW5rIGxhYmVsIGlzIG9uZSBvZiB0aGUgdmFsdWVzXG4vLyBsZWZ0IG91dC4gV2hpbGUgdGhlIGJsYW5rIGxhYmVsIGlzIHVua25vd24gKHVuZGVmaW5lZCkgdGhlIGxpbmUgc2F5c1xuLy8gbm90aGluZyBhYm91dCB0aGVtOiBhIGJsYW5rIGxhYmVsIGFtb25nIHRoZSBwaWNrcyB3b3VsZCBtYWtlICdhcmUga2VwdCdcbi8vIGZhbHNlLlxuZnVuY3Rpb24gZXhjbHVkZVRleHQoXG4gIGxhYmVsOiBzdHJpbmcsXG4gIHZhbHVlczogdW5rbm93bltdLFxuICBjb250ZXh0OiBSZXBvcnRGaWx0ZXJMaW5lQ29udGV4dCxcbiAgZm9ybTogUmVwb3J0RmlsdGVyTGluZUZvcm0sXG4pOiBzdHJpbmcge1xuICBjb25zdCB0ZXh0ID0gcGlja05hbWVzKHZhbHVlcywgY29udGV4dCkuam9pbignLCAnKTtcbiAgY29uc3QgYmxhbmtMYWJlbCA9IGNvbnRleHQuYmxhbmtMYWJlbDtcblxuICBpZiAoZm9ybSA9PT0gJ2NoaXAnIHx8IGJsYW5rTGFiZWwgPT09IHVuZGVmaW5lZCkge1xuICAgIHJldHVybiB0ZXh0O1xuICB9XG5cbiAgY29uc3QgYmxhbmsgPSBibGFua0xhYmVsICE9PSBudWxsICYmIHZhbHVlcy5zb21lKCh2YWx1ZSkgPT4gU3RyaW5nKHZhbHVlKSA9PT0gYmxhbmtMYWJlbCk7XG5cbiAgcmV0dXJuIGAke3RleHR9IChyb3dzIHdpdGggbm8gJHtsYWJlbH0gJHtibGFuayA/ICdhcmUgbGVmdCBvdXQnIDogJ2FyZSBrZXB0J30pYDtcbn1cblxuLy8gQSBudW1iZXIgcmFuZ2UncyBlbmRzIGluIHRoZSByZXBvcnQncyBsb2NhbGUsIG9yIG51bGwgd2l0aCBuZWl0aGVyLlxuZnVuY3Rpb24gcmFuZ2VUZXh0KHZhbHVlOiBGaWx0ZXJHcm91cFZhbHVlLCBjb250ZXh0OiBSZXBvcnRGaWx0ZXJMaW5lQ29udGV4dCwgZm9ybTogUmVwb3J0RmlsdGVyTGluZUZvcm0pOiBzdHJpbmcgfCBudWxsIHtcbiAgY29uc3QgbWluID0gZmluaXRlTnVtYmVyKHZhbHVlLm1pbik7XG4gIGNvbnN0IG1heCA9IGZpbml0ZU51bWJlcih2YWx1ZS5tYXgpO1xuICBjb25zdCB3cml0ZSA9IChlbmQ6IG51bWJlcikgPT4gZm9ybWF0UGxhaW5OdW1iZXIoZW5kLCBjb250ZXh0LmxvY2FsZSk7XG5cbiAgaWYgKG1pbiAhPT0gdW5kZWZpbmVkICYmIG1heCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgcmV0dXJuIGAke3dyaXRlKG1pbil9IHRvICR7d3JpdGUobWF4KX0ke2Zvcm0gPT09ICdsaW5lJyA/ICcgKGJvdGggaW5jbHVkZWQpJyA6ICcnfWA7XG4gIH1cblxuICBpZiAobWluICE9PSB1bmRlZmluZWQpIHtcbiAgICByZXR1cm4gYCR7d3JpdGUobWluKX0gb3IgbW9yZWA7XG4gIH1cblxuICByZXR1cm4gbWF4ICE9PSB1bmRlZmluZWQgPyBgJHt3cml0ZShtYXgpfSBvciBsZXNzYCA6IG51bGw7XG59XG5cbi8vIFRoZSBwaWNrcycgbmFtZXM6IHRoZSBvbmVzIHRoZSBjYWxsZXIgcmVzb2x2ZWQsIGVsc2UgZWFjaCBwaWNrIGFzIHN0b3JlZC5cbmZ1bmN0aW9uIHBpY2tOYW1lcyh2YWx1ZXM6IHVua25vd25bXSwgY29udGV4dDogUmVwb3J0RmlsdGVyTGluZUNvbnRleHQpOiBzdHJpbmdbXSB7XG4gIGNvbnN0IG5hbWVzID0gY29udGV4dC5uYW1lcztcblxuICByZXR1cm4gdmFsdWVzLm1hcCgodmFsdWUsIGluZGV4KSA9PiBuYW1lcz8uW2luZGV4XSA/PyBTdHJpbmcodmFsdWUpKTtcbn1cblxuLy8gT25lIGdyb3VwJ3MgbGluZSwgb25jZSBpdHMgcGlja3MgYXJlIG5hbWVkLiBBbiBleGNsdWRlIGxpbmUgc2F5cyB3aGF0XG4vLyBoYXBwZW5zIHRvIHRoZSBibGFuayByb3dzIGZyb20gdGhlIGdyb3VwJ3MgYmxhbmsgbGFiZWwsIHdoaWNoIHRoZSBzZXJ2ZXJcbi8vIHNlbmRzIG9uIGEgc2VsZWN0IGdyb3VwIChudWxsOiBibGFuayByb3dzIGhhdmUgbm9uZSkuIEFuIG9sZGVyIHNlcnZlclxuLy8gc2VuZHMgbm9uZSwgYW5kIHRoZSBsaW5lIHRoZW4gc2F5cyBub3RoaW5nIGFib3V0IHRoZW0uXG5mdW5jdGlvbiBncm91cExpbmUoZ3JvdXA6IFJlcG9ydEZpbHRlckdyb3VwLCBpbnB1dDogUmVwb3J0RXhwb3J0TGluZXNJbnB1dCk6IE9ic2VydmFibGU8UmVwb3J0RXhwb3J0TGluZSB8IG51bGw+IHtcbiAgY29uc3Qgc25hcHNob3QgPSBpbnB1dC5zbmFwc2hvdDtcbiAgY29uc3QgdmFsdWUgPSBzbmFwc2hvdC52YWx1ZXNbZ3JvdXAuaWRdO1xuXG4gIGlmICghdmFsdWUpIHtcbiAgICByZXR1cm4gb2YobnVsbCk7XG4gIH1cblxuICBjb25zdCBwaWNrcyA9IHZhbHVlLnN0YXJ0IHx8IHZhbHVlLmVuZCA/IFtdIDogKHZhbHVlLnZhbHVlcz8ubGVuZ3RoID8gdmFsdWUudmFsdWVzIDogdmFsdWUuZXhjbHVkZVZhbHVlcyA/PyBbXSk7XG4gIGNvbnN0IG5hbWVzJCA9IHBpY2tzLmxlbmd0aFxuICAgID8gaW5wdXQubmFtZXMoZ3JvdXAsIHBpY2tzKS5waXBlKGNhdGNoRXJyb3IoKCkgPT4gb2YobnVsbCkpKVxuICAgIDogb2YobnVsbCk7XG5cbiAgcmV0dXJuIG5hbWVzJC5waXBlKFxuICAgIG1hcCgobmFtZXMpOiBSZXBvcnRFeHBvcnRMaW5lIHwgbnVsbCA9PiB7XG4gICAgICBjb25zdCB0ZXh0ID0gZmlsdGVyTGluZVRleHQoZ3JvdXAsIHZhbHVlLCB7XG4gICAgICAgIGxvY2FsZTogc25hcHNob3QuZm9ybWF0Q29udGV4dC5sb2NhbGUsXG4gICAgICAgIG5hbWVzLFxuICAgICAgICBwcmVzZXQ6IHNuYXBzaG90LnByZXNldHNbZ3JvdXAuaWRdID8/IG51bGwsXG4gICAgICAgIHBhZ2VOYW1lOiBwYWdlTmFtZShpbnB1dC5yZXBvcnQsIGdyb3VwLnBhZ2VJZCksXG4gICAgICAgIGJsYW5rTGFiZWw6IGdyb3VwLmJsYW5rTGFiZWwsXG4gICAgICB9LCAnbGluZScpO1xuXG4gICAgICByZXR1cm4gdGV4dCA/IHsga2luZDogJ2dyb3VwJywgdGV4dCwgZ3JvdXBJZDogZ3JvdXAuaWQgfSA6IG51bGw7XG4gICAgfSksXG4gICk7XG59XG5cbi8vIFRoZSBncm91cC1ieSBncmFpbiB1bmRlciB0aGUgcmVwb3J0J3Mgb3duIG5hbWUgZm9yIHRoZSBjb250cm9sLCBvciBudWxsXG4vLyB3aGlsZSBubyBncmFpbiBpcyBwaWNrZWQuXG5mdW5jdGlvbiBncm91cEJ5TGluZShpbnB1dDogUmVwb3J0RXhwb3J0TGluZXNJbnB1dCk6IFJlcG9ydEV4cG9ydExpbmUgfCBudWxsIHtcbiAgY29uc3QgZnJlcXVlbmN5ID0gaW5wdXQuc25hcHNob3QuZnJlcXVlbmN5O1xuXG4gIGlmICghZnJlcXVlbmN5KSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBjb25zdCBvcHRpb24gPSBHUkFOVUxBUklUWV9PUFRJT05TLmZpbmQoKGl0ZW0pID0+IGl0ZW0udmFsdWUgPT09IGZyZXF1ZW5jeSk7XG4gIGNvbnN0IGxhYmVsID0gaW5wdXQucmVwb3J0LmNvbmZpZz8uZ3JvdXBCeT8ubGFiZWwgfHwgR1JPVVBfQllfTEFCRUw7XG5cbiAgcmV0dXJuIHsga2luZDogJ2dyb3VwQnknLCB0ZXh0OiBgJHtsYWJlbH06ICR7b3B0aW9uPy5uYW1lID8/IGZyZXF1ZW5jeX1gIH07XG59XG5cbi8vIE9uZSBsaW5lIHBlciBkcmlsbGVkIGNoYXJ0IG9mIHRoZSBleHBvcnQncyBwYWdlcywgd2hpbGUgdGhlIHNlcnZlciBkcmlsbHMuXG5mdW5jdGlvbiBkcmlsbExpbmVzKGlucHV0OiBSZXBvcnRFeHBvcnRMaW5lc0lucHV0KTogUmVwb3J0RXhwb3J0TGluZVtdIHtcbiAgY29uc3QgeyByZXBvcnQsIHNuYXBzaG90LCBwYWdlSWQgfSA9IGlucHV0O1xuXG4gIGlmICghc25hcHNob3QuZmVhdHVyZXMuaW5jbHVkZXMoJ2RyaWxsJykpIHtcbiAgICByZXR1cm4gW107XG4gIH1cblxuICByZXR1cm4gKHJlcG9ydC5wYWdlcyA/PyBbXSlcbiAgICAuZmlsdGVyKChwYWdlKSA9PiAhcGFnZUlkIHx8IHBhZ2UuaWQgPT09IHBhZ2VJZClcbiAgICAuZmxhdE1hcCgocGFnZSkgPT4gcGFnZS5jb21wb25lbnRzID8/IFtdKVxuICAgIC5maWx0ZXIoKGNvbXBvbmVudCkgPT4gY29tcG9uZW50LnR5cGUgPT09ICdjaGFydCcgJiYgISFzbmFwc2hvdC52aWV3LnRpbGVzPy5bY29tcG9uZW50LmlkXT8uZHJpbGw/Lmxlbmd0aClcbiAgICAubWFwKChjb21wb25lbnQpOiBSZXBvcnRFeHBvcnRMaW5lID0+ICh7XG4gICAgICBraW5kOiAnZHJpbGwnLFxuICAgICAgdGV4dDogZHJpbGxMaW5lVGV4dChjb21wb25lbnQsIHNuYXBzaG90LnZpZXcudGlsZXNbY29tcG9uZW50LmlkXS5kcmlsbCwgc25hcHNob3QuZm9ybWF0Q29udGV4dCksXG4gICAgICBjb21wb25lbnRJZDogY29tcG9uZW50LmlkLFxuICAgIH0pKTtcbn1cblxuLy8gVGhlIHRpbGVzIGEgZ3JvdXAncyBtZW1iZXJzIHNpdCBvbjogdGhlIHNlcnZlcidzIGxpc3QsIGVsc2UgdGhlIHRpbGVzIG9mXG4vLyBpdHMgZW5hYmxlZCBtZW1iZXJzIChhbiBvbGRlciBzZXJ2ZXIpLlxuZnVuY3Rpb24gZ3JvdXBNZW1iZXJJZHMoZ3JvdXA6IFJlcG9ydEZpbHRlckdyb3VwKTogbnVtYmVyW10ge1xuICByZXR1cm4gZ3JvdXAuY29tcG9uZW50SWRzXG4gICAgPz8gKGdyb3VwLmZpbHRlcnMgPz8gW10pLmZpbHRlcigobWVtYmVyKSA9PiBtZW1iZXIuZW5hYmxlZCkubWFwKChtZW1iZXIpID0+IG1lbWJlci5jb21wb25lbnRJZCk7XG59XG5cbi8vIEEgcGFnZSdzIG5hbWUgYXMgdGhlIGV4cG9ydCBuYW1lcyBpdCAoJ1BhZ2UgMicgd2hlbiBpdCBoYXMgbm9uZSksIG9yIG51bGxcbi8vIGZvciBubyBwYWdlLlxuZnVuY3Rpb24gcGFnZU5hbWUocmVwb3J0OiBSZXBvcnQsIHBhZ2VJZDogbnVtYmVyIHwgbnVsbCB8IHVuZGVmaW5lZCk6IHN0cmluZyB8IG51bGwge1xuICBjb25zdCBpbmRleCA9IHBhZ2VJZCA/IChyZXBvcnQucGFnZXMgPz8gW10pLmZpbmRJbmRleCgocGFnZSkgPT4gcGFnZS5pZCA9PT0gcGFnZUlkKSA6IC0xO1xuXG4gIGlmIChpbmRleCA8IDApIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHJldHVybiByZXBvcnQucGFnZXNbaW5kZXhdLm5hbWUgfHwgYFBhZ2UgJHtpbmRleCArIDF9YDtcbn1cbiJdfQ==