@siemens/charts-ng 47.6.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 (41) hide show
  1. package/LICENSE.md +20 -0
  2. package/README.md +47 -0
  3. package/components/index.d.ts +13 -0
  4. package/components/si-chart/index.d.ts +6 -0
  5. package/components/si-chart/si-chart.component.d.ts +341 -0
  6. package/components/si-chart/si-chart.interfaces.d.ts +97 -0
  7. package/components/si-chart-cartesian/index.d.ts +6 -0
  8. package/components/si-chart-cartesian/si-chart-cartesian.component.d.ts +53 -0
  9. package/components/si-chart-cartesian/si-chart-cartesian.interfaces.d.ts +35 -0
  10. package/components/si-chart-circle/index.d.ts +6 -0
  11. package/components/si-chart-circle/si-chart-circle.component.d.ts +18 -0
  12. package/components/si-chart-circle/si-chart-circle.interface.d.ts +38 -0
  13. package/components/si-chart-gauge/index.d.ts +6 -0
  14. package/components/si-chart-gauge/si-chart-gauge.component.d.ts +84 -0
  15. package/components/si-chart-gauge/si-chart-gauge.interface.d.ts +9 -0
  16. package/components/si-chart-loading-spinner/si-chart-loading-spinner.component.d.ts +5 -0
  17. package/components/si-chart-progress/index.d.ts +6 -0
  18. package/components/si-chart-progress/si-chart-progress.component.d.ts +39 -0
  19. package/components/si-chart-progress/si-chart-progress.interface.d.ts +12 -0
  20. package/components/si-chart-progress-bar/index.d.ts +6 -0
  21. package/components/si-chart-progress-bar/si-chart-progress-bar.component.d.ts +28 -0
  22. package/components/si-chart-progress-bar/si-chart-progress-bar.interface.d.ts +12 -0
  23. package/components/si-chart-sankey/index.d.ts +5 -0
  24. package/components/si-chart-sankey/si-chart-sankey.component.d.ts +11 -0
  25. package/components/si-chart-sunburst/index.d.ts +5 -0
  26. package/components/si-chart-sunburst/si-chart-sunburst.component.d.ts +11 -0
  27. package/components/si-custom-legend/index.d.ts +6 -0
  28. package/components/si-custom-legend/si-custom-legend.component.d.ts +25 -0
  29. package/components/si-custom-legend/si-custom-legend.interface.d.ts +33 -0
  30. package/fesm2022/siemens-charts-ng.mjs +3576 -0
  31. package/fesm2022/siemens-charts-ng.mjs.map +1 -0
  32. package/index.d.ts +5 -0
  33. package/package.json +43 -0
  34. package/projects/charts-ng/README.md +47 -0
  35. package/public-api.d.ts +7 -0
  36. package/public-api.module.d.ts +18 -0
  37. package/shared/echarts.custom.d.ts +2 -0
  38. package/shared/echarts.model.d.ts +15 -0
  39. package/shared/index.d.ts +8 -0
  40. package/shared/theme-support.d.ts +394 -0
  41. package/shared/themes/element.d.ts +384 -0
