@tapsellorg/angular-material-library
Version:
Angular library for Tapsell
740 lines (727 loc) • 73.1 kB
JavaScript
import * as i1 from '@angular/common';
import { getCurrencySymbol, CommonModule, DecimalPipe, PercentPipe, CurrencyPipe } from '@angular/common';
import * as i0 from '@angular/core';
import { signal, Injectable, InjectionToken, Inject, input, Optional, ViewEncapsulation, Component, model, ViewChild, inject, Directive, output, ContentChild, ContentChildren, DEFAULT_CURRENCY_CODE, LOCALE_ID, NgModule } from '@angular/core';
import { ObserversModule } from '@angular/cdk/observers';
import * as i4 from 'highcharts-angular';
import { HighchartsChartModule } from 'highcharts-angular';
import * as i2 from '@tapsellorg/angular-material-library/src/lib/help-indicator';
import { PghHelpIndicatorModule } from '@tapsellorg/angular-material-library/src/lib/help-indicator';
import Highcharts from 'highcharts';
import { ObjectUtils, MiscUtils, withDestroy, StringUtils } from '@tapsellorg/angular-material-library/src/lib/common';
import highchartsMap from 'highcharts/modules/map';
import { DateUtils } from '@tapsellorg/angular-material-library/src/lib/jalali-date-adapter';
import { ReplaySubject } from 'rxjs';
import * as i5 from '@tapsellorg/angular-material-library/src/lib/translate';
import { TranslateModule } from '@tapsellorg/angular-material-library/src/lib/translate';
import iranMap from '@highcharts/map-collection/countries/ir/ir-all.geo.json';
import { PghFilterChipsComponent } from '@tapsellorg/angular-material-library/src/lib/filter-chips';
import { takeUntil, distinctUntilChanged, debounceTime } from 'rxjs/operators';
import * as i4$1 from '@angular/material/icon';
import { MatIconModule } from '@angular/material/icon';
import * as i1$1 from '@angular/material/core';
import { MatRippleModule } from '@angular/material/core';
highchartsMap(Highcharts);
class ChartParent {
constructor() {
this.highcharts = Highcharts;
this.tooltip = signal(null);
}
get hasNoData() {
return (!this.series()?.length ||
(this.series().length === 1 && !this.series()[0].data?.length) ||
this.series() === this.CHART_PLACEHOLDER_SERIES);
}
getChartSeriesColor(index) {
const activeStatBoxes = this.statBoxService?.activeStatBoxes;
if (!activeStatBoxes || activeStatBoxes.length !== this.series()?.length) {
return this.chartColorsService.getChartSeriesColor(index);
}
return activeStatBoxes[index].color;
}
getChartSeries() {
if (this.hasNoData) {
return this.CHART_PLACEHOLDER_SERIES;
}
return (this.series() ?? []).map((s, i) => ({
...s,
type: s.type ?? this.defaultSeriesType(),
data: s.data.slice(),
color: this.getChartSeriesColor(i),
}));
}
createChartOptions(customOptions) {
const tooltipFormatter = this.getTooltipFormatter();
const series = this.getChartSeries();
return ObjectUtils.mergeDeep({
chart: {
backgroundColor: 'var(--fff)',
style: {
fontFamily: 'inherit',
},
},
colors: this.chartColorsService.chartColors,
title: { text: undefined },
credits: { enabled: false },
tooltip: {
borderWidth: 0,
backgroundColor: '',
useHTML: true,
formatter() {
return tooltipFormatter(this);
},
shared: true,
},
legend: {
itemStyle: {
cursor: 'pointer',
'font-size': '12px',
'font-weight': 'bold',
color: 'var(--000)',
fill: 'var(--000)',
},
},
series,
}, customOptions, this.userCustomChartOptions());
}
getTooltipFormatter() {
if (typeof this.tooltip() === 'function') {
return this.chartTooltipService.wrapTemplateOnFormatter(this.tooltip(), this.series());
}
else {
return this.chartTooltipService.wrapTemplateOnFormatter(this.chartTooltipService.getPredefinedFormatter(this.tooltip() ?? 'number'), this.series());
}
}
}
class PghChartTooltipService {
constructor(currencyPipe, percentPipe, decimalPipe) {
this.currencyPipe = currencyPipe;
this.percentPipe = percentPipe;
this.decimalPipe = decimalPipe;
//
// ***
// The followings are formatter util functions. They just get a point and format it
// ***
//
this.tooltipTemplate = (y, x, data) => {
const yAxisValuesTemplate = (data.points || [data])
.map((point, i) => `<div class="pgh-chart-tooltip-point">
<span>${y[i] || ''}</span>
<span class="pgh-chart-tooltip-point-indicator ms-1" style="--series-color:${point.color}"></span>
</div>`)
.join('');
return `<div class="pgh-highcharts-tooltip">
<div class="pgh-highcharts-tooltip-values">${yAxisValuesTemplate}</div>
<div class="tooltip-x" dir="auto">${x}</div>
</div>`;
};
// TODO: 'y' property existence isn't guaranteed
this.numberFormatter = (point) => this.decimalPipe.transform(point.y) ?? point.y.toString();
// TODO: 'y' property existence isn't guaranteed and adding '?? 0' is not safe
this.percentFormatter = (point) => this.percentPipe.transform(point.y ?? 0 / 100, '.2') ?? point.y.toString();
this.percentPieFormatter = (point) => `${point.percentage?.toFixed(2)}%`;
// TODO: 'y' property existence isn't guaranteed
this.currencyFormatter = (point) => this.currencyPipe.transform(point.y) ?? point.y.toString();
// TODO: 'x' property existence isn't guaranteed
this.xAxisDateTimeFormatter = (data) => {
const x = data.x || data.key;
return DateUtils.isValidDate(x)
? `${DateUtils.gregorianToJalali(x).format()} ${DateUtils.format(x, 'HH:MM')}`
: x.toString();
};
// TODO: 'x' property existence isn't guaranteed
this.xAxisDateFormatter = (data) => {
const x = data.x || data.key;
return DateUtils.isValidDate(x) ? DateUtils.gregorianToJalali(x).format() : x.toString();
};
// TODO: 'x' property existence isn't guaranteed
this.xAxisTimeFormatter = (data) => {
const x = data.x || data.key;
return DateUtils.isValidDate(x) ? DateUtils.format(x, 'HH:MM') : x.toString();
};
this.yAxisFormatters = {
number: this.numberFormatter,
currency: this.currencyFormatter,
percent: this.percentFormatter,
'percent-pie': this.percentPieFormatter,
};
this.xAxisFormatters = {
'date-time': this.xAxisDateTimeFormatter,
date: this.xAxisDateFormatter,
time: this.xAxisTimeFormatter,
};
}
getPredefinedYAxisFormatter(tooltipType) {
if (typeof tooltipType === 'function') {
return tooltipType;
}
return this.yAxisFormatters[tooltipType];
}
getPredefinedFormatter(tooltipType) {
const [yAxis, xAxis] = tooltipType.split(':');
const xAxisFormatter = this.xAxisFormatters[xAxis];
const yAxisFormatter = this.yAxisFormatters[yAxis];
if (!yAxisFormatter && !xAxisFormatter) {
throw new Error(`PghChartTooltipService: ${tooltipType} tooltip not found.`);
}
return (data) => ({
data: (data.points || [data]).map(p => yAxisFormatter?.(p) ?? p.y),
name: xAxisFormatter?.(data) ?? data.key,
});
}
wrapTemplateOnFormatter(tooltip, series) {
return (data) => {
const res = tooltip(data);
this.applySeriesTooltipFormatters(res, data, series);
// TODO: 'res.name ?? data.key' doesn't satisfy the 'tooltipTemplate' argument type and adding '?? ''' isn't very safe
return this.tooltipTemplate(res.data ?? (data.points || [data]).map(p => p.y), res.name ?? data.key ?? '', data);
};
}
applySeriesTooltipFormatters(res, data, series) {
res.data = (data.points || [data]).map((p, i) => {
const seriesTooltipFormatter = this.getPredefinedYAxisFormatter(series[i].tooltip || '');
return seriesTooltipFormatter ? seriesTooltipFormatter(p) : res.data?.[i];
});
}
fillUndefinedAxisFormattersWithDefaults(tooltip, defaultValues) {
if (typeof tooltip === 'function')
return tooltip;
const [yAxis, xAxis] = tooltip.split(':');
return `${yAxis || defaultValues.yAxis}:${xAxis || defaultValues.xAxis}`;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: PghChartTooltipService, deps: [{ token: i1.CurrencyPipe }, { token: i1.PercentPipe }, { token: i1.DecimalPipe }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: PghChartTooltipService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: PghChartTooltipService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root',
}]
}], ctorParameters: () => [{ type: i1.CurrencyPipe }, { type: i1.PercentPipe }, { type: i1.DecimalPipe }] });
const PGH_CHART_COLORS = new InjectionToken('chartColors', {
providedIn: 'root',
factory: () => ['var(--primary)', 'var(--accent)'],
});
const PGH_CHART_OPTIONS = new InjectionToken('chartOptions', {
providedIn: 'root',
factory: () => ({}),
});
class PghChartColorsService {
constructor(colors) {
this.FALL_BACK_COLORS = [...MiscUtils.ALL_MATERIAL_COLORS, ...MiscUtils.RANDOM_COLORS];
this.colors = [];
this.updateColors(colors);
}
get chartColors() {
return this.colors;
}
updateColors(colors) {
this.colors = [...colors, ...this.FALL_BACK_COLORS.filter(c => !colors.includes(c))];
}
getStatBoxColor(index) {
return this.colors[index % this.colors.length];
}
getChartSeriesColor(index) {
return this.colors[index % this.colors.length];
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: PghChartColorsService, deps: [{ token: PGH_CHART_COLORS }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: PghChartColorsService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: PghChartColorsService, decorators: [{
type: Injectable,
args: [{ providedIn: 'root' }]
}], ctorParameters: () => [{ type: undefined, decorators: [{
type: Inject,
args: [PGH_CHART_COLORS]
}] }] });
class PghStatBoxService {
get activeStatBoxes() {
return this.statBoxes.filter(sb => sb.isActive);
}
constructor() {
this.statBoxes = [];
this.$activeStatBoxes = new ReplaySubject(1);
}
setActiveStatBoxes(statBoxes) {
this.$activeStatBoxes.next(statBoxes);
}
addActiveStatBox(statBox) {
statBox.isActive = true;
this.setActiveStatBoxes(this.statBoxes.filter(sb => sb.isActive));
}
removeActiveStatBox(statBox) {
statBox.isActive = false;
this.setActiveStatBoxes(this.statBoxes.filter(sb => sb.isActive));
}
setOnlyActiveStatBox(statBox) {
this.statBoxes.forEach(sb => {
sb.isActive = false;
});
statBox.isActive = true;
this.setActiveStatBoxes([statBox]);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: PghStatBoxService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: PghStatBoxService }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: PghStatBoxService, decorators: [{
type: Injectable
}], ctorParameters: () => [] });
class PghMiniChartComponent extends ChartParent {
constructor(chartTooltipService, chartColorsService, statBoxService) {
super();
this.chartTooltipService = chartTooltipService;
this.chartColorsService = chartColorsService;
this.statBoxService = statBoxService;
this.chartOptions = signal({});
this.userCustomChartOptions = input({}, {
alias: 'customChartOptions',
});
this.series = input([]);
this.defaultSeriesType = input('column', {
alias: 'seriesType',
});
this.CHART_PLACEHOLDER_SERIES = [
{ name: 'name', data: [3, 5, 1, 2, 3, 2, 3, 5, 1, 10, 9, 13], type: this.defaultSeriesType() },
];
}
ngOnChanges(_changes) {
this.updateChartOptions();
}
updateChartOptions() {
const columnBorderRadius = (this.chartOptions().series?.length ?? 0) > 1 ? 0 : 4;
this.chartOptions.set(this.createChartOptions({
chart: {
className: 'mini-chart',
width: 90,
height: 80,
},
xAxis: {
lineWidth: 0,
gridLineWidth: 0,
lineColor: 'transparent',
minorTickLength: 0,
title: { text: undefined },
labels: { enabled: false },
tickLength: 0,
},
yAxis: {
min: 0,
title: { text: '' },
lineWidth: 0,
gridLineWidth: 0,
lineColor: 'transparent',
minorTickLength: 0,
tickLength: 0,
labels: { enabled: false },
},
plotOptions: {
column: {
pointPadding: 0.1,
borderWidth: 0,
stacking: 'normal',
borderRadius: columnBorderRadius,
},
},
legend: { enabled: false },
tooltip: { enabled: false },
}));
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: PghMiniChartComponent, deps: [{ token: PghChartTooltipService }, { token: PghChartColorsService }, { token: PghStatBoxService, optional: true }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "19.2.13", type: PghMiniChartComponent, isStandalone: false, selector: "pgh-mini-chart", inputs: { userCustomChartOptions: { classPropertyName: "userCustomChartOptions", publicName: "customChartOptions", isSignal: true, isRequired: false, transformFunction: null }, series: { classPropertyName: "series", publicName: "series", isSignal: true, isRequired: false, transformFunction: null }, defaultSeriesType: { classPropertyName: "defaultSeriesType", publicName: "seriesType", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "<div class=\"pgh-chart-wrapper\">\n <div class=\"pgh-chart-content\" [class.pgh-chart-no-data]=\"hasNoData\">\n <highcharts-chart\n [Highcharts]=\"highcharts\"\n constructorType=\"chart\"\n [options]=\"chartOptions()\"\n [oneToOne]=\"true\"\n [runOutsideAngular]=\"true\"\n ></highcharts-chart>\n </div>\n</div>\n", styles: [""], dependencies: [{ kind: "component", type: i4.HighchartsChartComponent, selector: "highcharts-chart", inputs: ["Highcharts", "constructorType", "callbackFunction", "oneToOne", "runOutsideAngular", "options", "update"], outputs: ["updateChange", "chartInstance"] }], encapsulation: i0.ViewEncapsulation.None }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: PghMiniChartComponent, decorators: [{
type: Component,
args: [{ selector: 'pgh-mini-chart', encapsulation: ViewEncapsulation.None, standalone: false, template: "<div class=\"pgh-chart-wrapper\">\n <div class=\"pgh-chart-content\" [class.pgh-chart-no-data]=\"hasNoData\">\n <highcharts-chart\n [Highcharts]=\"highcharts\"\n constructorType=\"chart\"\n [options]=\"chartOptions()\"\n [oneToOne]=\"true\"\n [runOutsideAngular]=\"true\"\n ></highcharts-chart>\n </div>\n</div>\n" }]
}], ctorParameters: () => [{ type: PghChartTooltipService }, { type: PghChartColorsService }, { type: PghStatBoxService, decorators: [{
type: Optional
}] }] });
class PghFullChartComponent extends ChartParent {
/** TODO: 'chartColorsService' injected but never used review its usage if the 'updateColors' in its constructor doesn't do anything in this scenario */
constructor(chartTooltipService, chartColorsService, globalChartOptions, statBoxService) {
super();
this.chartTooltipService = chartTooltipService;
this.chartColorsService = chartColorsService;
this.globalChartOptions = globalChartOptions;
this.statBoxService = statBoxService;
this.MIN_ZOOM_ENABLED_CHART_SERIES = 8;
this.chartOptions = signal({});
this.userCustomChartOptions = input({}, {
alias: 'customChartOptions',
});
this.series = input([]);
this.defaultSeriesType = input('areaspline', {
alias: 'seriesType',
});
this.xAxis = input([]);
this.yAxis = model([{}]);
// TODO: use typescript's template string `${PghChartTooltipType}:${PghChartTooltipXAxis}`
this.tooltip = model('percent-pie');
this.CHART_PLACEHOLDER_SERIES = [
{ name: 'name', data: [3, 5, 1, 2, 3, 2, 3, 5, 1, 10, 9, 13], type: this.defaultSeriesType() },
];
this.getXAxis = (xAxisValue) => DateUtils.isValidDate(xAxisValue)
? DateUtils.gregorianToJalali(xAxisValue).format()
: xAxisValue.toString();
}
ngAfterViewChecked() {
this.handleChartReflow();
}
handleChartReflow() {
if (!this.chartInstance ||
this.lastChartWrapperWidth === this.chartWrapper?.nativeElement.offsetWidth)
return;
this.lastChartWrapperWidth = this.chartWrapper?.nativeElement.offsetWidth;
/**
* TODO: using ChangeDetectorRef can be a better option instead of setTimeout
* see https://stackoverflow.com/questions/73145234/what-to-use-in-angular-instead-of-settimeout-for-certain-changes
* The decorator introduced in the above link is quite useful for this purpose
* */
setTimeout(() => {
this.chartInstance?.reflow();
});
}
ngOnChanges(changes) {
if (changes.yAxis && this.yAxis().length === 0) {
this.yAxis.set([{}]);
}
this.updateChartOptions();
}
updateChartOptions() {
this.tooltip.set(this.chartTooltipService.fillUndefinedAxisFormattersWithDefaults(this.tooltip(), {
xAxis: this.globalChartOptions.fullChartTooltip?.xAxis || 'date',
yAxis: this.globalChartOptions.fullChartTooltip?.yAxis,
}));
const xAxis = this.xAxis() ?? [];
this.chartOptions.set(this.createChartOptions({
chart: {
zooming: {
type: xAxis.length > this.MIN_ZOOM_ENABLED_CHART_SERIES ? 'x' : undefined,
},
className: 'full-chart',
type: 'areaspline',
},
xAxis: {
categories: xAxis,
labels: {
style: { fontSize: '14px', color: 'var(--444)' },
formatter: that => this.getXAxis(that.value),
},
zoomEnabled: true,
crosshair: true,
},
yAxis: this.yAxis().map(y => ({
title: { text: null },
labels: {
format: y?.labels?.format ?? '',
style: { fontSize: '13px', color: 'var(--666)' },
},
opposite: y.opposite,
gridLineColor: 'var(--eee)',
gridLineDashStyle: 'LongDashDot',
})),
plotOptions: {
column: {
borderColor: 'var(--fff)',
},
},
}));
}
onSetChartInstance(chartInstance) {
this.chartInstance = chartInstance;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: PghFullChartComponent, deps: [{ token: PghChartTooltipService }, { token: PghChartColorsService }, { token: PGH_CHART_OPTIONS }, { token: PghStatBoxService, optional: true }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "19.2.13", type: PghFullChartComponent, isStandalone: false, selector: "pgh-full-chart", inputs: { userCustomChartOptions: { classPropertyName: "userCustomChartOptions", publicName: "customChartOptions", isSignal: true, isRequired: false, transformFunction: null }, series: { classPropertyName: "series", publicName: "series", isSignal: true, isRequired: false, transformFunction: null }, defaultSeriesType: { classPropertyName: "defaultSeriesType", publicName: "seriesType", isSignal: true, isRequired: false, transformFunction: null }, xAxis: { classPropertyName: "xAxis", publicName: "xAxis", isSignal: true, isRequired: false, transformFunction: null }, yAxis: { classPropertyName: "yAxis", publicName: "yAxis", isSignal: true, isRequired: false, transformFunction: null }, tooltip: { classPropertyName: "tooltip", publicName: "tooltip", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { yAxis: "yAxisChange", tooltip: "tooltipChange" }, viewQueries: [{ propertyName: "chartWrapper", first: true, predicate: ["chartWrapperRef"], descendants: true }], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "<div #chartWrapperRef class=\"pgh-chart-wrapper\">\n <span class=\"pgh-chart-placeholder-text\">{{ 'FULL_CHART_PLACEHOLDER_TEXT' | translate }}</span>\n <div class=\"pgh-chart-content\" [class.pgh-chart-no-data]=\"hasNoData\">\n <highcharts-chart\n [Highcharts]=\"highcharts\"\n constructorType=\"chart\"\n [options]=\"chartOptions()\"\n [oneToOne]=\"true\"\n class=\"w-100 d-block\"\n [runOutsideAngular]=\"true\"\n (chartInstance)=\"onSetChartInstance($event)\"\n ></highcharts-chart>\n </div>\n</div>\n", styles: [".pgh-chart-placeholder-text{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);font-size:1.25rem}.pgh-chart-tooltip-point-indicator{height:8px;width:8px;border-radius:50%;display:inline-block;background:var(--series-color)}.pgh-chart-tooltip-point{display:flex;justify-content:flex-end;align-items:center;color:var(--000)}.pgh-highcharts-tooltip-values{text-shadow:0 0 .3px currentcolor}.highcharts-area{opacity:.4}\n"], dependencies: [{ kind: "component", type: i4.HighchartsChartComponent, selector: "highcharts-chart", inputs: ["Highcharts", "constructorType", "callbackFunction", "oneToOne", "runOutsideAngular", "options", "update"], outputs: ["updateChange", "chartInstance"] }, { kind: "pipe", type: i5.TranslatePipe, name: "translate" }], encapsulation: i0.ViewEncapsulation.None }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: PghFullChartComponent, decorators: [{
type: Component,
args: [{ selector: 'pgh-full-chart', encapsulation: ViewEncapsulation.None, standalone: false, template: "<div #chartWrapperRef class=\"pgh-chart-wrapper\">\n <span class=\"pgh-chart-placeholder-text\">{{ 'FULL_CHART_PLACEHOLDER_TEXT' | translate }}</span>\n <div class=\"pgh-chart-content\" [class.pgh-chart-no-data]=\"hasNoData\">\n <highcharts-chart\n [Highcharts]=\"highcharts\"\n constructorType=\"chart\"\n [options]=\"chartOptions()\"\n [oneToOne]=\"true\"\n class=\"w-100 d-block\"\n [runOutsideAngular]=\"true\"\n (chartInstance)=\"onSetChartInstance($event)\"\n ></highcharts-chart>\n </div>\n</div>\n", styles: [".pgh-chart-placeholder-text{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);font-size:1.25rem}.pgh-chart-tooltip-point-indicator{height:8px;width:8px;border-radius:50%;display:inline-block;background:var(--series-color)}.pgh-chart-tooltip-point{display:flex;justify-content:flex-end;align-items:center;color:var(--000)}.pgh-highcharts-tooltip-values{text-shadow:0 0 .3px currentcolor}.highcharts-area{opacity:.4}\n"] }]
}], ctorParameters: () => [{ type: PghChartTooltipService }, { type: PghChartColorsService }, { type: undefined, decorators: [{
type: Inject,
args: [PGH_CHART_OPTIONS]
}] }, { type: PghStatBoxService, decorators: [{
type: Optional
}] }], propDecorators: { chartWrapper: [{
type: ViewChild,
args: ['chartWrapperRef']
}] } });
class PghMapChartComponent extends ChartParent {
constructor(statBoxService) {
super();
this.statBoxService = statBoxService;
this.chartInstance = signal(undefined);
this.chartOptions = signal({});
this.series = input([]);
this.userCustomChartOptions = input({}, {
alias: 'customChartOptions',
});
this.defaultSeriesType = signal('map');
this.CHART_PLACEHOLDER_SERIES = [];
this.chartTooltipService = inject(PghChartTooltipService);
this.chartColorsService = inject(PghChartColorsService);
}
ngOnChanges(changes) {
if (changes['userCustomChartOptions']) {
this.setChartOptions();
}
if (changes['series']) {
this.updateChartData();
}
}
ngOnInit() {
this.setChartOptions();
}
setChartOptions() {
this.chartOptions.set(this.createChartOptions({
chart: {
map: iranMap,
backgroundColor: 'transparent',
},
title: { text: undefined },
credits: { enabled: false },
legend: { enabled: false },
colorAxis: {
stops: [
[0, '#B3ECDA'],
[1, '#00865C'],
],
},
tooltip: {
enabled: false,
},
plotOptions: {
series: {
animation: false,
},
},
series: [
{
type: 'map',
animation: false,
joinBy: ['hc-key', 'id'],
borderColor: '#FFFFFF',
borderWidth: 1,
states: {
hover: {
color: '#006042',
borderColor: '#FFFFFF',
borderWidth: 2,
},
},
},
],
}));
}
updateChartData() {
const seriesData = this.series()?.[0].data ?? [];
const chart = this.chartInstance();
if (chart && seriesData?.length) {
chart.series[0].setData(seriesData, true, false);
}
}
onChartInstanceReady(chart) {
this.chartInstance.set(chart);
this.updateChartData();
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: PghMapChartComponent, deps: [{ token: PghStatBoxService, optional: true }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "19.2.13", type: PghMapChartComponent, isStandalone: false, selector: "pgh-map-chart", inputs: { series: { classPropertyName: "series", publicName: "series", isSignal: true, isRequired: false, transformFunction: null }, userCustomChartOptions: { classPropertyName: "userCustomChartOptions", publicName: "customChartOptions", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "<div #chartWrapperRef class=\"pgh-chart-wrapper\">\n <div class=\"pgh-chart-content\" [class.pgh-chart-no-data]=\"hasNoData\">\n <highcharts-chart\n [Highcharts]=\"highcharts\"\n constructorType=\"mapChart\"\n [options]=\"chartOptions()\"\n [oneToOne]=\"true\"\n [runOutsideAngular]=\"true\"\n (chartInstance)=\"onChartInstanceReady($event)\"\n class=\"pgh-iran-map-chart w-100 d-block\"\n ></highcharts-chart>\n </div>\n</div>\n", styles: [""], dependencies: [{ kind: "component", type: i4.HighchartsChartComponent, selector: "highcharts-chart", inputs: ["Highcharts", "constructorType", "callbackFunction", "oneToOne", "runOutsideAngular", "options", "update"], outputs: ["updateChange", "chartInstance"] }], encapsulation: i0.ViewEncapsulation.None }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: PghMapChartComponent, decorators: [{
type: Component,
args: [{ selector: 'pgh-map-chart', encapsulation: ViewEncapsulation.None, standalone: false, template: "<div #chartWrapperRef class=\"pgh-chart-wrapper\">\n <div class=\"pgh-chart-content\" [class.pgh-chart-no-data]=\"hasNoData\">\n <highcharts-chart\n [Highcharts]=\"highcharts\"\n constructorType=\"mapChart\"\n [options]=\"chartOptions()\"\n [oneToOne]=\"true\"\n [runOutsideAngular]=\"true\"\n (chartInstance)=\"onChartInstanceReady($event)\"\n class=\"pgh-iran-map-chart w-100 d-block\"\n ></highcharts-chart>\n </div>\n</div>\n" }]
}], ctorParameters: () => [{ type: PghStatBoxService, decorators: [{
type: Optional
}] }] });
class PghChartStatBoxDirective {
constructor(template) {
this.template = template;
this.statBoxData = input(undefined, {
alias: 'pghStatsBox',
});
}
ngOnChanges(changes) {
this.handleNoStatBoxDataError();
}
ngOnInit() {
this.handleNoStatBoxDataError();
}
handleNoStatBoxDataError() {
if (!this.statBoxData()) {
throw new Error('Pass a statBox data to *pghStatsBox so you can use it in the (activeStatBoxesChange) listener');
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: PghChartStatBoxDirective, deps: [{ token: i0.TemplateRef }], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.2.13", type: PghChartStatBoxDirective, isStandalone: false, selector: "[pghStatsBox]", inputs: { statBoxData: { classPropertyName: "statBoxData", publicName: "pghStatsBox", isSignal: true, isRequired: false, transformFunction: null } }, exportAs: ["pghStatsBox"], usesOnChanges: true, ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: PghChartStatBoxDirective, decorators: [{
type: Directive,
args: [{
selector: '[pghStatsBox]',
exportAs: 'pghStatsBox',
standalone: false,
}]
}], ctorParameters: () => [{ type: i0.TemplateRef }] });
class PghChartStatBox {
get inputData() {
return this.markerDirective.statBoxData();
}
constructor(markerDirective, index, color) {
this.markerDirective = markerDirective;
this.index = index;
this.color = color;
this.isActive = false;
}
}
class PghChartDateRangePickerDirective {
constructor() { }
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: PghChartDateRangePickerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.13", type: PghChartDateRangePickerDirective, isStandalone: false, selector: "[pgh-chart-date-range-picker]", ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: PghChartDateRangePickerDirective, decorators: [{
type: Directive,
args: [{
selector: '[pgh-chart-date-range-picker]',
standalone: false,
}]
}], ctorParameters: () => [] });
class PghChartHeaderDirective {
constructor() { }
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: PghChartHeaderDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.13", type: PghChartHeaderDirective, isStandalone: false, selector: "[pgh-chart-header]", ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: PghChartHeaderDirective, decorators: [{
type: Directive,
args: [{
selector: '[pgh-chart-header]',
standalone: false,
}]
}], ctorParameters: () => [] });
class PghChartBoxComponent extends withDestroy() {
constructor(statBoxService, chartColorsService, chartOptions) {
super();
this.statBoxService = statBoxService;
this.chartColorsService = chartColorsService;
this.chartTitle = input();
this.activeMax = model(1);
this.colors = input();
this.disableChartBoxScroll = model(false);
this.activeStatBoxesChange = output();
this.dateRangePickerDirective = PghChartDateRangePickerDirective;
this.displayStatBoxesVertically = input(false);
this.isContainerOverflown = signal(false);
this.isContainerAtStart = signal(true);
this.isContainerAtEnd = signal(false);
this.activeMax.set(chartOptions.maxActiveChartBoxes ?? this.activeMax());
this.disableChartBoxScroll.set(chartOptions.disableChartBoxScroll ?? this.disableChartBoxScroll());
}
ngOnInit() {
this.handleActiveMaxChange();
let noDuplicate$ = this.statBoxService.$activeStatBoxes.pipe(takeUntil(this._destroyed$), distinctUntilChanged());
if (this.activeMax() === 'infinite' || Number(this.activeMax()) > 2) {
noDuplicate$ = noDuplicate$.pipe(debounceTime(700));
}
noDuplicate$.subscribe(activeStatBoxes => {
this.activeStatBoxesChange.emit({
statBoxes: activeStatBoxes.map(sb => sb),
indexes: activeStatBoxes.map(sb => sb.index),
});
});
}
ngOnChanges(changes) {
if (changes.color && this.colors()) {
this.chartColorsService.updateColors(this.colors());
}
if (changes.activeMax) {
this.handleActiveMaxChange();
}
}
handleActiveMaxChange() {
if (this.activeMax() === 'infinite') {
this.activeMax.set(999999999999999);
}
else if (Number(this.activeMax()) < 1) {
this.activeMax.set(1);
}
}
ngAfterContentInit() {
this.statBoxesTemplateChanged();
this.statBoxesDirectives?.changes.pipe(takeUntil(this._destroyed$)).subscribe(() => {
this.statBoxesTemplateChanged();
});
}
ngAfterContentChecked() {
this.isContainerOverflown.set(this.isStatBoxesContainerOverflown());
}
statBoxesTemplateChanged() {
this.updateStatBoxesBasedOnDirectives();
const { activeStatBoxes } = this.statBoxService;
if (!activeStatBoxes.length && this.statBoxService.statBoxes.length) {
this.changeStatBoxActiveState(this.statBoxService.statBoxes[0]);
}
}
updateStatBoxesBasedOnDirectives() {
if (!this.statBoxesDirectives)
return;
this.statBoxService.statBoxes = this.statBoxesDirectives.map((directive, i) => {
const existingStatBoxWithSameId = this.statBoxService.statBoxes.find(sb => sb.markerDirective.statBoxData() === directive.statBoxData());
return (existingStatBoxWithSameId ??
new PghChartStatBox(directive, i, this.chartColorsService.getStatBoxColor(i)));
});
}
changeStatBoxActiveState(statBox, statBoxContainerElm) {
const activeCount = this.statBoxService.activeStatBoxes.length;
if (this.activeMax() === 1) {
if (statBox.isActive)
return;
this.statBoxService.setOnlyActiveStatBox(statBox);
this.scrollIntoView(statBoxContainerElm);
return;
}
const canChangeState = this.activeMax() === 'infinite' ||
activeCount < Number(this.activeMax()) ||
(statBox.isActive && activeCount > 1);
if (!canChangeState)
return;
if (statBox.isActive) {
this.statBoxService.removeActiveStatBox(statBox);
}
else {
this.statBoxService.addActiveStatBox(statBox);
this.scrollIntoView(statBoxContainerElm);
}
}
shift(direction) {
if (!this.statBoxesScroller ||
(direction === 1 && this.isContainerAtStart()) ||
(direction === -1 && this.isContainerAtEnd()))
return;
this.statBoxesScroller.nativeElement.scrollBy({ left: direction * 300 });
}
isStatBoxesContainerOverflown() {
if (!this.statBoxesScroller || this.disableChartBoxScroll()) {
return false;
}
const element = this.statBoxesScroller.nativeElement;
return element.scrollWidth > element.clientWidth;
}
scrollIntoView(element) {
if (!element)
return;
element.scrollIntoView({
behavior: 'smooth',
block: 'nearest',
inline: 'center',
});
}
statBoxContainerScrollHandler() {
if (!this.statBoxesScroller)
return;
const element = this.statBoxesScroller.nativeElement;
this.isContainerAtStart.set(!element.scrollLeft);
this.isContainerAtEnd.set(element.scrollWidth + element.scrollLeft === element.clientWidth);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: PghChartBoxComponent, deps: [{ token: PghStatBoxService }, { token: PghChartColorsService }, { token: PGH_CHART_OPTIONS }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.13", type: PghChartBoxComponent, isStandalone: false, selector: "pgh-chart-box", inputs: { chartTitle: { classPropertyName: "chartTitle", publicName: "chartTitle", isSignal: true, isRequired: false, transformFunction: null }, activeMax: { classPropertyName: "activeMax", publicName: "activeMax", isSignal: true, isRequired: false, transformFunction: null }, colors: { classPropertyName: "colors", publicName: "colors", isSignal: true, isRequired: false, transformFunction: null }, disableChartBoxScroll: { classPropertyName: "disableChartBoxScroll", publicName: "disableChartBoxScroll", isSignal: true, isRequired: false, transformFunction: null }, displayStatBoxesVertically: { classPropertyName: "displayStatBoxesVertically", publicName: "displayStatBoxesVertically", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { activeMax: "activeMaxChange", disableChartBoxScroll: "disableChartBoxScrollChange", activeStatBoxesChange: "activeStatBoxesChange" }, providers: [PghStatBoxService], queries: [{ propertyName: "filterChipsComponent", first: true, predicate: PghFilterChipsComponent, descendants: true }, { propertyName: "dateRangePickerDirective", first: true, predicate: PghChartDateRangePickerDirective, descendants: true }, { propertyName: "headerDirective", first: true, predicate: PghChartHeaderDirective, descendants: true }, { propertyName: "statBoxesDirectives", predicate: PghChartStatBoxDirective }], viewQueries: [{ propertyName: "statBoxesScroller", first: true, predicate: ["statBoxesScroller"], descendants: true, static: true }], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "<div class=\"pgh-chart-box\" [class.pgh-chart-box-vertical-stats]=\"displayStatBoxesVertically()\">\n <div class=\"pgh-chart-box-header\">\n <div class=\"pgh-chart-box-header-section\" [hidden]=\"!chartTitle() && !headerDirective\">\n @if (chartTitle()) {\n <h4>{{ chartTitle() }}</h4>\n }\n <ng-content select=\"[pgh-chart-header]\"></ng-content>\n </div>\n <div class=\"pgh-chart-box-header-section\" [hidden]=\"!dateRangePickerDirective\">\n <ng-content select=\"[pgh-chart-date-range-picker]\"></ng-content>\n </div>\n </div>\n\n <div\n class=\"pgh-filters-wrapper\"\n [hidden]=\"!filtersWrapperRef.innerHTML.trim() && !actionButtonsWrapperRef.innerHTML.trim()\"\n >\n <div #filtersWrapperRef>\n <ng-content select=\"pgh-filter-chips\"></ng-content>\n <ng-content select=\"[pgh-chart-filters]\"></ng-content>\n </div>\n <div #actionButtonsWrapperRef class=\"pgh-action-buttons\">\n <ng-content select=\"[pgh-action-buttons]\"></ng-content>\n </div>\n </div>\n\n <div\n class=\"pgh-stats-container\"\n [hidden]=\"!statBoxService.statBoxes.length\"\n [class.pgh-chart-box-no-scroll-stats]=\"disableChartBoxScroll()\"\n >\n <div class=\"pgh-chart-stat-boxes\">\n <div\n #statBoxesScroller\n class=\"pgh-chart-stat-scroller\"\n [class.pgh-chart-stat-boxes-overflow]=\"isContainerOverflown()\"\n (scroll)=\"statBoxContainerScrollHandler()\"\n >\n @for (sb of statBoxService.statBoxes; track sb) {\n <div\n class=\"pgh-stat-box-container\"\n [class.pgh-is-active]=\"sb.isActive\"\n #statBoxContainerElm\n (click)=\"changeStatBoxActiveState(sb, statBoxContainerElm)\"\n [style.--chart-stat-box-bg-color]=\"sb.color\"\n >\n <ng-container\n *ngTemplateOutlet=\"sb.markerDirective.template; context: { isActive: sb.isActive }\"\n ></ng-container>\n </div>\n }\n </div>\n </div>\n @if (isContainerOverflown()) {\n <div\n class=\"pgh-slide-button pgh-chart-stat-boxes-slide-right\"\n [class.pgh-disabled]=\"isContainerAtStart()\"\n (click)=\"shift(1)\"\n >\n <mat-icon svgIcon=\"chevron_right\"></mat-icon>\n </div>\n } @if (isContainerOverflown()) {\n <div\n class=\"pgh-slide-button pgh-chart-stat-boxes-slide-left\"\n [class.pgh-disabled]=\"isContainerAtEnd()\"\n (click)=\"shift(-1)\"\n >\n <mat-icon svgIcon=\"chevron_left\"></mat-icon>\n </div>\n }\n </div>\n\n <div class=\"pgh-chart-container\">\n <ng-content></ng-content>\n </div>\n</div>\n", styles: [".font-monospaced-numbers{font-feature-settings:\"ss03\"!important}.font-english-numbers{font-feature-settings:normal!important}.font-weight-light{font-weight:300}.font-weight-normal{font-weight:400}.font-weight-bold{font-weight:600}.black-50{background-color:hsl(var(--_body-hue),var(--_body-saturation),var(--lightness-0),50%)!important}.white-50{background-color:hsl(var(--_body-hue),var(--_body-saturation),var(--lightness-1000),50%)!important}.pgh-chart-box{border-radius:var(--box-radius);background-color:var(--fff);box-shadow:var(--shadow);display:grid;grid-template-areas:\"header\" \"filter\" \"stats\" \"chart\";grid-template-rows:auto auto auto 1fr;grid-template-columns:1fr}.pgh-chart-box .pgh-filters-wrapper{min-width:0}.box .pgh-chart-box{box-shadow:none}.pgh-chart-box-header{grid-area:header;min-width:0}.pgh-chart-box-header .pgh-chart-box-header-section{padding-block:.25rem;padding-inline:1rem;min-height:3.125rem;border-bottom:1px solid var(--light-border-color);display:flex;align-items:center}.pgh-chart-box-header .pgh-chart-box-header-section h4{font-weight:600;font-size:1rem;margin-bottom:0}.pgh-stats-container{grid-area:stats;position:relative;min-width:0}.pgh-chart-stat-boxes{background-color:var(--eee);border-bottom:1px solid var(--light-border-color)}[dark=true] .pgh-chart-stat-boxes{background-color:var(--fff)}.pgh-chart-stat-scroller{display:flex;overflow-x:scroll;-webkit-overflow-scrolling:touch;transition:all .3s;-ms-overflow-style:none;scrollbar-width:none;position:relative}.pgh-chart-stat-scroller::-webkit-scrollbar{display:none}.pgh-chart-stat-scroller.pgh-chart-stat-boxes-overflow{margin-block:0;margin-inline:2rem}.pgh-chart-box-no-scroll-stats .pgh-chart-stat-boxes{padding-block:.125rem;padding-inline:0}.pgh-chart-box-no-scroll-stats .pgh-chart-stat-scroller{flex-wrap:wrap;border:1px solid var(--light-border-color);border-inline-start:none;border-inline-end:none}.pgh-chart-box-no-scroll-stats .pgh-stat-box-container:not(:last-child){margin-bottom:.125rem}.pgh-chart-box-no-scroll-stats .pgh-stat-box-container{flex-grow:1}.pgh-chart-box-vertical-stats{grid-template-areas:\"header header\" \"filter filter\" \"stats chart\";grid-template-rows:auto auto 1fr;grid-template-columns:max(200px,20%) 1fr}.pgh-chart-box-vertical-stats .pgh-chart-box-no-scroll-stats .pgh-chart-stat-boxes{padding:0;border-bottom:none}.pgh-chart-box-vertical-stats .pgh-stats-container:not(.pgh-chart-box-no-scroll-stats){min-height:100%;overflow:auto;height:0}.pgh-chart-box-vertical-stats .pgh-chart-stat-scroller{border:none;flex-direction:column}.pgh-chart-box-vertical-stats .pgh-stat-box-container:not(:last-child){margin-bottom:.125rem}.pgh-slide-button{cursor:pointer;position:absolute;top:0;bottom:0;width:1.875rem;display:flex;background-color:var(--fff);border:1px solid var(--light-border-color);border-top:none;align-items:center;justify-content:center}.pgh-slide-button.pgh-disabled{box-shadow:none;opacity:.5;cursor:initial}.pgh-chart-stat-boxes-slide-left{left:0;border-inline-end:none;box-shadow:6px 2px 10px #0000000f}.pgh-chart-stat-boxes-slide-right{right:0;border-inline-start:none;box-shadow:-6px 2px 10px #0000000f}.pgh-chart-container{grid-area:chart;padding-block:1rem;padding-inline:0;min-width:0}\n"], dependencies: [{ kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i4$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], encapsulation: i0.ViewEncapsulation.None }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: PghChartBoxComponent, decorators: [{
type: Component,
args: [{ selector: 'pgh-chart-box', encapsulation: ViewEncapsulation.None, providers: [PghStatBoxService], standalone: false, template: "<div class=\"pgh-chart-box\" [class.pgh-chart-box-vertical-stats]=\"displayStatBoxesVertically()\">\n <div class=\"pgh-chart-box-header\">\n <div class=\"pgh-chart-box-header-section\" [hidden]=\"!chartTitle() && !headerDirective\">\n @if (chartTitle()) {\n <h4>{{ chartTitle() }}</h4>\n }\n <ng-content select=\"[pgh-chart-header]\"></ng-content>\n </div>\n <div class=\"pgh-chart-box-header-section\" [hidden]=\"!dateRangePickerDirective\">\n <ng-content select=\"[pgh-chart-date-range-picker]\"></ng-content>\n </div>\n </div>\n\n <div\n class=\"pgh-filters-wrapper\"\n [hidden]=\"!filtersWrapperRef.innerHTML.trim() && !actionButtonsWrapperRef.innerHTML.trim()\"\n >\n <div #filtersWrapperRef>\n <ng-content select=\"pgh-filter-chips\"></ng-content>\n <ng-content select=\"[pgh-chart-filters]\"></ng-content>\n </div>\n <div #actionButtonsWrapperRef class=\"pgh-action-buttons\">\n <ng-content select=\"[pgh-action-buttons]\"></ng-content>\n </div>\n </div>\n\n <div\n class=\"pgh-stats-container\"\n [hidden]=\"!statBoxService.statBoxes.length\"\n [class.pgh-chart-box-no-scroll-stats]=\"disableChartBoxScroll()\"\n >\n <div class=\"pgh-chart-stat-boxes\">\n <div\n #statBoxesScroller\n class=\"pgh-chart-stat-scroller\"\n [class.pgh-chart-stat-boxes-overflow]=\"isContainerOverflown()\"\n (scroll)=\"statBoxContainerScrollHandler()\"\n >\n @for (sb of statBoxService.statBoxes; track sb) {\n <div\n class=\"pgh-stat-box-container\"\n [class.pgh-is-active]=\"sb.isActive\"\n #statBoxContainerElm\n (click)=\"changeStatBoxActiveState(sb, statBoxContainerElm)\"\n [style.--chart-stat-box-bg-color]=\"sb.color\"\n >\n <ng-container\n *ngTemplateOutlet=\"sb.markerDirective.template; context: { isActive: sb.isActive }\"\n ></ng-container>\n </div>\n }\n </div>\n </div>\n @if (isContainerOverflown()) {\n <div\n class=\"pgh-slide-button pgh-chart-stat-boxes-slide-right\"\n