@agorapulse/ui-charts 20.1.16 → 20.1.17

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.
@@ -1,82 +1,59 @@
1
1
  import * as Highcharts from 'highcharts';
2
2
  import { numberFormat, setOptions, dateFormat, Chart } from 'highcharts';
3
3
  import * as i0 from '@angular/core';
4
- import { Input, ViewChild, Directive, Component, input, EventEmitter, Output, effect, ChangeDetectionStrategy, signal, afterNextRender } from '@angular/core';
4
+ import { inject, DestroyRef, ElementRef, input, signal, afterNextRender, effect, Directive, ChangeDetectionStrategy, Component, output } from '@angular/core';
5
+ import { isPlainObject, cloneDeep, round } from 'es-toolkit';
5
6
  import { mapChart } from 'highcharts/highmaps';
6
- import * as i1 from '@angular/common';
7
- import { CommonModule } from '@angular/common';
8
- import { MatDividerModule } from '@angular/material/divider';
9
- import * as i2 from '@angular/material/list';
10
- import { MatListModule } from '@angular/material/list';
11
7
 
12
- /* eslint-disable @typescript-eslint/ban-ts-comment */
13
- const borderRadiusPlugin = function (H) {
14
- if (H.borderRadiusPlugininitialized) {
8
+ function borderRadiusPlugin(H) {
9
+ const runtime = H;
10
+ if (runtime.borderRadiusPlugininitialized)
15
11
  return;
16
- }
17
- H.borderRadiusPlugininitialized = true;
18
- H.wrap(H.seriesTypes.column.prototype, 'translate', function (proceed) {
19
- // @ts-ignore
20
- const options = this.options;
21
- const topMargin = options.topMargin || 0;
22
- const bottomMargin = options.bottomMargin || 0;
23
- const borderRadiusTopLeftSettings = options.borderRadiusTopLeft;
24
- const borderRadiusTopRightSettings = options.borderRadiusTopRight;
25
- const borderRadiusBottomLeftSettings = options.borderRadiusBottomLeft;
26
- const borderRadiusBottomRightSettings = options.borderRadiusBottomRight;
27
- // @ts-ignore
12
+ runtime.borderRadiusPlugininitialized = true;
13
+ H.wrap(runtime.seriesTypes.column.prototype, 'translate', function (proceed) {
14
+ const { topMargin = 0, bottomMargin = 0, borderRadiusTopLeft, borderRadiusTopRight, borderRadiusBottomLeft, borderRadiusBottomRight, } = this.options;
28
15
  proceed.call(this);
29
- // @ts-ignore
30
- if (!this.points) {
16
+ if (!this.points)
31
17
  return;
32
- }
33
- if (borderRadiusTopLeftSettings ||
34
- borderRadiusTopRightSettings ||
35
- borderRadiusBottomLeftSettings ||
36
- borderRadiusBottomRightSettings) {
37
- // @ts-ignore
38
- this.points.forEach(function (point) {
39
- roundPoint(borderRadiusTopLeftSettings, borderRadiusTopRightSettings, borderRadiusBottomLeftSettings, borderRadiusBottomRightSettings, point, H, topMargin, bottomMargin);
40
- });
41
- }
18
+ if (!borderRadiusTopLeft && !borderRadiusTopRight && !borderRadiusBottomLeft && !borderRadiusBottomRight)
19
+ return;
20
+ this.points.forEach(point => roundPoint(point, H, {
21
+ topMargin,
22
+ bottomMargin,
23
+ topLeft: borderRadiusTopLeft,
24
+ topRight: borderRadiusTopRight,
25
+ bottomLeft: borderRadiusBottomLeft,
26
+ bottomRight: borderRadiusBottomRight,
27
+ }));
42
28
  });
43
- };
44
- function roundPoint(borderRadiusTopLeftSettings, borderRadiusTopRightSettings, borderRadiusBottomLeftSettings, borderRadiusBottomRightSettings, point, H, topMargin, bottomMargin) {
45
- const w = point.shapeArgs.width;
46
- const h = point.shapeArgs.height;
47
- const x = point.shapeArgs.x;
48
- const y = point.shapeArgs.y;
49
- const borderRadiusTopLeft = borderRadiusTopLeftSettings?.length
50
- ? borderRadiusTopLeftSettings[point.index]
51
- : borderRadiusTopLeftSettings || 0;
52
- const borderRadiusTopRight = borderRadiusTopRightSettings?.length
53
- ? borderRadiusTopRightSettings[point.index]
54
- : borderRadiusTopRightSettings || 0;
55
- const borderRadiusBottomLeft = borderRadiusBottomLeftSettings?.length
56
- ? borderRadiusBottomLeftSettings[point.index]
57
- : borderRadiusBottomLeftSettings || 0;
58
- const borderRadiusBottomRight = borderRadiusBottomRightSettings?.length
59
- ? borderRadiusBottomRightSettings[point.index]
60
- : borderRadiusBottomRightSettings || 0;
61
- let radiusTopLeft = H.relativeLength(borderRadiusTopLeft, w);
62
- let radiusTopRight = H.relativeLength(borderRadiusTopRight, w);
63
- let radiusBottomRight = H.relativeLength(borderRadiusBottomRight, w);
64
- let radiusBottomLeft = H.relativeLength(borderRadiusBottomLeft, w);
29
+ }
30
+ function pickRadius(value, index) {
31
+ if (Array.isArray(value))
32
+ return value[index] ?? 0;
33
+ return value ?? 0;
34
+ }
35
+ function roundPoint(point, H, config) {
36
+ const { width: w, height: h, x, y } = point.shapeArgs;
65
37
  const maxR = Math.min(w, h) / 2;
66
- radiusTopLeft = radiusTopLeft > maxR ? maxR : radiusTopLeft;
67
- radiusTopRight = radiusTopRight > maxR ? maxR : radiusTopRight;
68
- radiusBottomRight = radiusBottomRight > maxR ? maxR : radiusBottomRight;
69
- radiusBottomLeft = radiusBottomLeft > maxR ? maxR : radiusBottomLeft;
38
+ const clamp = (radius) => (radius > maxR ? maxR : radius);
39
+ const radiusTopLeft = clamp(H.relativeLength(pickRadius(config.topLeft, point.index), w));
40
+ const radiusTopRight = clamp(H.relativeLength(pickRadius(config.topRight, point.index), w));
41
+ const radiusBottomRight = clamp(H.relativeLength(pickRadius(config.bottomRight, point.index), w));
42
+ const radiusBottomLeft = clamp(H.relativeLength(pickRadius(config.bottomLeft, point.index), w));
70
43
  point.dlBox = point.shapeArgs;
71
44
  point.shapeType = 'path';
72
45
  point.shapeArgs = {
46
+ width: w,
47
+ height: h,
48
+ x,
49
+ y,
73
50
  d: [
74
51
  'M',
75
52
  x + radiusTopLeft,
76
- y + topMargin,
53
+ y + config.topMargin,
77
54
  'L',
78
55
  x + w - radiusTopRight,
79
- y + topMargin,
56
+ y + config.topMargin,
80
57
  'C',
81
58
  x + w - radiusTopRight / 2,
82
59
  y,
@@ -93,10 +70,10 @@ function roundPoint(borderRadiusTopLeftSettings, borderRadiusTopRightSettings, b
93
70
  x + w - radiusBottomRight / 2,
94
71
  y + h,
95
72
  x + w - radiusBottomRight,
96
- y + h + bottomMargin,
73
+ y + h + config.bottomMargin,
97
74
  'L',
98
75
  x + radiusBottomLeft,
99
- y + h + bottomMargin,
76
+ y + h + config.bottomMargin,
100
77
  'C',
101
78
  x + radiusBottomLeft / 2,
102
79
  y + h,
@@ -233,61 +210,53 @@ class ChartColors {
233
210
  }
234
211
 
235
212
  class AbstractChartComponent {
236
- chartRef;
237
- chartOptions = {}; // https://api.highcharts.com/highcharts/
238
- color = ChartColor.ElectricBlue;
239
- labelDateFormat = '%m/%d';
240
- locale = 'en';
241
- series = [];
213
+ destroyRef = inject(DestroyRef);
214
+ /** Highcharts renders into the component's host element directly — no inner template ref needed. */
215
+ hostElement = inject(ElementRef).nativeElement;
216
+ chartOptions = input({}, ...(ngDevMode ? [{ debugName: "chartOptions" }] : []));
217
+ color = input(ChartColor.ElectricBlue, ...(ngDevMode ? [{ debugName: "color" }] : []));
218
+ labelDateFormat = input('%m/%d', ...(ngDevMode ? [{ debugName: "labelDateFormat" }] : []));
219
+ locale = input('en', ...(ngDevMode ? [{ debugName: "locale" }] : []));
242
220
  chart;
221
+ viewReady = signal(false, ...(ngDevMode ? [{ debugName: "viewReady" }] : []));
243
222
  resizeObserver;
244
- ngOnChanges(changes) {
245
- if ((changes.series && !changes.series.firstChange) ||
246
- (changes.color && !changes.color.firstChange) ||
247
- (changes.chartOptions && !changes.chartOptions.firstChange) ||
248
- (changes.locale && !changes.locale.firstChange) ||
249
- (changes.metricFormat && !changes.metricFormat.firstChange)) {
250
- this.initChart();
251
- }
252
- }
253
- ngAfterViewInit() {
254
- this.resizeObserver = new ResizeObserver(() => {
255
- const el = this.chartRef?.nativeElement;
256
- if (!el || el.clientWidth === 0) {
223
+ constructor() {
224
+ afterNextRender(() => {
225
+ this.resizeObserver = new ResizeObserver(() => this.onResize());
226
+ this.resizeObserver.observe(this.hostElement);
227
+ this.viewReady.set(true);
228
+ });
229
+ // Eager init once the view is ready: Highcharts handles 0-width containers via its
230
+ // default width and the ResizeObserver below reflows when the container later grows.
231
+ effect(() => {
232
+ if (!this.viewReady())
257
233
  return;
258
- }
259
- if (this.chart) {
260
- this.chart.reflow();
261
- }
262
- else if (this.series?.length) {
263
- this.initChart();
264
- }
234
+ this.rebuild();
265
235
  });
266
- this.resizeObserver.observe(this.chartRef.nativeElement);
236
+ this.destroyRef.onDestroy(() => {
237
+ this.resizeObserver?.disconnect();
238
+ this.chart?.destroy();
239
+ });
240
+ }
241
+ onResize() {
242
+ if (this.chart) {
243
+ this.chart.reflow();
244
+ }
245
+ else if (this.hostElement.clientWidth > 0 && this.series().length) {
246
+ this.rebuild();
247
+ }
267
248
  }
268
- ngOnDestroy() {
269
- this.resizeObserver?.disconnect();
249
+ rebuild() {
270
250
  this.chart?.destroy();
251
+ this.chart = undefined;
252
+ this.initChart();
271
253
  }
272
254
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: AbstractChartComponent, deps: [], target: i0.ɵɵFactoryTarget.Directive });
273
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.18", type: AbstractChartComponent, isStandalone: true, inputs: { chartOptions: "chartOptions", color: "color", labelDateFormat: "labelDateFormat", locale: "locale", series: "series" }, viewQueries: [{ propertyName: "chartRef", first: true, predicate: ["chart"], descendants: true }], usesOnChanges: true, ngImport: i0 });
255
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.3.18", type: AbstractChartComponent, isStandalone: true, inputs: { chartOptions: { classPropertyName: "chartOptions", publicName: "chartOptions", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, labelDateFormat: { classPropertyName: "labelDateFormat", publicName: "labelDateFormat", isSignal: true, isRequired: false, transformFunction: null }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 });
274
256
  }
275
257
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: AbstractChartComponent, decorators: [{
276
258
  type: Directive
277
- }], propDecorators: { chartRef: [{
278
- type: ViewChild,
279
- args: ['chart']
280
- }], chartOptions: [{
281
- type: Input
282
- }], color: [{
283
- type: Input
284
- }], labelDateFormat: [{
285
- type: Input
286
- }], locale: [{
287
- type: Input
288
- }], series: [{
289
- type: Input
290
- }] } });
259
+ }], ctorParameters: () => [], propDecorators: { chartOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "chartOptions", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], labelDateFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelDateFormat", required: false }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }] } });
291
260
 
292
261
  /**
293
262
  * Builds Highcharts locale options (lang + tooltip date formats) from a locale string.
@@ -332,22 +301,11 @@ function buildShortMonths(locale) {
332
301
  });
333
302
  }
334
303
 
304
+ const FONT_FAMILY = "Averta, 'Open Sans', Helvetica, sans-serif";
305
+ const LABEL_FONT_SIZE = '12px';
335
306
  class ChartOptions {
336
307
  static DEFAULT_DATE_FORMAT = '%A, %b %e, %Y';
337
308
  static DEFAULT_OPTIONS = {
338
- /*lang: {
339
- decimalPoint: (manager && manager.locale !== 'en') ? ',' : '.',
340
- resetZoom: resetZoomLabel,
341
- resetZoomTitle: resetZoomHtmlTitle,
342
- shortMonths: [
343
- shortJanuary, shortFebruary, shortMarch, shortApril, shortMay, shortJune,
344
- shortJuly, shortAugust, shortSeptember, shortOctober, shortNovember, shortDecember
345
- ],
346
- thousandsSep: (manager && manager.locale !== 'en') ? ' ' : ',',
347
- weekdays: this.weekDays,
348
- zoomIn: zoomInHtmlTitle,
349
- zoomOut: zoomOutHtmlTitle
350
- },*/
351
309
  chart: {
352
310
  spacingRight: 20,
353
311
  zooming: {
@@ -358,34 +316,22 @@ class ChartOptions {
358
316
  r: 4,
359
317
  style: {
360
318
  color: ChartColors.GREY_COLORS[100],
361
- fontSize: '12px',
319
+ fontSize: LABEL_FONT_SIZE,
362
320
  },
363
321
  states: {
364
- hover: {
365
- fill: ChartColors.GREY_COLORS[5],
366
- },
322
+ hover: { fill: ChartColors.GREY_COLORS[5] },
367
323
  },
368
324
  },
369
325
  },
370
326
  },
371
- panning: {
372
- enabled: true,
373
- },
327
+ panning: { enabled: true },
374
328
  panKey: 'shift',
375
- style: {
376
- fontFamily: "Averta, 'Open Sans', Helvetica, sans-serif",
377
- },
329
+ style: { fontFamily: FONT_FAMILY },
378
330
  },
379
331
  colorAxis: {
380
- labels: {
381
- style: {
382
- color: ChartColors.GREY_COLORS[60],
383
- },
384
- },
385
- },
386
- credits: {
387
- enabled: false,
332
+ labels: { style: { color: ChartColors.GREY_COLORS[60] } },
388
333
  },
334
+ credits: { enabled: false },
389
335
  legend: {
390
336
  borderWidth: 0,
391
337
  itemStyle: {
@@ -401,21 +347,15 @@ class ChartOptions {
401
347
  plotOptions: {
402
348
  series: {
403
349
  states: {
404
- hover: {
405
- brightness: 0,
406
- },
350
+ hover: { brightness: 0 },
407
351
  },
408
352
  connectNulls: true,
409
353
  },
410
354
  },
411
355
  navigation: {
412
- buttonOptions: {
413
- y: 0,
414
- },
415
- },
416
- title: {
417
- text: undefined,
356
+ buttonOptions: { y: 0 },
418
357
  },
358
+ title: { text: undefined },
419
359
  tooltip: {
420
360
  backgroundColor: ChartColors.WHITE_COLOR,
421
361
  borderRadius: 4,
@@ -432,22 +372,20 @@ class ChartOptions {
432
372
  shared: true,
433
373
  useHTML: true,
434
374
  headerFormat: `<div style="border-bottom: 1px solid ${ChartColors.GREY_COLORS[10]}; padding: 0 8px 7px">` +
435
- `<div style="white-space: wrap; font-size: 12px; color: ${ChartColors.GREY_COLORS[60]}">{point.key}</div></div>`,
375
+ `<div style="white-space: wrap; font-size: ${LABEL_FONT_SIZE}; color: ${ChartColors.GREY_COLORS[60]}">{point.key}</div></div>`,
436
376
  pointFormat: `<div style="font-size: 14px; color: ${ChartColors.GREY_COLORS[100]}; margin: 6px 8px 0 8px;">` +
437
- '<span style="color:{point.color}">\u25CF</span> {series.name}: <b>{point.y}</b> {point.custom.details}</div>',
377
+ '<span style="color:{point.color}">●</span> {series.name}: <b>{point.y}</b> {point.custom.details}</div>',
438
378
  },
439
379
  xAxis: {
440
380
  gridLineColor: ChartColors.GREY_COLORS[10],
441
381
  lineColor: ChartColors.GREY_COLORS[10],
442
382
  tickColor: ChartColors.GREY_COLORS[10],
443
383
  gridLineWidth: 1,
444
- title: {
445
- text: null,
446
- },
384
+ title: { text: null },
447
385
  labels: {
448
386
  style: {
449
387
  color: ChartColors.GREY_COLORS[85],
450
- fontSize: '12px',
388
+ fontSize: LABEL_FONT_SIZE,
451
389
  },
452
390
  },
453
391
  },
@@ -456,19 +394,14 @@ class ChartOptions {
456
394
  gridLineColor: ChartColors.GREY_COLORS[10],
457
395
  lineColor: ChartColors.GREY_COLORS[10],
458
396
  gridLineWidth: 1,
459
- title: {
460
- text: undefined,
461
- },
397
+ title: { text: undefined },
462
398
  labels: {
463
- formatter: function () {
464
- if (typeof this.value === 'string') {
465
- return this.value;
466
- }
467
- return numberFormat(this.value, -1);
399
+ formatter() {
400
+ return typeof this.value === 'string' ? this.value : numberFormat(this.value, -1);
468
401
  },
469
402
  style: {
470
403
  color: ChartColors.GREY_COLORS[85],
471
- fontSize: '12px',
404
+ fontSize: LABEL_FONT_SIZE,
472
405
  },
473
406
  },
474
407
  },
@@ -479,18 +412,15 @@ class ChartOptions {
479
412
  return mergeDeep(mergeDeep(ChartOptions.DEFAULT_OPTIONS, localeOptions), options);
480
413
  }
481
414
  static configure(series, options, color, labelDateFormat) {
482
- // Configure axis
483
415
  options.xAxis = mergeDeep({
484
416
  labels: {
485
- formatter: function () {
417
+ formatter() {
486
418
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
487
- // @ts-ignore
419
+ // @ts-ignore highcharts callback context types `value` as string | number
488
420
  return dateFormat(labelDateFormat ?? '%m/%d', this.value);
489
421
  },
490
422
  },
491
- //minTickInterval: 24 * 60 * 60 * 1000 // One day
492
423
  }, options.xAxis);
493
- // Configure series
494
424
  if (series?.length) {
495
425
  options.series = series;
496
426
  if (options.legend) {
@@ -500,113 +430,98 @@ class ChartOptions {
500
430
  }
501
431
  }
502
432
  static redrawWithHighestEdgesRounded(chart) {
503
- chart.series.forEach((serie, serieIndex, arr) => {
504
- ChartOptions.roundHighestSerie(arr, serie.options, serieIndex);
433
+ chart.series.forEach((serie, index, all) => {
434
+ ChartOptions.roundHighestSerie(all, serie.options, index);
505
435
  });
506
436
  chart.redraw(true);
507
437
  }
508
438
  static roundHighestSerie(series, serie, serieIndex) {
439
+ if (!serie.data)
440
+ return;
509
441
  const roundedTopMap = [];
510
442
  const roundedBottomMap = [];
511
- if (serie.data) {
512
- serie.data.forEach((point, columnIndex) => {
513
- const pointValue = ChartOptions.getPointValue(point);
514
- const pointX = ChartOptions.getPointX(point);
515
- const isNegative = pointValue !== null && pointValue < 0;
516
- if (isNegative) {
517
- // Negative bars go downward: the visual tip is the physical bottom.
518
- // Round bottom corners if no higher-index visible series has a negative value here
519
- // (meaning this series is the bottommost segment of the negative stack).
520
- const isBottommost = series.slice(serieIndex + 1).every(otherSerie => {
521
- if (!otherSerie.visible)
522
- return true;
523
- const otherPoint = ChartOptions.findPointAtAbscissa(otherSerie.options.data, pointX, columnIndex);
524
- if (otherPoint === undefined)
525
- return true;
526
- const val = ChartOptions.getPointValue(otherPoint);
527
- return val === null || val >= 0;
528
- });
529
- roundedTopMap[columnIndex] = 0;
530
- roundedBottomMap[columnIndex] = isBottommost ? 100 : 0;
531
- }
532
- else {
533
- // Positive bars go upward: the visual tip is the physical top.
534
- // Round top corners if all lower-index visible series are 0/missing here
535
- // (meaning this series is the topmost segment of the positive stack).
536
- const isTopmost = series.slice(0, serieIndex).every(otherSerie => {
537
- if (!otherSerie.visible)
538
- return true;
539
- const otherPoint = ChartOptions.findPointAtAbscissa(otherSerie.options.data, pointX, columnIndex);
540
- return otherPoint === undefined || ChartOptions.getPointValue(otherPoint) === 0;
541
- });
542
- roundedTopMap[columnIndex] = isTopmost ? 100 : 0;
543
- roundedBottomMap[columnIndex] = 0;
544
- }
545
- });
546
- serie.borderRadiusTopLeft = roundedTopMap;
547
- serie.borderRadiusTopRight = roundedTopMap;
548
- serie.borderRadiusBottomLeft = roundedBottomMap;
549
- serie.borderRadiusBottomRight = roundedBottomMap;
550
- }
551
- }
552
- static getPointX(point) {
553
- if (Array.isArray(point))
554
- return point[0];
555
- if (point && typeof point === 'object')
556
- return point.x ?? null;
557
- return null;
558
- }
559
- static findPointAtAbscissa(data, x, fallbackIndex) {
560
- if (!data)
561
- return undefined;
562
- if (x !== null) {
563
- return data.find(p => ChartOptions.getPointX(p) === x);
564
- }
565
- return data[fallbackIndex];
566
- }
567
- static getPointValue(point) {
568
- if (typeof point === 'number')
569
- return point;
570
- if (Array.isArray(point))
571
- return point[1];
572
- if (point && typeof point === 'object')
573
- return point.y ?? null;
574
- return null;
575
- }
576
- }
577
- function isObject(item) {
578
- return item && typeof item === 'object' && !Array.isArray(item);
579
- }
580
- function mergeDeep(target, source) {
581
- const output = deepCopy(target);
582
- if (isObject(target) && isObject(source)) {
583
- Object.keys(source).forEach(key => {
584
- if (isObject(source[key])) {
585
- if (!(key in target))
586
- Object.assign(output, { [key]: source[key] });
587
- else
588
- output[key] = mergeDeep(target[key], source[key]);
443
+ serie.data.forEach((point, columnIndex) => {
444
+ const pointValue = getPointValue(point);
445
+ const pointX = getPointX(point);
446
+ const isNegative = pointValue !== null && pointValue < 0;
447
+ if (isNegative) {
448
+ // Negative bars go downward: the visual tip is the physical bottom.
449
+ // Round bottom corners only on the bottommost segment of the negative stack.
450
+ const isBottommost = series.slice(serieIndex + 1).every(other => {
451
+ if (!other.visible)
452
+ return true;
453
+ const otherPoint = findPointAtAbscissa(other.options.data, pointX, columnIndex);
454
+ if (otherPoint === undefined)
455
+ return true;
456
+ const val = getPointValue(otherPoint);
457
+ return val === null || val >= 0;
458
+ });
459
+ roundedTopMap[columnIndex] = 0;
460
+ roundedBottomMap[columnIndex] = isBottommost ? 100 : 0;
589
461
  }
590
462
  else {
591
- Object.assign(output, { [key]: source[key] });
463
+ // Positive bars go upward: the visual tip is the physical top.
464
+ // Round top corners only on the topmost segment of the positive stack.
465
+ const isTopmost = series.slice(0, serieIndex).every(other => {
466
+ if (!other.visible)
467
+ return true;
468
+ const otherPoint = findPointAtAbscissa(other.options.data, pointX, columnIndex);
469
+ return otherPoint === undefined || getPointValue(otherPoint) === 0;
470
+ });
471
+ roundedTopMap[columnIndex] = isTopmost ? 100 : 0;
472
+ roundedBottomMap[columnIndex] = 0;
592
473
  }
593
474
  });
475
+ serie.borderRadiusTopLeft = roundedTopMap;
476
+ serie.borderRadiusTopRight = roundedTopMap;
477
+ serie.borderRadiusBottomLeft = roundedBottomMap;
478
+ serie.borderRadiusBottomRight = roundedBottomMap;
594
479
  }
595
- return output;
596
480
  }
597
- function deepCopy(source) {
598
- if (typeof source !== 'object' || source === null) {
599
- return source; // Return the value if source is not an object
481
+ function getPointX(point) {
482
+ if (Array.isArray(point))
483
+ return point[0];
484
+ if (point && typeof point === 'object')
485
+ return point.x ?? null;
486
+ return null;
487
+ }
488
+ function getPointValue(point) {
489
+ if (typeof point === 'number')
490
+ return point;
491
+ if (Array.isArray(point))
492
+ return point[1];
493
+ if (point && typeof point === 'object')
494
+ return point.y ?? null;
495
+ return null;
496
+ }
497
+ function findPointAtAbscissa(data, x, fallbackIndex) {
498
+ if (!data)
499
+ return undefined;
500
+ if (x !== null) {
501
+ return data.find(p => getPointX(p) === x);
600
502
  }
601
- // Create an array or object to hold the values
602
- const newObject = Array.isArray(source) ? [] : {};
603
- for (const key in source) {
604
- if (source.hasOwnProperty(key)) {
605
- // Recursively (deep) copy for nested objects, including arrays
606
- newObject[key] = deepCopy(source[key]);
503
+ return data[fallbackIndex];
504
+ }
505
+ /**
506
+ * Deep-merges `source` onto a clone of `target` without mutating either, with one deliberate
507
+ * deviation from `es-toolkit`'s `toMerged`: arrays are treated as opaque values (replaced wholesale)
508
+ * rather than element-merged, which matches how Highcharts options are intended to be overridden.
509
+ */
510
+ function mergeDeep(target, source) {
511
+ if (!isPlainObject(target) || !isPlainObject(source)) {
512
+ return target;
513
+ }
514
+ const output = cloneDeep(target);
515
+ for (const key of Object.keys(source)) {
516
+ const sourceValue = source[key];
517
+ if (isPlainObject(sourceValue)) {
518
+ output[key] = key in target ? mergeDeep(target[key], sourceValue) : cloneDeep(sourceValue);
519
+ }
520
+ else {
521
+ output[key] = sourceValue;
607
522
  }
608
523
  }
609
- return newObject;
524
+ return output;
610
525
  }
611
526
 
612
527
  class ChartBarOptions extends ChartOptions {
@@ -710,35 +625,30 @@ class ChartBarOptions extends ChartOptions {
710
625
  }
711
626
 
712
627
  class ChartBarComponent extends AbstractChartComponent {
713
- categories = [];
714
- opposite = false;
715
- stacked = false;
716
- series = [];
628
+ categories = input([], ...(ngDevMode ? [{ debugName: "categories" }] : []));
629
+ opposite = input(false, ...(ngDevMode ? [{ debugName: "opposite" }] : []));
630
+ stacked = input(false, ...(ngDevMode ? [{ debugName: "stacked" }] : []));
631
+ series = input([], ...(ngDevMode ? [{ debugName: "series" }] : []));
717
632
  initChart() {
718
- if (this.series) {
719
- const chartOptions = ChartBarOptions.buildBars(this.chartOptions, this.stacked, this.opposite, this.locale);
720
- ChartBarOptions.configureBar(this.series, this.categories, chartOptions, this.opposite, this.color, this.labelDateFormat);
721
- this.chart = new Chart(this.chartRef.nativeElement, chartOptions);
722
- if (this.chart && this.stacked && !this.opposite) {
723
- ChartOptions.redrawWithHighestEdgesRounded(this.chart);
724
- }
633
+ const options = ChartBarOptions.buildBars(this.chartOptions(), this.stacked(), this.opposite(), this.locale());
634
+ ChartBarOptions.configureBar(this.series(), this.categories(), options, this.opposite(), this.color(), this.labelDateFormat());
635
+ this.chart = new Chart(this.hostElement, options);
636
+ if (this.stacked() && !this.opposite()) {
637
+ ChartOptions.redrawWithHighestEdgesRounded(this.chart);
725
638
  }
726
639
  }
727
640
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: ChartBarComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
728
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: ChartBarComponent, isStandalone: true, selector: "ap-chart-bar", inputs: { categories: "categories", opposite: "opposite", stacked: "stacked", series: "series" }, usesInheritance: true, ngImport: i0, template: "<div #chart></div>\n" });
641
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.18", type: ChartBarComponent, isStandalone: true, selector: "ap-chart-bar", inputs: { categories: { classPropertyName: "categories", publicName: "categories", isSignal: true, isRequired: false, transformFunction: null }, opposite: { classPropertyName: "opposite", publicName: "opposite", isSignal: true, isRequired: false, transformFunction: null }, stacked: { classPropertyName: "stacked", publicName: "stacked", isSignal: true, isRequired: false, transformFunction: null }, series: { classPropertyName: "series", publicName: "series", isSignal: true, isRequired: false, transformFunction: null } }, host: { styleAttribute: "display: block" }, usesInheritance: true, ngImport: i0, template: '', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
729
642
  }
730
643
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: ChartBarComponent, decorators: [{
731
644
  type: Component,
732
- args: [{ selector: 'ap-chart-bar', standalone: true, template: "<div #chart></div>\n" }]
733
- }], propDecorators: { categories: [{
734
- type: Input
735
- }], opposite: [{
736
- type: Input
737
- }], stacked: [{
738
- type: Input
739
- }], series: [{
740
- type: Input
741
- }] } });
645
+ args: [{
646
+ selector: 'ap-chart-bar',
647
+ template: '',
648
+ host: { style: 'display: block' },
649
+ changeDetection: ChangeDetectionStrategy.OnPush,
650
+ }]
651
+ }], propDecorators: { categories: [{ type: i0.Input, args: [{ isSignal: true, alias: "categories", required: false }] }], opposite: [{ type: i0.Input, args: [{ isSignal: true, alias: "opposite", required: false }] }], stacked: [{ type: i0.Input, args: [{ isSignal: true, alias: "stacked", required: false }] }], series: [{ type: i0.Input, args: [{ isSignal: true, alias: "series", required: false }] }] } });
742
652
 
743
653
  class ChartColumnOptions extends ChartOptions {
744
654
  static buildColumn(options, stacked, locale) {
@@ -781,31 +691,30 @@ class ChartColumnOptions extends ChartOptions {
781
691
  }
782
692
 
783
693
  class ChartColumnComponent extends AbstractChartComponent {
784
- series = [];
785
694
  stacked = input(false, ...(ngDevMode ? [{ debugName: "stacked" }] : []));
786
- chartInitialized = new EventEmitter();
695
+ series = input([], ...(ngDevMode ? [{ debugName: "series" }] : []));
696
+ chartInitialized = output();
787
697
  initChart() {
788
- if (this.series) {
789
- const chartOptions = ChartColumnOptions.buildColumn(this.chartOptions, this.stacked(), this.locale);
790
- ChartColumnOptions.configure(this.series, chartOptions, this.color, this.labelDateFormat);
791
- this.chart = new Chart(this.chartRef.nativeElement, chartOptions);
792
- if (this.chart && this.stacked()) {
793
- ChartOptions.redrawWithHighestEdgesRounded(this.chart);
794
- }
795
- this.chartInitialized.emit(this.chart);
698
+ const options = ChartColumnOptions.buildColumn(this.chartOptions(), this.stacked(), this.locale());
699
+ ChartColumnOptions.configure(this.series(), options, this.color(), this.labelDateFormat());
700
+ this.chart = new Chart(this.hostElement, options);
701
+ if (this.stacked()) {
702
+ ChartOptions.redrawWithHighestEdgesRounded(this.chart);
796
703
  }
704
+ this.chartInitialized.emit(this.chart);
797
705
  }
798
706
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: ChartColumnComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
799
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.18", type: ChartColumnComponent, isStandalone: true, selector: "ap-chart-column", inputs: { series: { classPropertyName: "series", publicName: "series", isSignal: false, isRequired: false, transformFunction: null }, stacked: { classPropertyName: "stacked", publicName: "stacked", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { chartInitialized: "chartInitialized" }, usesInheritance: true, ngImport: i0, template: "<div #chart></div>\n" });
707
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.18", type: ChartColumnComponent, isStandalone: true, selector: "ap-chart-column", inputs: { stacked: { classPropertyName: "stacked", publicName: "stacked", isSignal: true, isRequired: false, transformFunction: null }, series: { classPropertyName: "series", publicName: "series", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { chartInitialized: "chartInitialized" }, host: { styleAttribute: "display: block" }, usesInheritance: true, ngImport: i0, template: '', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
800
708
  }
801
709
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: ChartColumnComponent, decorators: [{
802
710
  type: Component,
803
- args: [{ selector: 'ap-chart-column', standalone: true, template: "<div #chart></div>\n" }]
804
- }], propDecorators: { series: [{
805
- type: Input
806
- }], stacked: [{ type: i0.Input, args: [{ isSignal: true, alias: "stacked", required: false }] }], chartInitialized: [{
807
- type: Output
808
- }] } });
711
+ args: [{
712
+ selector: 'ap-chart-column',
713
+ template: '',
714
+ host: { style: 'display: block' },
715
+ changeDetection: ChangeDetectionStrategy.OnPush,
716
+ }]
717
+ }], propDecorators: { stacked: [{ type: i0.Input, args: [{ isSignal: true, alias: "stacked", required: false }] }], series: [{ type: i0.Input, args: [{ isSignal: true, alias: "series", required: false }] }], chartInitialized: [{ type: i0.Output, args: ["chartInitialized"] }] } });
809
718
 
810
719
  const HEATMAP_CONSTANTS = {
811
720
  CHART_HEIGHT: 680,
@@ -959,66 +868,28 @@ class ChartHeatmapOptions extends ChartOptions {
959
868
  }
960
869
 
961
870
  class ChartHeatmapComponent extends AbstractChartComponent {
962
- categoriesX = [];
963
- categoriesY = [];
964
- series = [];
871
+ categoriesX = input([], ...(ngDevMode ? [{ debugName: "categoriesX" }] : []));
872
+ categoriesY = input([], ...(ngDevMode ? [{ debugName: "categoriesY" }] : []));
873
+ series = input([], ...(ngDevMode ? [{ debugName: "series" }] : []));
965
874
  legendLabels = input(...(ngDevMode ? [undefined, { debugName: "legendLabels" }] : []));
966
- legendLabelsEffect = effect(() => {
967
- this.legendLabels();
968
- this.initChart();
969
- }, ...(ngDevMode ? [{ debugName: "legendLabelsEffect" }] : []));
970
875
  initChart() {
971
- if (this.series && this.chartRef) {
972
- const chartOptions = ChartHeatmapOptions.build(this.chartOptions, this.locale);
973
- ChartHeatmapOptions.configureHeatmap(this.categoriesX, this.categoriesY, this.series, chartOptions, this.color, this.legendLabels()?.least, this.legendLabels()?.most, this.labelDateFormat);
974
- mapChart(this.chartRef.nativeElement, chartOptions);
975
- }
876
+ const labels = this.legendLabels();
877
+ const options = ChartHeatmapOptions.build(this.chartOptions(), this.locale());
878
+ ChartHeatmapOptions.configureHeatmap(this.categoriesX(), this.categoriesY(), this.series(), options, this.color(), labels?.least, labels?.most, this.labelDateFormat());
879
+ this.chart = mapChart(this.hostElement, options);
976
880
  }
977
881
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: ChartHeatmapComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
978
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.18", type: ChartHeatmapComponent, isStandalone: true, selector: "ap-chart-heatmap", inputs: { categoriesX: { classPropertyName: "categoriesX", publicName: "categoriesX", isSignal: false, isRequired: false, transformFunction: null }, categoriesY: { classPropertyName: "categoriesY", publicName: "categoriesY", isSignal: false, isRequired: false, transformFunction: null }, series: { classPropertyName: "series", publicName: "series", isSignal: false, isRequired: false, transformFunction: null }, legendLabels: { classPropertyName: "legendLabels", publicName: "legendLabels", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: "<div #chart></div>\n" });
882
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.18", type: ChartHeatmapComponent, isStandalone: true, selector: "ap-chart-heatmap", inputs: { categoriesX: { classPropertyName: "categoriesX", publicName: "categoriesX", isSignal: true, isRequired: false, transformFunction: null }, categoriesY: { classPropertyName: "categoriesY", publicName: "categoriesY", isSignal: true, isRequired: false, transformFunction: null }, series: { classPropertyName: "series", publicName: "series", isSignal: true, isRequired: false, transformFunction: null }, legendLabels: { classPropertyName: "legendLabels", publicName: "legendLabels", isSignal: true, isRequired: false, transformFunction: null } }, host: { styleAttribute: "display: block" }, usesInheritance: true, ngImport: i0, template: '', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
979
883
  }
980
884
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: ChartHeatmapComponent, decorators: [{
981
885
  type: Component,
982
- args: [{ selector: 'ap-chart-heatmap', standalone: true, template: "<div #chart></div>\n" }]
983
- }], propDecorators: { categoriesX: [{
984
- type: Input
985
- }], categoriesY: [{
986
- type: Input
987
- }], series: [{
988
- type: Input
989
- }], legendLabels: [{ type: i0.Input, args: [{ isSignal: true, alias: "legendLabels", required: false }] }] } });
990
-
991
- var ChartMetricType;
992
- (function (ChartMetricType) {
993
- ChartMetricType[ChartMetricType["default"] = 0] = "default";
994
- ChartMetricType[ChartMetricType["total"] = 1] = "total";
995
- })(ChartMetricType || (ChartMetricType = {}));
996
- class ChartMetric {
997
- children;
998
- name = '';
999
- type;
1000
- value = 0;
1001
- }
1002
-
1003
- class ChartMetricsListComponent {
1004
- metrics = [];
1005
- locale = 'en';
1006
- ChartMetricType = ChartMetricType;
1007
- digitsInfo = '1.0-1';
1008
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: ChartMetricsListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1009
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.18", type: ChartMetricsListComponent, isStandalone: true, selector: "ap-chart-metrics-list", inputs: { metrics: "metrics", locale: "locale" }, ngImport: i0, template: "<mat-list>\n @if (metrics) {\n @for (metric of metrics; track metric; let i = $index) {\n <mat-list-item [ngClass]=\"{ 'chart-metric-total': metric.type === ChartMetricType.total }\">\n @if (!metric.children) {\n <div class=\"chart-metric-name metric-label\">\n {{ metric.name }}\n </div>\n }\n @if (metric.children) {\n <div class=\"chart-metric-name\">\n <span class=\"metric-label\">\n {{ metric.name }}\n </span>\n <span class=\"chart-metric-children\">\n @for (item of metric.children; track item) {\n <span>\n <span class=\"child-label\">{{ item.name }}</span>\n :\n <span class=\"child-value\">{{ item.value }}</span>\n </span>\n }\n </span>\n </div>\n }\n <div class=\"chart-metric-value metric-label\">\n {{ metric.value | number: digitsInfo : locale }}\n </div>\n </mat-list-item>\n }\n }\n</mat-list>\n", styles: ["[color=facebook]{color:#0866ff}[bgcolor=facebook],[hcolor=facebook]:hover{background-color:#0866ff}[border=facebook]{border:1px solid #0866ff}[color=google]{color:#4e85e8}[bgcolor=google],[hcolor=google]:hover{background-color:#4e85e8}[border=google]{border:1px solid #4e85e8}[color=instagram]{color:#e1306c}[bgcolor=instagram],[hcolor=instagram]:hover{background-color:#e1306c}[border=instagram]{border:1px solid #e1306c}[color=instagrammagenta]{color:#c13584}[bgcolor=instagrammagenta],[hcolor=instagrammagenta]:hover{background-color:#c13584}[border=instagrammagenta]{border:1px solid #c13584}[color=instagramblue]{color:#5851db}[bgcolor=instagramblue],[hcolor=instagramblue]:hover{background-color:#5851db}[border=instagramblue]{border:1px solid #5851db}[color=instagrampurple]{color:#833ab4}[bgcolor=instagrampurple],[hcolor=instagrampurple]:hover{background-color:#833ab4}[border=instagrampurple]{border:1px solid #833ab4}[color=instagramorange]{color:#f56040}[bgcolor=instagramorange],[hcolor=instagramorange]:hover{background-color:#f56040}[border=instagramorange]{border:1px solid #f56040}[color=instagramyellow]{color:#ffdc80}[bgcolor=instagramyellow],[hcolor=instagramyellow]:hover{background-color:#ffdc80}[border=instagramyellow]{border:1px solid #ffdc80}[color=linkedin]{color:#2c67bc}[bgcolor=linkedin],[hcolor=linkedin]:hover{background-color:#2c67bc}[border=linkedin]{border:1px solid #2c67bc}[color=twitter]{color:#55acee}[bgcolor=twitter],[hcolor=twitter]:hover{background-color:#55acee}[border=twitter]{border:1px solid #55acee}[color=youtube]{color:red}[bgcolor=youtube],[hcolor=youtube]:hover{background-color:red}[border=youtube]{border:1px solid #ff0000}[color=reddit]{color:#ff4500}[bgcolor=reddit],[hcolor=reddit]:hover{background-color:#ff4500}[border=reddit]{border:1px solid #ff4500}[color=blood-orange]{color:#ff4d00}[bgcolor=blood-orange],[hcolor=blood-orange]:hover{background-color:#ff4d00}[border=blood-orange]{border:1px solid #ff4d00}[color=pinkish-orange]{color:#ff7b49}[bgcolor=pinkish-orange],[hcolor=pinkish-orange]:hover{background-color:#ff7b49}[border=pinkish-orange]{border:1px solid #ff7b49}[color=charcoal-grey]{color:#2a2f34}[bgcolor=charcoal-grey],[hcolor=charcoal-grey]:hover{background-color:#2a2f34}[border=charcoal-grey]{border:1px solid #2a2f34}[color=azure]{color:#00aeef}[bgcolor=azure],[hcolor=azure]:hover{background-color:#00aeef}[border=azure]{border:1px solid #00aeef}[color=light-azure]{color:#eaf5fd}[bgcolor=light-azure],[hcolor=light-azure]:hover{background-color:#eaf5fd}[border=light-azure]{border:1px solid #eaf5fd}[color=blue-grey]{color:#8d98a9}[bgcolor=blue-grey],[hcolor=blue-grey]:hover{background-color:#8d98a9}[border=blue-grey]{border:1px solid #8d98a9}[color=silver]{color:#ced0da}[bgcolor=silver],[hcolor=silver]:hover{background-color:#ced0da}[border=silver]{border:1px solid #ced0da}[color=pale-grey]{color:#dfe3e9}[bgcolor=pale-grey],[hcolor=pale-grey]:hover{background-color:#dfe3e9}[border=pale-grey]{border:1px solid #dfe3e9}[color=grey-white]{color:#f5f7f8}[bgcolor=grey-white],[hcolor=grey-white]:hover{background-color:#f5f7f8}[border=grey-white]{border:1px solid #f5f7f8}[color=cool-grey]{color:#b4bbc6}[bgcolor=cool-grey],[hcolor=cool-grey]:hover{background-color:#b4bbc6}[border=cool-grey]{border:1px solid #b4bbc6}[color=black]{color:#344563}[bgcolor=black],[hcolor=black]:hover{background-color:#344563}[border=black]{border:1px solid #344563}[color=grey-blue]{color:#68768c}[bgcolor=grey-blue],[hcolor=grey-blue]:hover{background-color:#68768c}[border=grey-blue]{border:1px solid #68768c}[color=strawberry]{color:#f4282d}[bgcolor=strawberry],[hcolor=strawberry]:hover{background-color:#f4282d}[border=strawberry]{border:1px solid #f4282d}[color=light-strawberry]{color:#f8eded}[bgcolor=light-strawberry],[hcolor=light-strawberry]:hover{background-color:#f8eded}[border=light-strawberry]{border:1px solid #f8eded}[color=white]{color:#fff}[bgcolor=white],[hcolor=white]:hover{background-color:#fff}[border=white]{border:1px solid #ffffff}[color=cool-green]{color:#33c15d}[bgcolor=cool-green],[hcolor=cool-green]:hover{background-color:#33c15d}[border=cool-green]{border:1px solid #33c15d}[color=light-green]{color:#ebfaef}[bgcolor=light-green],[hcolor=light-green]:hover{background-color:#ebfaef}[border=light-green]{border:1px solid #ebfaef}[color=transparent]{color:transparent}[bgcolor=transparent],[hcolor=transparent]:hover{background-color:transparent}[border=transparent]{border:1px solid transparent}[color=c0]{color:#a566a5}[bgcolor=c0],[hcolor=c0]:hover{background-color:#a566a5}[border=c0]{border:1px solid #a566a5}[color=c1]{color:#c7ab82}[bgcolor=c1],[hcolor=c1]:hover{background-color:#c7ab82}[border=c1]{border:1px solid #c7ab82}[color=c2]{color:#f2713c}[bgcolor=c2],[hcolor=c2]:hover{background-color:#f2713c}[border=c2]{border:1px solid #f2713c}[color=c3]{color:#ffd006}[bgcolor=c3],[hcolor=c3]:hover{background-color:#ffd006}[border=c3]{border:1px solid #ffd006}[color=c4]{color:#94c5aa}[bgcolor=c4],[hcolor=c4]:hover{background-color:#94c5aa}[border=c4]{border:1px solid #94c5aa}[color=c5]{color:#2a9d8f}[bgcolor=c5],[hcolor=c5]:hover{background-color:#2a9d8f}[border=c5]{border:1px solid #2a9d8f}[color=c6]{color:#78acd8}[bgcolor=c6],[hcolor=c6]:hover{background-color:#78acd8}[border=c6]{border:1px solid #78acd8}[color=c7]{color:#525a9e}[bgcolor=c7],[hcolor=c7]:hover{background-color:#525a9e}[border=c7]{border:1px solid #525a9e}[color=c8]{color:#6a2459}[bgcolor=c8],[hcolor=c8]:hover{background-color:#6a2459}[border=c8]{border:1px solid #6a2459}[color=c9]{color:#74729e}[bgcolor=c9],[hcolor=c9]:hover{background-color:#74729e}[border=c9]{border:1px solid #74729e}.metric-label{font-size:14px;color:#5d6a82}.chart-metric-total .metric-label{font-size:16px;color:#344563!important;font-weight:700}.chart-metric-name .chart-metric-children{color:#aeb5c1;font-size:14px}.chart-metric-name .chart-metric-children .child-label{margin-left:16px}.chart-metric-value{justify-content:left;flex:1 0 0;flex-direction:row;text-align:end;color:#344563}.mat-mdc-list-item{height:35px}.mat-mdc-list-item ::ng-deep .mdc-list-item__content{padding:0}.mat-mdc-list-item ::ng-deep .mdc-list-item__content .mdc-list-item__primary-text{display:flex;align-items:center}.mat-mdc-list-item:not(:last-child){border-bottom:1px solid var(--sys-border-color-default)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: MatListModule }, { kind: "component", type: i2.MatList, selector: "mat-list", exportAs: ["matList"] }, { kind: "component", type: i2.MatListItem, selector: "mat-list-item, a[mat-list-item], button[mat-list-item]", inputs: ["activated"], exportAs: ["matListItem"] }, { kind: "ngmodule", type: MatDividerModule }, { kind: "pipe", type: i1.DecimalPipe, name: "number" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1010
- }
1011
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: ChartMetricsListComponent, decorators: [{
1012
- type: Component,
1013
- args: [{ changeDetection: ChangeDetectionStrategy.OnPush, selector: 'ap-chart-metrics-list', imports: [CommonModule, MatListModule, MatDividerModule], template: "<mat-list>\n @if (metrics) {\n @for (metric of metrics; track metric; let i = $index) {\n <mat-list-item [ngClass]=\"{ 'chart-metric-total': metric.type === ChartMetricType.total }\">\n @if (!metric.children) {\n <div class=\"chart-metric-name metric-label\">\n {{ metric.name }}\n </div>\n }\n @if (metric.children) {\n <div class=\"chart-metric-name\">\n <span class=\"metric-label\">\n {{ metric.name }}\n </span>\n <span class=\"chart-metric-children\">\n @for (item of metric.children; track item) {\n <span>\n <span class=\"child-label\">{{ item.name }}</span>\n :\n <span class=\"child-value\">{{ item.value }}</span>\n </span>\n }\n </span>\n </div>\n }\n <div class=\"chart-metric-value metric-label\">\n {{ metric.value | number: digitsInfo : locale }}\n </div>\n </mat-list-item>\n }\n }\n</mat-list>\n", styles: ["[color=facebook]{color:#0866ff}[bgcolor=facebook],[hcolor=facebook]:hover{background-color:#0866ff}[border=facebook]{border:1px solid #0866ff}[color=google]{color:#4e85e8}[bgcolor=google],[hcolor=google]:hover{background-color:#4e85e8}[border=google]{border:1px solid #4e85e8}[color=instagram]{color:#e1306c}[bgcolor=instagram],[hcolor=instagram]:hover{background-color:#e1306c}[border=instagram]{border:1px solid #e1306c}[color=instagrammagenta]{color:#c13584}[bgcolor=instagrammagenta],[hcolor=instagrammagenta]:hover{background-color:#c13584}[border=instagrammagenta]{border:1px solid #c13584}[color=instagramblue]{color:#5851db}[bgcolor=instagramblue],[hcolor=instagramblue]:hover{background-color:#5851db}[border=instagramblue]{border:1px solid #5851db}[color=instagrampurple]{color:#833ab4}[bgcolor=instagrampurple],[hcolor=instagrampurple]:hover{background-color:#833ab4}[border=instagrampurple]{border:1px solid #833ab4}[color=instagramorange]{color:#f56040}[bgcolor=instagramorange],[hcolor=instagramorange]:hover{background-color:#f56040}[border=instagramorange]{border:1px solid #f56040}[color=instagramyellow]{color:#ffdc80}[bgcolor=instagramyellow],[hcolor=instagramyellow]:hover{background-color:#ffdc80}[border=instagramyellow]{border:1px solid #ffdc80}[color=linkedin]{color:#2c67bc}[bgcolor=linkedin],[hcolor=linkedin]:hover{background-color:#2c67bc}[border=linkedin]{border:1px solid #2c67bc}[color=twitter]{color:#55acee}[bgcolor=twitter],[hcolor=twitter]:hover{background-color:#55acee}[border=twitter]{border:1px solid #55acee}[color=youtube]{color:red}[bgcolor=youtube],[hcolor=youtube]:hover{background-color:red}[border=youtube]{border:1px solid #ff0000}[color=reddit]{color:#ff4500}[bgcolor=reddit],[hcolor=reddit]:hover{background-color:#ff4500}[border=reddit]{border:1px solid #ff4500}[color=blood-orange]{color:#ff4d00}[bgcolor=blood-orange],[hcolor=blood-orange]:hover{background-color:#ff4d00}[border=blood-orange]{border:1px solid #ff4d00}[color=pinkish-orange]{color:#ff7b49}[bgcolor=pinkish-orange],[hcolor=pinkish-orange]:hover{background-color:#ff7b49}[border=pinkish-orange]{border:1px solid #ff7b49}[color=charcoal-grey]{color:#2a2f34}[bgcolor=charcoal-grey],[hcolor=charcoal-grey]:hover{background-color:#2a2f34}[border=charcoal-grey]{border:1px solid #2a2f34}[color=azure]{color:#00aeef}[bgcolor=azure],[hcolor=azure]:hover{background-color:#00aeef}[border=azure]{border:1px solid #00aeef}[color=light-azure]{color:#eaf5fd}[bgcolor=light-azure],[hcolor=light-azure]:hover{background-color:#eaf5fd}[border=light-azure]{border:1px solid #eaf5fd}[color=blue-grey]{color:#8d98a9}[bgcolor=blue-grey],[hcolor=blue-grey]:hover{background-color:#8d98a9}[border=blue-grey]{border:1px solid #8d98a9}[color=silver]{color:#ced0da}[bgcolor=silver],[hcolor=silver]:hover{background-color:#ced0da}[border=silver]{border:1px solid #ced0da}[color=pale-grey]{color:#dfe3e9}[bgcolor=pale-grey],[hcolor=pale-grey]:hover{background-color:#dfe3e9}[border=pale-grey]{border:1px solid #dfe3e9}[color=grey-white]{color:#f5f7f8}[bgcolor=grey-white],[hcolor=grey-white]:hover{background-color:#f5f7f8}[border=grey-white]{border:1px solid #f5f7f8}[color=cool-grey]{color:#b4bbc6}[bgcolor=cool-grey],[hcolor=cool-grey]:hover{background-color:#b4bbc6}[border=cool-grey]{border:1px solid #b4bbc6}[color=black]{color:#344563}[bgcolor=black],[hcolor=black]:hover{background-color:#344563}[border=black]{border:1px solid #344563}[color=grey-blue]{color:#68768c}[bgcolor=grey-blue],[hcolor=grey-blue]:hover{background-color:#68768c}[border=grey-blue]{border:1px solid #68768c}[color=strawberry]{color:#f4282d}[bgcolor=strawberry],[hcolor=strawberry]:hover{background-color:#f4282d}[border=strawberry]{border:1px solid #f4282d}[color=light-strawberry]{color:#f8eded}[bgcolor=light-strawberry],[hcolor=light-strawberry]:hover{background-color:#f8eded}[border=light-strawberry]{border:1px solid #f8eded}[color=white]{color:#fff}[bgcolor=white],[hcolor=white]:hover{background-color:#fff}[border=white]{border:1px solid #ffffff}[color=cool-green]{color:#33c15d}[bgcolor=cool-green],[hcolor=cool-green]:hover{background-color:#33c15d}[border=cool-green]{border:1px solid #33c15d}[color=light-green]{color:#ebfaef}[bgcolor=light-green],[hcolor=light-green]:hover{background-color:#ebfaef}[border=light-green]{border:1px solid #ebfaef}[color=transparent]{color:transparent}[bgcolor=transparent],[hcolor=transparent]:hover{background-color:transparent}[border=transparent]{border:1px solid transparent}[color=c0]{color:#a566a5}[bgcolor=c0],[hcolor=c0]:hover{background-color:#a566a5}[border=c0]{border:1px solid #a566a5}[color=c1]{color:#c7ab82}[bgcolor=c1],[hcolor=c1]:hover{background-color:#c7ab82}[border=c1]{border:1px solid #c7ab82}[color=c2]{color:#f2713c}[bgcolor=c2],[hcolor=c2]:hover{background-color:#f2713c}[border=c2]{border:1px solid #f2713c}[color=c3]{color:#ffd006}[bgcolor=c3],[hcolor=c3]:hover{background-color:#ffd006}[border=c3]{border:1px solid #ffd006}[color=c4]{color:#94c5aa}[bgcolor=c4],[hcolor=c4]:hover{background-color:#94c5aa}[border=c4]{border:1px solid #94c5aa}[color=c5]{color:#2a9d8f}[bgcolor=c5],[hcolor=c5]:hover{background-color:#2a9d8f}[border=c5]{border:1px solid #2a9d8f}[color=c6]{color:#78acd8}[bgcolor=c6],[hcolor=c6]:hover{background-color:#78acd8}[border=c6]{border:1px solid #78acd8}[color=c7]{color:#525a9e}[bgcolor=c7],[hcolor=c7]:hover{background-color:#525a9e}[border=c7]{border:1px solid #525a9e}[color=c8]{color:#6a2459}[bgcolor=c8],[hcolor=c8]:hover{background-color:#6a2459}[border=c8]{border:1px solid #6a2459}[color=c9]{color:#74729e}[bgcolor=c9],[hcolor=c9]:hover{background-color:#74729e}[border=c9]{border:1px solid #74729e}.metric-label{font-size:14px;color:#5d6a82}.chart-metric-total .metric-label{font-size:16px;color:#344563!important;font-weight:700}.chart-metric-name .chart-metric-children{color:#aeb5c1;font-size:14px}.chart-metric-name .chart-metric-children .child-label{margin-left:16px}.chart-metric-value{justify-content:left;flex:1 0 0;flex-direction:row;text-align:end;color:#344563}.mat-mdc-list-item{height:35px}.mat-mdc-list-item ::ng-deep .mdc-list-item__content{padding:0}.mat-mdc-list-item ::ng-deep .mdc-list-item__content .mdc-list-item__primary-text{display:flex;align-items:center}.mat-mdc-list-item:not(:last-child){border-bottom:1px solid var(--sys-border-color-default)}\n"] }]
1014
- }], propDecorators: { metrics: [{
1015
- type: Input,
1016
- args: [{
1017
- required: true,
1018
- }]
1019
- }], locale: [{
1020
- type: Input
1021
- }] } });
886
+ args: [{
887
+ selector: 'ap-chart-heatmap',
888
+ template: '',
889
+ host: { style: 'display: block' },
890
+ changeDetection: ChangeDetectionStrategy.OnPush,
891
+ }]
892
+ }], propDecorators: { categoriesX: [{ type: i0.Input, args: [{ isSignal: true, alias: "categoriesX", required: false }] }], categoriesY: [{ type: i0.Input, args: [{ isSignal: true, alias: "categoriesY", required: false }] }], series: [{ type: i0.Input, args: [{ isSignal: true, alias: "series", required: false }] }], legendLabels: [{ type: i0.Input, args: [{ isSignal: true, alias: "legendLabels", required: false }] }] } });
1022
893
 
1023
894
  class ChartMixedOptions extends ChartOptions {
1024
895
  static buildMixed(options, singleDayEnabled, locale) {
@@ -1061,31 +932,33 @@ class ChartMixedOptions extends ChartOptions {
1061
932
  }
1062
933
 
1063
934
  class ChartMixedComponent extends AbstractChartComponent {
1064
- series = [];
935
+ series = input([], ...(ngDevMode ? [{ debugName: "series" }] : []));
1065
936
  initChart() {
1066
- if (this.series) {
1067
- const singleDayEnabled = this.series.find(serie => serie.type === 'spline')?.data?.length === 1;
1068
- const chartOptions = ChartMixedOptions.buildMixed(this.chartOptions, singleDayEnabled, this.locale);
1069
- ChartMixedOptions.configure(this.series, chartOptions, this.color, this.labelDateFormat);
1070
- this.chart = new Chart(this.chartRef.nativeElement, chartOptions);
1071
- if (this.chart) {
1072
- ChartOptions.redrawWithHighestEdgesRounded(this.chart);
1073
- }
1074
- }
937
+ const series = this.series();
938
+ const splineSeries = series.find(serie => serie.type === 'spline');
939
+ const singleDayEnabled = splineSeries?.data?.length === 1;
940
+ const options = ChartMixedOptions.buildMixed(this.chartOptions(), singleDayEnabled, this.locale());
941
+ ChartMixedOptions.configure(series, options, this.color(), this.labelDateFormat());
942
+ this.chart = new Chart(this.hostElement, options);
943
+ ChartOptions.redrawWithHighestEdgesRounded(this.chart);
1075
944
  }
1076
945
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: ChartMixedComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1077
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: ChartMixedComponent, isStandalone: true, selector: "ap-chart-mixed", inputs: { series: "series" }, usesInheritance: true, ngImport: i0, template: "<div #chart></div>\n" });
946
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.18", type: ChartMixedComponent, isStandalone: true, selector: "ap-chart-mixed", inputs: { series: { classPropertyName: "series", publicName: "series", isSignal: true, isRequired: false, transformFunction: null } }, host: { styleAttribute: "display: block" }, usesInheritance: true, ngImport: i0, template: '', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
1078
947
  }
1079
948
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: ChartMixedComponent, decorators: [{
1080
949
  type: Component,
1081
- args: [{ selector: 'ap-chart-mixed', standalone: true, template: "<div #chart></div>\n" }]
1082
- }], propDecorators: { series: [{
1083
- type: Input
1084
- }] } });
950
+ args: [{
951
+ selector: 'ap-chart-mixed',
952
+ template: '',
953
+ host: { style: 'display: block' },
954
+ changeDetection: ChangeDetectionStrategy.OnPush,
955
+ }]
956
+ }], propDecorators: { series: [{ type: i0.Input, args: [{ isSignal: true, alias: "series", required: false }] }] } });
1085
957
 
1086
958
  const NAME_MAX_LENGTH = 30;
1087
- const RIGHT_TO_LEFT_CHARACTERS = /[\p{Script=Arabic}\p{Script=Hebrew}\p{Script=Syriac}\p{Script=Thaana}\p{Script=Nko}\p{Script=Samaritan}\p{Script=Mandaic}]/u; // Hebrew, Arabic, and other RTL characters
1088
- const RIGHT_TO_LEFT_EMBEDDING_CHARACTER = '\u202B'; // Right-to-left embedding character
959
+ // Hebrew, Arabic, and other RTL scripts
960
+ const RIGHT_TO_LEFT_CHARACTERS = /[\p{Script=Arabic}\p{Script=Hebrew}\p{Script=Syriac}\p{Script=Thaana}\p{Script=Nko}\p{Script=Samaritan}\p{Script=Mandaic}]/u;
961
+ const RIGHT_TO_LEFT_EMBEDDING_CHARACTER = '‫';
1089
962
  class ChartPieOptions extends ChartOptions {
1090
963
  static buildPie(options, innerLabels, metricFormat, locale) {
1091
964
  const defaultPieOptions = {
@@ -1105,51 +978,14 @@ class ChartPieOptions extends ChartOptions {
1105
978
  },
1106
979
  series: {
1107
980
  allowPointSelect: !innerLabels,
1108
- dataLabels: innerLabels
1109
- ? {
1110
- format: metricFormat === 'percentage' ? '{point.percentage:.1f}%' : '{point.y}',
1111
- style: {
1112
- fontSize: '16px',
1113
- color: 'white',
1114
- textOutline: '0',
1115
- },
1116
- }
1117
- : {
1118
- formatter: function () {
1119
- const name = this.name.length > NAME_MAX_LENGTH
1120
- ? this.name.substring(0, NAME_MAX_LENGTH) + '...'
1121
- : this.name;
1122
- const displayValue = metricFormat === 'percentage'
1123
- ? numberFormat(Math.round((this.percentage ?? 0) * 10) / 10, -1) + '%'
1124
- : numberFormat(this.y ?? 0, -1);
1125
- // Add right-to-left embedding character only if the first character is a right-to-left character
1126
- const prefix = RIGHT_TO_LEFT_CHARACTERS.test(this.name.charAt(0))
1127
- ? RIGHT_TO_LEFT_EMBEDDING_CHARACTER
1128
- : '';
1129
- return prefix + name + ': ' + displayValue;
1130
- },
1131
- style: {
1132
- fontSize: '12px',
1133
- color: ChartColors.GREY_COLORS[60],
1134
- },
1135
- },
981
+ dataLabels: innerLabels ? buildInnerLabels(metricFormat) : buildOuterLabels(metricFormat),
1136
982
  showInLegend: innerLabels,
1137
- states: {
1138
- inactive: {
1139
- opacity: 1,
1140
- },
1141
- },
1142
983
  },
1143
984
  },
1144
985
  tooltip: {
1145
986
  outside: true,
1146
987
  },
1147
- legend: innerLabels
1148
- ? {
1149
- symbolHeight: 10,
1150
- enabled: true,
1151
- }
1152
- : {},
988
+ legend: innerLabels ? { symbolHeight: 10, enabled: true } : {},
1153
989
  };
1154
990
  return super.build(mergeDeep(defaultPieOptions, options), locale);
1155
991
  }
@@ -1158,159 +994,83 @@ class ChartPieOptions extends ChartOptions {
1158
994
  if (innerLabels && options.legend) {
1159
995
  options.legend.enabled = true;
1160
996
  }
1161
- if (series && series.length > 0 && series[0]) {
1162
- options.colors = colors;
1163
- if (mouseEventEnabled && options.plotOptions?.pie) {
1164
- this.resetColors(series[0].data, innerLabels);
1165
- options.plotOptions.pie.point ??= {};
1166
- options.plotOptions.pie.point.events ??= {};
1167
- options.plotOptions.pie.events ??= {};
1168
- this.configureEnteringASlice(options, innerLabels);
1169
- this.configureLeavingASlice(options, innerLabels);
1170
- this.configureLeavingTheWholePie(options, innerLabels);
1171
- }
1172
- }
1173
- }
1174
- static resetColors(points, innerLabels) {
1175
- points?.forEach(point => {
1176
- delete point?.color;
1177
- if (innerLabels) {
1178
- delete point.dataLabels?.style?.color;
1179
- }
1180
- });
1181
- }
1182
- static configureEnteringASlice(options, innerLabels) {
1183
- if (options.plotOptions?.pie?.point?.events) {
1184
- options.plotOptions.pie.point.events.mouseOver = function () {
1185
- this.series.chart.series[0].points.forEach(point => {
1186
- if (point.index !== this.index) {
1187
- point.update({
1188
- color: ChartColors.GREY_COLORS[5],
1189
- }, false);
1190
- if (innerLabels) {
1191
- point.update({
1192
- dataLabels: {
1193
- style: {
1194
- color: ChartColors.GREY_COLORS[20],
1195
- },
1196
- },
1197
- }, false);
1198
- }
1199
- }
1200
- });
1201
- this.series.chart.redraw(false);
1202
- };
1203
- }
1204
- }
1205
- static configureLeavingASlice(options, innerLabels) {
1206
- if (options.plotOptions?.pie?.point?.events) {
1207
- options.plotOptions.pie.point.events.mouseOut = function () {
1208
- this.series.chart.series[0].points.forEach((point, i) => {
1209
- if (point.index !== this.index) {
1210
- point.update({
1211
- color: options.colors?.[i % options.colors.length],
1212
- }, false);
1213
- if (innerLabels) {
1214
- point.update({
1215
- dataLabels: {
1216
- style: {
1217
- color: 'white',
1218
- },
1219
- },
1220
- }, false);
1221
- }
1222
- }
1223
- });
1224
- };
997
+ if (!series?.[0]) {
998
+ return;
1225
999
  }
1226
- }
1227
- static configureLeavingTheWholePie(options, innerLabels) {
1228
- if (options.plotOptions?.pie?.events) {
1229
- options.plotOptions.pie.events.mouseOut = function () {
1230
- this.chart.series[0].points.forEach((point, i) => {
1231
- point.update({
1232
- color: options.colors?.[i % options.colors.length],
1233
- }, false);
1234
- if (innerLabels) {
1235
- point.update({
1236
- dataLabels: {
1237
- style: {
1238
- color: 'white',
1239
- },
1240
- },
1241
- }, false);
1242
- }
1243
- });
1244
- this.chart.redraw();
1245
- };
1000
+ options.colors = colors;
1001
+ // When mouse interaction is disabled (e.g. half-donut summary), turn off hover/tooltip
1002
+ // wholesale. Otherwise we rely on Highcharts' default `states.inactive.opacity` (0.2)
1003
+ // to fade non-hovered slices — see https://api.highcharts.com/highcharts/plotOptions.pie.states.inactive
1004
+ if (!mouseEventEnabled) {
1005
+ options.plotOptions ??= {};
1006
+ options.plotOptions.pie ??= {};
1007
+ options.plotOptions.pie.enableMouseTracking = false;
1246
1008
  }
1247
1009
  }
1248
1010
  }
1011
+ function buildInnerLabels(metricFormat) {
1012
+ return {
1013
+ format: metricFormat === 'percentage' ? '{point.percentage:.1f}%' : '{point.y}',
1014
+ style: {
1015
+ fontSize: '16px',
1016
+ color: 'white',
1017
+ textOutline: '0',
1018
+ },
1019
+ };
1020
+ }
1021
+ function buildOuterLabels(metricFormat) {
1022
+ return {
1023
+ formatter() {
1024
+ const truncatedName = this.name.length > NAME_MAX_LENGTH ? this.name.substring(0, NAME_MAX_LENGTH) + '...' : this.name;
1025
+ const displayValue = metricFormat === 'percentage' ? numberFormat(round(this.percentage ?? 0, 1), -1) + '%' : numberFormat(this.y ?? 0, -1);
1026
+ const prefix = RIGHT_TO_LEFT_CHARACTERS.test(this.name.charAt(0)) ? RIGHT_TO_LEFT_EMBEDDING_CHARACTER : '';
1027
+ return prefix + truncatedName + ': ' + displayValue;
1028
+ },
1029
+ style: {
1030
+ fontSize: '12px',
1031
+ color: ChartColors.GREY_COLORS[60],
1032
+ },
1033
+ };
1034
+ }
1249
1035
 
1250
1036
  class ChartPieComponent extends AbstractChartComponent {
1251
- innerLabels = false;
1252
- mouseEventEnabled = true;
1253
- series = [];
1037
+ innerLabels = input(false, ...(ngDevMode ? [{ debugName: "innerLabels" }] : []));
1038
+ mouseEventEnabled = input(true, ...(ngDevMode ? [{ debugName: "mouseEventEnabled" }] : []));
1039
+ series = input([], ...(ngDevMode ? [{ debugName: "series" }] : []));
1254
1040
  colors = input(...(ngDevMode ? [undefined, { debugName: "colors" }] : []));
1255
1041
  metricFormat = input('percentage', ...(ngDevMode ? [{ debugName: "metricFormat" }] : []));
1256
- domReady = signal(false, ...(ngDevMode ? [{ debugName: "domReady" }] : []));
1257
- constructor() {
1258
- super();
1259
- effect(() => {
1260
- if (this.domReady()) {
1261
- this.colors();
1262
- this.initChart();
1263
- }
1264
- });
1265
- afterNextRender(() => {
1266
- this.domReady.set(true);
1267
- });
1268
- }
1269
1042
  initChart() {
1270
- if (this.series) {
1271
- const dataAvailable = this.series[0]?.data && this.series[0].data.length > 0;
1272
- const chartOptions = ChartPieOptions.buildPie(this.chartOptions, this.innerLabels, this.metricFormat(), this.locale);
1273
- // Add placeholder series when there's no data
1274
- const updatedSeries = dataAvailable
1275
- ? this.series
1276
- : [
1277
- {
1278
- type: 'pie',
1279
- data: [
1280
- {
1281
- y: 1,
1282
- dataLabels: {
1283
- enabled: false,
1284
- },
1285
- },
1286
- ],
1287
- enableMouseTracking: false,
1288
- },
1289
- ];
1290
- let colors = this.colors();
1291
- if (!dataAvailable) {
1292
- colors = [ChartColors.GREY_COLORS[10]];
1293
- }
1294
- else if (!colors?.length) {
1295
- colors = ChartColors.getColors(this.series[0]?.data?.length ?? 0, this.color);
1296
- }
1297
- ChartPieOptions.configurePie(updatedSeries, chartOptions, colors, this.labelDateFormat, this.innerLabels, this.mouseEventEnabled);
1298
- this.chart = new Chart(this.chartRef.nativeElement, chartOptions);
1299
- }
1043
+ const series = this.series();
1044
+ const innerLabels = this.innerLabels();
1045
+ const dataAvailable = !!series[0]?.data?.length;
1046
+ const options = ChartPieOptions.buildPie(this.chartOptions(), innerLabels, this.metricFormat(), this.locale());
1047
+ const effectiveSeries = dataAvailable
1048
+ ? series
1049
+ : [
1050
+ {
1051
+ type: 'pie',
1052
+ data: [{ y: 1, dataLabels: { enabled: false } }],
1053
+ enableMouseTracking: false,
1054
+ },
1055
+ ];
1056
+ const effectiveColors = !dataAvailable
1057
+ ? [ChartColors.GREY_COLORS[10]]
1058
+ : (this.colors() ?? ChartColors.getColors(series[0]?.data?.length ?? 0, this.color()));
1059
+ ChartPieOptions.configurePie(effectiveSeries, options, effectiveColors, this.labelDateFormat(), innerLabels, this.mouseEventEnabled());
1060
+ this.chart = new Chart(this.hostElement, options);
1300
1061
  }
1301
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: ChartPieComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1302
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.18", type: ChartPieComponent, isStandalone: true, selector: "ap-chart-pie", inputs: { innerLabels: { classPropertyName: "innerLabels", publicName: "innerLabels", isSignal: false, isRequired: false, transformFunction: null }, mouseEventEnabled: { classPropertyName: "mouseEventEnabled", publicName: "mouseEventEnabled", isSignal: false, isRequired: false, transformFunction: null }, series: { classPropertyName: "series", publicName: "series", isSignal: false, isRequired: false, transformFunction: null }, colors: { classPropertyName: "colors", publicName: "colors", isSignal: true, isRequired: false, transformFunction: null }, metricFormat: { classPropertyName: "metricFormat", publicName: "metricFormat", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: "<div #chart></div>\n" });
1062
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: ChartPieComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1063
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.18", type: ChartPieComponent, isStandalone: true, selector: "ap-chart-pie", inputs: { innerLabels: { classPropertyName: "innerLabels", publicName: "innerLabels", isSignal: true, isRequired: false, transformFunction: null }, mouseEventEnabled: { classPropertyName: "mouseEventEnabled", publicName: "mouseEventEnabled", isSignal: true, isRequired: false, transformFunction: null }, series: { classPropertyName: "series", publicName: "series", isSignal: true, isRequired: false, transformFunction: null }, colors: { classPropertyName: "colors", publicName: "colors", isSignal: true, isRequired: false, transformFunction: null }, metricFormat: { classPropertyName: "metricFormat", publicName: "metricFormat", isSignal: true, isRequired: false, transformFunction: null } }, host: { styleAttribute: "display: block" }, usesInheritance: true, ngImport: i0, template: '', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
1303
1064
  }
1304
1065
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: ChartPieComponent, decorators: [{
1305
1066
  type: Component,
1306
- args: [{ selector: 'ap-chart-pie', standalone: true, template: "<div #chart></div>\n" }]
1307
- }], ctorParameters: () => [], propDecorators: { innerLabels: [{
1308
- type: Input
1309
- }], mouseEventEnabled: [{
1310
- type: Input
1311
- }], series: [{
1312
- type: Input
1313
- }], colors: [{ type: i0.Input, args: [{ isSignal: true, alias: "colors", required: false }] }], metricFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "metricFormat", required: false }] }] } });
1067
+ args: [{
1068
+ selector: 'ap-chart-pie',
1069
+ template: '',
1070
+ host: { style: 'display: block' },
1071
+ changeDetection: ChangeDetectionStrategy.OnPush,
1072
+ }]
1073
+ }], propDecorators: { innerLabels: [{ type: i0.Input, args: [{ isSignal: true, alias: "innerLabels", required: false }] }], mouseEventEnabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "mouseEventEnabled", required: false }] }], series: [{ type: i0.Input, args: [{ isSignal: true, alias: "series", required: false }] }], colors: [{ type: i0.Input, args: [{ isSignal: true, alias: "colors", required: false }] }], metricFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "metricFormat", required: false }] }] } });
1314
1074
 