@@ -0,0 +1,3576 @@
1
+ import * as i0 from '@angular/core';
2
+ import { ChangeDetectionStrategy, Component, viewChild, input, output, viewChildren, model, signal, inject, ChangeDetectorRef, NgZone, HostListener, booleanAttribute, LOCALE_ID, computed, SimpleChange, NgModule } from '@angular/core';
3
+ import { Subscription } from 'rxjs';
4
+ import { BarChart, CandlestickChart, CustomChart, GaugeChart, HeatmapChart, LineChart, PieChart, ScatterChart, SankeyChart, SunburstChart } from 'echarts/charts';
5
+ import { AxisPointerComponent, BrushComponent, DataZoomInsideComponent, DataZoomSliderComponent, DatasetComponent, GridComponent, LegendComponent, LegendScrollComponent, MarkAreaComponent, MarkLineComponent, MarkPointComponent, PolarComponent, SingleAxisComponent, TitleComponent, ToolboxComponent, TooltipComponent, VisualMapComponent } from 'echarts/components';
6
+ import * as echarts from 'echarts/core';
7
+ export { echarts };
8
+ import { CanvasRenderer, SVGRenderer } from 'echarts/renderers';
9
+ import { CommonModule } from '@angular/common';
10
+
11
+ /**
12
+ * Copyright Siemens 2016 - 2025.
13
+ * SPDX-License-Identifier: MIT
14
+ */
15
+ echarts.use([
16
+ // components
17
+ AxisPointerComponent,
18
+ BrushComponent,
19
+ DataZoomInsideComponent,
20
+ DataZoomSliderComponent,
21
+ DatasetComponent,
22
+ GridComponent,
23
+ LegendComponent,
24
+ LegendScrollComponent,
25
+ MarkAreaComponent,
26
+ MarkLineComponent,
27
+ MarkPointComponent,
28
+ PolarComponent,
29
+ SingleAxisComponent,
30
+ TitleComponent,
31
+ ToolboxComponent,
32
+ TooltipComponent,
33
+ VisualMapComponent,
34
+ // chart types
35
+ BarChart,
36
+ CandlestickChart,
37
+ CustomChart,
38
+ GaugeChart,
39
+ HeatmapChart,
40
+ LineChart,
41
+ PieChart,
42
+ ScatterChart,
43
+ SankeyChart,
44
+ SunburstChart,
45
+ // renderers
46
+ CanvasRenderer,
47
+ SVGRenderer
48
+ ]);
49
+
50
+ /**
51
+ * Copyright Siemens 2016 - 2025.
52
+ * SPDX-License-Identifier: MIT
53
+ */
54
+ const getProp = (style, prop) => {
55
+ return style.getPropertyValue(prop);
56
+ };
57
+ const candleStickValues = ['open', 'close', 'lowest', 'highest'];
58
+ const tooltipFormatter = (p) => {
59
+ const params = Array.isArray(p) ? p : [p];
60
+ const label = params[0]?.axisValueLabel ?? '';
61
+ let html = label;
62
+ for (const series of params) {
63
+ const isCandle = series.componentSubType === 'candlestick';
64
+ const isPie = series.componentSubType === 'pie';
65
+ const useName = series.name != series.axisValue;
66
+ const name = isPie
67
+ ? series.data.name
68
+ : useName
69
+ ? (series.name ?? series.seriesName)
70
+ : series.seriesName;
71
+ const valIndex = (series.encode.value ?? series.encode.y)[0];
72
+ const value = isCandle
73
+ ? ''
74
+ : isPie
75
+ ? series.percent + '%'
76
+ : Array.isArray(series.value)
77
+ ? series.value[valIndex]
78
+ : series.value;
79
+ html += '<div style="display: flex; align-items: center;">';
80
+ html += series.marker?.replace('margin-right', 'margin-inline-end');
81
+ html += `<span style="margin-inline: 4px 8px">${name}</span>`;
82
+ html += `<span style="margin-inline-start: auto">${value}</span>`;
83
+ html += '</div>';
84
+ if (isCandle) {
85
+ const miniMarker = `<span style="display:inline-block;vertical-align:middle;margin-inline:3px 8px;border-radius:4px;width:4px;height:4px;background:${series.color};"></span>`;
86
+ for (let i = 0; i < candleStickValues.length; i++) {
87
+ const v = candleStickValues[i];
88
+ const idx = series.encode.y[i];
89
+ html += '<div style="display: flex; align-items: center;">';
90
+ html += miniMarker;
91
+ html += `<span style="margin-inline-end: 8px">${v}</span>`;
92
+ html += `<span style="margin-inline-start: auto">${series.value[idx]}</span>`;
93
+ html += '</div>';
94
+ }
95
+ }
96
+ }
97
+ return html;
98
+ };
99
+ const themeElement = {
100
+ name: 'element',
101
+ style: () => {
102
+ const style = window.getComputedStyle(document.documentElement);
103
+ const elementUi0 = getProp(style, '--element-ui-0');
104
+ const elementUi0Hover = getProp(style, '--element-ui-0-hover');
105
+ const elementUi1 = getProp(style, '--element-ui-1');
106
+ const elementUi2 = getProp(style, '--element-ui-2');
107
+ const elementUi3 = getProp(style, '--element-ui-3');
108
+ const elementUi4 = getProp(style, '--element-ui-4');
109
+ const elementBase0 = getProp(style, '--element-base-0');
110
+ const elementBase1 = getProp(style, '--element-base-1');
111
+ const elementTextPrimary = getProp(style, '--element-text-primary');
112
+ const elementTextSecondary = getProp(style, '--element-text-secondary');
113
+ const elementTextInverse = getProp(style, '--element-text-inverse');
114
+ // The order of colors is provided by ux.
115
+ const colorPalettes = {
116
+ default: [
117
+ getProp(style, '--element-data-1'), // $siemens-data-petrol,
118
+ getProp(style, '--element-data-2'), // $siemens-data-turquoise-900,
119
+ getProp(style, '--element-data-4'), // $siemens-data-turquoise-700,
120
+ getProp(style, '--element-data-6'), // $siemens-data-interactive-coral-900,
121
+ getProp(style, '--element-data-5'), // $siemens-data-royal-blue-500,
122
+ getProp(style, '--element-data-7'), // $siemens-data-purple-700,
123
+ getProp(style, '--element-data-8'), // $siemens-data-purple-900,
124
+ getProp(style, '--element-data-9'), // $siemens-data-orchid-700,
125
+ getProp(style, '--element-data-11'), // $siemens-data-plum-900,
126
+ getProp(style, '--element-data-12'), // $siemens-data-plum-500
127
+ getProp(style, '--element-data-13'), // $siemens-data-royal-blue-700,
128
+ getProp(style, '--element-data-16'), // $siemens-data-sand-700,
129
+ getProp(style, '--element-data-17'), // $siemens-data-deep-blue-700
130
+ getProp(style, '--element-data-3'), // $siemens-data-green-700,
131
+ getProp(style, '--element-data-10'), // $siemens-data-red-700,
132
+ getProp(style, '--element-data-14'), // $siemens-data-orange-900,
133
+ getProp(style, '--element-data-15') // $siemens-data-yellow-900,
134
+ ]
135
+ };
136
+ const gradientColors = {
137
+ default: [
138
+ getProp(style, '--element-data-1'), // $siemens-data-petrol,
139
+ getProp(style, '--element-data-2') // $siemens-data-turquoise-900,
140
+ ]
141
+ };
142
+ const axisFontSize = 12;
143
+ const axisLineHeight = 12;
144
+ const axisLineColor = elementUi4;
145
+ const rootFontSizeRaw = getProp(style, 'font-size');
146
+ const rootFontSize = rootFontSizeRaw.endsWith('px') ? parseInt(rootFontSizeRaw) : 16;
147
+ // value based on body-2
148
+ const fontSize = rootFontSize * 0.875;
149
+ // diverging here by intention
150
+ const lineHeight = fontSize;
151
+ const textColor = elementTextPrimary;
152
+ const candlestickBull = colorPalettes.default[4];
153
+ const candlestickBear = colorPalettes.default[12];
154
+ const dataZoomFillerColor = echarts.color.modifyAlpha(elementUi4, 0.4);
155
+ const dataZoomBrushColor = elementUi0;
156
+ const dataZoomAreaColor = elementUi4;
157
+ const dataZoomLineColor = elementUi2;
158
+ const dataZoomHandleIcon = 'path://M-9.35,34.56V42m0-40V9.5m-2,0h4a2,2,0,0,1,2,2v21a2,2,0,0,1-2,2h-4a2,2,0,0,1-2-2v-21A2,2,0,0,1-11.35,9.5Z';
159
+ const dataZoomHandleColor = elementUi0;
160
+ const tooltipBackground = echarts.color.modifyAlpha(elementUi1, 0.8);
161
+ const rtl = style.direction === 'rtl';
162
+ // For E2E testing to get rid of font-loading instability.
163
+ const fontFamily = navigator.webdriver ? 'sans-serif' : undefined;
164
+ return {
165
+ textStyle: {
166
+ fontFamily
167
+ },
168
+ color: colorPalettes.default,
169
+ gradientColor: gradientColors.default,
170
+ backgroundColor: 'transparent',
171
+ animationDuration: 700,
172
+ title: {
173
+ padding: [10, 0, 0, 10],
174
+ textStyle: {
175
+ fontFamily,
176
+ lineHeight,
177
+ fontSize,
178
+ color: textColor
179
+ },
180
+ subtextStyle: {
181
+ fontFamily,
182
+ lineHeight,
183
+ fontSize,
184
+ color: elementTextSecondary
185
+ }
186
+ },
187
+ legend: {
188
+ backgroundColor: 'transparent',
189
+ inactiveColor: elementUi3,
190
+ left: 'auto',
191
+ right: 20,
192
+ top: 35,
193
+ textStyle: {
194
+ fontFamily,
195
+ color: textColor,
196
+ lineHeight,
197
+ fontSize
198
+ },
199
+ icon: 'circle',
200
+ pageTextStyle: {
201
+ color: textColor
202
+ },
203
+ itemStyle: {
204
+ borderWidth: 0,
205
+ itemGap: 12
206
+ }
207
+ },
208
+ tooltip: {
209
+ borderWidth: 0,
210
+ backgroundColor: tooltipBackground,
211
+ textStyle: {
212
+ fontFamily,
213
+ color: 'var(--element-text-inverse)',
214
+ fontWeight: 400
215
+ },
216
+ padding: [8, 12, 8, 12],
217
+ axisPointer: {
218
+ crossStyle: {
219
+ color: elementUi3,
220
+ width: 1
221
+ }
222
+ },
223
+ formatter: tooltipFormatter
224
+ },
225
+ axisPointer: {
226
+ label: {
227
+ fontFamily,
228
+ color: elementTextInverse,
229
+ backgroundColor: elementUi1,
230
+ lineHeight: axisLineHeight,
231
+ fontSize: axisFontSize
232
+ },
233
+ lineStyle: {
234
+ color: elementUi3,
235
+ width: 2
236
+ },
237
+ handle: {
238
+ color: 'rgba(0,0,0,0)',
239
+ margin: 0
240
+ }
241
+ },
242
+ grid: {
243
+ top: 85,
244
+ left: 32,
245
+ right: 32,
246
+ bottom: 30,
247
+ containLabel: true
248
+ },
249
+ valueAxis: {
250
+ nameTextStyle: {
251
+ fontFamily,
252
+ color: elementTextSecondary
253
+ },
254
+ axisLine: {
255
+ show: true,
256
+ lineStyle: {
257
+ color: axisLineColor
258
+ }
259
+ },
260
+ axisLabel: {
261
+ fontFamily,
262
+ color: textColor,
263
+ lineHeight: axisLineHeight,
264
+ fontSize: axisFontSize,
265
+ hideOverlap: true
266
+ },
267
+ axisTick: {
268
+ alignWithLabel: true
269
+ },
270
+ splitLine: {
271
+ lineStyle: {
272
+ color: axisLineColor
273
+ }
274
+ }
275
+ },
276
+ timeAxis: {
277
+ inverse: rtl,
278
+ nameTextStyle: {
279
+ fontFamily,
280
+ color: elementTextSecondary
281
+ },
282
+ axisLine: {
283
+ show: true,
284
+ lineStyle: {
285
+ color: axisLineColor
286
+ }
287
+ },
288
+ axisLabel: {
289
+ fontFamily,
290
+ color: textColor,
291
+ lineHeight: axisLineHeight,
292
+ fontSize: axisFontSize,
293
+ hideOverlap: true
294
+ },
295
+ axisTick: {
296
+ alignWithLabel: true
297
+ },
298
+ splitLine: {
299
+ lineStyle: {
300
+ color: axisLineColor
301
+ }
302
+ }
303
+ },
304
+ categoryAxis: {
305
+ inverse: rtl,
306
+ nameTextStyle: {
307
+ fontFamily,
308
+ color: elementTextSecondary
309
+ },
310
+ axisLine: {
311
+ show: true,
312
+ lineStyle: {
313
+ color: axisLineColor
314
+ }
315
+ },
316
+ axisLabel: {
317
+ fontFamily,
318
+ color: textColor,
319
+ lineHeight: axisLineHeight,
320
+ fontSize: axisFontSize,
321
+ hideOverlap: true
322
+ },
323
+ axisTick: {
324
+ alignWithLabel: true
325
+ },
326
+ splitLine: {
327
+ lineStyle: {
328
+ color: axisLineColor
329
+ }
330
+ }
331
+ },
332
+ dataZoom: {
333
+ textStyle: {
334
+ fontFamily,
335
+ color: textColor,
336
+ lineHeight: axisLineHeight,
337
+ fontSize: axisFontSize
338
+ },
339
+ borderColor: elementUi4,
340
+ fillerColor: dataZoomFillerColor,
341
+ handleIcon: dataZoomHandleIcon,
342
+ handleStyle: {
343
+ color: dataZoomHandleColor,
344
+ borderColor: elementUi4
345
+ },
346
+ moveHandleStyle: {
347
+ color: elementUi4,
348
+ opacity: 1
349
+ },
350
+ brushStyle: {
351
+ color: dataZoomBrushColor
352
+ },
353
+ dataBackground: {
354
+ areaStyle: {
355
+ color: dataZoomAreaColor
356
+ },
357
+ lineStyle: {
358
+ color: dataZoomLineColor
359
+ }
360
+ },
361
+ selectedDataBackground: {
362
+ areaStyle: {
363
+ color: dataZoomLineColor
364
+ },
365
+ lineStyle: {
366
+ color: dataZoomLineColor
367
+ }
368
+ },
369
+ emphasis: {
370
+ moveHandleStyle: {
371
+ color: elementUi0Hover,
372
+ opacity: 1
373
+ },
374
+ handleStyle: {
375
+ color: elementUi0Hover,
376
+ borderColor: elementUi4
377
+ }
378
+ }
379
+ },
380
+ toolbox: {
381
+ feature: {
382
+ dataZoom: {
383
+ brushStyle: {
384
+ color: dataZoomFillerColor
385
+ }
386
+ }
387
+ }
388
+ },
389
+ // different chart types
390
+ graph: {
391
+ color: colorPalettes.default
392
+ },
393
+ bar: {
394
+ barGap: 0,
395
+ label: {
396
+ fontFamily,
397
+ color: elementTextSecondary,
398
+ fontSize
399
+ }
400
+ },
401
+ line: {
402
+ areaStyle: {
403
+ opacity: 0.3
404
+ },
405
+ symbol: 'circle'
406
+ },
407
+ pie: {
408
+ label: {
409
+ fontFamily,
410
+ formatter: '{d}%',
411
+ color: elementTextSecondary,
412
+ lineHeight,
413
+ fontSize
414
+ },
415
+ labelLine: {
416
+ lineStyle: {
417
+ color: elementTextSecondary
418
+ }
419
+ },
420
+ itemStyle: {
421
+ borderWidth: 2,
422
+ borderColor: elementBase1
423
+ }
424
+ },
425
+ candlestick: {
426
+ itemStyle: {
427
+ color: candlestickBull,
428
+ color0: candlestickBear,
429
+ borderColor: candlestickBull,
430
+ borderColor0: candlestickBear
431
+ }
432
+ },
433
+ gauge: {
434
+ detail: {
435
+ color: elementTextPrimary,
436
+ rich: {
437
+ value: {
438
+ color: elementTextPrimary
439
+ },
440
+ unit: {
441
+ color: elementTextPrimary
442
+ }
443
+ }
444
+ },
445
+ axisLabel: {
446
+ fontFamily,
447
+ color: elementTextPrimary
448
+ },
449
+ axisTick: {
450
+ lineStyle: {
451
+ color: axisLineColor
452
+ }
453
+ },
454
+ splitLine: {
455
+ lineStyle: {
456
+ color: axisLineColor
457
+ }
458
+ }
459
+ },
460
+ sankey: {
461
+ label: {
462
+ fontFamily,
463
+ textBorderColor: 'transparent',
464
+ color: textColor
465
+ }
466
+ },
467
+ sunburst: {
468
+ label: {
469
+ fontFamily,
470
+ textBorderColor: 'transparent',
471
+ color: textColor
472
+ }
473
+ },
474
+ simpl: {
475
+ colorPalettes,
476
+ dataZoom: {
477
+ options: {
478
+ height: 36,
479
+ bottom: 20
480
+ },
481
+ grid: {
482
+ bottom: 80
483
+ }
484
+ },
485
+ timeRangeBar: {
486
+ height: 32
487
+ },
488
+ externalZoomSlider: {
489
+ grid: {
490
+ bottom: 10
491
+ }
492
+ },
493
+ legendLeft: {
494
+ left: 10,
495
+ width: '45%'
496
+ },
497
+ legendRight: {
498
+ right: 20,
499
+ width: '45%'
500
+ },
501
+ noTitle: {
502
+ grid: {
503
+ top: 60
504
+ },
505
+ legend: {
506
+ top: 15
507
+ }
508
+ },
509
+ subTitle: {
510
+ grid: {
511
+ top: 110
512
+ },
513
+ legend: {
514
+ top: 65
515
+ }
516
+ },
517
+ customLegend: {
518
+ grid: {
519
+ top: 64
520
+ }
521
+ },
522
+ progress: {
523
+ itemWidth: 6,
524
+ itemGap: 6,
525
+ grey: elementUi4
526
+ },
527
+ progressBar: {
528
+ labelColor: textColor,
529
+ itemWidth: 20,
530
+ grid: {
531
+ left: 16,
532
+ right: 52,
533
+ containLabel: true
534
+ }
535
+ },
536
+ gauge: {
537
+ grey: elementBase0,
538
+ value: elementTextPrimary,
539
+ unit: elementUi3,
540
+ defaultColor: elementUi0
541
+ }
542
+ }
543
+ };
544
+ }
545
+ };
546
+
547
+ /**
548
+ * Copyright Siemens 2016 - 2025.
549
+ * SPDX-License-Identifier: MIT
550
+ */
551
+ const themeSupport = {
552
+ _defaultTheme: themeElement,
553
+ _themes: {},
554
+ registerTheme(theme) {
555
+ if (theme.name) {
556
+ this._themes[theme.name] = theme;
557
+ }
558
+ },
559
+ getThemeNames() {
560
+ return Object.keys(this._themes);
561
+ },
562
+ getThemeByName(name) {
563
+ return this._themes[name];
564
+ },
565
+ setDefault(theme) {
566
+ this._defaultTheme = theme;
567
+ },
568
+ getDefault() {
569
+ return this._defaultTheme;
570
+ }
571
+ };
572
+
573
+ /**
574
+ * Copyright Siemens 2016 - 2025.
575
+ * SPDX-License-Identifier: MIT
576
+ */
577
+ class SiChartLoadingSpinnerComponent {
578
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.6", ngImport: i0, type: SiChartLoadingSpinnerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
579
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.0.6", type: SiChartLoadingSpinnerComponent, isStandalone: true, selector: "si-chart-loading-spinner", ngImport: i0, template: "<div class=\"loading\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\">\n <g>\n <path d=\"M256,156a16,16,0,0,1-16-16V80a16,16,0,0,1,32,0v60A16,16,0,0,1,256,156Z\" />\n <path\n d=\"M314.78,175.1a16,16,0,0,1-3.54-22.35l35.27-48.54A16,16,0,1,1,372.39,123l-35.26,48.54A16,16,0,0,1,314.78,175.1Z\"\n />\n <path\n d=\"M351.11,225.1a16,16,0,0,1,10.27-20.16l57.06-18.54a16,16,0,1,1,9.89,30.43l-57.06,18.54A16,16,0,0,1,351.11,225.1Z\"\n />\n <path\n d=\"M351.11,286.9a16,16,0,0,1,20.16-10.27l57.06,18.54a16,16,0,1,1-9.89,30.43l-57.06-18.54A16,16,0,0,1,351.11,286.9Z\"\n />\n <path\n d=\"M314.78,336.9a16,16,0,0,1,22.35,3.54L372.39,389a16,16,0,1,1-25.88,18.81l-35.27-48.54A16,16,0,0,1,314.78,336.9Z\"\n />\n <path d=\"M256,356a16,16,0,0,1,16,16v60a16,16,0,0,1-32,0V372A16,16,0,0,1,256,356Z\" />\n <path\n d=\"M197.22,336.9a16,16,0,0,1,3.54,22.35l-35.27,48.54A16,16,0,1,1,139.61,389l35.26-48.54A16,16,0,0,1,197.22,336.9Z\"\n />\n <path\n d=\"M160.89,286.9a16,16,0,0,1-10.27,20.16L93.56,325.6a16,16,0,0,1-9.89-30.43l57.06-18.54A16,16,0,0,1,160.89,286.9Z\"\n />\n <path\n d=\"M160.89,225.1a16,16,0,0,1-20.16,10.27L83.67,216.83a16,16,0,1,1,9.89-30.43l57.06,18.54A16,16,0,0,1,160.89,225.1Z\"\n />\n <path\n d=\"M197.22,175.1a16,16,0,0,1-22.35-3.54L139.61,123a16,16,0,1,1,25.88-18.81l35.27,48.54A16,16,0,0,1,197.22,175.1Z\"\n />\n </g>\n </svg>\n</div>\n", styles: ["@keyframes spinner-fade{0%{opacity:1}to{opacity:.05}}.loading{display:block;text-align:center}svg{inline-size:var(--loading-spinner-size, 64px);block-size:var(--loading-spinner-size, 64px)}path{fill:var(--element-ui-2, #656a6f);animation:spinner-fade 1s infinite linear}path:nth-child(1){animation-delay:0s;opacity:1}path:nth-child(2){animation-delay:.1s;opacity:.9}path:nth-child(3){animation-delay:.2s;opacity:.8}path:nth-child(4){animation-delay:.3s;opacity:.7}path:nth-child(5){animation-delay:.4s;opacity:.6}path:nth-child(6){animation-delay:.5s;opacity:.5}path:nth-child(7){animation-delay:.6s;opacity:.4}path:nth-child(8){animation-delay:.7s;opacity:.3}path:nth-child(9){animation-delay:.8s;opacity:.2}path:nth-child(10){animation-delay:.9s;opacity:.1}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
580
+ }
581
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.6", ngImport: i0, type: SiChartLoadingSpinnerComponent, decorators: [{
582
+ type: Component,
583
+ args: [{ selector: 'si-chart-loading-spinner', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"loading\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\">\n <g>\n <path d=\"M256,156a16,16,0,0,1-16-16V80a16,16,0,0,1,32,0v60A16,16,0,0,1,256,156Z\" />\n <path\n d=\"M314.78,175.1a16,16,0,0,1-3.54-22.35l35.27-48.54A16,16,0,1,1,372.39,123l-35.26,48.54A16,16,0,0,1,314.78,175.1Z\"\n />\n <path\n d=\"M351.11,225.1a16,16,0,0,1,10.27-20.16l57.06-18.54a16,16,0,1,1,9.89,30.43l-57.06,18.54A16,16,0,0,1,351.11,225.1Z\"\n />\n <path\n d=\"M351.11,286.9a16,16,0,0,1,20.16-10.27l57.06,18.54a16,16,0,1,1-9.89,30.43l-57.06-18.54A16,16,0,0,1,351.11,286.9Z\"\n />\n <path\n d=\"M314.78,336.9a16,16,0,0,1,22.35,3.54L372.39,389a16,16,0,1,1-25.88,18.81l-35.27-48.54A16,16,0,0,1,314.78,336.9Z\"\n />\n <path d=\"M256,356a16,16,0,0,1,16,16v60a16,16,0,0,1-32,0V372A16,16,0,0,1,256,356Z\" />\n <path\n d=\"M197.22,336.9a16,16,0,0,1,3.54,22.35l-35.27,48.54A16,16,0,1,1,139.61,389l35.26-48.54A16,16,0,0,1,197.22,336.9Z\"\n />\n <path\n d=\"M160.89,286.9a16,16,0,0,1-10.27,20.16L93.56,325.6a16,16,0,0,1-9.89-30.43l57.06-18.54A16,16,0,0,1,160.89,286.9Z\"\n />\n <path\n d=\"M160.89,225.1a16,16,0,0,1-20.16,10.27L83.67,216.83a16,16,0,1,1,9.89-30.43l57.06,18.54A16,16,0,0,1,160.89,225.1Z\"\n />\n <path\n d=\"M197.22,175.1a16,16,0,0,1-22.35-3.54L139.61,123a16,16,0,1,1,25.88-18.81l35.27,48.54A16,16,0,0,1,197.22,175.1Z\"\n />\n </g>\n </svg>\n</div>\n", styles: ["@keyframes spinner-fade{0%{opacity:1}to{opacity:.05}}.loading{display:block;text-align:center}svg{inline-size:var(--loading-spinner-size, 64px);block-size:var(--loading-spinner-size, 64px)}path{fill:var(--element-ui-2, #656a6f);animation:spinner-fade 1s infinite linear}path:nth-child(1){animation-delay:0s;opacity:1}path:nth-child(2){animation-delay:.1s;opacity:.9}path:nth-child(3){animation-delay:.2s;opacity:.8}path:nth-child(4){animation-delay:.3s;opacity:.7}path:nth-child(5){animation-delay:.4s;opacity:.6}path:nth-child(6){animation-delay:.5s;opacity:.5}path:nth-child(7){animation-delay:.6s;opacity:.4}path:nth-child(8){animation-delay:.7s;opacity:.3}path:nth-child(9){animation-delay:.8s;opacity:.2}path:nth-child(10){animation-delay:.9s;opacity:.1}\n"] }]
584
+ }] });
585
+
586
+ /**
587
+ * Copyright Siemens 2016 - 2025.
588
+ * SPDX-License-Identifier: MIT
589
+ */
590
+ class SiCustomLegendComponent {
591
+ /** @internal */
592
+ customLegendContainer = viewChild.required('customLegendContainer');
593
+ customLegend = input();
594
+ title = input();
595
+ subTitle = input();
596
+ titleColor = input();
597
+ subTitleColor = input();
598
+ textColor = input();
599
+ legendIconClickEvent = output();
600
+ legendClickEvent = output();
601
+ legendHoverStartEvent = output();
602
+ legendHoverEndEvent = output();
603
+ legendIconClick(legend) {
604
+ legend.selected = !legend.selected;
605
+ this.legendIconClickEvent.emit(legend);
606
+ }
607
+ legendClick(legend) {
608
+ legend.selected = !legend.selected;
609
+ this.legendClickEvent.emit(legend);
610
+ }
611
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.6", ngImport: i0, type: SiCustomLegendComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
612
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.6", type: SiCustomLegendComponent, isStandalone: true, selector: "si-custom-legend", inputs: { customLegend: { classPropertyName: "customLegend", publicName: "customLegend", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, subTitle: { classPropertyName: "subTitle", publicName: "subTitle", isSignal: true, isRequired: false, transformFunction: null }, titleColor: { classPropertyName: "titleColor", publicName: "titleColor", isSignal: true, isRequired: false, transformFunction: null }, subTitleColor: { classPropertyName: "subTitleColor", publicName: "subTitleColor", isSignal: true, isRequired: false, transformFunction: null }, textColor: { classPropertyName: "textColor", publicName: "textColor", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { legendIconClickEvent: "legendIconClickEvent", legendClickEvent: "legendClickEvent", legendHoverStartEvent: "legendHoverStartEvent", legendHoverEndEvent: "legendHoverEndEvent" }, viewQueries: [{ propertyName: "customLegendContainer", first: true, predicate: ["customLegendContainer"], descendants: true, isSignal: true }], ngImport: i0, template: "@if (customLegend() && customLegend()?.customLegends) {\n <div #customLegendContainer class=\"legend-container si-body-2\">\n @for (leg of customLegend()?.customLegends; track legendIndex; let legendIndex = $index) {\n @if (legendIndex === 0 && leg && leg.list && leg.list.length > 0) {\n <div\n class=\"left-legends legend-item-container\"\n [class.legend-empty]=\"\n customLegend()?.legendAxis !== 'left' && customLegend()?.legendAxis !== 'both'\n \"\n [class.legend-single-axis]=\"customLegend()?.legendAxis === 'left'\"\n [class.both-legend-container]=\"customLegend()?.legendAxis === 'both'\"\n >\n <div\n class=\"both-scenario-left-unit-container\"\n [class.left-scenario-unit-container]=\"customLegend()?.legendAxis === 'left'\"\n >\n <span class=\"text-secondary\">{{ leg.unit }}</span>\n </div>\n <div\n class=\"legend-item-container both-scenario-legend-container custom-legend-left\"\n [class.legend-single-axis]=\"customLegend()?.legendAxis === 'left'\"\n >\n @for (legendItem of leg.list; track legendItem.name) {\n <div class=\"legend-item\" [class.hidden-legend]=\"!legendItem.selected\">\n <div\n class=\"me-2 mb-2\"\n (click)=\"legendIconClick(legendItem)\"\n (mouseenter)=\"legendHoverStartEvent.emit(legendItem)\"\n (mouseleave)=\"legendHoverEndEvent.emit(legendItem)\"\n >\n <svg width=\"12\" height=\"12\" xmlns=\"http://www.w3.org/2000/svg\">\n <path [attr.d]=\"legendItem.symbol\" [attr.fill]=\"legendItem.color\" />\n </svg>\n </div>\n <span\n class=\"legend-text text-truncate\"\n [style.color]=\"textColor()\"\n (click)=\"legendClick(legendItem)\"\n (mouseenter)=\"legendHoverStartEvent.emit(legendItem)\"\n (mouseleave)=\"legendHoverEndEvent.emit(legendItem)\"\n >\n {{ legendItem.displayName }}\n </span>\n @if (legendItem.tooltip) {\n <div class=\"tooltip show bs-tooltip-bottom\" role=\"tooltip\">\n <div class=\"tooltip-arrow\"></div>\n <div class=\"tooltip-inner\">{{ legendItem.tooltip }}</div>\n </div>\n }\n </div>\n }\n </div>\n </div>\n }\n }\n\n @for (leg of customLegend()?.customLegends; track legendIndex; let legendIndex = $index) {\n @if (legendIndex === 1 && leg && leg.list && leg.list.length > 0) {\n <div\n class=\"right-legends legend-item-container\"\n [class.legend-empty]=\"\n customLegend()?.legendAxis !== 'right' && customLegend()?.legendAxis !== 'both'\n \"\n [class.legend-single-axis]=\"customLegend()?.legendAxis === 'right'\"\n [class.both-legend-container]=\"customLegend()?.legendAxis === 'both'\"\n >\n <div\n class=\"legend-item-container custom-legend-right legend-item-container-right-floating-inner\"\n >\n @for (legendItem of leg.list; track legendItem.name) {\n <div\n class=\"legend-item legend-item-right\"\n [class.hidden-legend]=\"!legendItem.selected\"\n >\n <span\n class=\"legend-text text-truncate\"\n [style.color]=\"textColor()\"\n (click)=\"legendClick(legendItem)\"\n >\n {{ legendItem.displayName }}\n </span>\n <div class=\"right-legend-circle\" (click)=\"legendIconClick(legendItem)\">\n <svg width=\"12\" height=\"12\" xmlns=\"http://www.w3.org/2000/svg\">\n <path [attr.d]=\"legendItem.symbol\" [attr.fill]=\"legendItem.color\" />\n </svg>\n </div>\n @if (legendItem.tooltip) {\n <div class=\"tooltip show bs-tooltip-bottom\" role=\"tooltip\">\n <div class=\"tooltip-arrow\"></div>\n <div class=\"tooltip-inner\">{{ legendItem.tooltip }}</div>\n </div>\n }\n </div>\n }\n </div>\n <div\n class=\"both-scenario-right-unit-container\"\n [class.right-scenario-unit-container]=\"customLegend()?.legendAxis === 'right'\"\n >\n <span class=\"right-unit-text text-secondary\">{{ leg.unit }}</span>\n </div>\n </div>\n }\n }\n </div>\n}\n", styles: [":host{--flex-dir1: row;--flex-dir2: row-reverse;margin:12px;display:flex;flex-direction:column}:host-context(:dir(rtl)){--flex-dir1: row-reverse;--flex-dir2: row}:host-context([dir=rtl]){--flex-dir1: row-reverse;--flex-dir2: row}.legend-container{display:flex;flex-direction:var(--flex-dir1);max-height:40px;flex:1 1 auto}.legend-item-container{width:50%;vertical-align:top;display:flex;flex-wrap:wrap;flex:1 1 100%;flex-direction:var(--flex-dir1);height:fit-content;max-height:40px;max-width:50%;min-width:50%;overflow-y:auto;scrollbar-width:thin}.legend-item-container::-webkit-scrollbar{width:4px;height:6px;background-color:var(--element-base-0, #f0f2f5)}.legend-item-container::-webkit-scrollbar-thumb{border-radius:12px;-webkit-box-shadow:inset 0 0 6px rgba(0,0,0,.3)}.legend-item-container::-webkit-scrollbar-track{-webkit-box-shadow:inset 0 0 6px rgba(0,0,0,.3);border-radius:12px;background-color:var(--element-base-0, #f0f2f5)}.legend-item-container .custom-legend-left{flex-direction:var(--flex-dir1);flex:1 1 50%}.legend-item-container .custom-legend-right{flex-direction:var(--flex-dir2);flex:1 1 50%}.legend-item-container-right-floating-inner{max-width:calc(100% - 32px);min-width:calc(100% - 32px);padding-right:12px;float:left}.legend-single-axis{max-width:100%;min-width:100%}.legend-empty{width:0%}.tooltip{display:none;max-width:375px;word-break:break-word;margin-top:16px;inset-block-start:0;margin-inline-start:-6px}.tooltip-arrow{left:12px}.legend-item{cursor:pointer;margin-right:8px;display:flex;flex-direction:var(--flex-dir1);align-items:center;height:20px;position:initial;width:calc(100% - 12px);max-width:fit-content}.legend-item:hover .tooltip{display:block}.legend-item-right{margin-right:0;margin-left:12px}.right-legend-circle{margin-right:0;margin-left:4px}.legend-text{box-sizing:inherit;display:inline;cursor:pointer}.hidden-legend .right-legend-circle,.hidden-legend div:first-child,.hidden-legend .legend-text{opacity:.4}.both-scenario-left-unit-container,.both-scenario-right-unit-container{min-width:32px;max-width:32px;overflow:hidden}.both-scenario-right-unit-container{max-height:100%}.both-scenario-left-unit-container{min-height:100%}.both-scenario-legend-container{max-width:calc(100% - 32px);min-width:calc(100% - 32px);padding-left:12px}.right-unit-text{min-width:100%;min-height:100%;padding-left:2px}.left-legends{padding-right:36px}.right-legends{padding-left:28px}.both-legend-container{padding-right:0;padding-left:0}\n"] });
613
+ }
614
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.6", ngImport: i0, type: SiCustomLegendComponent, decorators: [{
615
+ type: Component,
616
+ args: [{ selector: 'si-custom-legend', template: "@if (customLegend() && customLegend()?.customLegends) {\n <div #customLegendContainer class=\"legend-container si-body-2\">\n @for (leg of customLegend()?.customLegends; track legendIndex; let legendIndex = $index) {\n @if (legendIndex === 0 && leg && leg.list && leg.list.length > 0) {\n <div\n class=\"left-legends legend-item-container\"\n [class.legend-empty]=\"\n customLegend()?.legendAxis !== 'left' && customLegend()?.legendAxis !== 'both'\n \"\n [class.legend-single-axis]=\"customLegend()?.legendAxis === 'left'\"\n [class.both-legend-container]=\"customLegend()?.legendAxis === 'both'\"\n >\n <div\n class=\"both-scenario-left-unit-container\"\n [class.left-scenario-unit-container]=\"customLegend()?.legendAxis === 'left'\"\n >\n <span class=\"text-secondary\">{{ leg.unit }}</span>\n </div>\n <div\n class=\"legend-item-container both-scenario-legend-container custom-legend-left\"\n [class.legend-single-axis]=\"customLegend()?.legendAxis === 'left'\"\n >\n @for (legendItem of leg.list; track legendItem.name) {\n <div class=\"legend-item\" [class.hidden-legend]=\"!legendItem.selected\">\n <div\n class=\"me-2 mb-2\"\n (click)=\"legendIconClick(legendItem)\"\n (mouseenter)=\"legendHoverStartEvent.emit(legendItem)\"\n (mouseleave)=\"legendHoverEndEvent.emit(legendItem)\"\n >\n <svg width=\"12\" height=\"12\" xmlns=\"http://www.w3.org/2000/svg\">\n <path [attr.d]=\"legendItem.symbol\" [attr.fill]=\"legendItem.color\" />\n </svg>\n </div>\n <span\n class=\"legend-text text-truncate\"\n [style.color]=\"textColor()\"\n (click)=\"legendClick(legendItem)\"\n (mouseenter)=\"legendHoverStartEvent.emit(legendItem)\"\n (mouseleave)=\"legendHoverEndEvent.emit(legendItem)\"\n >\n {{ legendItem.displayName }}\n </span>\n @if (legendItem.tooltip) {\n <div class=\"tooltip show bs-tooltip-bottom\" role=\"tooltip\">\n <div class=\"tooltip-arrow\"></div>\n <div class=\"tooltip-inner\">{{ legendItem.tooltip }}</div>\n </div>\n }\n </div>\n }\n </div>\n </div>\n }\n }\n\n @for (leg of customLegend()?.customLegends; track legendIndex; let legendIndex = $index) {\n @if (legendIndex === 1 && leg && leg.list && leg.list.length > 0) {\n <div\n class=\"right-legends legend-item-container\"\n [class.legend-empty]=\"\n customLegend()?.legendAxis !== 'right' && customLegend()?.legendAxis !== 'both'\n \"\n [class.legend-single-axis]=\"customLegend()?.legendAxis === 'right'\"\n [class.both-legend-container]=\"customLegend()?.legendAxis === 'both'\"\n >\n <div\n class=\"legend-item-container custom-legend-right legend-item-container-right-floating-inner\"\n >\n @for (legendItem of leg.list; track legendItem.name) {\n <div\n class=\"legend-item legend-item-right\"\n [class.hidden-legend]=\"!legendItem.selected\"\n >\n <span\n class=\"legend-text text-truncate\"\n [style.color]=\"textColor()\"\n (click)=\"legendClick(legendItem)\"\n >\n {{ legendItem.displayName }}\n </span>\n <div class=\"right-legend-circle\" (click)=\"legendIconClick(legendItem)\">\n <svg width=\"12\" height=\"12\" xmlns=\"http://www.w3.org/2000/svg\">\n <path [attr.d]=\"legendItem.symbol\" [attr.fill]=\"legendItem.color\" />\n </svg>\n </div>\n @if (legendItem.tooltip) {\n <div class=\"tooltip show bs-tooltip-bottom\" role=\"tooltip\">\n <div class=\"tooltip-arrow\"></div>\n <div class=\"tooltip-inner\">{{ legendItem.tooltip }}</div>\n </div>\n }\n </div>\n }\n </div>\n <div\n class=\"both-scenario-right-unit-container\"\n [class.right-scenario-unit-container]=\"customLegend()?.legendAxis === 'right'\"\n >\n <span class=\"right-unit-text text-secondary\">{{ leg.unit }}</span>\n </div>\n </div>\n }\n }\n </div>\n}\n", styles: [":host{--flex-dir1: row;--flex-dir2: row-reverse;margin:12px;display:flex;flex-direction:column}:host-context(:dir(rtl)){--flex-dir1: row-reverse;--flex-dir2: row}:host-context([dir=rtl]){--flex-dir1: row-reverse;--flex-dir2: row}.legend-container{display:flex;flex-direction:var(--flex-dir1);max-height:40px;flex:1 1 auto}.legend-item-container{width:50%;vertical-align:top;display:flex;flex-wrap:wrap;flex:1 1 100%;flex-direction:var(--flex-dir1);height:fit-content;max-height:40px;max-width:50%;min-width:50%;overflow-y:auto;scrollbar-width:thin}.legend-item-container::-webkit-scrollbar{width:4px;height:6px;background-color:var(--element-base-0, #f0f2f5)}.legend-item-container::-webkit-scrollbar-thumb{border-radius:12px;-webkit-box-shadow:inset 0 0 6px rgba(0,0,0,.3)}.legend-item-container::-webkit-scrollbar-track{-webkit-box-shadow:inset 0 0 6px rgba(0,0,0,.3);border-radius:12px;background-color:var(--element-base-0, #f0f2f5)}.legend-item-container .custom-legend-left{flex-direction:var(--flex-dir1);flex:1 1 50%}.legend-item-container .custom-legend-right{flex-direction:var(--flex-dir2);flex:1 1 50%}.legend-item-container-right-floating-inner{max-width:calc(100% - 32px);min-width:calc(100% - 32px);padding-right:12px;float:left}.legend-single-axis{max-width:100%;min-width:100%}.legend-empty{width:0%}.tooltip{display:none;max-width:375px;word-break:break-word;margin-top:16px;inset-block-start:0;margin-inline-start:-6px}.tooltip-arrow{left:12px}.legend-item{cursor:pointer;margin-right:8px;display:flex;flex-direction:var(--flex-dir1);align-items:center;height:20px;position:initial;width:calc(100% - 12px);max-width:fit-content}.legend-item:hover .tooltip{display:block}.legend-item-right{margin-right:0;margin-left:12px}.right-legend-circle{margin-right:0;margin-left:4px}.legend-text{box-sizing:inherit;display:inline;cursor:pointer}.hidden-legend .right-legend-circle,.hidden-legend div:first-child,.hidden-legend .legend-text{opacity:.4}.both-scenario-left-unit-container,.both-scenario-right-unit-container{min-width:32px;max-width:32px;overflow:hidden}.both-scenario-right-unit-container{max-height:100%}.both-scenario-left-unit-container{min-height:100%}.both-scenario-legend-container{max-width:calc(100% - 32px);min-width:calc(100% - 32px);padding-left:12px}.right-unit-text{min-width:100%;min-height:100%;padding-left:2px}.left-legends{padding-right:36px}.right-legends{padding-left:28px}.both-legend-container{padding-right:0;padding-left:0}\n"] }]
617
+ }] });
618
+
619
+ /**
620
+ * Copyright Siemens 2016 - 2025.
621
+ * SPDX-License-Identifier: MIT
622
+ */
623
+ class SiChartComponent {
624
+ /**
625
+ * reference to the wrapper container. Used for setting scroll position, etc.
626
+ *
627
+ * @defaultValue
628
+ * ```
629
+ * viewChild.required<ElementRef>('chartContainerWrapper')
630
+ * ```
631
+ */
632
+ chartContainerWrapper = viewChild.required('chartContainerWrapper');
633
+ chartContainer = viewChild('chart');
634
+ externalZoomSliderContainer = viewChild('externalZoomSlider');
635
+ siCustomLegend = viewChildren('siCustomLegend', {
636
+ read: SiCustomLegendComponent
637
+ });
638
+ /**
639
+ * See [ECharts 5.x Documentation]{@link https://echarts.apache.org/en/option.html}
640
+ * for all available options.
641
+ */
642
+ options = input();
643
+ /** Used to override specific properties set in `options`. */
644
+ additionalOptions = input();
645
+ title = input();
646
+ subTitle = input();
647
+ /** @defaultValue true */
648
+ showLegend = model(true);
649
+ /** @defaultValue false */
650
+ showCustomLegend = input(false);
651
+ /**
652
+ * the renderer to use: canvas or svg
653
+ *
654
+ * @defaultValue 'canvas'
655
+ */
656
+ renderer = input('canvas');
657
+ /**
658
+ * Enables the zoom slider below the chart.
659
+ *
660
+ * @defaultValue false
661
+ */
662
+ zoomSlider = input(false);
663
+ /**
664
+ * Shows data shadow in dataZoom slider, use together with `zoomSlider`.
665
+ *
666
+ * @defaultValue true
667
+ */
668
+ zoomSliderShadow = input(true);
669
+ /**
670
+ * realtime update mode for zoom slider
671
+ *
672
+ * @defaultValue true
673
+ */
674
+ zoomSliderRealtime = input(true);
675
+ /**
676
+ * enable brush mode for zoom slider
677
+ *
678
+ * @defaultValue true
679
+ */
680
+ zoomSliderBrush = input(true);
681
+ /**
682
+ * Enables zooming inside the chart with the mouse wheel/touch.
683
+ *
684
+ * @defaultValue false
685
+ */
686
+ zoomInside = input(false);
687
+ /** @defaultValue 1000 */
688
+ maxEntries = input(1000);
689
+ /**
690
+ * No auto dataZoom update) by default. Use together with `autoZoomSeriesIndex`.
691
+ *
692
+ * @defaultValue -1
693
+ */
694
+ visibleEntries = model(-1);
695
+ /**
696
+ * No auto dataZoom update) by default. Use together with `autoZoomSeriesIndex`.
697
+ *
698
+ * @defaultValue -1
699
+ */
700
+ visibleRange = model(-1);
701
+ /**
702
+ * No auto dataZoom update) by default. Use together with `visibleEntries`.
703
+ *
704
+ * @defaultValue -1
705
+ */
706
+ autoZoomSeriesIndex = input(-1);
707
+ /** The desired theme to load. */
708
+ theme = input();
709
+ /** Used to override specific options of loaded `theme`. */
710
+ themeCustomization = input();
711
+ /**
712
+ * The name of the color palette (if any) of the loaded `theme`.
713
+ *
714
+ * @defaultValue undefined
715
+ */
716
+ palette = input();
717
+ /**
718
+ * Used to display `axisPointer` line either by click or mouse-move.
719
+ *
720
+ * @defaultValue false
721
+ */
722
+ axisPointer = input(false);
723
+ dataZoomRange = input();
724
+ dataZoomMinValueSpan = input();
725
+ dataZoomMaxValueSpan = input();
726
+ /** @defaultValue 'none' */
727
+ dataZoomFilterMode = input('none');
728
+ customLegendAction = input();
729
+ /**
730
+ * @defaultValue
731
+ * ```
732
+ * { legendItemName: '' }
733
+ * ```
734
+ */
735
+ selectedItem = input({ legendItemName: '' });
736
+ eChartContainerHeight = input();
737
+ /**
738
+ * Flag to use external zoom slider
739
+ *
740
+ * @defaultValue false
741
+ */
742
+ externalZoomSlider = input(false);
743
+ /** External XAxis Formatter from consumer */
744
+ externalXAxisFormatter = input();
745
+ /**
746
+ * If true, add consumer-provided time range bar. Use together with `zoomSlider`.
747
+ * @deprecated The input will be removed in future versions as the time range bar slot is deprecated.
748
+ *
749
+ * @defaultValue false
750
+ */
751
+ showTimeRangeBar = input(false);
752
+ /** Event emitted when data zoom changes. */
753
+ dataZoom = output();
754
+ /** Event emitted when axis pointer moves. */
755
+ pointer = output();
756
+ selectionChanged = output();
757
+ chartSeriesClick = output();
758
+ /** Event emitted when chart grid is resized. */
759
+ chartGridResized = output();
760
+ customLegendMultiLineInfoEvent = output();
761
+ /** Emitted when datazoom changes, indicating the time range in milliseconds, 0 for full range */
762
+ timeRangeChange = output();
763
+ /** Allow to override options specific for a chart type. */
764
+ actualOptions = {};
765
+ customLegend = [
766
+ {
767
+ customLegends: [
768
+ { list: [], unit: '' },
769
+ { list: [], unit: '' }
770
+ ],
771
+ legendAxis: 'both'
772
+ }
773
+ ];
774
+ /** @internal */
775
+ chart;
776
+ extZoomSliderChart;
777
+ echartElement;
778
+ eChartExtSliderElement;
779
+ inProgress = signal(false);
780
+ backgroundColor = signal('');
781
+ textColor = signal('');
782
+ titleColor = signal('');
783
+ subTitleColor = signal('');
784
+ selectedSeriesColors = {};
785
+ unselectedSeriesColors = {};
786
+ seriesSelectionState = {};
787
+ containerHeight = signal(null);
788
+ activeTheme;
789
+ autoZoomUpdate = true;
790
+ subscriptions = new Subscription();
791
+ prevAxisPointer = {};
792
+ lastValidDataZoom = {};
793
+ presetDataZoomRange;
794
+ dataZoomSetupDone = false;
795
+ requestedDataZoom;
796
+ measureCanvas;
797
+ cdRef = inject(ChangeDetectorRef);
798
+ curWidth = 0;
799
+ curHeight = 0;
800
+ timeBarBottom = signal(50);
801
+ timeBarLeft = signal(32);
802
+ timeBarRight = signal(32);
803
+ timeBarHeight = signal(32);
804
+ gridCoordinates = {
805
+ x: 0,
806
+ y: 0,
807
+ width: 0,
808
+ height: 0,
809
+ containerWidth: 0,
810
+ containerHeight: 0
811
+ };
812
+ customLegendsMultiLineInfo = [];
813
+ extZoomSliderOptions = {
814
+ animation: false,
815
+ dataZoom: [
816
+ { type: 'slider', showDataShadow: false },
817
+ { type: 'inside', showDataShadow: false }
818
+ ],
819
+ grid: [{ left: 32, right: 32, top: 0, height: 0, containLabel: false }],
820
+ xAxis: [{ type: 'time', axisLine: { onZero: true }, zlevel: 1 }],
821
+ yAxis: [{ type: 'value', boundaryGap: [0, '100%'], splitLine: { show: false }, show: false }],
822
+ series: [{ type: 'line', showSymbol: false, lineStyle: { opacity: 0 }, data: [] }]
823
+ };
824
+ echartMouseDown = () => this.handleChartMouseDown();
825
+ echartMouseUp = (event) => this.handleChartMouseUp(event);
826
+ echartExtSliderMouseDown = () => this.handleExtChartMouseDown();
827
+ echartExtSliderMouseUp = (event) => this.handleExtChartMouseUp(event);
828
+ ngZone = inject(NgZone);
829
+ shapePaths = {
830
+ circle: 'M6 0A6 6 0 1 1 6 12A6 6 0 1 1 6 0Z',
831
+ rect: 'M0 0H12V12H0Z',
832
+ roundRect: 'M2 0H10A2 2 0 0 1 12 2V10A2 2 0 0 1 10 12H2A2 2 0 0 1 0 10V2A2 2 0 0 1 2 0Z',
833
+ triangle: 'M6 0L12 12H0L6 0Z',
834
+ diamond: 'M6 0L12 6L6 12L0 6L6 0Z',
835
+ pin: 'M6.00049 0C8.48577 0 10.5005 2.01472 10.5005 4.5C10.5005 5.51817 10.0175 6.461 9.46826 7.31836C8.42358 8.94924 7.16317 10.4497 6.00049 12C4.83781 10.4497 3.57642 8.94924 2.53174 7.31836C1.98255 6.461 1.49951 5.51817 1.49951 4.5C1.49951 2.01472 3.51521 0 6.00049 0Z'
836
+ };
837
+ /**
838
+ * Allow consuming applications to re-draw chart on window resizes.
839
+ */
840
+ resize() {
841
+ if (!this.chart) {
842
+ return;
843
+ }
844
+ const rect = this.chartContainer()?.nativeElement.getBoundingClientRect();
845
+ const width = Math.floor(rect.width);
846
+ const height = Math.floor(rect.height);
847
+ if (width && height && (width !== this.curWidth || height !== this.curHeight)) {
848
+ this.curWidth = width;
849
+ this.curHeight = height;
850
+ this.ngZone.runOutsideAngular(() => {
851
+ this.chart.resize({ width, height: this.containerHeight() ?? height });
852
+ if (this.externalZoomSlider()) {
853
+ this.extZoomSliderChart.resize();
854
+ }
855
+ setTimeout(() => this.checkGridSizeChange());
856
+ });
857
+ this.afterChartResize();
858
+ }
859
+ this.updateCustomLegendMultiLineInfo();
860
+ }
861
+ ngOnChanges(changes) {
862
+ if (changes.options?.currentValue) {
863
+ this.actualOptions = this.options();
864
+ }
865
+ if (!this.chart) {
866
+ return;
867
+ }
868
+ if (changes.eChartContainerHeight) {
869
+ this.setContainerHeight();
870
+ }
871
+ const selectedLegendItem = changes.selectedItem;
872
+ if (selectedLegendItem &&
873
+ !selectedLegendItem.isFirstChange() &&
874
+ selectedLegendItem.currentValue) {
875
+ const event = {
876
+ name: selectedLegendItem.currentValue.legendItemName,
877
+ type: 'legendToggleSelect'
878
+ };
879
+ this.dispatchEChartAction(event);
880
+ }
881
+ if (this.customLegendAction() &&
882
+ changes.options &&
883
+ !changes.options.isFirstChange() &&
884
+ !changes.options.currentValue.color.length) {
885
+ this.actualOptions.color = changes.options.previousValue.color;
886
+ }
887
+ if (changes.theme || changes.renderer) {
888
+ // need to completely redo the chart for the theme change to take effect
889
+ return this.resetChart();
890
+ }
891
+ let updates = 0;
892
+ let applyAll = false;
893
+ let skipMerge = false;
894
+ if (changes.forceAll ||
895
+ changes.yAxis ||
896
+ changes.xAxis ||
897
+ changes.options ||
898
+ changes.series ||
899
+ changes.value) {
900
+ // this is to clean the legend item list
901
+ if (this.showCustomLegend() && this.customLegend && this.customLegend.length > 0) {
902
+ this.customLegend.forEach(cl => {
903
+ cl.customLegends = [
904
+ { list: [], unit: '' },
905
+ { list: [], unit: '' }
906
+ ];
907
+ });
908
+ }
909
+ this.applyOptions();
910
+ applyAll = true;
911
+ skipMerge =
912
+ changes.series?.previousValue &&
913
+ changes.series.currentValue &&
914
+ changes.series.currentValue.length < changes.series.previousValue.length;
915
+ updates++;
916
+ }
917
+ if (!applyAll && (changes.title || changes.subTitle)) {
918
+ // already called when `applyOptions()` has been called
919
+ this.applyTitles();
920
+ updates++;
921
+ }
922
+ if (applyAll ||
923
+ changes.forceAll ||
924
+ changes.zoomSlider ||
925
+ changes.zoomSliderShadow ||
926
+ changes.zoomSliderRealtime ||
927
+ changes.zoomSliderBrush ||
928
+ changes.zoomInside ||
929
+ changes.axisPointer ||
930
+ changes.autoZoomSeriesIndex ||
931
+ changes.visibleEntries ||
932
+ changes.visibleRange) {
933
+ this.applyDataZoom();
934
+ updates++;
935
+ }
936
+ if (applyAll || changes.forceAll || changes.palette || changes.additionalOptions) {
937
+ this.applyAdditionalOptions();
938
+ updates++;
939
+ }
940
+ if (applyAll) {
941
+ this.applyStyles();
942
+ setTimeout(() => this.updateCustomLegendMultiLineInfo());
943
+ }
944
+ let skipDz = false;
945
+ if (updates) {
946
+ if (changes.dataZoomRange) {
947
+ this.setDataZoomRange(true);
948
+ skipDz = true;
949
+ }
950
+ const dz = this.actualOptions.dataZoom;
951
+ let currentDataZoom;
952
+ if (skipMerge && this.hasDataZoom() && this.hasData() && !skipDz) {
953
+ // forced updated is required when adding/removing series, see:
954
+ // https://github.com/apache/incubator-echarts/issues/6202
955
+ // in order not to mess up current datazoom, save the current value and add it to options
956
+ this.saveCurrentDataZoom();
957
+ if (this.lastValidDataZoom) {
958
+ currentDataZoom = dz[0];
959
+ const newDataZoom = {};
960
+ echarts.util.merge(newDataZoom, dz[0], true);
961
+ echarts.util.merge(newDataZoom, this.lastValidDataZoom, true);
962
+ dz[0] = newDataZoom;
963
+ }
964
+ }
965
+ this.updateEChart(skipMerge);
966
+ if (currentDataZoom) {
967
+ dz[0] = currentDataZoom;
968
+ this.updateEChart(false, { dataZoom: this.actualOptions.dataZoom });
969
+ }
970
+ this.applyColorsToCustomLegends();
971
+ }
972
+ if (!skipDz && changes.dataZoomRange) {
973
+ // this is done after a possible setOptions call to ensure echarts has all the desired states
974
+ this.setDataZoomRange();
975
+ }
976
+ this.cdRef.markForCheck();
977
+ }
978
+ ngOnInit() {
979
+ const canvas = document.createElement('canvas');
980
+ this.measureCanvas = canvas.getContext('2d');
981
+ this.measureCanvas.font = '12px "Siemens Sans"';
982
+ const externalXAxisFormatter = this.externalXAxisFormatter();
983
+ if (this.externalZoomSlider() && externalXAxisFormatter) {
984
+ const consumerFormatter = externalXAxisFormatter;
985
+ this.extZoomSliderOptions.xAxis[0].axisLabel = {
986
+ formatter: (value) => consumerFormatter(value, this.visibleRange())
987
+ };
988
+ }
989
+ this.applyTheme();
990
+ // this is to clean the legend item list
991
+ if (this.showCustomLegend() && this.customLegend && this.customLegend.length > 0) {
992
+ this.customLegend.forEach(cl => {
993
+ cl.customLegends = [
994
+ { list: [], unit: '' },
995
+ { list: [], unit: '' }
996
+ ];
997
+ });
998
+ }
999
+ this.applyOptions();
1000
+ this.applyAdditionalOptions();
1001
+ this.applyDataZoom();
1002
+ this.applyStyles();
1003
+ if (this.customLegendAction()) {
1004
+ this.fetchSeriesColors();
1005
+ }
1006
+ }
1007
+ ngAfterViewInit(skipZoom) {
1008
+ this.ngZone.runOutsideAngular(() => {
1009
+ const chartContainerEl = this.chartContainer().nativeElement;
1010
+ // set current dimension to avoid initial resize() call on chart
1011
+ const rect = chartContainerEl.getBoundingClientRect();
1012
+ this.curWidth = Math.floor(rect.width);
1013
+ this.curHeight = Math.floor(rect.height);
1014
+ const opts = { renderer: this.renderer() };
1015
+ this.chart = echarts.init(chartContainerEl, this.activeTheme, opts);
1016
+ this.echartElement = chartContainerEl;
1017
+ this.getEChartInner()?.addEventListener('mousedown', this.echartMouseDown);
1018
+ this.chart.setOption(this.actualOptions);
1019
+ setTimeout(() => this.checkGridSizeChange());
1020
+ if (this.externalZoomSlider()) {
1021
+ this.extZoomSliderChart = echarts.init(this.externalZoomSliderContainer().nativeElement, this.activeTheme, opts);
1022
+ this.eChartExtSliderElement = this.externalZoomSliderContainer()
1023
+ .nativeElement;
1024
+ this.getEChartExternalSliderInner()?.addEventListener('mousedown', this.echartExtSliderMouseDown);
1025
+ this.extZoomSliderChart.setOption(this.extZoomSliderOptions);
1026
+ this.extZoomSliderChart.on('datazoom', (event) => this.handleExtDataZoom(event));
1027
+ }
1028
+ this.afterChartInit(skipZoom);
1029
+ });
1030
+ setTimeout(() => {
1031
+ this.resize();
1032
+ this.applyColorsToCustomLegends();
1033
+ });
1034
+ }
1035
+ calculateTextWidth(text) {
1036
+ if (!this.measureCanvas) {
1037
+ return 150;
1038
+ }
1039
+ return Math.ceil(this.measureCanvas.measureText(text).width);
1040
+ }
1041
+ disposeChart() {
1042
+ if (this.chart && !this.chart.isDisposed()) {
1043
+ this.chart.dispose();
1044
+ }
1045
+ if (this.extZoomSliderChart && !this.extZoomSliderChart.isDisposed()) {
1046
+ this.extZoomSliderChart.dispose();
1047
+ }
1048
+ }
1049
+ ngOnDestroy() {
1050
+ this.subscriptions.unsubscribe();
1051
+ this.disposeChart();
1052
+ }
1053
+ /**
1054
+ * Re-render the whole chart.
1055
+ */
1056
+ resetChart() {
1057
+ this.applyTheme();
1058
+ if (!this.actualOptions) {
1059
+ // this can happen if the SiThemeService fires the theme switch when the chart is not
1060
+ // yet completely initialized
1061
+ return;
1062
+ }
1063
+ this.disposeChart();
1064
+ this.applyPalette();
1065
+ const addOpts = this.additionalOptions();
1066
+ if (addOpts?.palette) {
1067
+ echarts.util.merge(this.actualOptions.palette, addOpts.palette, true);
1068
+ }
1069
+ this.themeChanged();
1070
+ this.applyStyles();
1071
+ this.applyTitles();
1072
+ this.ngAfterViewInit(true); // eslint-disable-line @angular-eslint/no-lifecycle-call
1073
+ this.cdRef.markForCheck();
1074
+ }
1075
+ handleLegendClick(legend) {
1076
+ this.doToggleSeriesVisibility(legend.name, legend.selected, legend);
1077
+ this.cdRef.markForCheck();
1078
+ }
1079
+ handleLegendHover(legend, start) {
1080
+ this.dispatchEChartAction({
1081
+ type: start ? 'highlight' : 'downplay',
1082
+ [legend.alternativeNaming ? 'name' : 'seriesName']: legend.name
1083
+ });
1084
+ }
1085
+ /**
1086
+ * Toggle visibility of a series.
1087
+ */
1088
+ toggleSeriesVisibility(name, visible) {
1089
+ const legendItem = this.findCustomLegendItem(name);
1090
+ this.doToggleSeriesVisibility(name, visible, legendItem);
1091
+ this.cdRef.markForCheck();
1092
+ }
1093
+ doToggleSeriesVisibility(name, visible, legendItem) {
1094
+ if (legendItem) {
1095
+ legendItem.selected = visible;
1096
+ }
1097
+ this.dispatchEChartAction({ type: visible ? 'legendSelect' : 'legendUnSelect', name });
1098
+ if (this.externalZoomSlider()) {
1099
+ this.ngZone.runOutsideAngular(() => {
1100
+ this.extZoomSliderChart.dispatchAction({
1101
+ type: visible ? 'legendSelect' : 'legendUnSelect',
1102
+ name
1103
+ });
1104
+ });
1105
+ }
1106
+ const opt = this.getOptionNoClone();
1107
+ if (Array.isArray(opt.legend)) {
1108
+ const selection = {};
1109
+ opt.legend.forEach((l) => Object.assign(selection, l.selected));
1110
+ this.handleSelectionChanged({ selected: selection });
1111
+ }
1112
+ }
1113
+ findCustomLegendItem(name) {
1114
+ if (this.showCustomLegend()) {
1115
+ for (const cl of this.customLegend) {
1116
+ for (const l of cl.customLegends) {
1117
+ for (const item of l.list) {
1118
+ if (item.name === name) {
1119
+ return item;
1120
+ }
1121
+ }
1122
+ }
1123
+ }
1124
+ }
1125
+ return undefined;
1126
+ }
1127
+ getValidXAxis() {
1128
+ return undefined;
1129
+ }
1130
+ setZoomMode() { }
1131
+ applyTheme() {
1132
+ // Set default theme if no theme provided
1133
+ const theme = this.theme();
1134
+ if (theme?.style) {
1135
+ this.activeTheme = theme.style();
1136
+ }
1137
+ else if (themeSupport._defaultTheme?.style) {
1138
+ this.activeTheme = themeSupport._defaultTheme.style();
1139
+ }
1140
+ const themeCustomization = this.themeCustomization();
1141
+ if (themeCustomization) {
1142
+ const custom = echarts.util.merge({}, themeCustomization);
1143
+ this.activeTheme = echarts.util.merge(custom, this.activeTheme);
1144
+ }
1145
+ }
1146
+ themeChanged() { }
1147
+ applyOptions() { }
1148
+ applyCustomLegendPosition() {
1149
+ if (this.showLegend() && this.showCustomLegend()) {
1150
+ this.customLegend.forEach(cl => {
1151
+ if (cl.customLegends?.[0].list && cl.customLegends?.[1].list) {
1152
+ const leftLegend = cl.customLegends[0];
1153
+ const rightLegend = cl.customLegends[1];
1154
+ // if we have left and right axis
1155
+ if (leftLegend.list.length > 0 && rightLegend.list.length > 0) {
1156
+ cl.legendAxis = 'both';
1157
+ }
1158
+ else if (leftLegend.list.length > 0 && rightLegend.list.length === 0) {
1159
+ // if we have only left axis data
1160
+ cl.legendAxis = 'left';
1161
+ }
1162
+ else if (leftLegend.list.length === 0 && rightLegend.list.length > 0) {
1163
+ // if we have only right axis data
1164
+ cl.legendAxis = 'right';
1165
+ }
1166
+ else {
1167
+ cl.legendAxis = 'both';
1168
+ }
1169
+ }
1170
+ else {
1171
+ cl.legendAxis = 'both';
1172
+ }
1173
+ });
1174
+ this.cdRef.markForCheck();
1175
+ }
1176
+ }
1177
+ applyAdditionalOptions() {
1178
+ // need to merge palette before the additionalOptions so that overrides work as expected
1179
+ this.applyPalette();
1180
+ if (this.additionalOptions()) {
1181
+ echarts.util.merge(this.actualOptions, this.additionalOptions(), true);
1182
+ }
1183
+ }
1184
+ applyPalette() {
1185
+ const paletteValue = this.palette() ?? 'default';
1186
+ if (paletteValue) {
1187
+ const palette = this.getThemeCustomValue(['colorPalettes', paletteValue], null);
1188
+ if (palette) {
1189
+ this.actualOptions.color = palette;
1190
+ if (this.customLegendAction()) {
1191
+ this.fetchSeriesColors(palette);
1192
+ }
1193
+ }
1194
+ }
1195
+ }
1196
+ applyDataZoom() {
1197
+ if (!this.actualOptions.grid) {
1198
+ return;
1199
+ }
1200
+ this.actualOptions.dataZoom ??= [];
1201
+ const sliderOptions = {};
1202
+ const dataZoomMinValueSpan = this.dataZoomMinValueSpan();
1203
+ if (dataZoomMinValueSpan) {
1204
+ sliderOptions.minValueSpan = dataZoomMinValueSpan;
1205
+ }
1206
+ const dataZoomMaxValueSpan = this.dataZoomMaxValueSpan();
1207
+ if (dataZoomMaxValueSpan) {
1208
+ sliderOptions.maxValueSpan = dataZoomMaxValueSpan;
1209
+ }
1210
+ sliderOptions.realtime = this.zoomSliderRealtime();
1211
+ sliderOptions.brushSelect = this.zoomSliderBrush();
1212
+ sliderOptions.showDataShadow = this.zoomSliderShadow();
1213
+ sliderOptions.filterMode = this.dataZoomFilterMode();
1214
+ sliderOptions.showDetail = false;
1215
+ // keep external zoom slider in sync, always at index 0
1216
+ Object.assign(this.extZoomSliderOptions.dataZoom[0], sliderOptions);
1217
+ const dz = this.actualOptions.dataZoom;
1218
+ const sliderIdx = dz.findIndex(z => z.type === 'slider');
1219
+ const insideIdx = dz.findIndex(z => z.type === 'inside');
1220
+ const zoomSlider = this.zoomSlider();
1221
+ if (zoomSlider && sliderIdx === -1) {
1222
+ // for the non-external, merge with other options
1223
+ const customOptions = this.getThemeCustomValue(['dataZoom', 'options'], {});
1224
+ const dzSliderOptions = Object.assign({ type: 'slider' }, customOptions, sliderOptions);
1225
+ Object.assign(this.extZoomSliderOptions.dataZoom[0], customOptions);
1226
+ const externalZoomSlider = this.externalZoomSlider();
1227
+ if (externalZoomSlider) {
1228
+ dzSliderOptions.show = false;
1229
+ }
1230
+ dz.push(dzSliderOptions);
1231
+ const gridOptions = externalZoomSlider
1232
+ ? this.getThemeCustomValue(['externalZoomSlider', 'grid'], {})
1233
+ : this.getThemeCustomValue(['dataZoom', 'grid'], {});
1234
+ if (this.showTimeRangeBar()) {
1235
+ const timeBarOptions = this.getThemeCustomValue(['timeRangeBar'], {});
1236
+ if (customOptions.height && customOptions.bottom) {
1237
+ this.timeBarBottom.set(customOptions.height + customOptions.bottom);
1238
+ }
1239
+ this.timeBarHeight.set(timeBarOptions?.height ?? 32);
1240
+ if (!externalZoomSlider) {
1241
+ gridOptions.bottom = (gridOptions?.bottom ?? 0) + this.timeBarHeight();
1242
+ }
1243
+ }
1244
+ echarts.util.merge(this.actualOptions.grid, gridOptions, true);
1245
+ }
1246
+ else if (zoomSlider && sliderIdx >= 0) {
1247
+ // update existing
1248
+ const dzSliderOptions = dz[sliderIdx];
1249
+ Object.assign(dzSliderOptions, sliderOptions);
1250
+ }
1251
+ else if (!zoomSlider && sliderIdx >= 0) {
1252
+ dz.splice(sliderIdx, 1);
1253
+ }
1254
+ const zoomInside = this.zoomInside();
1255
+ if (zoomInside && insideIdx === -1) {
1256
+ dz.push({ type: 'inside', filterMode: this.dataZoomFilterMode() });
1257
+ }
1258
+ else if (!zoomInside && insideIdx >= 0) {
1259
+ dz.splice(insideIdx, 1);
1260
+ }
1261
+ if (this.actualOptions.xAxis) {
1262
+ this.handleAxisPointer(this.actualOptions);
1263
+ }
1264
+ this.cdRef.markForCheck();
1265
+ }
1266
+ handleAxisPointer(options) {
1267
+ const axisPointer = this.axisPointer();
1268
+ if (axisPointer !== undefined) {
1269
+ options.axisPointer ??= {};
1270
+ }
1271
+ if (axisPointer === true) {
1272
+ options.axisPointer.triggerOn = 'click';
1273
+ }
1274
+ else if (axisPointer === false) {
1275
+ options.axisPointer.triggerOn = 'mousemove|click';
1276
+ }
1277
+ else if (typeof axisPointer === 'string') {
1278
+ options.axisPointer.triggerOn = axisPointer;
1279
+ }
1280
+ if (Array.isArray(options.xAxis)) {
1281
+ const xAxisArray = options.xAxis;
1282
+ xAxisArray.forEach(axis => this.handleAxisPointerSingleAxis(axis));
1283
+ }
1284
+ else {
1285
+ this.handleAxisPointerSingleAxis(options.xAxis);
1286
+ }
1287
+ }
1288
+ handleAxisPointerSingleAxis(xAxis) {
1289
+ if (this.axisPointer()) {
1290
+ echarts.util.merge(xAxis, { axisPointer: { handle: { show: true } } }, true);
1291
+ }
1292
+ else {
1293
+ echarts.util.merge(xAxis, { axisPointer: { handle: { show: false } } }, true);
1294
+ }
1295
+ }
1296
+ hasDataZoom() {
1297
+ return !!this.actualOptions.dataZoom?.length;
1298
+ }
1299
+ getThemeValue(props, defaultValue, ns) {
1300
+ if (!this.activeTheme) {
1301
+ return defaultValue;
1302
+ }
1303
+ let currentValue = this.activeTheme;
1304
+ if (ns) {
1305
+ currentValue = currentValue[ns];
1306
+ }
1307
+ for (let i = 0; currentValue && i < props.length; i++) {
1308
+ currentValue = currentValue[props[i]];
1309
+ }
1310
+ return currentValue ?? defaultValue;
1311
+ }
1312
+ getThemeCustomValue(props, defaultValue) {
1313
+ return this.getThemeValue(props, defaultValue, 'simpl');
1314
+ }
1315
+ applyTitles() {
1316
+ const title = this.title();
1317
+ const subTitle = this.subTitle();
1318
+ const options = this.actualOptions;
1319
+ if (this.showLegend() && this.showCustomLegend()) {
1320
+ if (options.title) {
1321
+ options.title.show = false;
1322
+ }
1323
+ options.legend?.forEach(legend => {
1324
+ legend.show = false;
1325
+ legend.height = 0;
1326
+ });
1327
+ if (options.grid) {
1328
+ const gridOptions = this.getThemeCustomValue(['customLegend', 'grid'], {});
1329
+ echarts.util.merge(options.grid, gridOptions, true);
1330
+ }
1331
+ this.titleColor.set(this.getThemeValue(['title', 'textStyle', 'color'], null));
1332
+ this.subTitleColor.set(this.getThemeValue(['title', 'subtextStyle', 'color'], this.titleColor));
1333
+ this.textColor.set(this.getThemeValue(['legend', 'textStyle', 'color'], null));
1334
+ this.backgroundColor.set(this.getThemeValue(['backgroundColor'], null));
1335
+ }
1336
+ else if (title || subTitle) {
1337
+ options.title = {
1338
+ text: title,
1339
+ subtext: subTitle
1340
+ };
1341
+ if (subTitle) {
1342
+ this.modifyTopAlignment('subTitle');
1343
+ }
1344
+ }
1345
+ else if (!title && !subTitle) {
1346
+ this.modifyTopAlignment('noTitle');
1347
+ }
1348
+ }
1349
+ modifyTopAlignment(key) {
1350
+ const options = this.actualOptions;
1351
+ if (options.grid) {
1352
+ const gridOptions = this.getThemeCustomValue([key, 'grid'], {});
1353
+ echarts.util.merge(options.grid, gridOptions, true);
1354
+ }
1355
+ const legendOptions = this.getThemeCustomValue([key, 'legend'], {});
1356
+ options.legend?.forEach(legend => echarts.util.merge(legend, legendOptions, true));
1357
+ }
1358
+ afterChartInit(skipZoom) {
1359
+ this.chart.on('datazoom', (event) => this.handleDataZoom(event, 'echart'));
1360
+ if (!this.customLegendAction()) {
1361
+ // default generic si-chart behavior
1362
+ this.chart.on('legendselectchanged', (event) => this.handleSelectionChanged(event));
1363
+ this.chart.on('click', (event) => this.handleClickOnChart(event, false));
1364
+ }
1365
+ else {
1366
+ // custom chart behaviour
1367
+ this.chart.on('legendselectchanged', (event) => this.handleSelectionChangedCustom(event));
1368
+ this.chart.on('click', (event) => this.handleClickOnChart(event, true));
1369
+ }
1370
+ this.chart.on('updateaxispointer', (event) => this.handleUpdateAxisPointer(event));
1371
+ if (!skipZoom) {
1372
+ this.setDataZoomRange();
1373
+ }
1374
+ this.cdRef.markForCheck();
1375
+ }
1376
+ afterChartResize() { }
1377
+ getEChartInner() {
1378
+ return this.echartElement.querySelector(':scope > div:first-child');
1379
+ }
1380
+ getEChartExternalSliderInner() {
1381
+ return this.eChartExtSliderElement.querySelector(':scope > div:first-child');
1382
+ }
1383
+ handleExtChartMouseDown() {
1384
+ window.addEventListener('mouseup', this.echartExtSliderMouseUp);
1385
+ }
1386
+ handleExtChartMouseUp(event) {
1387
+ window.removeEventListener('mouseup', this.echartExtSliderMouseUp);
1388
+ const newEvent = new MouseEvent('mouseup', event);
1389
+ setTimeout(() => {
1390
+ this.getEChartExternalSliderInner()?.dispatchEvent(newEvent);
1391
+ this.cdRef.markForCheck();
1392
+ }, 1);
1393
+ }
1394
+ handleChartMouseDown() {
1395
+ window.addEventListener('mouseup', this.echartMouseUp);
1396
+ }
1397
+ handleChartMouseUp(event) {
1398
+ window.removeEventListener('mouseup', this.echartMouseUp);
1399
+ const newEvent = new MouseEvent('mouseup', event);
1400
+ setTimeout(() => {
1401
+ this.getEChartInner()?.dispatchEvent(newEvent);
1402
+ this.cdRef.markForCheck();
1403
+ }, 1);
1404
+ }
1405
+ setDataZoomRange(skipUpdate) {
1406
+ // Checking if we received a valid dataZoomRange Object
1407
+ const dataZoomRange = this.dataZoomRange();
1408
+ if (dataZoomRange && Object.keys(dataZoomRange).length > 0) {
1409
+ // If series has data, then directly dispatch action for the dataZoom event
1410
+ // Else, Store the dataZoomRange values in presetDataZoomRange variable for applying zoom
1411
+ // after data is received in chart
1412
+ // No need to reassign presetDataZoomRange if earlier value is not consumed
1413
+ if (this.hasData()) {
1414
+ const dz = this.getPresetDataZoom(dataZoomRange);
1415
+ if (dz) {
1416
+ const requested = { ...dataZoomRange };
1417
+ this.presetDataZoomRange = undefined;
1418
+ this.updateDataZoom(dz);
1419
+ if (!skipUpdate) {
1420
+ this.updateEChart(false, { dataZoom: [dz] });
1421
+ }
1422
+ // update user with proper data
1423
+ setTimeout(() => {
1424
+ this.ngZone.runOutsideAngular(() => {
1425
+ this.requestedDataZoom = requested;
1426
+ this.handleDataZoom(dz, 'setDataZoomRange');
1427
+ });
1428
+ });
1429
+ return;
1430
+ }
1431
+ }
1432
+ this.presetDataZoomRange = dataZoomRange;
1433
+ }
1434
+ }
1435
+ handleDataZoom(event, source) {
1436
+ // events can be batched
1437
+ if (event.batch?.length) {
1438
+ event = event.batch[0];
1439
+ }
1440
+ if (Number.isNaN(event.start) || Number.isNaN(event.end)) {
1441
+ // need to fix to the last valid dataZoom setting, see below
1442
+ this.chart.dispatchAction({ type: 'dataZoom', ...this.lastValidDataZoom });
1443
+ return;
1444
+ }
1445
+ const effectiveOpts = this.getOptionNoClone();
1446
+ // in case of pane by chart area, event.start and event.end are always undefined.
1447
+ // and in case of slider move, they has values in percentage(0-100)
1448
+ // so, to handle in case of pane, we need to get start and end values from datazoom property
1449
+ // following condition will be executed only if autozoom is false; and start and end are undefined(undefined means call is from pane)
1450
+ const dz = effectiveOpts.dataZoom[0];
1451
+ this.autoZoomUpdate = !!dz && dz.end === 100;
1452
+ // Due to chart updates outside Angular, we need to emit events back
1453
+ // inside Angular to activate Angular's change detection.
1454
+ const range = this.getVisibleRange();
1455
+ if (range) {
1456
+ range.source = source ?? event.source;
1457
+ this.calculateVisibleRange(range);
1458
+ if (this.requestedDataZoom) {
1459
+ range.requested = this.requestedDataZoom;
1460
+ this.requestedDataZoom = undefined;
1461
+ }
1462
+ this.ngZone.run(() => {
1463
+ this.dataZoom.emit(range);
1464
+ this.timeRangeChange.emit(dz.start === 0 && dz.end === 100 ? 0 : range.rangeEnd - range.rangeStart);
1465
+ });
1466
+ setTimeout(() => this.checkGridSizeChange());
1467
+ this.presetDataZoomRange = undefined;
1468
+ this.dataZoomSetupDone = true;
1469
+ // sync/store values
1470
+ this.updateDataZoom({ startValue: range.rangeStart, endValue: range.rangeEnd });
1471
+ if (event.source !== 'extSlider') {
1472
+ this.extZoomSliderChart?.dispatchAction({
1473
+ type: 'dataZoom',
1474
+ source: 'mainChart',
1475
+ startValue: range.rangeStart,
1476
+ endValue: range.rangeEnd
1477
+ });
1478
+ }
1479
+ }
1480
+ this.cdRef.markForCheck();
1481
+ }
1482
+ handleExtDataZoom(event) {
1483
+ if (event.batch?.length) {
1484
+ event = event.batch[0];
1485
+ }
1486
+ if (event.source === 'mainChart') {
1487
+ return;
1488
+ }
1489
+ const zoomModel = this.extZoomSliderChart._model;
1490
+ const range = this.doGetVisibleRange(zoomModel);
1491
+ if (range) {
1492
+ this.calculateVisibleRange(range);
1493
+ this.chart?.dispatchAction({
1494
+ type: 'dataZoom',
1495
+ source: 'extSlider',
1496
+ startValue: range.rangeStart,
1497
+ endValue: range.rangeEnd
1498
+ });
1499
+ }
1500
+ }
1501
+ handleSelectionChanged(event) {
1502
+ this.selectionChanged.emit(event);
1503
+ for (const a in event.selected) {
1504
+ if (event.selected[a] !== false) {
1505
+ return;
1506
+ }
1507
+ }
1508
+ this.saveCurrentDataZoom();
1509
+ }
1510
+ /**
1511
+ * Creates two objects that stores the colors for selected and unselected series. Used only for custom legend actions.
1512
+ */
1513
+ fetchSeriesColors(colorsToBeUSed) {
1514
+ const options = this.actualOptions;
1515
+ if (!options.color?.length && this.activeTheme) {
1516
+ options.color = [...this.activeTheme.color];
1517
+ }
1518
+ if (!colorsToBeUSed && !this.activeTheme) {
1519
+ return;
1520
+ }
1521
+ options.series?.forEach((element, index) => {
1522
+ this.unselectedSeriesColors[element.name] = {
1523
+ color: this.getThemeValue(['legend', 'unselected', 'color'], '#ccc'),
1524
+ index
1525
+ };
1526
+ const colors = colorsToBeUSed ?? this.activeTheme.color;
1527
+ this.selectedSeriesColors[element.name] = { color: colors[index], index };
1528
+ });
1529
+ }
1530
+ /**
1531
+ * Handles legend select event in non echart native way.
1532
+ * @param event - legend select
1533
+ */
1534
+ handleSelectionChangedCustom(event) {
1535
+ const optionsToChange = this.styleSelectedSeries(event.name, false, event.dataIndex);
1536
+ this.ngZone.runOutsideAngular(() => {
1537
+ this.chart.setOption(optionsToChange);
1538
+ this.chart.dispatchAction({ type: 'legendSelect', name: event.name });
1539
+ });
1540
+ }
1541
+ /**
1542
+ * Handles click on series in non echart native way.
1543
+ * @param event - click
1544
+ */
1545
+ handleClickOnChart(event, toggleVisibility) {
1546
+ if (event.componentType !== 'series') {
1547
+ return;
1548
+ }
1549
+ if (toggleVisibility) {
1550
+ const optionsToChange = this.styleSelectedSeries(event.seriesName, true, event.dataIndex);
1551
+ this.chart.setOption(optionsToChange);
1552
+ }
1553
+ else {
1554
+ this.ngZone.run(() => this.chartSeriesClick.emit({
1555
+ itemName: event.seriesName,
1556
+ dataIndex: event.dataIndex
1557
+ }));
1558
+ }
1559
+ }
1560
+ /**
1561
+ * Selects or unselects the series based on series state object
1562
+ * @param seriesName - series to be selected/unselected
1563
+ * @param emit - if true event is emitted otherwise no event is emitted
1564
+ */
1565
+ styleSelectedSeries(seriesName, emit, seriesDataIndex) {
1566
+ if (this.seriesSelectionState?.[seriesName]) {
1567
+ const elementToStyle = this.actualOptions.series?.find(element => element.name === seriesName);
1568
+ this.seriesSelectionState[seriesName] = false;
1569
+ return this.selectSeries(elementToStyle, emit, seriesDataIndex);
1570
+ }
1571
+ else {
1572
+ const elementToStyle = this.actualOptions.series?.find(element => element.name === seriesName);
1573
+ this.seriesSelectionState[seriesName] = true;
1574
+ return this.unselectSeries(elementToStyle, emit, seriesDataIndex);
1575
+ }
1576
+ }
1577
+ /**
1578
+ * Selects the series
1579
+ * @param element - to be styled as selected
1580
+ * @param emit - if true event is emitted otherwise no event is emitted
1581
+ */
1582
+ selectSeries(element, emit, seriesDataIndex) {
1583
+ const options = this.actualOptions;
1584
+ const optionsToChange = { color: options.color, series: [options.series] };
1585
+ const optionsColorIndex = this.selectedSeriesColors[element.name].index;
1586
+ optionsToChange.color[optionsColorIndex] = this.selectedSeriesColors[element.name].color;
1587
+ if (element.areaStyle) {
1588
+ element.areaStyle.opacity = 0.4;
1589
+ optionsToChange.series[this.selectedSeriesColors[element.name].index] = element;
1590
+ }
1591
+ if (emit) {
1592
+ this.chartSeriesClick.emit({
1593
+ itemName: element.name,
1594
+ dataIndex: seriesDataIndex,
1595
+ selected: false,
1596
+ color: this.selectedSeriesColors[element.name].color
1597
+ });
1598
+ }
1599
+ return optionsToChange;
1600
+ }
1601
+ /**
1602
+ * Unselects the series
1603
+ * @param element - to be styled as unselected
1604
+ * @param emit - if true event is emitted otherwise no event is emitted
1605
+ */
1606
+ unselectSeries(element, emit, seriesDataIndex) {
1607
+ const options = this.actualOptions;
1608
+ const optionsToChange = { color: options.color, series: [options.series] };
1609
+ const optionsColorIndex = this.selectedSeriesColors[element.name].index;
1610
+ optionsToChange.color[optionsColorIndex] = this.unselectedSeriesColors[element.name].color;
1611
+ if (element.areaStyle) {
1612
+ element.areaStyle.opacity = 0;
1613
+ optionsToChange.series[this.unselectedSeriesColors[element.name].index] = element;
1614
+ }
1615
+ if (emit) {
1616
+ this.chartSeriesClick.emit({
1617
+ itemName: element.name,
1618
+ dataIndex: seriesDataIndex,
1619
+ selected: true,
1620
+ color: this.selectedSeriesColors[element.name].color
1621
+ });
1622
+ }
1623
+ return optionsToChange;
1624
+ }
1625
+ isValidDataZoomValue(val) {
1626
+ return val !== null && val !== undefined && !Number.isNaN(val);
1627
+ }
1628
+ saveCurrentDataZoom() {
1629
+ const options = this.actualOptions;
1630
+ if (!options.grid || !options.dataZoom) {
1631
+ return;
1632
+ }
1633
+ // When the last item on the legend is disabled, remember the current valid
1634
+ // dataZoom setting. Due to a bug in ECharts it happens
1635
+ // that the zoom slider disappears not to ever reappear again. To work around
1636
+ // the problem, we simply inject the last valid dataZoom settings saved here
1637
+ // once the invalid values (NaN) are detected
1638
+ const currentOpts = this.getOptionNoClone();
1639
+ if (!currentOpts?.dataZoom?.[0]) {
1640
+ return;
1641
+ }
1642
+ const dz = currentOpts.dataZoom[0];
1643
+ if (dz) {
1644
+ this.lastValidDataZoom = {};
1645
+ if (this.isValidDataZoomValue(dz.startValue)) {
1646
+ this.lastValidDataZoom.startValue = dz.startValue;
1647
+ }
1648
+ else if (this.isValidDataZoomValue(dz.start)) {
1649
+ this.lastValidDataZoom.start = dz.start;
1650
+ }
1651
+ if (this.isValidDataZoomValue(dz.endValue)) {
1652
+ this.lastValidDataZoom.endValue = dz.endValue;
1653
+ }
1654
+ else if (this.isValidDataZoomValue(dz.end)) {
1655
+ this.lastValidDataZoom.end = dz.end;
1656
+ }
1657
+ }
1658
+ }
1659
+ /**
1660
+ * Get color by series name.
1661
+ */
1662
+ getSeriesColorBySeriesName(seriesName) {
1663
+ return this.doGetSeriesColorBySeriesName(seriesName).color;
1664
+ }
1665
+ doGetSeriesColorBySeriesName(seriesName) {
1666
+ const ecModel = this.internalGetModel();
1667
+ const ecSeries = ecModel.getSeriesByName(seriesName);
1668
+ if (ecSeries && ecSeries.length > 0) {
1669
+ return { color: ecSeries[0].getData().getVisual('style')?.fill, altName: false };
1670
+ }
1671
+ let ret = { color: undefined, altName: false };
1672
+ ecModel.eachRawSeries((seriesModel) => {
1673
+ const idx = seriesModel.legendVisualProvider?.indexOfName(seriesName) ?? -1;
1674
+ if (idx >= 0) {
1675
+ ret = {
1676
+ color: seriesModel.legendVisualProvider.getItemVisual(idx, 'style')?.fill,
1677
+ altName: true
1678
+ };
1679
+ }
1680
+ });
1681
+ return ret;
1682
+ }
1683
+ applyColorsToCustomLegends() {
1684
+ if (!this.showLegend() || !this.showCustomLegend()) {
1685
+ return;
1686
+ }
1687
+ this.customLegend.forEach(cl => {
1688
+ cl.customLegends.forEach(legendAxis => {
1689
+ legendAxis?.list.forEach(legend => {
1690
+ const color = this.doGetSeriesColorBySeriesName(legend.name);
1691
+ legend.color = color.color;
1692
+ legend.alternativeNaming = color.altName;
1693
+ });
1694
+ });
1695
+ });
1696
+ this.cdRef.markForCheck();
1697
+ }
1698
+ handleUpdateAxisPointer(event) {
1699
+ if (event.seriesIndex !== this.prevAxisPointer.seriesIndex ||
1700
+ event.dataIndex !== this.prevAxisPointer.dataIndex) {
1701
+ this.prevAxisPointer.seriesIndex = event.seriesIndex;
1702
+ this.prevAxisPointer.dataIndex = event.dataIndex;
1703
+ if (this.axisPointer() && event.seriesIndex === undefined) {
1704
+ return;
1705
+ }
1706
+ // Due to chart updates outside Angular, we need to emit events back
1707
+ // inside Angular to activate Angular's change detection.
1708
+ this.ngZone.run(() => {
1709
+ this.pointer.emit({
1710
+ seriesIndex: event.seriesIndex,
1711
+ dataIndex: event.dataIndex
1712
+ });
1713
+ });
1714
+ }
1715
+ }
1716
+ /**
1717
+ * Get current data zoom range.
1718
+ */
1719
+ getVisibleRange() {
1720
+ return this.doGetVisibleRange(this.internalGetModel());
1721
+ }
1722
+ internalGetModel() {
1723
+ return this.chart._model;
1724
+ }
1725
+ /**
1726
+ * returns the current EChart options, w/o cloning anything. Be very careful
1727
+ * not to change anything in the data structure in it.
1728
+ */
1729
+ getOptionNoClone() {
1730
+ return this.internalGetModel().option;
1731
+ }
1732
+ parsePercent(percent, all) {
1733
+ if (typeof percent === 'string') {
1734
+ if (percent.match(/\d+%/)) {
1735
+ return (parseFloat(percent) / 100) * all;
1736
+ }
1737
+ return parseFloat(percent);
1738
+ }
1739
+ return percent;
1740
+ }
1741
+ doGetVisibleRange(zoomModel) {
1742
+ const effectiveOpts = zoomModel.option;
1743
+ const xAxis = effectiveOpts.xAxis?.[0];
1744
+ const dz = effectiveOpts.dataZoom[0];
1745
+ const rangeStartArray = [];
1746
+ const rangeEndArray = [];
1747
+ for (let i = 0; i < effectiveOpts.xAxis?.length; i++) {
1748
+ const axis = zoomModel.getComponent('xAxis', i);
1749
+ const extent = axis?.axis?.scale?.getExtent();
1750
+ if (extent?.length) {
1751
+ if (this.isValidDataZoomValue(extent[0])) {
1752
+ rangeStartArray.push(extent[0]);
1753
+ }
1754
+ if (this.isValidDataZoomValue(extent[1])) {
1755
+ rangeEndArray.push(extent[1]);
1756
+ }
1757
+ }
1758
+ }
1759
+ const rangeStart = rangeStartArray.length ? Math.min(...rangeStartArray) : dz?.startValue;
1760
+ const rangeEnd = rangeEndArray.length ? Math.max(...rangeEndArray) : dz?.endValue;
1761
+ if (!this.isValidDataZoomValue(rangeEnd)) {
1762
+ return;
1763
+ }
1764
+ let gridWidth;
1765
+ if (effectiveOpts.grid && effectiveOpts.grid.length > 0) {
1766
+ const width = this.chart.getWidth();
1767
+ const grid = effectiveOpts.grid[0];
1768
+ gridWidth =
1769
+ width - this.parsePercent(grid.left, width) - this.parsePercent(grid.right, width);
1770
+ }
1771
+ return {
1772
+ rangeType: xAxis.type,
1773
+ rangeStart,
1774
+ rangeEnd,
1775
+ width: gridWidth,
1776
+ autoZoomUpdate: this.autoZoomUpdate
1777
+ };
1778
+ }
1779
+ updateEChart(force = false, options) {
1780
+ if (!this.chart) {
1781
+ return;
1782
+ }
1783
+ let axisDZUpdated = this.updateAxisAndDataZoom(options);
1784
+ options ??= this.actualOptions;
1785
+ const isFilledArray = (v) => Array.isArray(v) && v.length > 0;
1786
+ if (isFilledArray(options.grid) &&
1787
+ isFilledArray(options.xAxis) &&
1788
+ isFilledArray(options.dataZoom)) {
1789
+ // adjust grid for axis labels
1790
+ let max = 0;
1791
+ options.yAxis.forEach((axis) => {
1792
+ if (axis.position !== 'right' && isFilledArray(axis.data)) {
1793
+ axis.data.forEach((label) => {
1794
+ const width = this.calculateTextWidth(label);
1795
+ max = Math.max(max, width);
1796
+ });
1797
+ }
1798
+ });
1799
+ max += 16; // long text getting truncated, so add some padding
1800
+ const grids = options.grid;
1801
+ grids.forEach(g => (g.left = Math.max(g.left, max)));
1802
+ // update dataZoom if not already set
1803
+ const zoom = options.dataZoom[0];
1804
+ if (!this.isValidDataZoomValue(zoom?.startValue) &&
1805
+ !this.isValidDataZoomValue(zoom?.endValue) &&
1806
+ !this.isValidDataZoomValue(zoom?.end)) {
1807
+ const range = this.getVisibleRange();
1808
+ if (range) {
1809
+ this.updateDataZoom({ startValue: range.rangeStart, endValue: range.rangeEnd });
1810
+ }
1811
+ }
1812
+ // change in grid/axis requires a full update
1813
+ force = true;
1814
+ axisDZUpdated = true;
1815
+ }
1816
+ this.ngZone.runOutsideAngular(() => {
1817
+ this.chart.setOption(options, force);
1818
+ this.setZoomMode();
1819
+ if (axisDZUpdated && this.externalZoomSlider()) {
1820
+ this.extZoomSliderChart.setOption(this.extZoomSliderOptions, false);
1821
+ }
1822
+ });
1823
+ setTimeout(() => this.checkGridSizeChange());
1824
+ }
1825
+ updateAxisAndDataZoom(inOptions) {
1826
+ const options = this.actualOptions;
1827
+ if (!options.xAxis) {
1828
+ return false;
1829
+ }
1830
+ const isFull = !inOptions || inOptions === options;
1831
+ inOptions = inOptions ?? {};
1832
+ if (!isFull && !inOptions.series && !options.dataZoom) {
1833
+ return false;
1834
+ }
1835
+ const xAxis = Array.isArray(options.xAxis) ? options.xAxis : [options.xAxis];
1836
+ if (!isFull && !inOptions.xAxis) {
1837
+ // for delta update, make sure we have same-sized axis array
1838
+ inOptions.xAxis = xAxis.map(() => ({}));
1839
+ }
1840
+ const minMax = this.getSeriesMinMax();
1841
+ // extend range if DZ is bigger than actual data
1842
+ const dz = inOptions?.dataZoom?.[0];
1843
+ if (dz?.startValue != null &&
1844
+ (minMax.min === undefined || dz.startValue < minMax.min)) {
1845
+ minMax.min = dz.startValue;
1846
+ }
1847
+ if (dz?.endValue != null &&
1848
+ (minMax.max === undefined || dz.endValue > minMax.max)) {
1849
+ minMax.max = dz.endValue;
1850
+ }
1851
+ // Update all sub chart index to be controlled by the dataZoom
1852
+ let xAxisIndexes = [];
1853
+ xAxis.forEach((axis, index) => {
1854
+ if (axis.gridIndex >= 0) {
1855
+ // set min/max the same on all axis so that datazoom can work
1856
+ axis.min = minMax.min;
1857
+ axis.max = minMax.max;
1858
+ if (!isFull) {
1859
+ inOptions.xAxis[index].min = minMax.min;
1860
+ inOptions.xAxis[index].max = minMax.max;
1861
+ }
1862
+ xAxisIndexes.push(index);
1863
+ }
1864
+ });
1865
+ // update dataZoom
1866
+ const effectiveOpts = this.getOptionNoClone();
1867
+ const effectiveXAxis = effectiveOpts.xAxis;
1868
+ if (effectiveXAxis.length > 1) {
1869
+ // 1. find out all visible series
1870
+ // 2. find out valid x index
1871
+ // 3. remove invalid x axis from the xAxisIndex array
1872
+ const validXAxis = this.getValidXAxis();
1873
+ if (validXAxis) {
1874
+ xAxisIndexes = xAxisIndexes.filter(index => validXAxis.has(index));
1875
+ }
1876
+ }
1877
+ if (xAxisIndexes.length) {
1878
+ const allDataZoom = options.dataZoom;
1879
+ allDataZoom.forEach(zoom => (zoom.xAxisIndex = xAxisIndexes));
1880
+ if (!isFull && inOptions.dataZoom) {
1881
+ inOptions.dataZoom.forEach(zoom => (zoom.xAxisIndex = xAxisIndexes));
1882
+ }
1883
+ }
1884
+ // update external slider if required
1885
+ if (this.externalZoomSlider()) {
1886
+ const extSliderAxis = this.extZoomSliderOptions.xAxis[0];
1887
+ if (extSliderAxis.min !== minMax.min || extSliderAxis.max !== minMax.max) {
1888
+ extSliderAxis.min = minMax.min;
1889
+ extSliderAxis.max = minMax.max;
1890
+ this.extZoomSliderOptions.series[0].data = [
1891
+ [minMax.min, null],
1892
+ [minMax.max, null]
1893
+ ];
1894
+ }
1895
+ }
1896
+ return true;
1897
+ }
1898
+ /**
1899
+ * Send action to echart.
1900
+ * @see https://echarts.apache.org/en/api.html#action
1901
+ */
1902
+ dispatchEChartAction(action) {
1903
+ if (!this.chart) {
1904
+ return;
1905
+ }
1906
+ this.ngZone.runOutsideAngular(() => {
1907
+ this.chart.dispatchAction(action);
1908
+ });
1909
+ this.cdRef.markForCheck();
1910
+ }
1911
+ getSeriesMinMax(visibleOnly = false) {
1912
+ const legend = visibleOnly ? this.internalGetModel().getComponent('legend') : undefined;
1913
+ let min;
1914
+ let max;
1915
+ this.actualOptions.series?.forEach(s => {
1916
+ const seriesData = s.data;
1917
+ if (seriesData?.length > 1 && (!legend || legend.isSelected(s.name))) {
1918
+ const start = seriesData[0][0]?.valueOf();
1919
+ const last = seriesData[seriesData.length - 1];
1920
+ // end value is can be undefined sometimes, if we don't have milliseconds as a value, instead
1921
+ // we have value[] array of Date, so to handle that scenario we are taking value[0].valueOf() to
1922
+ // calculate the millisecond value i.e from Date(value[0])
1923
+ const end = last[0]?.valueOf() ?? last.value?.[0]?.valueOf();
1924
+ if (this.isValidDataZoomValue(start) && this.isValidDataZoomValue(end)) {
1925
+ if (min === undefined || start < min) {
1926
+ min = start;
1927
+ }
1928
+ if (max === undefined || end > max) {
1929
+ max = end;
1930
+ }
1931
+ }
1932
+ }
1933
+ });
1934
+ return { min, max };
1935
+ }
1936
+ calculateVisibleRange(range) {
1937
+ const options = this.actualOptions;
1938
+ if (!options.xAxis || !this.hasDataZoom() || !range) {
1939
+ return;
1940
+ }
1941
+ if (!Array.isArray(options.xAxis) && options.xAxis.type === 'category') {
1942
+ this.visibleRange.set(Math.ceil(range.rangeEnd) - Math.floor(range.rangeStart));
1943
+ }
1944
+ else {
1945
+ this.visibleRange.set(Math.round(range.rangeEnd - range.rangeStart));
1946
+ }
1947
+ // once in range mode, disable the entries mode to prevent overriding the user
1948
+ this.visibleEntries.set(-1);
1949
+ }
1950
+ getValueFromSeriesPoint(point) {
1951
+ return Array.isArray(point) ? point : point.value;
1952
+ }
1953
+ calculateZoomStartValue() {
1954
+ const options = this.actualOptions;
1955
+ if (!options.series) {
1956
+ return null;
1957
+ }
1958
+ const seriesData = options.series[this.autoZoomSeriesIndex()]?.data;
1959
+ if (!seriesData) {
1960
+ return null;
1961
+ }
1962
+ if (this.visibleEntries() > -1) {
1963
+ const offset = Math.min(seriesData.length, this.visibleEntries());
1964
+ const data = seriesData[seriesData.length - offset];
1965
+ return data ? this.getValueFromSeriesPoint(data)[0] : null;
1966
+ }
1967
+ else if (this.visibleRange() > -1) {
1968
+ const minMax = this.getSeriesMinMax(true);
1969
+ if (minMax.min && minMax.max) {
1970
+ // make sure startValue is >= the min data value
1971
+ return Math.max(minMax.min, minMax.max - this.visibleRange());
1972
+ }
1973
+ const data = seriesData[seriesData.length - 1];
1974
+ return data ? this.getValueFromSeriesPoint(data)[0] - this.visibleRange() : null;
1975
+ }
1976
+ return null;
1977
+ }
1978
+ hasData() {
1979
+ return this.actualOptions.series?.some(s => s.data?.length > 0) ?? false;
1980
+ }
1981
+ /**
1982
+ * Re-render the chart series data. This method should be called on series data changes.
1983
+ */
1984
+ refreshSeries(isLive = true, dzToSet) {
1985
+ dzToSet ??= this.presetDataZoomRange;
1986
+ const optionsToUpdate = {
1987
+ series: this.actualOptions.series
1988
+ };
1989
+ if (!isLive) {
1990
+ this.updateEChart(false, optionsToUpdate);
1991
+ return;
1992
+ }
1993
+ if (this.hasDataZoom() && this.hasData()) {
1994
+ if (dzToSet) {
1995
+ this.dataZoomSetupDone = true;
1996
+ const dz = this.getPresetDataZoom(dzToSet);
1997
+ if (dz) {
1998
+ const requested = { ...dzToSet };
1999
+ this.presetDataZoomRange = undefined;
2000
+ this.updateDataZoom(dz, optionsToUpdate);
2001
+ // dispatch the same async. reasoning: the sync here is needed to prevent
2002
+ // flickering, the async dispatch to ensure a DataZoomEvent is fired so
2003
+ // that any consumer of this event work as expected
2004
+ setTimeout(() => {
2005
+ this.ngZone.runOutsideAngular(() => {
2006
+ this.requestedDataZoom = requested;
2007
+ this.handleDataZoom(dz, 'refreshSeries');
2008
+ });
2009
+ });
2010
+ }
2011
+ }
2012
+ else if (!this.dataZoomSetupDone) {
2013
+ // need to do this async to have the data in ECharts
2014
+ setTimeout(() => {
2015
+ if (!this.dataZoomSetupDone && !this.dataZoomRange() && this.chart) {
2016
+ this.calculateVisibleRange(this.getVisibleRange());
2017
+ }
2018
+ this.dataZoomSetupDone = true;
2019
+ });
2020
+ }
2021
+ else if (this.zoomSlider() && this.autoZoomUpdate && this.autoZoomSeriesIndex() !== -1) {
2022
+ // this ensures the slider is at the end and the window size remains stable, showing new data
2023
+ const startValue = this.calculateZoomStartValue();
2024
+ if (this.isValidDataZoomValue(startValue)) {
2025
+ this.updateDataZoom({ startValue, end: 100 }, optionsToUpdate);
2026
+ }
2027
+ if (isLive) {
2028
+ this.dispatchEChartAction({ type: 'hideTip' });
2029
+ }
2030
+ }
2031
+ else {
2032
+ // this ensures the current displayed window stays stable as new data arrives
2033
+ const dz = this.getOptionNoClone().dataZoom[0];
2034
+ if (this.isValidDataZoomValue(dz.startValue) &&
2035
+ this.isValidDataZoomValue(dz.endValue) &&
2036
+ dz.end !== 100) {
2037
+ this.updateDataZoom({ startValue: dz.startValue, endValue: dz.endValue }, optionsToUpdate);
2038
+ }
2039
+ }
2040
+ }
2041
+ this.updateEChart(false, optionsToUpdate);
2042
+ }
2043
+ // this ensures DZ is in sync everywhere
2044
+ updateDataZoom(dz, optionsToUpdate) {
2045
+ const options = this.actualOptions;
2046
+ if (options.dataZoom?.[0]) {
2047
+ this.doUpdateDZ(dz, options.dataZoom[0]);
2048
+ }
2049
+ if (optionsToUpdate && optionsToUpdate !== options) {
2050
+ if (Array.isArray(optionsToUpdate.dataZoom)) {
2051
+ this.doUpdateDZ(dz, optionsToUpdate.dataZoom[0]);
2052
+ }
2053
+ else if (optionsToUpdate.dataZoom) {
2054
+ this.doUpdateDZ(dz, optionsToUpdate.dataZoom);
2055
+ }
2056
+ else {
2057
+ optionsToUpdate.dataZoom = [{ ...dz }];
2058
+ }
2059
+ }
2060
+ if (this.externalZoomSlider()) {
2061
+ this.doUpdateDZ(dz, this.extZoomSliderOptions.dataZoom[0]);
2062
+ }
2063
+ }
2064
+ doUpdateDZ(dz, dzOptions) {
2065
+ // make sure only to have value or percent
2066
+ if (this.isValidDataZoomValue(dz.startValue)) {
2067
+ dzOptions.startValue = dz.startValue;
2068
+ dzOptions.start = undefined;
2069
+ }
2070
+ else if (this.isValidDataZoomValue(dz.start)) {
2071
+ dzOptions.start = dz.start;
2072
+ dzOptions.startValue = undefined;
2073
+ }
2074
+ if (this.isValidDataZoomValue(dz.endValue)) {
2075
+ dzOptions.endValue = dz.endValue;
2076
+ dzOptions.end = undefined;
2077
+ }
2078
+ else if (this.isValidDataZoomValue(dz.end)) {
2079
+ dzOptions.end = dz.end;
2080
+ dzOptions.endValue = undefined;
2081
+ }
2082
+ }
2083
+ applyStyles() {
2084
+ const bodyStyle = window.getComputedStyle(document.body);
2085
+ const options = this.actualOptions;
2086
+ options.textStyle = {
2087
+ fontFamily: bodyStyle.fontFamily,
2088
+ fontSize: bodyStyle.fontSize
2089
+ };
2090
+ this.extZoomSliderOptions.textStyle = options.textStyle;
2091
+ }
2092
+ addLegendItem(name, visible, index = 0, gridIndex = 0, customLegendProp, seriesSymbol) {
2093
+ const options = this.actualOptions;
2094
+ if (!options.legend?.length) {
2095
+ return;
2096
+ }
2097
+ const legend = options.legend[options.legend.length > index ? index : 0];
2098
+ const unitText = customLegendProp ? customLegendProp.unit : undefined;
2099
+ const customLegendItem = {
2100
+ name: '',
2101
+ displayName: '',
2102
+ color: '',
2103
+ selected: false,
2104
+ tooltip: customLegendProp ? customLegendProp.tooltip : '',
2105
+ symbol: this.getPath(seriesSymbol, false)
2106
+ };
2107
+ legend.data?.push({
2108
+ name,
2109
+ icon: this.getPath(seriesSymbol, true)
2110
+ });
2111
+ legend.selected ??= {};
2112
+ if (visible !== null && visible !== undefined) {
2113
+ legend.selected[name] = visible;
2114
+ customLegendItem.selected = visible;
2115
+ }
2116
+ const showCustomLegend = this.showCustomLegend();
2117
+ if (this.showLegend() && showCustomLegend) {
2118
+ if (visible !== false) {
2119
+ customLegendItem.selected = true;
2120
+ }
2121
+ customLegendItem.name = name;
2122
+ customLegendItem.displayName = customLegendProp?.displayName ?? name;
2123
+ if (showCustomLegend) {
2124
+ this.addCustomLegend(customLegendItem, unitText, index, gridIndex);
2125
+ }
2126
+ }
2127
+ this.cdRef.markForCheck();
2128
+ }
2129
+ getPath(seriesSymbol, prefix) {
2130
+ const path = seriesSymbol ? this.shapePaths[seriesSymbol] : this.shapePaths.circle;
2131
+ return prefix ? 'path://' + path : path;
2132
+ }
2133
+ addCustomLegend(customLegendItem, unitText, index, gridIndex = 0) {
2134
+ if (this.actualOptions.legend) {
2135
+ if (!this.customLegend[gridIndex].customLegends) {
2136
+ this.customLegend[gridIndex].customLegends = [
2137
+ { list: [], unit: '' },
2138
+ { list: [], unit: '' }
2139
+ ];
2140
+ }
2141
+ // index = 0 means left legend
2142
+ if (index === 0) {
2143
+ if (!this.customLegend[gridIndex]?.customLegends[0]?.list) {
2144
+ this.customLegend[gridIndex].customLegends[0] = { list: [customLegendItem] };
2145
+ }
2146
+ else {
2147
+ // legend with same id and name not found
2148
+ this.customLegend[gridIndex].customLegends[0].list.push(customLegendItem);
2149
+ }
2150
+ this.customLegend[gridIndex].customLegends[0].unit = unitText;
2151
+ }
2152
+ else {
2153
+ // index = 1 means right legend
2154
+ if (!this.customLegend[gridIndex]?.customLegends[1]?.list) {
2155
+ this.customLegend[gridIndex].customLegends[1] = { list: [customLegendItem] };
2156
+ }
2157
+ else {
2158
+ this.customLegend[gridIndex].customLegends[1].list.push(customLegendItem);
2159
+ }
2160
+ this.customLegend[gridIndex].customLegends[1].unit = unitText;
2161
+ }
2162
+ this.applyCustomLegendPosition();
2163
+ }
2164
+ }
2165
+ /**
2166
+ * Show loading indicator.
2167
+ */
2168
+ startProgressIndication() {
2169
+ this.inProgress.set(true);
2170
+ }
2171
+ /**
2172
+ * Hide loading indicator.
2173
+ */
2174
+ stopProgressIndication() {
2175
+ this.inProgress.set(false);
2176
+ }
2177
+ /**
2178
+ * Set the data zoom range for the chart in milliseconds.
2179
+ * As an example one hour is the value 3600000.
2180
+ */
2181
+ setTimeRange(range) {
2182
+ const currentDZ = this.getVisibleRange();
2183
+ const minMax = this.getSeriesMinMax(true);
2184
+ if (!currentDZ || minMax.min == null || minMax.max == null) {
2185
+ return;
2186
+ }
2187
+ const mid = (currentDZ.rangeStart + currentDZ.rangeEnd) / 2;
2188
+ const halfRange = range / 2;
2189
+ let start = 0;
2190
+ let end = 0;
2191
+ if (range === 0 || range > minMax.max - minMax.min) {
2192
+ start = minMax.min;
2193
+ end = minMax.max;
2194
+ }
2195
+ else {
2196
+ start = mid - halfRange;
2197
+ end = mid + halfRange;
2198
+ // at start
2199
+ if (start < minMax.min) {
2200
+ start = minMax.min;
2201
+ end = start + range;
2202
+ }
2203
+ // at end. Special case: if already at end, keep end
2204
+ if (end > minMax.max || currentDZ.rangeEnd === minMax.max) {
2205
+ start = minMax.max - range;
2206
+ end = minMax.max;
2207
+ }
2208
+ }
2209
+ this.dispatchEChartAction({ type: 'dataZoom', startValue: start, endValue: end });
2210
+ }
2211
+ addDataInternal(series) {
2212
+ const options = this.actualOptions;
2213
+ series.forEach(update => {
2214
+ const currentSeries = options.series[update.index];
2215
+ if (!currentSeries) {
2216
+ return;
2217
+ }
2218
+ const seriesData = currentSeries.data;
2219
+ seriesData.push(update.data);
2220
+ if (this.maxEntries() > 0 && seriesData.length > this.maxEntries()) {
2221
+ seriesData.splice(0, seriesData.length - this.maxEntries());
2222
+ }
2223
+ });
2224
+ this.refreshSeries();
2225
+ }
2226
+ getPresetDataZoom(range) {
2227
+ let ret;
2228
+ if (range.visibleWidth && this.autoZoomSeriesIndex() !== -1) {
2229
+ this.visibleRange.set(range.visibleWidth);
2230
+ const startValue = this.calculateZoomStartValue();
2231
+ if (this.isValidDataZoomValue(startValue)) {
2232
+ this.autoZoomUpdate = true;
2233
+ ret = { startValue, end: 100 };
2234
+ }
2235
+ }
2236
+ else if (this.isValidDataZoomValue(range.startValue) &&
2237
+ this.isValidDataZoomValue(range.endValue)) {
2238
+ // handling the case when startValue and endValue is given as a fixed time interval
2239
+ ret = {
2240
+ startValue: range.startValue,
2241
+ endValue: range.endValue
2242
+ };
2243
+ this.autoZoomUpdate = false;
2244
+ }
2245
+ else {
2246
+ ret = { ...range };
2247
+ }
2248
+ return ret;
2249
+ }
2250
+ checkGridSizeChange() {
2251
+ if (!this.chart) {
2252
+ return;
2253
+ }
2254
+ const gridRectNew = this.internalGetModel()?.getComponent('grid')?.coordinateSystem?._rect;
2255
+ if (gridRectNew) {
2256
+ const nativeWrapper = this.chartContainerWrapper().nativeElement;
2257
+ gridRectNew.containerWidth = nativeWrapper.offsetWidth;
2258
+ gridRectNew.containerHeight = nativeWrapper.offsetHeight;
2259
+ let isGridResized = false;
2260
+ for (const objKey of Object.keys(this.gridCoordinates)) {
2261
+ if (this.gridSizeItemChanged(gridRectNew[objKey], this.gridCoordinates[objKey])) {
2262
+ isGridResized = true;
2263
+ break;
2264
+ }
2265
+ }
2266
+ if (isGridResized) {
2267
+ // update new coordinates and emit event
2268
+ this.gridCoordinates = gridRectNew;
2269
+ this.timeBarLeft.set(this.gridCoordinates.x);
2270
+ this.timeBarRight.set(this.gridCoordinates.containerWidth - this.gridCoordinates.x - this.gridCoordinates.width);
2271
+ if (this.externalZoomSlider() && Array.isArray(this.extZoomSliderOptions?.grid)) {
2272
+ this.extZoomSliderOptions.grid[0].left = this.timeBarLeft();
2273
+ this.extZoomSliderOptions.grid[0].right = this.timeBarRight();
2274
+ this.extZoomSliderChart.setOption({ grid: this.extZoomSliderOptions.grid }, false);
2275
+ }
2276
+ this.ngZone.run(() => this.chartGridResized.emit(this.gridCoordinates));
2277
+ }
2278
+ }
2279
+ this.cdRef.markForCheck();
2280
+ }
2281
+ gridSizeItemChanged(a, b) {
2282
+ return Array.isArray(a)
2283
+ ? a.length !== b.length || a.some((item, index) => item !== b[index])
2284
+ : a !== b;
2285
+ }
2286
+ setContainerHeight() {
2287
+ const newHeight = parseInt(this.eChartContainerHeight(), 10) || null;
2288
+ if (newHeight !== this.containerHeight()) {
2289
+ this.containerHeight.set(newHeight);
2290
+ this.ngZone.runOutsideAngular(() => {
2291
+ this.chart?.resize({ width: this.curWidth, height: newHeight ?? this.curHeight });
2292
+ if (this.externalZoomSlider()) {
2293
+ this.extZoomSliderChart.resize();
2294
+ }
2295
+ });
2296
+ }
2297
+ }
2298
+ updateCustomLegendMultiLineInfo() {
2299
+ const event = [];
2300
+ this.siCustomLegend().forEach((legend, index) => {
2301
+ event.push({
2302
+ customLegendId: index,
2303
+ isCustomLegendMultilined: legend.customLegendContainer().nativeElement.offsetHeight > 20
2304
+ });
2305
+ });
2306
+ if (event.length !== this.customLegendsMultiLineInfo.length ||
2307
+ event.some((e, index) => e.isCustomLegendMultilined !==
2308
+ this.customLegendsMultiLineInfo[index].isCustomLegendMultilined)) {
2309
+ this.customLegendsMultiLineInfo = event;
2310
+ this.customLegendMultiLineInfoEvent.emit(event);
2311
+ }
2312
+ this.cdRef.markForCheck();
2313
+ }
2314
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.6", ngImport: i0, type: SiChartComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2315
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.6", type: SiChartComponent, isStandalone: true, selector: "si-chart", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, additionalOptions: { classPropertyName: "additionalOptions", publicName: "additionalOptions", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, subTitle: { classPropertyName: "subTitle", publicName: "subTitle", isSignal: true, isRequired: false, transformFunction: null }, showLegend: { classPropertyName: "showLegend", publicName: "showLegend", isSignal: true, isRequired: false, transformFunction: null }, showCustomLegend: { classPropertyName: "showCustomLegend", publicName: "showCustomLegend", isSignal: true, isRequired: false, transformFunction: null }, renderer: { classPropertyName: "renderer", publicName: "renderer", isSignal: true, isRequired: false, transformFunction: null }, zoomSlider: { classPropertyName: "zoomSlider", publicName: "zoomSlider", isSignal: true, isRequired: false, transformFunction: null }, zoomSliderShadow: { classPropertyName: "zoomSliderShadow", publicName: "zoomSliderShadow", isSignal: true, isRequired: false, transformFunction: null }, zoomSliderRealtime: { classPropertyName: "zoomSliderRealtime", publicName: "zoomSliderRealtime", isSignal: true, isRequired: false, transformFunction: null }, zoomSliderBrush: { classPropertyName: "zoomSliderBrush", publicName: "zoomSliderBrush", isSignal: true, isRequired: false, transformFunction: null }, zoomInside: { classPropertyName: "zoomInside", publicName: "zoomInside", isSignal: true, isRequired: false, transformFunction: null }, maxEntries: { classPropertyName: "maxEntries", publicName: "maxEntries", isSignal: true, isRequired: false, transformFunction: null }, visibleEntries: { classPropertyName: "visibleEntries", publicName: "visibleEntries", isSignal: true, isRequired: false, transformFunction: null }, visibleRange: { classPropertyName: "visibleRange", publicName: "visibleRange", isSignal: true, isRequired: false, transformFunction: null }, autoZoomSeriesIndex: { classPropertyName: "autoZoomSeriesIndex", publicName: "autoZoomSeriesIndex", isSignal: true, isRequired: false, transformFunction: null }, theme: { classPropertyName: "theme", publicName: "theme", isSignal: true, isRequired: false, transformFunction: null }, themeCustomization: { classPropertyName: "themeCustomization", publicName: "themeCustomization", isSignal: true, isRequired: false, transformFunction: null }, palette: { classPropertyName: "palette", publicName: "palette", isSignal: true, isRequired: false, transformFunction: null }, axisPointer: { classPropertyName: "axisPointer", publicName: "axisPointer", isSignal: true, isRequired: false, transformFunction: null }, dataZoomRange: { classPropertyName: "dataZoomRange", publicName: "dataZoomRange", isSignal: true, isRequired: false, transformFunction: null }, dataZoomMinValueSpan: { classPropertyName: "dataZoomMinValueSpan", publicName: "dataZoomMinValueSpan", isSignal: true, isRequired: false, transformFunction: null }, dataZoomMaxValueSpan: { classPropertyName: "dataZoomMaxValueSpan", publicName: "dataZoomMaxValueSpan", isSignal: true, isRequired: false, transformFunction: null }, dataZoomFilterMode: { classPropertyName: "dataZoomFilterMode", publicName: "dataZoomFilterMode", isSignal: true, isRequired: false, transformFunction: null }, customLegendAction: { classPropertyName: "customLegendAction", publicName: "customLegendAction", isSignal: true, isRequired: false, transformFunction: null }, selectedItem: { classPropertyName: "selectedItem", publicName: "selectedItem", isSignal: true, isRequired: false, transformFunction: null }, eChartContainerHeight: { classPropertyName: "eChartContainerHeight", publicName: "eChartContainerHeight", isSignal: true, isRequired: false, transformFunction: null }, externalZoomSlider: { classPropertyName: "externalZoomSlider", publicName: "externalZoomSlider", isSignal: true, isRequired: false, transformFunction: null }, externalXAxisFormatter: { classPropertyName: "externalXAxisFormatter", publicName: "externalXAxisFormatter", isSignal: true, isRequired: false, transformFunction: null }, showTimeRangeBar: { classPropertyName: "showTimeRangeBar", publicName: "showTimeRangeBar", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { showLegend: "showLegendChange", visibleEntries: "visibleEntriesChange", visibleRange: "visibleRangeChange", dataZoom: "dataZoom", pointer: "pointer", selectionChanged: "selectionChanged", chartSeriesClick: "chartSeriesClick", chartGridResized: "chartGridResized", customLegendMultiLineInfoEvent: "customLegendMultiLineInfoEvent", timeRangeChange: "timeRangeChange" }, host: { listeners: { "window:theme-switch": "resetChart()" } }, viewQueries: [{ propertyName: "chartContainerWrapper", first: true, predicate: ["chartContainerWrapper"], descendants: true, isSignal: true }, { propertyName: "chartContainer", first: true, predicate: ["chart"], descendants: true, isSignal: true }, { propertyName: "externalZoomSliderContainer", first: true, predicate: ["externalZoomSlider"], descendants: true, isSignal: true }, { propertyName: "siCustomLegend", predicate: ["siCustomLegend"], descendants: true, read: SiCustomLegendComponent, isSignal: true }], usesOnChanges: true, ngImport: i0, template: "@if (showCustomLegend() && (title() || subTitle())) {\n <div\n class=\"si-title-2 chart-title chart-title-width\"\n [style.background-color]=\"backgroundColor()\"\n >\n <div class=\"chart-title-text\" [style.color]=\"titleColor()\">{{ title() }}</div>\n @if (subTitle()) {\n <div class=\"si-body-2\" [style.color]=\"subTitleColor()\">{{ subTitle() }}</div>\n }\n </div>\n}\n\n<div\n #chartContainerWrapper\n class=\"chart-container-wrapper\"\n [class.chart-scroll]=\"containerHeight()\"\n [attr.tabindex]=\"containerHeight() ? '0' : null\"\n>\n <div class=\"chart-container\" [style.height.px]=\"containerHeight()\">\n @if (showCustomLegend()) {\n @for (cl of customLegend; track $index) {\n <si-custom-legend\n #siCustomLegend\n class=\"custom-legend\"\n [style.top.px]=\"cl.top\"\n [title]=\"title()\"\n [subTitle]=\"subTitle()\"\n [customLegend]=\"cl\"\n [style.background-color]=\"backgroundColor()\"\n [titleColor]=\"titleColor()\"\n [subTitleColor]=\"subTitleColor()\"\n [textColor]=\"textColor()\"\n (legendIconClickEvent)=\"handleLegendClick($event)\"\n (legendClickEvent)=\"handleLegendClick($event)\"\n (legendHoverStartEvent)=\"handleLegendHover($event, true)\"\n (legendHoverEndEvent)=\"handleLegendHover($event, false)\"\n />\n }\n }\n <div #chart class=\"echart-container\" [style.height.px]=\"containerHeight()\"></div>\n </div>\n</div>\n@if (externalZoomSlider()) {\n <div\n #externalZoomSlider\n class=\"external-zoom-container\"\n [class.has-time-range-bar]=\"showTimeRangeBar()\"\n [style.--time-bar-height.px]=\"timeBarHeight()\"\n ></div>\n}\n\n@if (showTimeRangeBar() && zoomSlider()) {\n <div\n class=\"time-range-bar\"\n [style.bottom.px]=\"timeBarBottom()\"\n [style.padding-left.px]=\"timeBarLeft()\"\n [style.padding-right.px]=\"timeBarRight()\"\n >\n <ng-content select=\"[slot=timeRangeBar]\" />\n </div>\n}\n\n@if (inProgress()) {\n <div class=\"progress-container\">\n <si-chart-loading-spinner />\n </div>\n}\n", styles: [":host{block-size:100%;position:relative;display:flex!important;flex-direction:column;inline-size:100%}.chart-container-wrapper{display:flex;flex:1 0 0;inline-size:inherit;overflow:hidden}.chart-scroll{overflow-y:auto}.chart-container{position:relative;display:flex;flex:1 0 0;overflow:hidden}.echart-container{flex:1 0 0;inline-size:100%;min-block-size:var(--si-chart-min-height, 200px);overflow:hidden}.custom-legend{position:absolute;z-index:2;inline-size:100%}.chart-title{padding-block:12px 8px;padding-inline-start:24px}.external-zoom-container{display:flex;flex:1 0 0;inline-size:inherit;max-block-size:112px}.external-zoom-container.has-time-range-bar{max-block-size:calc(112px + var(--time-bar-height))}.tooltip-inner{max-inline-size:375px;min-inline-size:375px;color:#162938;font-size:18px;background-color:#162938}.time-range-bar{position:absolute;inset-inline:0;z-index:2}.progress-container{position:absolute;inset:0;pointer-events:none;z-index:100;display:flex;justify-content:center;align-items:center}\n"], dependencies: [{ kind: "component", type: SiCustomLegendComponent, selector: "si-custom-legend", inputs: ["customLegend", "title", "subTitle", "titleColor", "subTitleColor", "textColor"], outputs: ["legendIconClickEvent", "legendClickEvent", "legendHoverStartEvent", "legendHoverEndEvent"] }, { kind: "component", type: SiChartLoadingSpinnerComponent, selector: "si-chart-loading-spinner" }] });
2316
+ }
2317
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.6", ngImport: i0, type: SiChartComponent, decorators: [{
2318
+ type: Component,
2319
+ args: [{ selector: 'si-chart', imports: [SiCustomLegendComponent, SiChartLoadingSpinnerComponent], template: "@if (showCustomLegend() && (title() || subTitle())) {\n <div\n class=\"si-title-2 chart-title chart-title-width\"\n [style.background-color]=\"backgroundColor()\"\n >\n <div class=\"chart-title-text\" [style.color]=\"titleColor()\">{{ title() }}</div>\n @if (subTitle()) {\n <div class=\"si-body-2\" [style.color]=\"subTitleColor()\">{{ subTitle() }}</div>\n }\n </div>\n}\n\n<div\n #chartContainerWrapper\n class=\"chart-container-wrapper\"\n [class.chart-scroll]=\"containerHeight()\"\n [attr.tabindex]=\"containerHeight() ? '0' : null\"\n>\n <div class=\"chart-container\" [style.height.px]=\"containerHeight()\">\n @if (showCustomLegend()) {\n @for (cl of customLegend; track $index) {\n <si-custom-legend\n #siCustomLegend\n class=\"custom-legend\"\n [style.top.px]=\"cl.top\"\n [title]=\"title()\"\n [subTitle]=\"subTitle()\"\n [customLegend]=\"cl\"\n [style.background-color]=\"backgroundColor()\"\n [titleColor]=\"titleColor()\"\n [subTitleColor]=\"subTitleColor()\"\n [textColor]=\"textColor()\"\n (legendIconClickEvent)=\"handleLegendClick($event)\"\n (legendClickEvent)=\"handleLegendClick($event)\"\n (legendHoverStartEvent)=\"handleLegendHover($event, true)\"\n (legendHoverEndEvent)=\"handleLegendHover($event, false)\"\n />\n }\n }\n <div #chart class=\"echart-container\" [style.height.px]=\"containerHeight()\"></div>\n </div>\n</div>\n@if (externalZoomSlider()) {\n <div\n #externalZoomSlider\n class=\"external-zoom-container\"\n [class.has-time-range-bar]=\"showTimeRangeBar()\"\n [style.--time-bar-height.px]=\"timeBarHeight()\"\n ></div>\n}\n\n@if (showTimeRangeBar() && zoomSlider()) {\n <div\n class=\"time-range-bar\"\n [style.bottom.px]=\"timeBarBottom()\"\n [style.padding-left.px]=\"timeBarLeft()\"\n [style.padding-right.px]=\"timeBarRight()\"\n >\n <ng-content select=\"[slot=timeRangeBar]\" />\n </div>\n}\n\n@if (inProgress()) {\n <div class=\"progress-container\">\n <si-chart-loading-spinner />\n </div>\n}\n", styles: [":host{block-size:100%;position:relative;display:flex!important;flex-direction:column;inline-size:100%}.chart-container-wrapper{display:flex;flex:1 0 0;inline-size:inherit;overflow:hidden}.chart-scroll{overflow-y:auto}.chart-container{position:relative;display:flex;flex:1 0 0;overflow:hidden}.echart-container{flex:1 0 0;inline-size:100%;min-block-size:var(--si-chart-min-height, 200px);overflow:hidden}.custom-legend{position:absolute;z-index:2;inline-size:100%}.chart-title{padding-block:12px 8px;padding-inline-start:24px}.external-zoom-container{display:flex;flex:1 0 0;inline-size:inherit;max-block-size:112px}.external-zoom-container.has-time-range-bar{max-block-size:calc(112px + var(--time-bar-height))}.tooltip-inner{max-inline-size:375px;min-inline-size:375px;color:#162938;font-size:18px;background-color:#162938}.time-range-bar{position:absolute;inset-inline:0;z-index:2}.progress-container{position:absolute;inset:0;pointer-events:none;z-index:100;display:flex;justify-content:center;align-items:center}\n"] }]
2320
+ }], propDecorators: { resetChart: [{
2321
+ type: HostListener,
2322
+ args: ['window:theme-switch']
2323
+ }] } });
2324
+
2325
+ /**
2326
+ * Copyright Siemens 2016 - 2025.
2327
+ * SPDX-License-Identifier: MIT
2328
+ */
2329
+
2330
+ /**
2331
+ * Copyright Siemens 2016 - 2025.
2332
+ * SPDX-License-Identifier: MIT
2333
+ */
2334
+ class SiChartCartesianComponent extends SiChartComponent {
2335
+ series = input();
2336
+ subChartGrids = input();
2337
+ yAxis = input();
2338
+ xAxis = input();
2339
+ tooltipFormatter = input();
2340
+ /**
2341
+ * Used to display the chart as a stacked one.
2342
+ *
2343
+ * @defaultValue false
2344
+ */
2345
+ stacked = input(false);
2346
+ /** Enable or disable brush zoom mode */
2347
+ zoomMode = input();
2348
+ // Used to toggle different chart types
2349
+ ngOnChanges(changes) {
2350
+ if (changes.zoomMode) {
2351
+ this.setZoomMode();
2352
+ }
2353
+ if (changes.stacked) {
2354
+ changes.forceAll = changes.stacked;
2355
+ }
2356
+ if (changes.subChartGrids) {
2357
+ changes.forceAll = changes.subChartGrids;
2358
+ }
2359
+ super.ngOnChanges(changes);
2360
+ }
2361
+ formatTooltip(p) {
2362
+ const params = Array.isArray(p) ? p : [p];
2363
+ const label = params[0]?.axisValueLabel ?? '';
2364
+ let html = label;
2365
+ for (const series of params) {
2366
+ const isCandle = series.componentSubType === 'candlestick';
2367
+ const isPie = series.componentSubType === 'pie';
2368
+ const useName = series.name != series.axisValue;
2369
+ const name = isPie
2370
+ ? series.data.name
2371
+ : useName
2372
+ ? (series.name ?? series.seriesName)
2373
+ : series.seriesName;
2374
+ const valIndex = (series.encode.value ?? series.encode.y)[0];
2375
+ const value = isCandle
2376
+ ? ''
2377
+ : isPie
2378
+ ? series.percent + '%'
2379
+ : Array.isArray(series.value)
2380
+ ? series.value[valIndex]
2381
+ : series.value;
2382
+ html += '<div style="display: flex; align-items: center;">';
2383
+ html += this.getSeriesMarkerSvg(name);
2384
+ html += `<span style="margin-inline: 4px 8px">${name}</span>`;
2385
+ html += `<span style="margin-inline-start: auto">${value}</span>`;
2386
+ html += '</div>';
2387
+ }
2388
+ return html;
2389
+ }
2390
+ /**
2391
+ * Get the series marker svg by series name.
2392
+ */
2393
+ getSeriesMarkerSvg(seriesName) {
2394
+ const seriesValue = this.actualOptions.series;
2395
+ let sym;
2396
+ if (seriesValue) {
2397
+ sym = this.getSeriesMarker(seriesName);
2398
+ const symbol = this.shapePaths[sym];
2399
+ const color = this.getSeriesColorBySeriesName(seriesName);
2400
+ return `<svg width="12" height="12" xmlns="http://www.w3.org/2000/svg">
2401
+ <path d="${symbol}" fill="${color}" />
2402
+ </svg>`;
2403
+ }
2404
+ return '';
2405
+ }
2406
+ /**
2407
+ * Get the series marker by series name.
2408
+ */
2409
+ getSeriesMarker(seriesName) {
2410
+ const seriesValue = this.actualOptions.series;
2411
+ if (seriesValue) {
2412
+ const seriesMarker = seriesValue.find(ser => ser.name === seriesName);
2413
+ if (seriesMarker && 'symbol' in seriesMarker) {
2414
+ return seriesMarker.symbol;
2415
+ }
2416
+ }
2417
+ return 'circle';
2418
+ }
2419
+ afterChartInit(skipZoom) {
2420
+ super.afterChartInit(skipZoom);
2421
+ if (this.zoomMode()) {
2422
+ this.setZoomMode();
2423
+ }
2424
+ }
2425
+ setZoomMode() {
2426
+ this.dispatchEChartAction({
2427
+ type: 'takeGlobalCursor',
2428
+ key: 'dataZoomSelect',
2429
+ dataZoomSelectActive: this.zoomMode()
2430
+ });
2431
+ }
2432
+ getValidXAxis() {
2433
+ const validXAxis = new Set();
2434
+ this.series()?.forEach(series => {
2435
+ if (series.visible !== false && series.xAxisIndex !== undefined) {
2436
+ validXAxis.add(series.xAxisIndex);
2437
+ }
2438
+ });
2439
+ return validXAxis;
2440
+ }
2441
+ applyOptions() {
2442
+ this.actualOptions = {
2443
+ series: [],
2444
+ xAxis: this.xAxis(),
2445
+ grid: this.getGrid(),
2446
+ yAxis: this.yAxis(),
2447
+ toolbox: {
2448
+ showTitle: false,
2449
+ itemSize: 0,
2450
+ feature: {
2451
+ dataZoom: {
2452
+ filterMode: 'none',
2453
+ xAxisIndex: 'all',
2454
+ yAxisIndex: false,
2455
+ icon: {
2456
+ zoom: 'image://',
2457
+ back: 'image://'
2458
+ }
2459
+ }
2460
+ }
2461
+ },
2462
+ legend: [
2463
+ {
2464
+ data: []
2465
+ },
2466
+ {
2467
+ data: []
2468
+ }
2469
+ ],
2470
+ tooltip: {
2471
+ trigger: 'axis'
2472
+ }
2473
+ };
2474
+ const tooltipFormatter = this.tooltipFormatter();
2475
+ if (tooltipFormatter) {
2476
+ this.actualOptions.tooltip.formatter = tooltipFormatter;
2477
+ }
2478
+ else if (this.hasDifferentMarker()) {
2479
+ this.actualOptions.tooltip.formatter = this.formatTooltip.bind(this);
2480
+ }
2481
+ const yAxis = this.yAxis();
2482
+ const yAxisArray = Array.isArray(yAxis) ? yAxis : yAxis ? [yAxis] : [];
2483
+ const numRight = yAxisArray.reduce((acc, cur) => acc + (cur.position === 'right' ? 1 : 0), 0);
2484
+ const numLeft = yAxisArray.length - numRight;
2485
+ const legendLeftOptions = this.getThemeCustomValue(['legendLeft'], {});
2486
+ const legendRightOptions = this.getThemeCustomValue(['legendRight'], {});
2487
+ let leftUnitText;
2488
+ let rightUnitText;
2489
+ const legends = this.actualOptions.legend;
2490
+ if (numLeft && numRight) {
2491
+ echarts.util.merge(legends[0], legendLeftOptions, true);
2492
+ echarts.util.merge(legends[1], legendRightOptions, true);
2493
+ }
2494
+ else if (Array.isArray(this.yAxis()) && numLeft) {
2495
+ echarts.util.merge(legends[0], { left: legendLeftOptions.left }, true);
2496
+ }
2497
+ else if (numRight) {
2498
+ echarts.util.merge(legends[1], { right: legendRightOptions.right }, true);
2499
+ }
2500
+ const subChartGrids = this.subChartGrids();
2501
+ if (subChartGrids) {
2502
+ if (subChartGrids.length !== this.customLegend.length) {
2503
+ const diff = subChartGrids.length - this.customLegend.length;
2504
+ if (diff < 0) {
2505
+ this.customLegend.length = subChartGrids.length;
2506
+ }
2507
+ else {
2508
+ for (let i = 0; i < diff; i++) {
2509
+ // Add default custom legends for all grids
2510
+ const cl = {
2511
+ customLegends: [
2512
+ { list: [], unit: '' },
2513
+ { list: [], unit: '' }
2514
+ ],
2515
+ legendAxis: 'both'
2516
+ };
2517
+ this.customLegend.push(cl);
2518
+ }
2519
+ }
2520
+ }
2521
+ const margin = 16;
2522
+ // calculate custom legend positions from top according to subcharts.
2523
+ for (let i = 0; i < subChartGrids.length; i++) {
2524
+ if (i === 0) {
2525
+ this.customLegend[i].top = 0;
2526
+ }
2527
+ else {
2528
+ const prevGrid = subChartGrids[i - 1];
2529
+ const subChartTop = prevGrid.top ?? 0;
2530
+ const subChartHeight = prevGrid.height ?? 0;
2531
+ this.customLegend[i].top = subChartTop + subChartHeight + margin;
2532
+ }
2533
+ }
2534
+ }
2535
+ const seriesValue = this.series();
2536
+ if (seriesValue) {
2537
+ const optionSeries = this.actualOptions.series;
2538
+ seriesValue.forEach(series => {
2539
+ const s = Object.assign({
2540
+ stack: this.stacked()
2541
+ }, series);
2542
+ if (s.type === 'line' && s.area) {
2543
+ delete s.area;
2544
+ s.areaStyle = {};
2545
+ }
2546
+ else {
2547
+ s.areaStyle ??= null;
2548
+ }
2549
+ delete s.visible;
2550
+ if ('symbol' in series && !this.shapePaths[series.symbol]) {
2551
+ s.symbol = 'circle';
2552
+ }
2553
+ optionSeries.push(s);
2554
+ if (this.showLegend() && series.name) {
2555
+ let legendIndex = 0;
2556
+ const axis = yAxisArray[series.yAxisIndex ?? 0];
2557
+ if (axis && axis.position === 'right') {
2558
+ legendIndex = 1;
2559
+ }
2560
+ let customLegendProp;
2561
+ if (this.showCustomLegend()) {
2562
+ // get left and right axis units from axis array
2563
+ if (axis && (axis.show === undefined || axis.show)) {
2564
+ if ((!leftUnitText || leftUnitText !== axis.name) && axis.position === 'left') {
2565
+ if (axis.name != null) {
2566
+ // axis.name is the same property name which eChart uses to display axis title,
2567
+ // hence in case of custom legends units were shown at two places i.e. at axis
2568
+ // title as well as custom legend unit section. Thus changing the property name
2569
+ // to customLegendUnit only in case custom legends are used.
2570
+ axis.customLegendUnit = axis.name;
2571
+ }
2572
+ if (axis.customLegendUnit != null) {
2573
+ leftUnitText = axis.customLegendUnit;
2574
+ }
2575
+ }
2576
+ else if ((!rightUnitText || rightUnitText !== axis.name) &&
2577
+ axis.position === 'right') {
2578
+ if (axis.name != null) {
2579
+ // axis.name is the same property name which eChart uses to display axis title,
2580
+ // hence in case of custom legends units were shown at two places i.e. at axis
2581
+ // title as well as custom legend unit section. Thus changing the property name
2582
+ // to customLegendUnit only in case custom legends are used.
2583
+ axis.customLegendUnit = axis.name;
2584
+ }
2585
+ if (axis.customLegendUnit != null) {
2586
+ rightUnitText = axis.customLegendUnit;
2587
+ }
2588
+ }
2589
+ delete axis.name;
2590
+ }
2591
+ const unitText = axis.position === 'right' ? rightUnitText : leftUnitText;
2592
+ customLegendProp = {
2593
+ displayName: s.displayName,
2594
+ tooltip: s.customLegendToolTip,
2595
+ unit: unitText
2596
+ };
2597
+ }
2598
+ // As we have only 1 xAxis per sub chart, xAxisIndex equals grid index.
2599
+ const seriesSymbol = 'symbol' in s ? s.symbol : 'circle';
2600
+ this.addLegendItem(series.name, series.visible, legendIndex, series.xAxisIndex, customLegendProp, seriesSymbol);
2601
+ }
2602
+ });
2603
+ }
2604
+ this.applyTitles();
2605
+ if (this.externalZoomSlider()) {
2606
+ this.extZoomSliderOptions.legend = this.actualOptions.legend;
2607
+ }
2608
+ }
2609
+ hasDifferentMarker() {
2610
+ const seriesValue = this.series();
2611
+ return !!seriesValue?.some(series => 'symbol' in series && series.symbol !== 'circle');
2612
+ }
2613
+ getGrid() {
2614
+ const subChartGrids = this.subChartGrids();
2615
+ if (subChartGrids) {
2616
+ subChartGrids.forEach(g => (g.containLabel = false));
2617
+ return subChartGrids;
2618
+ }
2619
+ return {};
2620
+ }
2621
+ refreshSeries(isLive = true, dzToSet) {
2622
+ const seriesValue = this.series();
2623
+ if (!seriesValue) {
2624
+ return;
2625
+ }
2626
+ const optionSeries = this.actualOptions.series;
2627
+ seriesValue.forEach((series, i) => {
2628
+ optionSeries[i].data = series.data;
2629
+ });
2630
+ super.refreshSeries(isLive, dzToSet);
2631
+ }
2632
+ hasData() {
2633
+ return this.series()?.some(s => s.visible !== false && s.data && s.data.length > 0) ?? false;
2634
+ }
2635
+ handleSelectionChanged(event) {
2636
+ if (event?.selected) {
2637
+ this.series()?.forEach(series => (series.visible = event.selected[series.name] !== false));
2638
+ }
2639
+ super.handleSelectionChanged(event);
2640
+ }
2641
+ /**
2642
+ * Update single chart data entry.
2643
+ */
2644
+ addData(index, data) {
2645
+ this.addDataInternal([{ index, data }]);
2646
+ }
2647
+ /**
2648
+ * Append charts data entries to the end of the series.
2649
+ */
2650
+ addDataMulti(series) {
2651
+ this.addDataInternal(series);
2652
+ }
2653
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.6", ngImport: i0, type: SiChartCartesianComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
2654
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.6", type: SiChartCartesianComponent, isStandalone: true, selector: "si-chart-cartesian", inputs: { series: { classPropertyName: "series", publicName: "series", isSignal: true, isRequired: false, transformFunction: null }, subChartGrids: { classPropertyName: "subChartGrids", publicName: "subChartGrids", isSignal: true, isRequired: false, transformFunction: null }, yAxis: { classPropertyName: "yAxis", publicName: "yAxis", isSignal: true, isRequired: false, transformFunction: null }, xAxis: { classPropertyName: "xAxis", publicName: "xAxis", isSignal: true, isRequired: false, transformFunction: null }, tooltipFormatter: { classPropertyName: "tooltipFormatter", publicName: "tooltipFormatter", isSignal: true, isRequired: false, transformFunction: null }, stacked: { classPropertyName: "stacked", publicName: "stacked", isSignal: true, isRequired: false, transformFunction: null }, zoomMode: { classPropertyName: "zoomMode", publicName: "zoomMode", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "@if (showCustomLegend() && (title() || subTitle())) {\n <div\n class=\"si-title-2 chart-title chart-title-width\"\n [style.background-color]=\"backgroundColor()\"\n >\n <div class=\"chart-title-text\" [style.color]=\"titleColor()\">{{ title() }}</div>\n @if (subTitle()) {\n <div class=\"si-body-2\" [style.color]=\"subTitleColor()\">{{ subTitle() }}</div>\n }\n </div>\n}\n\n<div\n #chartContainerWrapper\n class=\"chart-container-wrapper\"\n [class.chart-scroll]=\"containerHeight()\"\n [attr.tabindex]=\"containerHeight() ? '0' : null\"\n>\n <div class=\"chart-container\" [style.height.px]=\"containerHeight()\">\n @if (showCustomLegend()) {\n @for (cl of customLegend; track $index) {\n <si-custom-legend\n #siCustomLegend\n class=\"custom-legend\"\n [style.top.px]=\"cl.top\"\n [title]=\"title()\"\n [subTitle]=\"subTitle()\"\n [customLegend]=\"cl\"\n [style.background-color]=\"backgroundColor()\"\n [titleColor]=\"titleColor()\"\n [subTitleColor]=\"subTitleColor()\"\n [textColor]=\"textColor()\"\n (legendIconClickEvent)=\"handleLegendClick($event)\"\n (legendClickEvent)=\"handleLegendClick($event)\"\n (legendHoverStartEvent)=\"handleLegendHover($event, true)\"\n (legendHoverEndEvent)=\"handleLegendHover($event, false)\"\n />\n }\n }\n <div #chart class=\"echart-container\" [style.height.px]=\"containerHeight()\"></div>\n </div>\n</div>\n@if (externalZoomSlider()) {\n <div\n #externalZoomSlider\n class=\"external-zoom-container\"\n [class.has-time-range-bar]=\"showTimeRangeBar()\"\n [style.--time-bar-height.px]=\"timeBarHeight()\"\n ></div>\n}\n\n@if (showTimeRangeBar() && zoomSlider()) {\n <div\n class=\"time-range-bar\"\n [style.bottom.px]=\"timeBarBottom()\"\n [style.padding-left.px]=\"timeBarLeft()\"\n [style.padding-right.px]=\"timeBarRight()\"\n >\n <ng-content select=\"[slot=timeRangeBar]\" />\n </div>\n}\n\n@if (inProgress()) {\n <div class=\"progress-container\">\n <si-chart-loading-spinner />\n </div>\n}\n", styles: [":host{block-size:100%;position:relative;display:flex!important;flex-direction:column;inline-size:100%}.chart-container-wrapper{display:flex;flex:1 0 0;inline-size:inherit;overflow:hidden}.chart-scroll{overflow-y:auto}.chart-container{position:relative;display:flex;flex:1 0 0;overflow:hidden}.echart-container{flex:1 0 0;inline-size:100%;min-block-size:var(--si-chart-min-height, 200px);overflow:hidden}.custom-legend{position:absolute;z-index:2;inline-size:100%}.chart-title{padding-block:12px 8px;padding-inline-start:24px}.external-zoom-container{display:flex;flex:1 0 0;inline-size:inherit;max-block-size:112px}.external-zoom-container.has-time-range-bar{max-block-size:calc(112px + var(--time-bar-height))}.tooltip-inner{max-inline-size:375px;min-inline-size:375px;color:#162938;font-size:18px;background-color:#162938}.time-range-bar{position:absolute;inset-inline:0;z-index:2}.progress-container{position:absolute;inset:0;pointer-events:none;z-index:100;display:flex;justify-content:center;align-items:center}\n"], dependencies: [{ kind: "component", type: SiCustomLegendComponent, selector: "si-custom-legend", inputs: ["customLegend", "title", "subTitle", "titleColor", "subTitleColor", "textColor"], outputs: ["legendIconClickEvent", "legendClickEvent", "legendHoverStartEvent", "legendHoverEndEvent"] }, { kind: "component", type: SiChartLoadingSpinnerComponent, selector: "si-chart-loading-spinner" }] });
2655
+ }
2656
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.6", ngImport: i0, type: SiChartCartesianComponent, decorators: [{
2657
+ type: Component,
2658
+ args: [{ selector: 'si-chart-cartesian', imports: [SiCustomLegendComponent, SiChartLoadingSpinnerComponent], template: "@if (showCustomLegend() && (title() || subTitle())) {\n <div\n class=\"si-title-2 chart-title chart-title-width\"\n [style.background-color]=\"backgroundColor()\"\n >\n <div class=\"chart-title-text\" [style.color]=\"titleColor()\">{{ title() }}</div>\n @if (subTitle()) {\n <div class=\"si-body-2\" [style.color]=\"subTitleColor()\">{{ subTitle() }}</div>\n }\n </div>\n}\n\n<div\n #chartContainerWrapper\n class=\"chart-container-wrapper\"\n [class.chart-scroll]=\"containerHeight()\"\n [attr.tabindex]=\"containerHeight() ? '0' : null\"\n>\n <div class=\"chart-container\" [style.height.px]=\"containerHeight()\">\n @if (showCustomLegend()) {\n @for (cl of customLegend; track $index) {\n <si-custom-legend\n #siCustomLegend\n class=\"custom-legend\"\n [style.top.px]=\"cl.top\"\n [title]=\"title()\"\n [subTitle]=\"subTitle()\"\n [customLegend]=\"cl\"\n [style.background-color]=\"backgroundColor()\"\n [titleColor]=\"titleColor()\"\n [subTitleColor]=\"subTitleColor()\"\n [textColor]=\"textColor()\"\n (legendIconClickEvent)=\"handleLegendClick($event)\"\n (legendClickEvent)=\"handleLegendClick($event)\"\n (legendHoverStartEvent)=\"handleLegendHover($event, true)\"\n (legendHoverEndEvent)=\"handleLegendHover($event, false)\"\n />\n }\n }\n <div #chart class=\"echart-container\" [style.height.px]=\"containerHeight()\"></div>\n </div>\n</div>\n@if (externalZoomSlider()) {\n <div\n #externalZoomSlider\n class=\"external-zoom-container\"\n [class.has-time-range-bar]=\"showTimeRangeBar()\"\n [style.--time-bar-height.px]=\"timeBarHeight()\"\n ></div>\n}\n\n@if (showTimeRangeBar() && zoomSlider()) {\n <div\n class=\"time-range-bar\"\n [style.bottom.px]=\"timeBarBottom()\"\n [style.padding-left.px]=\"timeBarLeft()\"\n [style.padding-right.px]=\"timeBarRight()\"\n >\n <ng-content select=\"[slot=timeRangeBar]\" />\n </div>\n}\n\n@if (inProgress()) {\n <div class=\"progress-container\">\n <si-chart-loading-spinner />\n </div>\n}\n", styles: [":host{block-size:100%;position:relative;display:flex!important;flex-direction:column;inline-size:100%}.chart-container-wrapper{display:flex;flex:1 0 0;inline-size:inherit;overflow:hidden}.chart-scroll{overflow-y:auto}.chart-container{position:relative;display:flex;flex:1 0 0;overflow:hidden}.echart-container{flex:1 0 0;inline-size:100%;min-block-size:var(--si-chart-min-height, 200px);overflow:hidden}.custom-legend{position:absolute;z-index:2;inline-size:100%}.chart-title{padding-block:12px 8px;padding-inline-start:24px}.external-zoom-container{display:flex;flex:1 0 0;inline-size:inherit;max-block-size:112px}.external-zoom-container.has-time-range-bar{max-block-size:calc(112px + var(--time-bar-height))}.tooltip-inner{max-inline-size:375px;min-inline-size:375px;color:#162938;font-size:18px;background-color:#162938}.time-range-bar{position:absolute;inset-inline:0;z-index:2}.progress-container{position:absolute;inset:0;pointer-events:none;z-index:100;display:flex;justify-content:center;align-items:center}\n"] }]
2659
+ }] });
2660
+
2661
+ /**
2662
+ * Copyright Siemens 2016 - 2025.
2663
+ * SPDX-License-Identifier: MIT
2664
+ */
2665
+
2666
+ /**
2667
+ * Copyright Siemens 2016 - 2025.
2668
+ * SPDX-License-Identifier: MIT
2669
+ */
2670
+ class SiChartCircleComponent extends SiChartComponent {
2671
+ series = input();
2672
+ applyOptions() {
2673
+ this.actualOptions = {
2674
+ series: [],
2675
+ legend: [
2676
+ {
2677
+ data: []
2678
+ }
2679
+ ],
2680
+ tooltip: {
2681
+ trigger: 'item',
2682
+ confine: true
2683
+ }
2684
+ };
2685
+ const optionSeries = this.actualOptions.series;
2686
+ const offset = !this.showCustomLegend() && this.subTitle()
2687
+ ? this.getThemeCustomValue(['subTitle', 'legend', 'top'], 0)
2688
+ : 0;
2689
+ const top = 32 + offset;
2690
+ this.series()?.forEach(series => {
2691
+ const s = Object.assign({ type: 'pie', top }, series);
2692
+ optionSeries.push(s);
2693
+ if (this.showLegend()) {
2694
+ series.data.forEach(data => {
2695
+ if (data.name) {
2696
+ this.addLegendItem(data.name);
2697
+ }
2698
+ });
2699
+ }
2700
+ });
2701
+ this.applyTitles();
2702
+ }
2703
+ applyDataZoom() { }
2704
+ /**
2705
+ * Update single value of the circle chart.
2706
+ */
2707
+ changeSingleValue(index, valueIndex, value) {
2708
+ const optionSeries = this.actualOptions.series;
2709
+ const series = optionSeries[index].data;
2710
+ series[valueIndex].value = value;
2711
+ this.updateEChart();
2712
+ }
2713
+ /**
2714
+ * Update multiple values of the circle chart.
2715
+ */
2716
+ changeMultiValues(updateValues) {
2717
+ const optionSeries = this.actualOptions.series;
2718
+ updateValues.forEach(update => {
2719
+ const currentSeries = optionSeries[update.seriesIndex].data;
2720
+ if (!currentSeries) {
2721
+ return;
2722
+ }
2723
+ currentSeries[update.valueIndex].value = update.value;
2724
+ });
2725
+ this.updateEChart();
2726
+ }
2727
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.6", ngImport: i0, type: SiChartCircleComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
2728
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.6", type: SiChartCircleComponent, isStandalone: true, selector: "si-chart-circle", inputs: { series: { classPropertyName: "series", publicName: "series", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: "@if (showCustomLegend() && (title() || subTitle())) {\n <div\n class=\"si-title-2 chart-title chart-title-width\"\n [style.background-color]=\"backgroundColor()\"\n >\n <div class=\"chart-title-text\" [style.color]=\"titleColor()\">{{ title() }}</div>\n @if (subTitle()) {\n <div class=\"si-body-2\" [style.color]=\"subTitleColor()\">{{ subTitle() }}</div>\n }\n </div>\n}\n\n<div\n #chartContainerWrapper\n class=\"chart-container-wrapper\"\n [class.chart-scroll]=\"containerHeight()\"\n [attr.tabindex]=\"containerHeight() ? '0' : null\"\n>\n <div class=\"chart-container\" [style.height.px]=\"containerHeight()\">\n @if (showCustomLegend()) {\n @for (cl of customLegend; track $index) {\n <si-custom-legend\n #siCustomLegend\n class=\"custom-legend\"\n [style.top.px]=\"cl.top\"\n [title]=\"title()\"\n [subTitle]=\"subTitle()\"\n [customLegend]=\"cl\"\n [style.background-color]=\"backgroundColor()\"\n [titleColor]=\"titleColor()\"\n [subTitleColor]=\"subTitleColor()\"\n [textColor]=\"textColor()\"\n (legendIconClickEvent)=\"handleLegendClick($event)\"\n (legendClickEvent)=\"handleLegendClick($event)\"\n (legendHoverStartEvent)=\"handleLegendHover($event, true)\"\n (legendHoverEndEvent)=\"handleLegendHover($event, false)\"\n />\n }\n }\n <div #chart class=\"echart-container\" [style.height.px]=\"containerHeight()\"></div>\n </div>\n</div>\n@if (externalZoomSlider()) {\n <div\n #externalZoomSlider\n class=\"external-zoom-container\"\n [class.has-time-range-bar]=\"showTimeRangeBar()\"\n [style.--time-bar-height.px]=\"timeBarHeight()\"\n ></div>\n}\n\n@if (showTimeRangeBar() && zoomSlider()) {\n <div\n class=\"time-range-bar\"\n [style.bottom.px]=\"timeBarBottom()\"\n [style.padding-left.px]=\"timeBarLeft()\"\n [style.padding-right.px]=\"timeBarRight()\"\n >\n <ng-content select=\"[slot=timeRangeBar]\" />\n </div>\n}\n\n@if (inProgress()) {\n <div class=\"progress-container\">\n <si-chart-loading-spinner />\n </div>\n}\n", styles: [":host{block-size:100%;position:relative;display:flex!important;flex-direction:column;inline-size:100%}.chart-container-wrapper{display:flex;flex:1 0 0;inline-size:inherit;overflow:hidden}.chart-scroll{overflow-y:auto}.chart-container{position:relative;display:flex;flex:1 0 0;overflow:hidden}.echart-container{flex:1 0 0;inline-size:100%;min-block-size:var(--si-chart-min-height, 200px);overflow:hidden}.custom-legend{position:absolute;z-index:2;inline-size:100%}.chart-title{padding-block:12px 8px;padding-inline-start:24px}.external-zoom-container{display:flex;flex:1 0 0;inline-size:inherit;max-block-size:112px}.external-zoom-container.has-time-range-bar{max-block-size:calc(112px + var(--time-bar-height))}.tooltip-inner{max-inline-size:375px;min-inline-size:375px;color:#162938;font-size:18px;background-color:#162938}.time-range-bar{position:absolute;inset-inline:0;z-index:2}.progress-container{position:absolute;inset:0;pointer-events:none;z-index:100;display:flex;justify-content:center;align-items:center}\n"], dependencies: [{ kind: "component", type: SiCustomLegendComponent, selector: "si-custom-legend", inputs: ["customLegend", "title", "subTitle", "titleColor", "subTitleColor", "textColor"], outputs: ["legendIconClickEvent", "legendClickEvent", "legendHoverStartEvent", "legendHoverEndEvent"] }, { kind: "component", type: SiChartLoadingSpinnerComponent, selector: "si-chart-loading-spinner" }] });
2729
+ }
2730
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.6", ngImport: i0, type: SiChartCircleComponent, decorators: [{
2731
+ type: Component,
2732
+ args: [{ selector: 'si-chart-circle', imports: [SiCustomLegendComponent, SiChartLoadingSpinnerComponent], template: "@if (showCustomLegend() && (title() || subTitle())) {\n <div\n class=\"si-title-2 chart-title chart-title-width\"\n [style.background-color]=\"backgroundColor()\"\n >\n <div class=\"chart-title-text\" [style.color]=\"titleColor()\">{{ title() }}</div>\n @if (subTitle()) {\n <div class=\"si-body-2\" [style.color]=\"subTitleColor()\">{{ subTitle() }}</div>\n }\n </div>\n}\n\n<div\n #chartContainerWrapper\n class=\"chart-container-wrapper\"\n [class.chart-scroll]=\"containerHeight()\"\n [attr.tabindex]=\"containerHeight() ? '0' : null\"\n>\n <div class=\"chart-container\" [style.height.px]=\"containerHeight()\">\n @if (showCustomLegend()) {\n @for (cl of customLegend; track $index) {\n <si-custom-legend\n #siCustomLegend\n class=\"custom-legend\"\n [style.top.px]=\"cl.top\"\n [title]=\"title()\"\n [subTitle]=\"subTitle()\"\n [customLegend]=\"cl\"\n [style.background-color]=\"backgroundColor()\"\n [titleColor]=\"titleColor()\"\n [subTitleColor]=\"subTitleColor()\"\n [textColor]=\"textColor()\"\n (legendIconClickEvent)=\"handleLegendClick($event)\"\n (legendClickEvent)=\"handleLegendClick($event)\"\n (legendHoverStartEvent)=\"handleLegendHover($event, true)\"\n (legendHoverEndEvent)=\"handleLegendHover($event, false)\"\n />\n }\n }\n <div #chart class=\"echart-container\" [style.height.px]=\"containerHeight()\"></div>\n </div>\n</div>\n@if (externalZoomSlider()) {\n <div\n #externalZoomSlider\n class=\"external-zoom-container\"\n [class.has-time-range-bar]=\"showTimeRangeBar()\"\n [style.--time-bar-height.px]=\"timeBarHeight()\"\n ></div>\n}\n\n@if (showTimeRangeBar() && zoomSlider()) {\n <div\n class=\"time-range-bar\"\n [style.bottom.px]=\"timeBarBottom()\"\n [style.padding-left.px]=\"timeBarLeft()\"\n [style.padding-right.px]=\"timeBarRight()\"\n >\n <ng-content select=\"[slot=timeRangeBar]\" />\n </div>\n}\n\n@if (inProgress()) {\n <div class=\"progress-container\">\n <si-chart-loading-spinner />\n </div>\n}\n", styles: [":host{block-size:100%;position:relative;display:flex!important;flex-direction:column;inline-size:100%}.chart-container-wrapper{display:flex;flex:1 0 0;inline-size:inherit;overflow:hidden}.chart-scroll{overflow-y:auto}.chart-container{position:relative;display:flex;flex:1 0 0;overflow:hidden}.echart-container{flex:1 0 0;inline-size:100%;min-block-size:var(--si-chart-min-height, 200px);overflow:hidden}.custom-legend{position:absolute;z-index:2;inline-size:100%}.chart-title{padding-block:12px 8px;padding-inline-start:24px}.external-zoom-container{display:flex;flex:1 0 0;inline-size:inherit;max-block-size:112px}.external-zoom-container.has-time-range-bar{max-block-size:calc(112px + var(--time-bar-height))}.tooltip-inner{max-inline-size:375px;min-inline-size:375px;color:#162938;font-size:18px;background-color:#162938}.time-range-bar{position:absolute;inset-inline:0;z-index:2}.progress-container{position:absolute;inset:0;pointer-events:none;z-index:100;display:flex;justify-content:center;align-items:center}\n"] }]
2733
+ }] });
2734
+
2735
+ /**
2736
+ * Copyright Siemens 2016 - 2025.
2737
+ * SPDX-License-Identifier: MIT
2738
+ */
2739
+
2740
+ /**
2741
+ * Copyright Siemens 2016 - 2025.
2742
+ * SPDX-License-Identifier: MIT
2743
+ */
2744
+ class SiChartGaugeComponent extends SiChartComponent {
2745
+ /** @defaultValue 0 */
2746
+ minValue = input(0);
2747
+ /** @defaultValue 100 */
2748
+ maxValue = input(100);
2749
+ /** @defaultValue 0 */
2750
+ value = input(0);
2751
+ splitSteps = input();
2752
+ /** @defaultValue true */
2753
+ responsiveSplitSteps = input(true);
2754
+ /** @defaultValue '%' */
2755
+ unit = input('%');
2756
+ /** @defaultValue false */
2757
+ unitsOnSplit = input(false);
2758
+ /**
2759
+ * Custom formatter for axis labels and value.
2760
+ * Takes precedence when specified, i.e. number of decimals, unit etc needs
2761
+ * to be set by the user using this formatter.
2762
+ */
2763
+ labelFormatter = input();
2764
+ /**
2765
+ * Sets the number of decimals.
2766
+ * @deprecated Use `minNumberOfDecimals` and `maxNumberOfDecimals` instead.
2767
+ * @defaultValue undefined */
2768
+ numberOfDecimals = input();
2769
+ /**
2770
+ * Min number of decimals.
2771
+ * @defaultValue 0
2772
+ */
2773
+ minNumberOfDecimals = input(0);
2774
+ /**
2775
+ * Max number of decimals.
2776
+ * @defaultValue 0
2777
+ */
2778
+ maxNumberOfDecimals = input(0);
2779
+ /**
2780
+ * Number of decimals on the axis.
2781
+ * @defaultValue 0
2782
+ */
2783
+ axisNumberOfDecimals = input(0);
2784
+ /** @defaultValue false */
2785
+ hideAxisLabels = input(false, { transform: booleanAttribute });
2786
+ /**
2787
+ * Segments on the arc from 0 (implicit) to 1 (explicit)
2788
+ * E.g. 0.2 means from 0 to 0.2 of the possible range (maxValue - minValue)
2789
+ *
2790
+ * @defaultValue [0.2, 0.8, 1]
2791
+ */
2792
+ segments = input([0.2, 0.8, 1]);
2793
+ /**
2794
+ * Colors for the defined segments.
2795
+ * If there are less colors then segments, the colors will be repeated. Defaults to the standard color palette
2796
+ */
2797
+ colors = input();
2798
+ locale = inject(LOCALE_ID).toString();
2799
+ actualMinNumberOfDecimals = computed(() => this.numberOfDecimals() ?? this.minNumberOfDecimals());
2800
+ actualMaxNumberOfDecimals = computed(() => this.numberOfDecimals() ?? this.maxNumberOfDecimals());
2801
+ numberFormat = computed(() => {
2802
+ const minDecimals = this.actualMinNumberOfDecimals();
2803
+ return new Intl.NumberFormat(this.locale, {
2804
+ minimumFractionDigits: minDecimals,
2805
+ maximumFractionDigits: Math.max(minDecimals, this.actualMaxNumberOfDecimals())
2806
+ });
2807
+ });
2808
+ axisNumberFormat = computed(() => {
2809
+ const decimals = this.axisNumberOfDecimals();
2810
+ return new Intl.NumberFormat(this.locale, {
2811
+ minimumFractionDigits: decimals,
2812
+ maximumFractionDigits: decimals
2813
+ });
2814
+ });
2815
+ afterChartInit() {
2816
+ super.afterChartInit();
2817
+ this.applyOptions();
2818
+ this.updateColors();
2819
+ this.refreshSeries();
2820
+ }
2821
+ updateColors() {
2822
+ // gauge doesn't respect color palette, it needs a bit convincing
2823
+ const effectiveOpts = this.getOptionNoClone();
2824
+ const colors = this.colors() ?? effectiveOpts.color;
2825
+ const hasIndicator = !!this.segments().length;
2826
+ let newColors;
2827
+ if (hasIndicator) {
2828
+ newColors = this.segments().map((threshold, index) => {
2829
+ const color = colors[index % colors.length];
2830
+ return [threshold, color];
2831
+ });
2832
+ }
2833
+ else {
2834
+ const colorsValue = this.colors();
2835
+ const dataColor = colorsValue?.length
2836
+ ? colorsValue[0]
2837
+ : this.getThemeCustomValue(['gauge', 'defaultColor'], colors[0]);
2838
+ newColors = [[1, dataColor]];
2839
+ }
2840
+ if (hasIndicator) {
2841
+ this.setAxisLineColor(newColors, this.actualOptions.series[0].axisLine);
2842
+ }
2843
+ this.actualOptions.series[0].axisLine.show = hasIndicator;
2844
+ this.setAxisLineColor(newColors, this.actualOptions.series[2].axisLine);
2845
+ this.refreshSeries();
2846
+ }
2847
+ setAxisLineColor(colors, axisLine) {
2848
+ axisLine.lineStyle = axisLine.lineStyle ?? {};
2849
+ axisLine.lineStyle.color = colors;
2850
+ }
2851
+ getResponsiveConfig() {
2852
+ const marginY = 12;
2853
+ const maxHeight = this.curHeight - marginY;
2854
+ const dim = Math.min(this.curWidth / 2, maxHeight);
2855
+ const top = dim < maxHeight ? this.curHeight / 2 + dim / 2 : maxHeight;
2856
+ if (dim < 150) {
2857
+ const splits = dim < 100 ? 1 : 4;
2858
+ const axisLabelDist = dim < 100 ? -6 : 0;
2859
+ return {
2860
+ outerRadius: dim - 4,
2861
+ center: ['50%', top],
2862
+ progressWidth: 8,
2863
+ indicatorWidth: 1,
2864
+ gap: 2,
2865
+ splits,
2866
+ axisLabelDist,
2867
+ axisFontSize: 12,
2868
+ valueFontSize: 18,
2869
+ unitFontSize: 12
2870
+ };
2871
+ }
2872
+ if (dim < 200) {
2873
+ return {
2874
+ outerRadius: dim - 7,
2875
+ center: ['50%', top],
2876
+ progressWidth: 14,
2877
+ indicatorWidth: 3,
2878
+ gap: 3,
2879
+ splits: 6,
2880
+ axisLabelDist: 12,
2881
+ axisFontSize: 16,
2882
+ valueFontSize: 30,
2883
+ unitFontSize: 14
2884
+ };
2885
+ }
2886
+ return {
2887
+ outerRadius: dim - 12,
2888
+ center: ['50%', top],
2889
+ progressWidth: 24,
2890
+ indicatorWidth: 4,
2891
+ gap: 5,
2892
+ splits: 0,
2893
+ axisLabelDist: 20,
2894
+ axisFontSize: 20,
2895
+ valueFontSize: 48,
2896
+ unitFontSize: 16
2897
+ };
2898
+ }
2899
+ calcValue(value) {
2900
+ // workaround for bug in echarts
2901
+ if (value === this.minValue()) {
2902
+ return value + 0.0001;
2903
+ }
2904
+ return value;
2905
+ }
2906
+ axisLabelFormatter = (value) => {
2907
+ const formatted = this.axisNumberFormat().format(Number(value));
2908
+ return this.unitsOnSplit() ? `${formatted} ${this.unit()}` : formatted;
2909
+ };
2910
+ applyOptions() {
2911
+ const resp = this.getResponsiveConfig();
2912
+ const hasIndicator = !!this.segments().length;
2913
+ const splitNumber = this.responsiveSplitSteps() && resp.splits ? resp.splits : this.splitSteps();
2914
+ const grey = this.getThemeCustomValue(['gauge', 'grey'], '#F0F2F5');
2915
+ const axisColor = this.getThemeCustomValue(['gauge', 'unit'], '#656A6F');
2916
+ const indicator = {
2917
+ type: 'gauge',
2918
+ radius: resp.outerRadius - resp.progressWidth - resp.gap,
2919
+ startAngle: 180,
2920
+ endAngle: 0,
2921
+ min: this.minValue(),
2922
+ max: this.maxValue(),
2923
+ center: resp.center,
2924
+ axisLine: {
2925
+ show: hasIndicator,
2926
+ lineStyle: { width: resp.indicatorWidth }
2927
+ },
2928
+ axisTick: {
2929
+ length: 0,
2930
+ splitNumber: 1,
2931
+ lineStyle: {
2932
+ width: 2,
2933
+ color: axisColor
2934
+ }
2935
+ },
2936
+ splitLine: {
2937
+ length: 0,
2938
+ lineStyle: {
2939
+ width: 1,
2940
+ color: axisColor
2941
+ }
2942
+ },
2943
+ axisLabel: { show: false }
2944
+ };
2945
+ const labelDistance = resp.axisLabelDist + (hasIndicator ? resp.indicatorWidth + resp.gap : 0);
2946
+ const shade = {
2947
+ type: 'gauge',
2948
+ radius: resp.outerRadius,
2949
+ startAngle: 180,
2950
+ endAngle: 0,
2951
+ min: this.minValue(),
2952
+ max: this.maxValue(),
2953
+ splitNumber,
2954
+ axisTick: { show: false },
2955
+ splitLine: { show: false },
2956
+ title: { show: false },
2957
+ center: resp.center,
2958
+ axisLine: {
2959
+ lineStyle: {
2960
+ width: resp.progressWidth,
2961
+ opacity: 0.6,
2962
+ color: [[1, grey]]
2963
+ }
2964
+ },
2965
+ axisLabel: {
2966
+ show: !this.hideAxisLabels(),
2967
+ distance: labelDistance,
2968
+ color: axisColor,
2969
+ fontSize: resp.axisFontSize,
2970
+ formatter: this.labelFormatter() ?? this.axisLabelFormatter
2971
+ }
2972
+ };
2973
+ const data = {
2974
+ type: 'gauge',
2975
+ silent: false,
2976
+ radius: resp.outerRadius,
2977
+ startAngle: 180,
2978
+ endAngle: 0,
2979
+ min: this.minValue(),
2980
+ max: this.maxValue(),
2981
+ splitNumber,
2982
+ progress: {
2983
+ show: true,
2984
+ itemStyle: { color: 'auto' },
2985
+ width: resp.progressWidth
2986
+ },
2987
+ emphasis: {
2988
+ // This code is added to avoid flickering when the progress is hovered and
2989
+ // when mouse effects are enabled with `silent: false` flag. The issue occurs
2990
+ // because of the progress.itemStyle.color is set to `auto` which tries to
2991
+ // calculate the color dynamically and it conflicts with the mouse hover action
2992
+ // which tries to apply the hover style
2993
+ itemStyle: { color: 'auto' }
2994
+ },
2995
+ pointer: {
2996
+ show: true,
2997
+ length: '0%',
2998
+ itemStyle: {
2999
+ color: 'auto',
3000
+ opacity: 0.001
3001
+ }
3002
+ },
3003
+ center: resp.center,
3004
+ axisLine: {
3005
+ show: false,
3006
+ lineStyle: { opacity: 0.6 }
3007
+ },
3008
+ axisTick: { show: false },
3009
+ splitLine: { show: false },
3010
+ axisLabel: { show: false },
3011
+ title: { show: false },
3012
+ detail: {
3013
+ offsetCenter: [0, -0.5 * resp.valueFontSize],
3014
+ valueAnimation: true,
3015
+ formatter: this.valueFormatter(),
3016
+ rich: {
3017
+ value: {
3018
+ fontSize: resp.valueFontSize,
3019
+ lineHeight: resp.valueFontSize,
3020
+ fontWeight: 'bolder'
3021
+ },
3022
+ unit: {
3023
+ fontSize: resp.unitFontSize,
3024
+ lineHeight: resp.unitFontSize,
3025
+ padding: [0, 0, (resp.unitFontSize - resp.valueFontSize) / 2, 0]
3026
+ }
3027
+ }
3028
+ },
3029
+ data: [{ value: this.calcValue(this.value()) }]
3030
+ };
3031
+ const series = [indicator, shade, data];
3032
+ this.showLegend.set(false);
3033
+ this.actualOptions.series = series;
3034
+ this.applyTitles();
3035
+ }
3036
+ valueFormatter() {
3037
+ return (this.labelFormatter() ??
3038
+ ((value) => {
3039
+ const formattedValue = this.numberFormat().format(value);
3040
+ const unit = this.unit();
3041
+ const formattedUnit = unit
3042
+ ? unit.length > 5
3043
+ ? `\n{unit|${unit}}`
3044
+ : ` {unit|${unit}}`
3045
+ : '';
3046
+ return `{value|${formattedValue}}${formattedUnit}`;
3047
+ }));
3048
+ }
3049
+ ngOnChanges(changes) {
3050
+ if (this.chart && (changes.palette || changes.colors || changes.segments)) {
3051
+ this.updateColors();
3052
+ }
3053
+ changes.forceAll = new SimpleChange(false, true, false);
3054
+ super.ngOnChanges(changes);
3055
+ }
3056
+ applyDataZoom() { }
3057
+ afterChartResize() {
3058
+ this.applyOptions();
3059
+ this.refreshSeries();
3060
+ }
3061
+ /**
3062
+ * Update gauge chart value.
3063
+ */
3064
+ setValue(value) {
3065
+ const optionSeries = this.actualOptions.series;
3066
+ optionSeries[2].data[0].value = this.calcValue(value);
3067
+ this.refreshSeries();
3068
+ }
3069
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.6", ngImport: i0, type: SiChartGaugeComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
3070
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.6", type: SiChartGaugeComponent, isStandalone: true, selector: "si-chart-gauge", inputs: { minValue: { classPropertyName: "minValue", publicName: "minValue", isSignal: true, isRequired: false, transformFunction: null }, maxValue: { classPropertyName: "maxValue", publicName: "maxValue", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, splitSteps: { classPropertyName: "splitSteps", publicName: "splitSteps", isSignal: true, isRequired: false, transformFunction: null }, responsiveSplitSteps: { classPropertyName: "responsiveSplitSteps", publicName: "responsiveSplitSteps", isSignal: true, isRequired: false, transformFunction: null }, unit: { classPropertyName: "unit", publicName: "unit", isSignal: true, isRequired: false, transformFunction: null }, unitsOnSplit: { classPropertyName: "unitsOnSplit", publicName: "unitsOnSplit", isSignal: true, isRequired: false, transformFunction: null }, labelFormatter: { classPropertyName: "labelFormatter", publicName: "labelFormatter", isSignal: true, isRequired: false, transformFunction: null }, numberOfDecimals: { classPropertyName: "numberOfDecimals", publicName: "numberOfDecimals", isSignal: true, isRequired: false, transformFunction: null }, minNumberOfDecimals: { classPropertyName: "minNumberOfDecimals", publicName: "minNumberOfDecimals", isSignal: true, isRequired: false, transformFunction: null }, maxNumberOfDecimals: { classPropertyName: "maxNumberOfDecimals", publicName: "maxNumberOfDecimals", isSignal: true, isRequired: false, transformFunction: null }, axisNumberOfDecimals: { classPropertyName: "axisNumberOfDecimals", publicName: "axisNumberOfDecimals", isSignal: true, isRequired: false, transformFunction: null }, hideAxisLabels: { classPropertyName: "hideAxisLabels", publicName: "hideAxisLabels", isSignal: true, isRequired: false, transformFunction: null }, segments: { classPropertyName: "segments", publicName: "segments", isSignal: true, isRequired: false, transformFunction: null }, colors: { classPropertyName: "colors", publicName: "colors", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "@if (showCustomLegend() && (title() || subTitle())) {\n <div\n class=\"si-title-2 chart-title chart-title-width\"\n [style.background-color]=\"backgroundColor()\"\n >\n <div class=\"chart-title-text\" [style.color]=\"titleColor()\">{{ title() }}</div>\n @if (subTitle()) {\n <div class=\"si-body-2\" [style.color]=\"subTitleColor()\">{{ subTitle() }}</div>\n }\n </div>\n}\n\n<div\n #chartContainerWrapper\n class=\"chart-container-wrapper\"\n [class.chart-scroll]=\"containerHeight()\"\n [attr.tabindex]=\"containerHeight() ? '0' : null\"\n>\n <div class=\"chart-container\" [style.height.px]=\"containerHeight()\">\n @if (showCustomLegend()) {\n @for (cl of customLegend; track $index) {\n <si-custom-legend\n #siCustomLegend\n class=\"custom-legend\"\n [style.top.px]=\"cl.top\"\n [title]=\"title()\"\n [subTitle]=\"subTitle()\"\n [customLegend]=\"cl\"\n [style.background-color]=\"backgroundColor()\"\n [titleColor]=\"titleColor()\"\n [subTitleColor]=\"subTitleColor()\"\n [textColor]=\"textColor()\"\n (legendIconClickEvent)=\"handleLegendClick($event)\"\n (legendClickEvent)=\"handleLegendClick($event)\"\n (legendHoverStartEvent)=\"handleLegendHover($event, true)\"\n (legendHoverEndEvent)=\"handleLegendHover($event, false)\"\n />\n }\n }\n <div #chart class=\"echart-container\" [style.height.px]=\"containerHeight()\"></div>\n </div>\n</div>\n@if (externalZoomSlider()) {\n <div\n #externalZoomSlider\n class=\"external-zoom-container\"\n [class.has-time-range-bar]=\"showTimeRangeBar()\"\n [style.--time-bar-height.px]=\"timeBarHeight()\"\n ></div>\n}\n\n@if (showTimeRangeBar() && zoomSlider()) {\n <div\n class=\"time-range-bar\"\n [style.bottom.px]=\"timeBarBottom()\"\n [style.padding-left.px]=\"timeBarLeft()\"\n [style.padding-right.px]=\"timeBarRight()\"\n >\n <ng-content select=\"[slot=timeRangeBar]\" />\n </div>\n}\n\n@if (inProgress()) {\n <div class=\"progress-container\">\n <si-chart-loading-spinner />\n </div>\n}\n", styles: [":host{block-size:100%;position:relative;display:flex!important;flex-direction:column;inline-size:100%}.chart-container-wrapper{display:flex;flex:1 0 0;inline-size:inherit;overflow:hidden}.chart-scroll{overflow-y:auto}.chart-container{position:relative;display:flex;flex:1 0 0;overflow:hidden}.echart-container{flex:1 0 0;inline-size:100%;min-block-size:var(--si-chart-min-height, 200px);overflow:hidden}.custom-legend{position:absolute;z-index:2;inline-size:100%}.chart-title{padding-block:12px 8px;padding-inline-start:24px}.external-zoom-container{display:flex;flex:1 0 0;inline-size:inherit;max-block-size:112px}.external-zoom-container.has-time-range-bar{max-block-size:calc(112px + var(--time-bar-height))}.tooltip-inner{max-inline-size:375px;min-inline-size:375px;color:#162938;font-size:18px;background-color:#162938}.time-range-bar{position:absolute;inset-inline:0;z-index:2}.progress-container{position:absolute;inset:0;pointer-events:none;z-index:100;display:flex;justify-content:center;align-items:center}\n"], dependencies: [{ kind: "component", type: SiCustomLegendComponent, selector: "si-custom-legend", inputs: ["customLegend", "title", "subTitle", "titleColor", "subTitleColor", "textColor"], outputs: ["legendIconClickEvent", "legendClickEvent", "legendHoverStartEvent", "legendHoverEndEvent"] }, { kind: "component", type: SiChartLoadingSpinnerComponent, selector: "si-chart-loading-spinner" }] });
3071
+ }
3072
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.6", ngImport: i0, type: SiChartGaugeComponent, decorators: [{
3073
+ type: Component,
3074
+ args: [{ selector: 'si-chart-gauge', imports: [SiCustomLegendComponent, SiChartLoadingSpinnerComponent], template: "@if (showCustomLegend() && (title() || subTitle())) {\n <div\n class=\"si-title-2 chart-title chart-title-width\"\n [style.background-color]=\"backgroundColor()\"\n >\n <div class=\"chart-title-text\" [style.color]=\"titleColor()\">{{ title() }}</div>\n @if (subTitle()) {\n <div class=\"si-body-2\" [style.color]=\"subTitleColor()\">{{ subTitle() }}</div>\n }\n </div>\n}\n\n<div\n #chartContainerWrapper\n class=\"chart-container-wrapper\"\n [class.chart-scroll]=\"containerHeight()\"\n [attr.tabindex]=\"containerHeight() ? '0' : null\"\n>\n <div class=\"chart-container\" [style.height.px]=\"containerHeight()\">\n @if (showCustomLegend()) {\n @for (cl of customLegend; track $index) {\n <si-custom-legend\n #siCustomLegend\n class=\"custom-legend\"\n [style.top.px]=\"cl.top\"\n [title]=\"title()\"\n [subTitle]=\"subTitle()\"\n [customLegend]=\"cl\"\n [style.background-color]=\"backgroundColor()\"\n [titleColor]=\"titleColor()\"\n [subTitleColor]=\"subTitleColor()\"\n [textColor]=\"textColor()\"\n (legendIconClickEvent)=\"handleLegendClick($event)\"\n (legendClickEvent)=\"handleLegendClick($event)\"\n (legendHoverStartEvent)=\"handleLegendHover($event, true)\"\n (legendHoverEndEvent)=\"handleLegendHover($event, false)\"\n />\n }\n }\n <div #chart class=\"echart-container\" [style.height.px]=\"containerHeight()\"></div>\n </div>\n</div>\n@if (externalZoomSlider()) {\n <div\n #externalZoomSlider\n class=\"external-zoom-container\"\n [class.has-time-range-bar]=\"showTimeRangeBar()\"\n [style.--time-bar-height.px]=\"timeBarHeight()\"\n ></div>\n}\n\n@if (showTimeRangeBar() && zoomSlider()) {\n <div\n class=\"time-range-bar\"\n [style.bottom.px]=\"timeBarBottom()\"\n [style.padding-left.px]=\"timeBarLeft()\"\n [style.padding-right.px]=\"timeBarRight()\"\n >\n <ng-content select=\"[slot=timeRangeBar]\" />\n </div>\n}\n\n@if (inProgress()) {\n <div class=\"progress-container\">\n <si-chart-loading-spinner />\n </div>\n}\n", styles: [":host{block-size:100%;position:relative;display:flex!important;flex-direction:column;inline-size:100%}.chart-container-wrapper{display:flex;flex:1 0 0;inline-size:inherit;overflow:hidden}.chart-scroll{overflow-y:auto}.chart-container{position:relative;display:flex;flex:1 0 0;overflow:hidden}.echart-container{flex:1 0 0;inline-size:100%;min-block-size:var(--si-chart-min-height, 200px);overflow:hidden}.custom-legend{position:absolute;z-index:2;inline-size:100%}.chart-title{padding-block:12px 8px;padding-inline-start:24px}.external-zoom-container{display:flex;flex:1 0 0;inline-size:inherit;max-block-size:112px}.external-zoom-container.has-time-range-bar{max-block-size:calc(112px + var(--time-bar-height))}.tooltip-inner{max-inline-size:375px;min-inline-size:375px;color:#162938;font-size:18px;background-color:#162938}.time-range-bar{position:absolute;inset-inline:0;z-index:2}.progress-container{position:absolute;inset:0;pointer-events:none;z-index:100;display:flex;justify-content:center;align-items:center}\n"] }]
3075
+ }] });
3076
+
3077
+ /**
3078
+ * Copyright Siemens 2016 - 2025.
3079
+ * SPDX-License-Identifier: MIT
3080
+ */
3081
+
3082
+ /**
3083
+ * Copyright Siemens 2016 - 2025.
3084
+ * SPDX-License-Identifier: MIT
3085
+ */
3086
+ class SiChartProgressComponent extends SiChartComponent {
3087
+ series = input();
3088
+ /**
3089
+ * How big the data can get in degrees.
3090
+ *
3091
+ * @defaultValue 220
3092
+ */
3093
+ dataAngle = input(220);
3094
+ // item width in % radius
3095
+ itemWidth;
3096
+ // item gap in % radius
3097
+ itemGap;
3098
+ // base radius of an item
3099
+ baseRadius = 98;
3100
+ sizeFactor;
3101
+ // placement chart in % on canvas
3102
+ center;
3103
+ // color of disabled part of item
3104
+ grey;
3105
+ // where the data starts. not very intuitive:
3106
+ // 0° is at 3 o'clock, goes counterclockwise, but series drawing goes clockwise
3107
+ startAngle;
3108
+ afterChartInit() {
3109
+ this.chart.on('legendselectchanged', (params) => {
3110
+ this.updateRadius(params.selected);
3111
+ this.updateEChart();
3112
+ });
3113
+ }
3114
+ themeChanged() {
3115
+ this.applyOptions();
3116
+ }
3117
+ handleSelectionChanged(event) {
3118
+ super.handleSelectionChanged(event);
3119
+ this.updateRadius(event.selected);
3120
+ this.updateEChart();
3121
+ }
3122
+ applyOptions() {
3123
+ this.actualOptions = {
3124
+ series: [],
3125
+ legend: [
3126
+ {
3127
+ data: []
3128
+ }
3129
+ ]
3130
+ };
3131
+ const dataAngle = this.dataAngle();
3132
+ this.startAngle = dataAngle === 360 ? 90 : 270 - (360 - dataAngle) / 2;
3133
+ this.itemWidth = this.getThemeCustomValue(['progress', 'itemWidth'], 6);
3134
+ this.itemGap = this.getThemeCustomValue(['progress', 'itemGap'], 6);
3135
+ this.grey = this.getThemeCustomValue(['progress', 'grey'], '#E6E6E6');
3136
+ // a factor to change the size of base radius and center related to
3137
+ // dataAngle proportionately
3138
+ this.sizeFactor = 1 - Math.sin((((this.dataAngle() - 180) / 2) * Math.PI) / 180);
3139
+ this.center = 50 + 25 * this.sizeFactor;
3140
+ const seriesValue = this.series();
3141
+ if (seriesValue) {
3142
+ seriesValue.forEach(series => {
3143
+ this.addSeries(series.name, series.percent);
3144
+ if (this.showLegend()) {
3145
+ this.addLegendItem(series.name);
3146
+ }
3147
+ });
3148
+ }
3149
+ this.applyTitles();
3150
+ }
3151
+ labelFormatter(p) {
3152
+ return p.seriesName + '\n' + Math.round((100 / this.dataAngle()) * p.value) + ' %';
3153
+ }
3154
+ addSeries(name, percent) {
3155
+ const optionSeries = this.actualOptions.series;
3156
+ const index = optionSeries.length;
3157
+ const offset = !this.showCustomLegend() && this.subTitle()
3158
+ ? this.getThemeCustomValue(['subTitle', 'legend', 'top'], 0)
3159
+ : 0;
3160
+ const top = !this.sizeFactor ? 32 + offset : Math.floor(offset / 2);
3161
+ const bottom = !this.sizeFactor ? undefined : -offset;
3162
+ const item = {
3163
+ top,
3164
+ bottom,
3165
+ center: ['50%', this.center + '%'],
3166
+ name,
3167
+ type: 'pie',
3168
+ colorBy: 'series',
3169
+ radius: this.calculateRadius(index),
3170
+ avoidLabelOverlap: false,
3171
+ tooltip: { show: false },
3172
+ startAngle: this.startAngle,
3173
+ label: {
3174
+ show: false,
3175
+ formatter: p => this.labelFormatter(p),
3176
+ position: 'center'
3177
+ },
3178
+ labelLine: {
3179
+ show: false
3180
+ },
3181
+ emphasis: {
3182
+ label: {
3183
+ show: true,
3184
+ lineHeight: 30,
3185
+ fontSize: '30',
3186
+ fontWeight: 'bold'
3187
+ }
3188
+ },
3189
+ itemStyle: {
3190
+ borderWidth: 0
3191
+ },
3192
+ data: [
3193
+ {
3194
+ value: 0,
3195
+ name: 'v' + index,
3196
+ label: {
3197
+ lineHeight: 30,
3198
+ fontSize: 30,
3199
+ color: 'inherit'
3200
+ }
3201
+ },
3202
+ {
3203
+ value: 0,
3204
+ name: 'a' + index,
3205
+ itemStyle: { color: this.grey },
3206
+ emphasis: {
3207
+ scale: false,
3208
+ itemStyle: { color: this.grey }
3209
+ },
3210
+ cursor: 'default',
3211
+ label: { show: false }
3212
+ },
3213
+ {
3214
+ value: 0,
3215
+ name: 'b' + index,
3216
+ itemStyle: { color: 'rgba(0,0,0,0)' },
3217
+ cursor: 'default',
3218
+ label: { show: false }
3219
+ }
3220
+ ]
3221
+ };
3222
+ this.updateData(item, percent);
3223
+ optionSeries.push(item);
3224
+ }
3225
+ updateData(series, percent) {
3226
+ const angle = (this.dataAngle() * percent) / 100;
3227
+ series.data[0].value = angle;
3228
+ series.data[1].value = this.dataAngle() - angle;
3229
+ series.data[2].value = 360 - this.dataAngle();
3230
+ series.realValue = percent;
3231
+ }
3232
+ calculateRadius(index) {
3233
+ const outerRadius = this.baseRadius - index * (this.itemWidth + this.itemGap);
3234
+ const innerRadius = outerRadius - this.itemWidth;
3235
+ return [innerRadius + '%', outerRadius + '%'];
3236
+ }
3237
+ updateRadius(selected) {
3238
+ let visibleIndex = 0;
3239
+ const optionSeries = this.actualOptions.series;
3240
+ optionSeries.forEach(series => {
3241
+ if (selected[series.name] === false) {
3242
+ return;
3243
+ }
3244
+ series.radius = this.calculateRadius(visibleIndex);
3245
+ visibleIndex++;
3246
+ });
3247
+ }
3248
+ applyDataZoom() { }
3249
+ /**
3250
+ * Update single value of the progress chart.
3251
+ */
3252
+ changeSingleValue(index, percent) {
3253
+ const optionSeries = this.actualOptions.series;
3254
+ this.updateData(optionSeries[index], percent);
3255
+ this.updateEChart();
3256
+ }
3257
+ /**
3258
+ * Update multiple values of the progress chart.
3259
+ */
3260
+ changeMultiValues(updateValues) {
3261
+ const optionSeries = this.actualOptions.series;
3262
+ updateValues.forEach(update => {
3263
+ const currentSeries = optionSeries[update.seriesIndex];
3264
+ if (!currentSeries) {
3265
+ return;
3266
+ }
3267
+ this.updateData(currentSeries, update.percent);
3268
+ });
3269
+ this.updateEChart();
3270
+ }
3271
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.6", ngImport: i0, type: SiChartProgressComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
3272
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.6", type: SiChartProgressComponent, isStandalone: true, selector: "si-chart-progress", inputs: { series: { classPropertyName: "series", publicName: "series", isSignal: true, isRequired: false, transformFunction: null }, dataAngle: { classPropertyName: "dataAngle", publicName: "dataAngle", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: "@if (showCustomLegend() && (title() || subTitle())) {\n <div\n class=\"si-title-2 chart-title chart-title-width\"\n [style.background-color]=\"backgroundColor()\"\n >\n <div class=\"chart-title-text\" [style.color]=\"titleColor()\">{{ title() }}</div>\n @if (subTitle()) {\n <div class=\"si-body-2\" [style.color]=\"subTitleColor()\">{{ subTitle() }}</div>\n }\n </div>\n}\n\n<div\n #chartContainerWrapper\n class=\"chart-container-wrapper\"\n [class.chart-scroll]=\"containerHeight()\"\n [attr.tabindex]=\"containerHeight() ? '0' : null\"\n>\n <div class=\"chart-container\" [style.height.px]=\"containerHeight()\">\n @if (showCustomLegend()) {\n @for (cl of customLegend; track $index) {\n <si-custom-legend\n #siCustomLegend\n class=\"custom-legend\"\n [style.top.px]=\"cl.top\"\n [title]=\"title()\"\n [subTitle]=\"subTitle()\"\n [customLegend]=\"cl\"\n [style.background-color]=\"backgroundColor()\"\n [titleColor]=\"titleColor()\"\n [subTitleColor]=\"subTitleColor()\"\n [textColor]=\"textColor()\"\n (legendIconClickEvent)=\"handleLegendClick($event)\"\n (legendClickEvent)=\"handleLegendClick($event)\"\n (legendHoverStartEvent)=\"handleLegendHover($event, true)\"\n (legendHoverEndEvent)=\"handleLegendHover($event, false)\"\n />\n }\n }\n <div #chart class=\"echart-container\" [style.height.px]=\"containerHeight()\"></div>\n </div>\n</div>\n@if (externalZoomSlider()) {\n <div\n #externalZoomSlider\n class=\"external-zoom-container\"\n [class.has-time-range-bar]=\"showTimeRangeBar()\"\n [style.--time-bar-height.px]=\"timeBarHeight()\"\n ></div>\n}\n\n@if (showTimeRangeBar() && zoomSlider()) {\n <div\n class=\"time-range-bar\"\n [style.bottom.px]=\"timeBarBottom()\"\n [style.padding-left.px]=\"timeBarLeft()\"\n [style.padding-right.px]=\"timeBarRight()\"\n >\n <ng-content select=\"[slot=timeRangeBar]\" />\n </div>\n}\n\n@if (inProgress()) {\n <div class=\"progress-container\">\n <si-chart-loading-spinner />\n </div>\n}\n", styles: [":host{block-size:100%;position:relative;display:flex!important;flex-direction:column;inline-size:100%}.chart-container-wrapper{display:flex;flex:1 0 0;inline-size:inherit;overflow:hidden}.chart-scroll{overflow-y:auto}.chart-container{position:relative;display:flex;flex:1 0 0;overflow:hidden}.echart-container{flex:1 0 0;inline-size:100%;min-block-size:var(--si-chart-min-height, 200px);overflow:hidden}.custom-legend{position:absolute;z-index:2;inline-size:100%}.chart-title{padding-block:12px 8px;padding-inline-start:24px}.external-zoom-container{display:flex;flex:1 0 0;inline-size:inherit;max-block-size:112px}.external-zoom-container.has-time-range-bar{max-block-size:calc(112px + var(--time-bar-height))}.tooltip-inner{max-inline-size:375px;min-inline-size:375px;color:#162938;font-size:18px;background-color:#162938}.time-range-bar{position:absolute;inset-inline:0;z-index:2}.progress-container{position:absolute;inset:0;pointer-events:none;z-index:100;display:flex;justify-content:center;align-items:center}\n"], dependencies: [{ kind: "component", type: SiCustomLegendComponent, selector: "si-custom-legend", inputs: ["customLegend", "title", "subTitle", "titleColor", "subTitleColor", "textColor"], outputs: ["legendIconClickEvent", "legendClickEvent", "legendHoverStartEvent", "legendHoverEndEvent"] }, { kind: "component", type: SiChartLoadingSpinnerComponent, selector: "si-chart-loading-spinner" }] });
3273
+ }
3274
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.6", ngImport: i0, type: SiChartProgressComponent, decorators: [{
3275
+ type: Component,
3276
+ args: [{ selector: 'si-chart-progress', imports: [SiCustomLegendComponent, SiChartLoadingSpinnerComponent], template: "@if (showCustomLegend() && (title() || subTitle())) {\n <div\n class=\"si-title-2 chart-title chart-title-width\"\n [style.background-color]=\"backgroundColor()\"\n >\n <div class=\"chart-title-text\" [style.color]=\"titleColor()\">{{ title() }}</div>\n @if (subTitle()) {\n <div class=\"si-body-2\" [style.color]=\"subTitleColor()\">{{ subTitle() }}</div>\n }\n </div>\n}\n\n<div\n #chartContainerWrapper\n class=\"chart-container-wrapper\"\n [class.chart-scroll]=\"containerHeight()\"\n [attr.tabindex]=\"containerHeight() ? '0' : null\"\n>\n <div class=\"chart-container\" [style.height.px]=\"containerHeight()\">\n @if (showCustomLegend()) {\n @for (cl of customLegend; track $index) {\n <si-custom-legend\n #siCustomLegend\n class=\"custom-legend\"\n [style.top.px]=\"cl.top\"\n [title]=\"title()\"\n [subTitle]=\"subTitle()\"\n [customLegend]=\"cl\"\n [style.background-color]=\"backgroundColor()\"\n [titleColor]=\"titleColor()\"\n [subTitleColor]=\"subTitleColor()\"\n [textColor]=\"textColor()\"\n (legendIconClickEvent)=\"handleLegendClick($event)\"\n (legendClickEvent)=\"handleLegendClick($event)\"\n (legendHoverStartEvent)=\"handleLegendHover($event, true)\"\n (legendHoverEndEvent)=\"handleLegendHover($event, false)\"\n />\n }\n }\n <div #chart class=\"echart-container\" [style.height.px]=\"containerHeight()\"></div>\n </div>\n</div>\n@if (externalZoomSlider()) {\n <div\n #externalZoomSlider\n class=\"external-zoom-container\"\n [class.has-time-range-bar]=\"showTimeRangeBar()\"\n [style.--time-bar-height.px]=\"timeBarHeight()\"\n ></div>\n}\n\n@if (showTimeRangeBar() && zoomSlider()) {\n <div\n class=\"time-range-bar\"\n [style.bottom.px]=\"timeBarBottom()\"\n [style.padding-left.px]=\"timeBarLeft()\"\n [style.padding-right.px]=\"timeBarRight()\"\n >\n <ng-content select=\"[slot=timeRangeBar]\" />\n </div>\n}\n\n@if (inProgress()) {\n <div class=\"progress-container\">\n <si-chart-loading-spinner />\n </div>\n}\n", styles: [":host{block-size:100%;position:relative;display:flex!important;flex-direction:column;inline-size:100%}.chart-container-wrapper{display:flex;flex:1 0 0;inline-size:inherit;overflow:hidden}.chart-scroll{overflow-y:auto}.chart-container{position:relative;display:flex;flex:1 0 0;overflow:hidden}.echart-container{flex:1 0 0;inline-size:100%;min-block-size:var(--si-chart-min-height, 200px);overflow:hidden}.custom-legend{position:absolute;z-index:2;inline-size:100%}.chart-title{padding-block:12px 8px;padding-inline-start:24px}.external-zoom-container{display:flex;flex:1 0 0;inline-size:inherit;max-block-size:112px}.external-zoom-container.has-time-range-bar{max-block-size:calc(112px + var(--time-bar-height))}.tooltip-inner{max-inline-size:375px;min-inline-size:375px;color:#162938;font-size:18px;background-color:#162938}.time-range-bar{position:absolute;inset-inline:0;z-index:2}.progress-container{position:absolute;inset:0;pointer-events:none;z-index:100;display:flex;justify-content:center;align-items:center}\n"] }]
3277
+ }] });
3278
+
3279
+ /**
3280
+ * Copyright Siemens 2016 - 2025.
3281
+ * SPDX-License-Identifier: MIT
3282
+ */
3283
+
3284
+ /**
3285
+ * Copyright Siemens 2016 - 2025.
3286
+ * SPDX-License-Identifier: MIT
3287
+ */
3288
+ class SiChartProgressBarComponent extends SiChartComponent {
3289
+ series = input();
3290
+ /** Used to display the label in inline or above the progress-bar. */
3291
+ labelPosition = input();
3292
+ maxValue = 100;
3293
+ xAxisConfig = { type: 'value', max: this.maxValue };
3294
+ yAxis = {
3295
+ type: 'category',
3296
+ data: [],
3297
+ axisLabel: {
3298
+ show: true,
3299
+ fontSize: 14
3300
+ }
3301
+ };
3302
+ formatter = new Intl.NumberFormat(undefined, { maximumFractionDigits: 1 });
3303
+ labelPositionOption;
3304
+ labelPositionOptionForValue;
3305
+ labelFormatter(p) {
3306
+ return this.formatter.format(this.maxValue - p.value) + ' %';
3307
+ }
3308
+ themeChanged() {
3309
+ this.applyOptions();
3310
+ }
3311
+ applyOptions() {
3312
+ this.showLegend.set(false);
3313
+ const grey = this.getThemeCustomValue(['progress', 'grey'], '#E6E6E6');
3314
+ const labelColor = this.getThemeCustomValue(['progressBar', 'labelColor'], '#000');
3315
+ const itemWidth = this.getThemeCustomValue(['progressBar', 'itemWidth'], 20);
3316
+ if (this.labelPosition() === 'top') {
3317
+ this.yAxis.axisLabel = false;
3318
+ this.labelPositionOption = {
3319
+ position: [0, -16],
3320
+ formatter: '{b}',
3321
+ fontSize: 14,
3322
+ color: labelColor,
3323
+ show: true
3324
+ };
3325
+ this.labelPositionOptionForValue = {
3326
+ position: ['100%', '-80%'],
3327
+ align: 'right',
3328
+ show: true,
3329
+ formatter: p => this.labelFormatter(p),
3330
+ color: labelColor,
3331
+ fontWeight: 700
3332
+ };
3333
+ }
3334
+ else {
3335
+ this.yAxis.axisLabel.show = true;
3336
+ this.labelPositionOption = {
3337
+ show: false
3338
+ };
3339
+ this.labelPositionOptionForValue = {
3340
+ position: 'right',
3341
+ show: true,
3342
+ formatter: p => this.labelFormatter(p),
3343
+ color: labelColor,
3344
+ fontWeight: 700
3345
+ };
3346
+ }
3347
+ this.actualOptions = {
3348
+ series: [],
3349
+ xAxis: this.xAxisConfig,
3350
+ yAxis: this.yAxis,
3351
+ grid: {},
3352
+ tooltip: {}
3353
+ };
3354
+ const categoryAxisOpts = {
3355
+ axisLine: { show: false },
3356
+ axisTick: { show: false },
3357
+ splitLine: { show: false },
3358
+ axisLabel: { show: this.yAxis.axisLabel },
3359
+ inverse: true
3360
+ };
3361
+ const valueAxisOpts = {
3362
+ axisLabel: { show: false },
3363
+ axisLine: { show: false },
3364
+ axisTick: { show: false },
3365
+ splitLine: { show: false }
3366
+ };
3367
+ echarts.util.merge(this.actualOptions.yAxis, categoryAxisOpts, true);
3368
+ echarts.util.merge(this.actualOptions.xAxis, valueAxisOpts, true);
3369
+ this.actualOptions.grid = this.getThemeCustomValue(['progressBar', 'grid'], {});
3370
+ const series = this.series();
3371
+ if (series) {
3372
+ const optionSeries = this.actualOptions.series;
3373
+ this.actualOptions.yAxis.data = series.map(item => item.name);
3374
+ const dataItem = {
3375
+ type: 'bar',
3376
+ stack: 'chart',
3377
+ z: 3,
3378
+ barWidth: itemWidth,
3379
+ label: this.labelPositionOption,
3380
+ data: series.map(item => item.percent)
3381
+ };
3382
+ const fillerItem = {
3383
+ type: 'bar',
3384
+ stack: 'chart',
3385
+ silent: true,
3386
+ label: this.labelPositionOptionForValue,
3387
+ itemStyle: {
3388
+ color: grey
3389
+ },
3390
+ data: series.map(item => this.maxValue - item.percent)
3391
+ };
3392
+ optionSeries.push(dataItem);
3393
+ optionSeries.push(fillerItem);
3394
+ }
3395
+ this.applyTitles();
3396
+ }
3397
+ applyDataZoom() { }
3398
+ /**
3399
+ * Updates single value of a single progress bar.
3400
+ */
3401
+ changeSingleValue(valueIndex, value) {
3402
+ const optionSeries = this.actualOptions.series;
3403
+ optionSeries[0].data[valueIndex] = value;
3404
+ optionSeries[1].data[valueIndex] = this.maxValue - value;
3405
+ this.updateEChart();
3406
+ }
3407
+ /**
3408
+ * Updates multiple values of a single progress bar.
3409
+ */
3410
+ changeMultiValues(updateValues) {
3411
+ const optionSeries = this.actualOptions.series;
3412
+ updateValues.forEach(update => {
3413
+ const currentDataItem = optionSeries[0].data[update.valueIndex];
3414
+ if (!currentDataItem) {
3415
+ return;
3416
+ }
3417
+ optionSeries[0].data[update.valueIndex] = update.value;
3418
+ optionSeries[1].data[update.valueIndex] = this.maxValue - update.value;
3419
+ });
3420
+ this.updateEChart();
3421
+ }
3422
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.6", ngImport: i0, type: SiChartProgressBarComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
3423
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.6", type: SiChartProgressBarComponent, isStandalone: true, selector: "si-chart-progress-bar", inputs: { series: { classPropertyName: "series", publicName: "series", isSignal: true, isRequired: false, transformFunction: null }, labelPosition: { classPropertyName: "labelPosition", publicName: "labelPosition", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: "@if (showCustomLegend() && (title() || subTitle())) {\n <div\n class=\"si-title-2 chart-title chart-title-width\"\n [style.background-color]=\"backgroundColor()\"\n >\n <div class=\"chart-title-text\" [style.color]=\"titleColor()\">{{ title() }}</div>\n @if (subTitle()) {\n <div class=\"si-body-2\" [style.color]=\"subTitleColor()\">{{ subTitle() }}</div>\n }\n </div>\n}\n\n<div\n #chartContainerWrapper\n class=\"chart-container-wrapper\"\n [class.chart-scroll]=\"containerHeight()\"\n [attr.tabindex]=\"containerHeight() ? '0' : null\"\n>\n <div class=\"chart-container\" [style.height.px]=\"containerHeight()\">\n @if (showCustomLegend()) {\n @for (cl of customLegend; track $index) {\n <si-custom-legend\n #siCustomLegend\n class=\"custom-legend\"\n [style.top.px]=\"cl.top\"\n [title]=\"title()\"\n [subTitle]=\"subTitle()\"\n [customLegend]=\"cl\"\n [style.background-color]=\"backgroundColor()\"\n [titleColor]=\"titleColor()\"\n [subTitleColor]=\"subTitleColor()\"\n [textColor]=\"textColor()\"\n (legendIconClickEvent)=\"handleLegendClick($event)\"\n (legendClickEvent)=\"handleLegendClick($event)\"\n (legendHoverStartEvent)=\"handleLegendHover($event, true)\"\n (legendHoverEndEvent)=\"handleLegendHover($event, false)\"\n />\n }\n }\n <div #chart class=\"echart-container\" [style.height.px]=\"containerHeight()\"></div>\n </div>\n</div>\n@if (externalZoomSlider()) {\n <div\n #externalZoomSlider\n class=\"external-zoom-container\"\n [class.has-time-range-bar]=\"showTimeRangeBar()\"\n [style.--time-bar-height.px]=\"timeBarHeight()\"\n ></div>\n}\n\n@if (showTimeRangeBar() && zoomSlider()) {\n <div\n class=\"time-range-bar\"\n [style.bottom.px]=\"timeBarBottom()\"\n [style.padding-left.px]=\"timeBarLeft()\"\n [style.padding-right.px]=\"timeBarRight()\"\n >\n <ng-content select=\"[slot=timeRangeBar]\" />\n </div>\n}\n\n@if (inProgress()) {\n <div class=\"progress-container\">\n <si-chart-loading-spinner />\n </div>\n}\n", styles: [":host{block-size:100%;position:relative;display:flex!important;flex-direction:column;inline-size:100%}.chart-container-wrapper{display:flex;flex:1 0 0;inline-size:inherit;overflow:hidden}.chart-scroll{overflow-y:auto}.chart-container{position:relative;display:flex;flex:1 0 0;overflow:hidden}.echart-container{flex:1 0 0;inline-size:100%;min-block-size:var(--si-chart-min-height, 200px);overflow:hidden}.custom-legend{position:absolute;z-index:2;inline-size:100%}.chart-title{padding-block:12px 8px;padding-inline-start:24px}.external-zoom-container{display:flex;flex:1 0 0;inline-size:inherit;max-block-size:112px}.external-zoom-container.has-time-range-bar{max-block-size:calc(112px + var(--time-bar-height))}.tooltip-inner{max-inline-size:375px;min-inline-size:375px;color:#162938;font-size:18px;background-color:#162938}.time-range-bar{position:absolute;inset-inline:0;z-index:2}.progress-container{position:absolute;inset:0;pointer-events:none;z-index:100;display:flex;justify-content:center;align-items:center}\n"], dependencies: [{ kind: "component", type: SiCustomLegendComponent, selector: "si-custom-legend", inputs: ["customLegend", "title", "subTitle", "titleColor", "subTitleColor", "textColor"], outputs: ["legendIconClickEvent", "legendClickEvent", "legendHoverStartEvent", "legendHoverEndEvent"] }, { kind: "component", type: SiChartLoadingSpinnerComponent, selector: "si-chart-loading-spinner" }] });
3424
+ }
3425
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.6", ngImport: i0, type: SiChartProgressBarComponent, decorators: [{
3426
+ type: Component,
3427
+ args: [{ selector: 'si-chart-progress-bar', imports: [SiCustomLegendComponent, SiChartLoadingSpinnerComponent], template: "@if (showCustomLegend() && (title() || subTitle())) {\n <div\n class=\"si-title-2 chart-title chart-title-width\"\n [style.background-color]=\"backgroundColor()\"\n >\n <div class=\"chart-title-text\" [style.color]=\"titleColor()\">{{ title() }}</div>\n @if (subTitle()) {\n <div class=\"si-body-2\" [style.color]=\"subTitleColor()\">{{ subTitle() }}</div>\n }\n </div>\n}\n\n<div\n #chartContainerWrapper\n class=\"chart-container-wrapper\"\n [class.chart-scroll]=\"containerHeight()\"\n [attr.tabindex]=\"containerHeight() ? '0' : null\"\n>\n <div class=\"chart-container\" [style.height.px]=\"containerHeight()\">\n @if (showCustomLegend()) {\n @for (cl of customLegend; track $index) {\n <si-custom-legend\n #siCustomLegend\n class=\"custom-legend\"\n [style.top.px]=\"cl.top\"\n [title]=\"title()\"\n [subTitle]=\"subTitle()\"\n [customLegend]=\"cl\"\n [style.background-color]=\"backgroundColor()\"\n [titleColor]=\"titleColor()\"\n [subTitleColor]=\"subTitleColor()\"\n [textColor]=\"textColor()\"\n (legendIconClickEvent)=\"handleLegendClick($event)\"\n (legendClickEvent)=\"handleLegendClick($event)\"\n (legendHoverStartEvent)=\"handleLegendHover($event, true)\"\n (legendHoverEndEvent)=\"handleLegendHover($event, false)\"\n />\n }\n }\n <div #chart class=\"echart-container\" [style.height.px]=\"containerHeight()\"></div>\n </div>\n</div>\n@if (externalZoomSlider()) {\n <div\n #externalZoomSlider\n class=\"external-zoom-container\"\n [class.has-time-range-bar]=\"showTimeRangeBar()\"\n [style.--time-bar-height.px]=\"timeBarHeight()\"\n ></div>\n}\n\n@if (showTimeRangeBar() && zoomSlider()) {\n <div\n class=\"time-range-bar\"\n [style.bottom.px]=\"timeBarBottom()\"\n [style.padding-left.px]=\"timeBarLeft()\"\n [style.padding-right.px]=\"timeBarRight()\"\n >\n <ng-content select=\"[slot=timeRangeBar]\" />\n </div>\n}\n\n@if (inProgress()) {\n <div class=\"progress-container\">\n <si-chart-loading-spinner />\n </div>\n}\n", styles: [":host{block-size:100%;position:relative;display:flex!important;flex-direction:column;inline-size:100%}.chart-container-wrapper{display:flex;flex:1 0 0;inline-size:inherit;overflow:hidden}.chart-scroll{overflow-y:auto}.chart-container{position:relative;display:flex;flex:1 0 0;overflow:hidden}.echart-container{flex:1 0 0;inline-size:100%;min-block-size:var(--si-chart-min-height, 200px);overflow:hidden}.custom-legend{position:absolute;z-index:2;inline-size:100%}.chart-title{padding-block:12px 8px;padding-inline-start:24px}.external-zoom-container{display:flex;flex:1 0 0;inline-size:inherit;max-block-size:112px}.external-zoom-container.has-time-range-bar{max-block-size:calc(112px + var(--time-bar-height))}.tooltip-inner{max-inline-size:375px;min-inline-size:375px;color:#162938;font-size:18px;background-color:#162938}.time-range-bar{position:absolute;inset-inline:0;z-index:2}.progress-container{position:absolute;inset:0;pointer-events:none;z-index:100;display:flex;justify-content:center;align-items:center}\n"] }]
3428
+ }] });
3429
+
3430
+ /**
3431
+ * Copyright Siemens 2016 - 2025.
3432
+ * SPDX-License-Identifier: MIT
3433
+ */
3434
+
3435
+ /**
3436
+ * Copyright Siemens 2016 - 2025.
3437
+ * SPDX-License-Identifier: MIT
3438
+ */
3439
+
3440
+ /**
3441
+ * Copyright Siemens 2016 - 2025.
3442
+ * SPDX-License-Identifier: MIT
3443
+ */
3444
+ class SiChartSankeyComponent extends SiChartComponent {
3445
+ series = input();
3446
+ /** @defaultValue false */
3447
+ toolTip = input(false);
3448
+ applyOptions() {
3449
+ const series = this.series();
3450
+ this.actualOptions = {
3451
+ series: series ? Object.assign({ type: 'sankey' }, series) : [],
3452
+ tooltip: { show: this.toolTip() }
3453
+ };
3454
+ this.applyTitles();
3455
+ }
3456
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.6", ngImport: i0, type: SiChartSankeyComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
3457
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.6", type: SiChartSankeyComponent, isStandalone: true, selector: "si-chart-sankey", inputs: { series: { classPropertyName: "series", publicName: "series", isSignal: true, isRequired: false, transformFunction: null }, toolTip: { classPropertyName: "toolTip", publicName: "toolTip", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: "@if (showCustomLegend() && (title() || subTitle())) {\n <div\n class=\"si-title-2 chart-title chart-title-width\"\n [style.background-color]=\"backgroundColor()\"\n >\n <div class=\"chart-title-text\" [style.color]=\"titleColor()\">{{ title() }}</div>\n @if (subTitle()) {\n <div class=\"si-body-2\" [style.color]=\"subTitleColor()\">{{ subTitle() }}</div>\n }\n </div>\n}\n\n<div\n #chartContainerWrapper\n class=\"chart-container-wrapper\"\n [class.chart-scroll]=\"containerHeight()\"\n [attr.tabindex]=\"containerHeight() ? '0' : null\"\n>\n <div class=\"chart-container\" [style.height.px]=\"containerHeight()\">\n @if (showCustomLegend()) {\n @for (cl of customLegend; track $index) {\n <si-custom-legend\n #siCustomLegend\n class=\"custom-legend\"\n [style.top.px]=\"cl.top\"\n [title]=\"title()\"\n [subTitle]=\"subTitle()\"\n [customLegend]=\"cl\"\n [style.background-color]=\"backgroundColor()\"\n [titleColor]=\"titleColor()\"\n [subTitleColor]=\"subTitleColor()\"\n [textColor]=\"textColor()\"\n (legendIconClickEvent)=\"handleLegendClick($event)\"\n (legendClickEvent)=\"handleLegendClick($event)\"\n (legendHoverStartEvent)=\"handleLegendHover($event, true)\"\n (legendHoverEndEvent)=\"handleLegendHover($event, false)\"\n />\n }\n }\n <div #chart class=\"echart-container\" [style.height.px]=\"containerHeight()\"></div>\n </div>\n</div>\n@if (externalZoomSlider()) {\n <div\n #externalZoomSlider\n class=\"external-zoom-container\"\n [class.has-time-range-bar]=\"showTimeRangeBar()\"\n [style.--time-bar-height.px]=\"timeBarHeight()\"\n ></div>\n}\n\n@if (showTimeRangeBar() && zoomSlider()) {\n <div\n class=\"time-range-bar\"\n [style.bottom.px]=\"timeBarBottom()\"\n [style.padding-left.px]=\"timeBarLeft()\"\n [style.padding-right.px]=\"timeBarRight()\"\n >\n <ng-content select=\"[slot=timeRangeBar]\" />\n </div>\n}\n\n@if (inProgress()) {\n <div class=\"progress-container\">\n <si-chart-loading-spinner />\n </div>\n}\n", styles: [":host{block-size:100%;position:relative;display:flex!important;flex-direction:column;inline-size:100%}.chart-container-wrapper{display:flex;flex:1 0 0;inline-size:inherit;overflow:hidden}.chart-scroll{overflow-y:auto}.chart-container{position:relative;display:flex;flex:1 0 0;overflow:hidden}.echart-container{flex:1 0 0;inline-size:100%;min-block-size:var(--si-chart-min-height, 200px);overflow:hidden}.custom-legend{position:absolute;z-index:2;inline-size:100%}.chart-title{padding-block:12px 8px;padding-inline-start:24px}.external-zoom-container{display:flex;flex:1 0 0;inline-size:inherit;max-block-size:112px}.external-zoom-container.has-time-range-bar{max-block-size:calc(112px + var(--time-bar-height))}.tooltip-inner{max-inline-size:375px;min-inline-size:375px;color:#162938;font-size:18px;background-color:#162938}.time-range-bar{position:absolute;inset-inline:0;z-index:2}.progress-container{position:absolute;inset:0;pointer-events:none;z-index:100;display:flex;justify-content:center;align-items:center}\n"], dependencies: [{ kind: "component", type: SiCustomLegendComponent, selector: "si-custom-legend", inputs: ["customLegend", "title", "subTitle", "titleColor", "subTitleColor", "textColor"], outputs: ["legendIconClickEvent", "legendClickEvent", "legendHoverStartEvent", "legendHoverEndEvent"] }, { kind: "component", type: SiChartLoadingSpinnerComponent, selector: "si-chart-loading-spinner" }] });
3458
+ }
3459
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.6", ngImport: i0, type: SiChartSankeyComponent, decorators: [{
3460
+ type: Component,
3461
+ args: [{ selector: 'si-chart-sankey', imports: [SiCustomLegendComponent, SiChartLoadingSpinnerComponent], template: "@if (showCustomLegend() && (title() || subTitle())) {\n <div\n class=\"si-title-2 chart-title chart-title-width\"\n [style.background-color]=\"backgroundColor()\"\n >\n <div class=\"chart-title-text\" [style.color]=\"titleColor()\">{{ title() }}</div>\n @if (subTitle()) {\n <div class=\"si-body-2\" [style.color]=\"subTitleColor()\">{{ subTitle() }}</div>\n }\n </div>\n}\n\n<div\n #chartContainerWrapper\n class=\"chart-container-wrapper\"\n [class.chart-scroll]=\"containerHeight()\"\n [attr.tabindex]=\"containerHeight() ? '0' : null\"\n>\n <div class=\"chart-container\" [style.height.px]=\"containerHeight()\">\n @if (showCustomLegend()) {\n @for (cl of customLegend; track $index) {\n <si-custom-legend\n #siCustomLegend\n class=\"custom-legend\"\n [style.top.px]=\"cl.top\"\n [title]=\"title()\"\n [subTitle]=\"subTitle()\"\n [customLegend]=\"cl\"\n [style.background-color]=\"backgroundColor()\"\n [titleColor]=\"titleColor()\"\n [subTitleColor]=\"subTitleColor()\"\n [textColor]=\"textColor()\"\n (legendIconClickEvent)=\"handleLegendClick($event)\"\n (legendClickEvent)=\"handleLegendClick($event)\"\n (legendHoverStartEvent)=\"handleLegendHover($event, true)\"\n (legendHoverEndEvent)=\"handleLegendHover($event, false)\"\n />\n }\n }\n <div #chart class=\"echart-container\" [style.height.px]=\"containerHeight()\"></div>\n </div>\n</div>\n@if (externalZoomSlider()) {\n <div\n #externalZoomSlider\n class=\"external-zoom-container\"\n [class.has-time-range-bar]=\"showTimeRangeBar()\"\n [style.--time-bar-height.px]=\"timeBarHeight()\"\n ></div>\n}\n\n@if (showTimeRangeBar() && zoomSlider()) {\n <div\n class=\"time-range-bar\"\n [style.bottom.px]=\"timeBarBottom()\"\n [style.padding-left.px]=\"timeBarLeft()\"\n [style.padding-right.px]=\"timeBarRight()\"\n >\n <ng-content select=\"[slot=timeRangeBar]\" />\n </div>\n}\n\n@if (inProgress()) {\n <div class=\"progress-container\">\n <si-chart-loading-spinner />\n </div>\n}\n", styles: [":host{block-size:100%;position:relative;display:flex!important;flex-direction:column;inline-size:100%}.chart-container-wrapper{display:flex;flex:1 0 0;inline-size:inherit;overflow:hidden}.chart-scroll{overflow-y:auto}.chart-container{position:relative;display:flex;flex:1 0 0;overflow:hidden}.echart-container{flex:1 0 0;inline-size:100%;min-block-size:var(--si-chart-min-height, 200px);overflow:hidden}.custom-legend{position:absolute;z-index:2;inline-size:100%}.chart-title{padding-block:12px 8px;padding-inline-start:24px}.external-zoom-container{display:flex;flex:1 0 0;inline-size:inherit;max-block-size:112px}.external-zoom-container.has-time-range-bar{max-block-size:calc(112px + var(--time-bar-height))}.tooltip-inner{max-inline-size:375px;min-inline-size:375px;color:#162938;font-size:18px;background-color:#162938}.time-range-bar{position:absolute;inset-inline:0;z-index:2}.progress-container{position:absolute;inset:0;pointer-events:none;z-index:100;display:flex;justify-content:center;align-items:center}\n"] }]
3462
+ }] });
3463
+
3464
+ /**
3465
+ * Copyright Siemens 2016 - 2025.
3466
+ * SPDX-License-Identifier: MIT
3467
+ */
3468
+
3469
+ /**
3470
+ * Copyright Siemens 2016 - 2025.
3471
+ * SPDX-License-Identifier: MIT
3472
+ */
3473
+ class SiChartSunburstComponent extends SiChartComponent {
3474
+ series = input();
3475
+ /** @defaultValue false */
3476
+ toolTip = input(false);
3477
+ applyOptions() {
3478
+ const series = this.series();
3479
+ this.actualOptions = {
3480
+ series: series ? Object.assign({ type: 'sunburst' }, series) : [],
3481
+ tooltip: { show: this.toolTip() }
3482
+ };
3483
+ this.applyTitles();
3484
+ }
3485
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.6", ngImport: i0, type: SiChartSunburstComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
3486
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.6", type: SiChartSunburstComponent, isStandalone: true, selector: "si-chart-sunburst", inputs: { series: { classPropertyName: "series", publicName: "series", isSignal: true, isRequired: false, transformFunction: null }, toolTip: { classPropertyName: "toolTip", publicName: "toolTip", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: "@if (showCustomLegend() && (title() || subTitle())) {\n <div\n class=\"si-title-2 chart-title chart-title-width\"\n [style.background-color]=\"backgroundColor()\"\n >\n <div class=\"chart-title-text\" [style.color]=\"titleColor()\">{{ title() }}</div>\n @if (subTitle()) {\n <div class=\"si-body-2\" [style.color]=\"subTitleColor()\">{{ subTitle() }}</div>\n }\n </div>\n}\n\n<div\n #chartContainerWrapper\n class=\"chart-container-wrapper\"\n [class.chart-scroll]=\"containerHeight()\"\n [attr.tabindex]=\"containerHeight() ? '0' : null\"\n>\n <div class=\"chart-container\" [style.height.px]=\"containerHeight()\">\n @if (showCustomLegend()) {\n @for (cl of customLegend; track $index) {\n <si-custom-legend\n #siCustomLegend\n class=\"custom-legend\"\n [style.top.px]=\"cl.top\"\n [title]=\"title()\"\n [subTitle]=\"subTitle()\"\n [customLegend]=\"cl\"\n [style.background-color]=\"backgroundColor()\"\n [titleColor]=\"titleColor()\"\n [subTitleColor]=\"subTitleColor()\"\n [textColor]=\"textColor()\"\n (legendIconClickEvent)=\"handleLegendClick($event)\"\n (legendClickEvent)=\"handleLegendClick($event)\"\n (legendHoverStartEvent)=\"handleLegendHover($event, true)\"\n (legendHoverEndEvent)=\"handleLegendHover($event, false)\"\n />\n }\n }\n <div #chart class=\"echart-container\" [style.height.px]=\"containerHeight()\"></div>\n </div>\n</div>\n@if (externalZoomSlider()) {\n <div\n #externalZoomSlider\n class=\"external-zoom-container\"\n [class.has-time-range-bar]=\"showTimeRangeBar()\"\n [style.--time-bar-height.px]=\"timeBarHeight()\"\n ></div>\n}\n\n@if (showTimeRangeBar() && zoomSlider()) {\n <div\n class=\"time-range-bar\"\n [style.bottom.px]=\"timeBarBottom()\"\n [style.padding-left.px]=\"timeBarLeft()\"\n [style.padding-right.px]=\"timeBarRight()\"\n >\n <ng-content select=\"[slot=timeRangeBar]\" />\n </div>\n}\n\n@if (inProgress()) {\n <div class=\"progress-container\">\n <si-chart-loading-spinner />\n </div>\n}\n", styles: [":host{block-size:100%;position:relative;display:flex!important;flex-direction:column;inline-size:100%}.chart-container-wrapper{display:flex;flex:1 0 0;inline-size:inherit;overflow:hidden}.chart-scroll{overflow-y:auto}.chart-container{position:relative;display:flex;flex:1 0 0;overflow:hidden}.echart-container{flex:1 0 0;inline-size:100%;min-block-size:var(--si-chart-min-height, 200px);overflow:hidden}.custom-legend{position:absolute;z-index:2;inline-size:100%}.chart-title{padding-block:12px 8px;padding-inline-start:24px}.external-zoom-container{display:flex;flex:1 0 0;inline-size:inherit;max-block-size:112px}.external-zoom-container.has-time-range-bar{max-block-size:calc(112px + var(--time-bar-height))}.tooltip-inner{max-inline-size:375px;min-inline-size:375px;color:#162938;font-size:18px;background-color:#162938}.time-range-bar{position:absolute;inset-inline:0;z-index:2}.progress-container{position:absolute;inset:0;pointer-events:none;z-index:100;display:flex;justify-content:center;align-items:center}\n"], dependencies: [{ kind: "component", type: SiCustomLegendComponent, selector: "si-custom-legend", inputs: ["customLegend", "title", "subTitle", "titleColor", "subTitleColor", "textColor"], outputs: ["legendIconClickEvent", "legendClickEvent", "legendHoverStartEvent", "legendHoverEndEvent"] }, { kind: "component", type: SiChartLoadingSpinnerComponent, selector: "si-chart-loading-spinner" }] });
3487
+ }
3488
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.6", ngImport: i0, type: SiChartSunburstComponent, decorators: [{
3489
+ type: Component,
3490
+ args: [{ selector: 'si-chart-sunburst', imports: [SiCustomLegendComponent, SiChartLoadingSpinnerComponent], template: "@if (showCustomLegend() && (title() || subTitle())) {\n <div\n class=\"si-title-2 chart-title chart-title-width\"\n [style.background-color]=\"backgroundColor()\"\n >\n <div class=\"chart-title-text\" [style.color]=\"titleColor()\">{{ title() }}</div>\n @if (subTitle()) {\n <div class=\"si-body-2\" [style.color]=\"subTitleColor()\">{{ subTitle() }}</div>\n }\n </div>\n}\n\n<div\n #chartContainerWrapper\n class=\"chart-container-wrapper\"\n [class.chart-scroll]=\"containerHeight()\"\n [attr.tabindex]=\"containerHeight() ? '0' : null\"\n>\n <div class=\"chart-container\" [style.height.px]=\"containerHeight()\">\n @if (showCustomLegend()) {\n @for (cl of customLegend; track $index) {\n <si-custom-legend\n #siCustomLegend\n class=\"custom-legend\"\n [style.top.px]=\"cl.top\"\n [title]=\"title()\"\n [subTitle]=\"subTitle()\"\n [customLegend]=\"cl\"\n [style.background-color]=\"backgroundColor()\"\n [titleColor]=\"titleColor()\"\n [subTitleColor]=\"subTitleColor()\"\n [textColor]=\"textColor()\"\n (legendIconClickEvent)=\"handleLegendClick($event)\"\n (legendClickEvent)=\"handleLegendClick($event)\"\n (legendHoverStartEvent)=\"handleLegendHover($event, true)\"\n (legendHoverEndEvent)=\"handleLegendHover($event, false)\"\n />\n }\n }\n <div #chart class=\"echart-container\" [style.height.px]=\"containerHeight()\"></div>\n </div>\n</div>\n@if (externalZoomSlider()) {\n <div\n #externalZoomSlider\n class=\"external-zoom-container\"\n [class.has-time-range-bar]=\"showTimeRangeBar()\"\n [style.--time-bar-height.px]=\"timeBarHeight()\"\n ></div>\n}\n\n@if (showTimeRangeBar() && zoomSlider()) {\n <div\n class=\"time-range-bar\"\n [style.bottom.px]=\"timeBarBottom()\"\n [style.padding-left.px]=\"timeBarLeft()\"\n [style.padding-right.px]=\"timeBarRight()\"\n >\n <ng-content select=\"[slot=timeRangeBar]\" />\n </div>\n}\n\n@if (inProgress()) {\n <div class=\"progress-container\">\n <si-chart-loading-spinner />\n </div>\n}\n", styles: [":host{block-size:100%;position:relative;display:flex!important;flex-direction:column;inline-size:100%}.chart-container-wrapper{display:flex;flex:1 0 0;inline-size:inherit;overflow:hidden}.chart-scroll{overflow-y:auto}.chart-container{position:relative;display:flex;flex:1 0 0;overflow:hidden}.echart-container{flex:1 0 0;inline-size:100%;min-block-size:var(--si-chart-min-height, 200px);overflow:hidden}.custom-legend{position:absolute;z-index:2;inline-size:100%}.chart-title{padding-block:12px 8px;padding-inline-start:24px}.external-zoom-container{display:flex;flex:1 0 0;inline-size:inherit;max-block-size:112px}.external-zoom-container.has-time-range-bar{max-block-size:calc(112px + var(--time-bar-height))}.tooltip-inner{max-inline-size:375px;min-inline-size:375px;color:#162938;font-size:18px;background-color:#162938}.time-range-bar{position:absolute;inset-inline:0;z-index:2}.progress-container{position:absolute;inset:0;pointer-events:none;z-index:100;display:flex;justify-content:center;align-items:center}\n"] }]
3491
+ }] });
3492
+
3493
+ /**
3494
+ * Copyright Siemens 2016 - 2025.
3495
+ * SPDX-License-Identifier: MIT
3496
+ */
3497
+
3498
+ /**
3499
+ * Copyright Siemens 2016 - 2025.
3500
+ * SPDX-License-Identifier: MIT
3501
+ */
3502
+
3503
+ /**
3504
+ * Copyright Siemens 2016 - 2025.
3505
+ * SPDX-License-Identifier: MIT
3506
+ */
3507
+
3508
+ /**
3509
+ * Copyright Siemens 2016 - 2025.
3510
+ * SPDX-License-Identifier: MIT
3511
+ */
3512
+ class SiChartsNgModule {
3513
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.6", ngImport: i0, type: SiChartsNgModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
3514
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.0.6", ngImport: i0, type: SiChartsNgModule, imports: [CommonModule,
3515
+ SiChartCartesianComponent,
3516
+ SiChartCircleComponent,
3517
+ SiChartComponent,
3518
+ SiChartGaugeComponent,
3519
+ SiChartLoadingSpinnerComponent,
3520
+ SiChartProgressBarComponent,
3521
+ SiChartProgressComponent,
3522
+ SiChartSankeyComponent,
3523
+ SiChartSunburstComponent,
3524
+ SiCustomLegendComponent], exports: [SiChartCartesianComponent,
3525
+ SiChartCircleComponent,
3526
+ SiChartComponent,
3527
+ SiChartGaugeComponent,
3528
+ SiChartProgressBarComponent,
3529
+ SiChartProgressComponent,
3530
+ SiChartSankeyComponent,
3531
+ SiChartSunburstComponent,
3532
+ SiCustomLegendComponent] });
3533
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.0.6", ngImport: i0, type: SiChartsNgModule, imports: [CommonModule] });
3534
+ }
3535
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.6", ngImport: i0, type: SiChartsNgModule, decorators: [{
3536
+ type: NgModule,
3537
+ args: [{
3538
+ imports: [
3539
+ CommonModule,
3540
+ SiChartCartesianComponent,
3541
+ SiChartCircleComponent,
3542
+ SiChartComponent,
3543
+ SiChartGaugeComponent,
3544
+ SiChartLoadingSpinnerComponent,
3545
+ SiChartProgressBarComponent,
3546
+ SiChartProgressComponent,
3547
+ SiChartSankeyComponent,
3548
+ SiChartSunburstComponent,
3549
+ SiCustomLegendComponent
3550
+ ],
3551
+ exports: [
3552
+ SiChartCartesianComponent,
3553
+ SiChartCircleComponent,
3554
+ SiChartComponent,
3555
+ SiChartGaugeComponent,
3556
+ SiChartProgressBarComponent,
3557
+ SiChartProgressComponent,
3558
+ SiChartSankeyComponent,
3559
+ SiChartSunburstComponent,
3560
+ SiCustomLegendComponent
3561
+ ]
3562
+ }]
3563
+ }] });
3564
+
3565
+ /**
3566
+ * Copyright Siemens 2016 - 2025.
3567
+ * SPDX-License-Identifier: MIT
3568
+ */
3569
+ // Public API Surface
3570
+
3571
+ /**
3572
+ * Generated bundle index. Do not edit.
3573
+ */
3574
+
3575
+ export { SiChartCartesianComponent, SiChartCircleComponent, SiChartComponent, SiChartGaugeComponent, SiChartProgressBarComponent, SiChartProgressComponent, SiChartSankeyComponent, SiChartSunburstComponent, SiChartsNgModule, SiCustomLegendComponent, SiChartsNgModule as SimplChartsNgModule, themeElement, themeSupport };
3576
+ //# sourceMappingURL=siemens-charts-ng.mjs.map