1315
1075
  class ChartSplineOptions extends ChartOptions {
1316
1076
  static buildSpline(options, singleDayEnabled, locale) {
@@ -1337,36 +1097,34 @@ class ChartSplineOptions extends ChartOptions {
1337
1097
  }
1338
1098
 
1339
1099
  class ChartSplineComponent extends AbstractChartComponent {
1340
- series = [];
1341
- chartInitialized = new EventEmitter();
1100
+ series = input([], ...(ngDevMode ? [{ debugName: "series" }] : []));
1101
+ chartInitialized = output();
1342
1102
  initChart() {
1343
- if (this.series) {
1344
- const chartOptions = ChartSplineOptions.buildSpline(this.chartOptions, this.series[0]?.data?.length === 1, this.locale);
1345
- ChartSplineOptions.configure(this.series, chartOptions, this.color, this.labelDateFormat);
1346
- this.chart = new Chart(this.chartRef.nativeElement, chartOptions);
1347
- this.chartInitialized.emit(this.chart);
1348
- }
1103
+ const series = this.series();
1104
+ const singleDayEnabled = series[0]?.data?.length === 1;
1105
+ const options = ChartSplineOptions.buildSpline(this.chartOptions(), singleDayEnabled, this.locale());
1106
+ ChartSplineOptions.configure(series, options, this.color(), this.labelDateFormat());
1107
+ this.chart = new Chart(this.hostElement, options);
1108
+ this.chartInitialized.emit(this.chart);
1349
1109
  }
1350
1110
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: ChartSplineComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1351
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: ChartSplineComponent, isStandalone: true, selector: "ap-chart-spline", inputs: { series: "series" }, outputs: { chartInitialized: "chartInitialized" }, usesInheritance: true, ngImport: i0, template: "<div #chart></div>\n" });
1111
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.18", type: ChartSplineComponent, isStandalone: true, selector: "ap-chart-spline", inputs: { series: { classPropertyName: "series", publicName: "series", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { chartInitialized: "chartInitialized" }, host: { styleAttribute: "display: block" }, usesInheritance: true, ngImport: i0, template: '', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
1352
1112
  }
1353
1113
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: ChartSplineComponent, decorators: [{
1354
1114
  type: Component,
1355
- args: [{ selector: 'ap-chart-spline', standalone: true, template: "<div #chart></div>\n" }]
1356
- }], propDecorators: { series: [{
1357
- type: Input
1358
- }], chartInitialized: [{
1359
- type: Output
1360
- }] } });
1115
+ args: [{
1116
+ selector: 'ap-chart-spline',
1117
+ template: '',
1118
+ host: { style: 'display: block' },
1119
+ changeDetection: ChangeDetectionStrategy.OnPush,
1120
+ }]
1121
+ }], propDecorators: { series: [{ type: i0.Input, args: [{ isSignal: true, alias: "series", required: false }] }], chartInitialized: [{ type: i0.Output, args: ["chartInitialized"] }] } });
1361
1122
 
1362
- /*
1363
- * Public API Surface of ui-charts
1364
- */
1365
1123
  borderRadiusPlugin(Highcharts);
1366
1124
 
1367
1125
  /**
1368
1126
  * Generated bundle index. Do not edit.
1369
1127
  */
1370
1128
 
1371
- export { AbstractChartComponent, ChartBarComponent, ChartColor, ChartColors, ChartColumnComponent, ChartHeatmapComponent, ChartMetric, ChartMetricType, ChartMetricsListComponent, ChartMixedComponent, ChartOptions, ChartPieComponent, ChartSplineComponent, borderRadiusPlugin, mergeDeep };
1129
+ export { AbstractChartComponent, ChartBarComponent, ChartColor, ChartColors, ChartColumnComponent, ChartHeatmapComponent, ChartMixedComponent, ChartOptions, ChartPieComponent, ChartSplineComponent, borderRadiusPlugin, mergeDeep };
1372
1130
  //# sourceMappingURL=agorapulse-ui-charts.mjs.map