@acorex/charts 22.0.0-next.3 → 22.0.0-next.30
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.
- package/fesm2022/acorex-charts-bar-chart.mjs +20 -50
- package/fesm2022/acorex-charts-bar-chart.mjs.map +1 -1
- package/fesm2022/acorex-charts-chart-legend.mjs +16 -11
- package/fesm2022/acorex-charts-chart-legend.mjs.map +1 -1
- package/fesm2022/acorex-charts-chart-tooltip.mjs +8 -7
- package/fesm2022/acorex-charts-chart-tooltip.mjs.map +1 -1
- package/fesm2022/acorex-charts-donut-chart.mjs +74 -33
- package/fesm2022/acorex-charts-donut-chart.mjs.map +1 -1
- package/fesm2022/acorex-charts-funnel-chart.mjs +40 -20
- package/fesm2022/acorex-charts-funnel-chart.mjs.map +1 -1
- package/fesm2022/acorex-charts-gauge-chart.mjs +13 -14
- package/fesm2022/acorex-charts-gauge-chart.mjs.map +1 -1
- package/fesm2022/acorex-charts-heatmap-chart.mjs +36 -20
- package/fesm2022/acorex-charts-heatmap-chart.mjs.map +1 -1
- package/fesm2022/acorex-charts-hierarchy-chart.mjs +25 -64
- package/fesm2022/acorex-charts-hierarchy-chart.mjs.map +1 -1
- package/fesm2022/acorex-charts-line-chart.mjs +21 -14
- package/fesm2022/acorex-charts-line-chart.mjs.map +1 -1
- package/fesm2022/acorex-charts.mjs +29 -25
- package/fesm2022/acorex-charts.mjs.map +1 -1
- package/package.json +1 -1
- package/types/acorex-charts-bar-chart.d.ts +4 -4
- package/types/acorex-charts-chart-legend.d.ts +7 -1
- package/types/acorex-charts-donut-chart.d.ts +7 -1
- package/types/acorex-charts-funnel-chart.d.ts +3 -4
- package/types/acorex-charts-gauge-chart.d.ts +1 -0
- package/types/acorex-charts-heatmap-chart.d.ts +3 -2
- package/types/acorex-charts-hierarchy-chart.d.ts +0 -8
- package/types/acorex-charts-line-chart.d.ts +4 -0
- package/types/acorex-charts.d.ts +4 -3
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as i1 from '@angular/common';
|
|
2
2
|
import { CommonModule } from '@angular/common';
|
|
3
3
|
import * as i0 from '@angular/core';
|
|
4
|
-
import { input, output, viewChild, computed, ViewEncapsulation, Component } from '@angular/core';
|
|
4
|
+
import { input, output, viewChild, signal, computed, ViewEncapsulation, Component } from '@angular/core';
|
|
5
5
|
|
|
6
6
|
class AXChartLegendComponent {
|
|
7
7
|
/**
|
|
@@ -33,6 +33,8 @@ class AXChartLegendComponent {
|
|
|
33
33
|
*/
|
|
34
34
|
legendContainer = viewChild('legendContainer', /* @ts-ignore */
|
|
35
35
|
...(ngDevMode ? [{ debugName: "legendContainer" }] : /* istanbul ignore next */ []));
|
|
36
|
+
interactionVersion = signal(0, /* @ts-ignore */
|
|
37
|
+
...(ngDevMode ? [{ debugName: "interactionVersion" }] : /* istanbul ignore next */ []));
|
|
36
38
|
// Computed values for the template
|
|
37
39
|
showValues = computed(() => this.options()?.showValues !== false, /* @ts-ignore */
|
|
38
40
|
...(ngDevMode ? [{ debugName: "showValues" }] : /* istanbul ignore next */ []));
|
|
@@ -54,7 +56,10 @@ class AXChartLegendComponent {
|
|
|
54
56
|
...(ngDevMode ? [{ debugName: "isInteractive" }] : /* istanbul ignore next */ []));
|
|
55
57
|
// Compute the items to display from the chart
|
|
56
58
|
displayItems = computed(() => {
|
|
57
|
-
|
|
59
|
+
const chart = this.chart();
|
|
60
|
+
chart.legendStateVersion?.();
|
|
61
|
+
this.interactionVersion();
|
|
62
|
+
return chart.getLegendItems();
|
|
58
63
|
}, /* @ts-ignore */
|
|
59
64
|
...(ngDevMode ? [{ debugName: "displayItems" }] : /* istanbul ignore next */ []));
|
|
60
65
|
/**
|
|
@@ -62,20 +67,17 @@ class AXChartLegendComponent {
|
|
|
62
67
|
*/
|
|
63
68
|
onItemClick(item) {
|
|
64
69
|
const chartInstance = this.chart();
|
|
65
|
-
// If we have a chart and it's interactive, toggle the segment
|
|
66
70
|
if (this.isInteractive()) {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
item.hidden = !isVisible;
|
|
71
|
+
chartInstance.toggleSegment(item.id);
|
|
72
|
+
this.interactionVersion.update((version) => version + 1);
|
|
70
73
|
}
|
|
71
|
-
|
|
72
|
-
this.itemClick.emit(
|
|
74
|
+
const refreshedItem = this.displayItems().find((legendItem) => legendItem.id === item.id) ?? item;
|
|
75
|
+
this.itemClick.emit(refreshedItem);
|
|
73
76
|
}
|
|
74
77
|
/**
|
|
75
78
|
* Handle mouse enter on legend items
|
|
76
79
|
*/
|
|
77
80
|
onItemMouseEnter(item) {
|
|
78
|
-
this.chart().highlightSegment(null);
|
|
79
81
|
this.itemMouseEnter.emit(item);
|
|
80
82
|
this.chart().highlightSegment(item.id);
|
|
81
83
|
}
|
|
@@ -86,6 +88,9 @@ class AXChartLegendComponent {
|
|
|
86
88
|
this.itemMouseLeave.emit(item);
|
|
87
89
|
this.chart().highlightSegment(null);
|
|
88
90
|
}
|
|
91
|
+
hasValidPercentage(value) {
|
|
92
|
+
return value != null && !Number.isNaN(value);
|
|
93
|
+
}
|
|
89
94
|
/**
|
|
90
95
|
* Get legend container dimensions
|
|
91
96
|
*/
|
|
@@ -99,11 +104,11 @@ class AXChartLegendComponent {
|
|
|
99
104
|
};
|
|
100
105
|
}
|
|
101
106
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXChartLegendComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
102
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXChartLegendComponent, isStandalone: true, selector: "ax-chart-legend", inputs: { chart: { classPropertyName: "chart", publicName: "chart", isSignal: true, isRequired: true, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { itemClick: "itemClick", itemMouseEnter: "itemMouseEnter", itemMouseLeave: "itemMouseLeave" }, viewQueries: [{ propertyName: "legendContainer", first: true, predicate: ["legendContainer"], descendants: true, isSignal: true }], ngImport: i0, template: "<div #legendContainer [ngClass]=\"containerClass()\">\n @for (item of displayItems(); track item.id) {\n <div class=\"ax-legend-item\" [class.ax-legend-item-hidden]=\"item.hidden\" (click)=\"onItemClick(item)\"\n (mouseenter)=\"onItemMouseEnter(item)\" (mouseleave)=\"onItemMouseLeave(item)\">\n <span class=\"ax-legend-color\" [style.background-color]=\"item.color\"></span>\n <span class=\"ax-legend-name\">{{ item.name }}</span>\n @if (showValues()) {\n <span class=\"ax-legend-value\">{{ item.value | number: '1.0-2' }}</span>\n }\n @if (showPercentage()) {\n <span class=\"ax-legend-percentage\">{{ item.percentage | number: '1.0-2' }}%</span>\n }\n </div>\n }\n</div>", styles: ["@
|
|
107
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXChartLegendComponent, isStandalone: true, selector: "ax-chart-legend", inputs: { chart: { classPropertyName: "chart", publicName: "chart", isSignal: true, isRequired: true, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { itemClick: "itemClick", itemMouseEnter: "itemMouseEnter", itemMouseLeave: "itemMouseLeave" }, viewQueries: [{ propertyName: "legendContainer", first: true, predicate: ["legendContainer"], descendants: true, isSignal: true }], ngImport: i0, template: "<div #legendContainer [ngClass]=\"containerClass()\">\n @for (item of displayItems(); track item.id) {\n <div class=\"ax-legend-item\" [class.ax-legend-item-hidden]=\"item.hidden\" (click)=\"onItemClick(item)\"\n (mouseenter)=\"onItemMouseEnter(item)\" (mouseleave)=\"onItemMouseLeave(item)\">\n <span class=\"ax-legend-color\" [style.background-color]=\"item.color\"></span>\n <span class=\"ax-legend-name\">{{ item.name }}</span>\n @if (showValues()) {\n <span class=\"ax-legend-value\">{{ item.value | number: '1.0-2' }}</span>\n }\n @if (showPercentage() && hasValidPercentage(item.percentage)) {\n <span class=\"ax-legend-percentage\">{{ item.percentage | number: '1.0-2' }}%</span>\n }\n </div>\n }\n</div>", styles: ["@layer properties;@layer components{ax-chart-legend{display:block;height:100%;width:100%;--ax-legend-bg: var(--ax-sys-color-lightest-surface);--ax-legend-text: var(--ax-sys-color-on-lightest-surface);--ax-legend-border: var(--ax-sys-color-border-surface);--ax-legend-radius: .5rem;--ax-legend-padding: .75rem;--ax-legend-gap: .5rem;--ax-legend-item-height: 1.75rem}.ax-chart-legend{display:flex;max-height:100%;width:100%;flex-direction:column;overflow-y:auto;background-color:rgba(var(--ax-legend-bg));border-radius:var(--ax-legend-radius);border:1px solid rgba(var(--ax-legend-border));padding:var(--ax-legend-padding);gap:var(--ax-legend-gap);color:rgba(var(--ax-legend-text))}.ax-chart-legend.ax-legend-horizontal{flex-direction:row;flex-wrap:wrap;align-items:center}.ax-legend-item{display:flex;cursor:pointer;align-items:baseline;gap:calc(var(--spacing, .25rem) * 2);border-radius:.25rem;padding-inline:calc(var(--spacing, .25rem) * 2);padding-block:calc(var(--spacing, .25rem) * 1);white-space:nowrap;height:var(--ax-legend-item-height);transition:background-color .15s ease,opacity .15s ease,transform .15s ease;color:rgba(var(--ax-legend-text))}.ax-legend-item:hover{background-color:rgba(var(--ax-legend-text))}@supports (color: color-mix(in lab,red,red)){.ax-legend-item:hover{background-color:color-mix(in srgb,rgba(var(--ax-legend-text)) 6%,transparent)}}.ax-legend-item:active{transform:scale(.98)}.ax-legend-item.ax-legend-item-hidden{opacity:75%}.ax-legend-item.ax-legend-item-hidden>.ax-legend-name{text-decoration-line:line-through}.ax-legend-item.ax-legend-item-hidden .ax-legend-color{position:relative;opacity:40%}.ax-legend-item.ax-legend-item-hidden .ax-legend-color:after{content:\"\";position:absolute;inset:calc(var(--spacing, .25rem) * 0);background:repeating-linear-gradient(45deg,rgba(var(--ax-legend-text)),rgba(var(--ax-legend-text)) 2px,transparent 2px,transparent 4px);border-radius:inherit}@supports (color: color-mix(in lab,red,red)){.ax-legend-item.ax-legend-item-hidden .ax-legend-color:after{background:repeating-linear-gradient(45deg,color-mix(in srgb,rgba(var(--ax-legend-text)) 35%,transparent),color-mix(in srgb,rgba(var(--ax-legend-text)) 35%,transparent) 2px,transparent 2px,transparent 4px)}}.ax-legend-color{width:calc(var(--spacing, .25rem) * 3);height:calc(var(--spacing, .25rem) * 3);flex-shrink:0;border-radius:3px}.ax-legend-name{font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500)}.ax-legend-value{margin-inline-start:calc(var(--spacing, .25rem) * 1);font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));opacity:70%}.ax-legend-percentage{margin-inline-start:.35rem;border-radius:var(--radius-lg, .5rem);padding-inline:.35rem;padding-block:.1rem;font-size:.7rem;--tw-leading: 1;line-height:1;--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500);background-color:rgba(var(--ax-legend-text))}@supports (color: color-mix(in lab,red,red)){.ax-legend-percentage{background-color:color-mix(in srgb,rgba(var(--ax-legend-text)) 10%,transparent)}}}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@property --tw-leading{syntax: \"*\"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-font-weight: initial;--tw-leading: initial}}}\n/*! tailwindcss v4.1.16 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "pipe", type: i1.DecimalPipe, name: "number" }], encapsulation: i0.ViewEncapsulation.None });
|
|
103
108
|
}
|
|
104
109
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXChartLegendComponent, decorators: [{
|
|
105
110
|
type: Component,
|
|
106
|
-
args: [{ selector: 'ax-chart-legend', imports: [CommonModule], encapsulation: ViewEncapsulation.None, template: "<div #legendContainer [ngClass]=\"containerClass()\">\n @for (item of displayItems(); track item.id) {\n <div class=\"ax-legend-item\" [class.ax-legend-item-hidden]=\"item.hidden\" (click)=\"onItemClick(item)\"\n (mouseenter)=\"onItemMouseEnter(item)\" (mouseleave)=\"onItemMouseLeave(item)\">\n <span class=\"ax-legend-color\" [style.background-color]=\"item.color\"></span>\n <span class=\"ax-legend-name\">{{ item.name }}</span>\n @if (showValues()) {\n <span class=\"ax-legend-value\">{{ item.value | number: '1.0-2' }}</span>\n }\n @if (showPercentage()) {\n <span class=\"ax-legend-percentage\">{{ item.percentage | number: '1.0-2' }}%</span>\n }\n </div>\n }\n</div>", styles: ["@
|
|
111
|
+
args: [{ selector: 'ax-chart-legend', imports: [CommonModule], encapsulation: ViewEncapsulation.None, template: "<div #legendContainer [ngClass]=\"containerClass()\">\n @for (item of displayItems(); track item.id) {\n <div class=\"ax-legend-item\" [class.ax-legend-item-hidden]=\"item.hidden\" (click)=\"onItemClick(item)\"\n (mouseenter)=\"onItemMouseEnter(item)\" (mouseleave)=\"onItemMouseLeave(item)\">\n <span class=\"ax-legend-color\" [style.background-color]=\"item.color\"></span>\n <span class=\"ax-legend-name\">{{ item.name }}</span>\n @if (showValues()) {\n <span class=\"ax-legend-value\">{{ item.value | number: '1.0-2' }}</span>\n }\n @if (showPercentage() && hasValidPercentage(item.percentage)) {\n <span class=\"ax-legend-percentage\">{{ item.percentage | number: '1.0-2' }}%</span>\n }\n </div>\n }\n</div>", styles: ["@layer properties;@layer components{ax-chart-legend{display:block;height:100%;width:100%;--ax-legend-bg: var(--ax-sys-color-lightest-surface);--ax-legend-text: var(--ax-sys-color-on-lightest-surface);--ax-legend-border: var(--ax-sys-color-border-surface);--ax-legend-radius: .5rem;--ax-legend-padding: .75rem;--ax-legend-gap: .5rem;--ax-legend-item-height: 1.75rem}.ax-chart-legend{display:flex;max-height:100%;width:100%;flex-direction:column;overflow-y:auto;background-color:rgba(var(--ax-legend-bg));border-radius:var(--ax-legend-radius);border:1px solid rgba(var(--ax-legend-border));padding:var(--ax-legend-padding);gap:var(--ax-legend-gap);color:rgba(var(--ax-legend-text))}.ax-chart-legend.ax-legend-horizontal{flex-direction:row;flex-wrap:wrap;align-items:center}.ax-legend-item{display:flex;cursor:pointer;align-items:baseline;gap:calc(var(--spacing, .25rem) * 2);border-radius:.25rem;padding-inline:calc(var(--spacing, .25rem) * 2);padding-block:calc(var(--spacing, .25rem) * 1);white-space:nowrap;height:var(--ax-legend-item-height);transition:background-color .15s ease,opacity .15s ease,transform .15s ease;color:rgba(var(--ax-legend-text))}.ax-legend-item:hover{background-color:rgba(var(--ax-legend-text))}@supports (color: color-mix(in lab,red,red)){.ax-legend-item:hover{background-color:color-mix(in srgb,rgba(var(--ax-legend-text)) 6%,transparent)}}.ax-legend-item:active{transform:scale(.98)}.ax-legend-item.ax-legend-item-hidden{opacity:75%}.ax-legend-item.ax-legend-item-hidden>.ax-legend-name{text-decoration-line:line-through}.ax-legend-item.ax-legend-item-hidden .ax-legend-color{position:relative;opacity:40%}.ax-legend-item.ax-legend-item-hidden .ax-legend-color:after{content:\"\";position:absolute;inset:calc(var(--spacing, .25rem) * 0);background:repeating-linear-gradient(45deg,rgba(var(--ax-legend-text)),rgba(var(--ax-legend-text)) 2px,transparent 2px,transparent 4px);border-radius:inherit}@supports (color: color-mix(in lab,red,red)){.ax-legend-item.ax-legend-item-hidden .ax-legend-color:after{background:repeating-linear-gradient(45deg,color-mix(in srgb,rgba(var(--ax-legend-text)) 35%,transparent),color-mix(in srgb,rgba(var(--ax-legend-text)) 35%,transparent) 2px,transparent 2px,transparent 4px)}}.ax-legend-color{width:calc(var(--spacing, .25rem) * 3);height:calc(var(--spacing, .25rem) * 3);flex-shrink:0;border-radius:3px}.ax-legend-name{font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500)}.ax-legend-value{margin-inline-start:calc(var(--spacing, .25rem) * 1);font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));opacity:70%}.ax-legend-percentage{margin-inline-start:.35rem;border-radius:var(--radius-lg, .5rem);padding-inline:.35rem;padding-block:.1rem;font-size:.7rem;--tw-leading: 1;line-height:1;--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500);background-color:rgba(var(--ax-legend-text))}@supports (color: color-mix(in lab,red,red)){.ax-legend-percentage{background-color:color-mix(in srgb,rgba(var(--ax-legend-text)) 10%,transparent)}}}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@property --tw-leading{syntax: \"*\"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-font-weight: initial;--tw-leading: initial}}}\n/*! tailwindcss v4.1.16 | MIT License | https://tailwindcss.com */\n"] }]
|
|
107
112
|
}], propDecorators: { chart: [{ type: i0.Input, args: [{ isSignal: true, alias: "chart", required: true }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], itemClick: [{ type: i0.Output, args: ["itemClick"] }], itemMouseEnter: [{ type: i0.Output, args: ["itemMouseEnter"] }], itemMouseLeave: [{ type: i0.Output, args: ["itemMouseLeave"] }], legendContainer: [{ type: i0.ViewChild, args: ['legendContainer', { isSignal: true }] }] } });
|
|
108
113
|
|
|
109
114
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"acorex-charts-chart-legend.mjs","sources":["../../../../packages/charts/chart-legend/src/lib/chart-legend.component.ts","../../../../packages/charts/chart-legend/src/lib/chart-legend.component.html","../../../../packages/charts/chart-legend/src/acorex-charts-chart-legend.ts"],"sourcesContent":["import { CommonModule } from '@angular/common';\nimport { Component, ElementRef, ViewEncapsulation, computed, input, output, viewChild } from '@angular/core';\nimport { AXChartLegendCompatible, AXChartLegendItem, AXChartLegendOptions } from './chart-legend.type';\n\n@Component({\n selector: 'ax-chart-legend',\n templateUrl: './chart-legend.component.html',\n styleUrls: ['./chart-legend.component.css'],\n imports: [CommonModule],\n\n encapsulation: ViewEncapsulation.None,\n})\nexport class AXChartLegendComponent {\n /**\n * Chart component instance\n * Must implement AXChartLegendCompatible interface\n */\n chart = input.required<AXChartLegendCompatible>();\n\n /**\n * Configuration options for the legend\n */\n options = input<AXChartLegendOptions>({});\n\n /**\n * Event emitted when a legend item is clicked\n * Returns the item that was clicked\n */\n itemClick = output<AXChartLegendItem>();\n\n /**\n * Event emitted when the mouse enters a legend item\n */\n itemMouseEnter = output<AXChartLegendItem>();\n\n /**\n * Event emitted when the mouse leaves a legend item\n */\n itemMouseLeave = output<AXChartLegendItem>();\n\n /**\n * Reference to legend container for measuring dimensions\n */\n legendContainer = viewChild<ElementRef<HTMLDivElement>>('legendContainer');\n\n // Computed values for the template\n protected showValues = computed(() => this.options()?.showValues !== false);\n protected showPercentage = computed(() => this.options()?.showPercentage !== false);\n protected containerClass = computed(() => {\n const opts = this.options();\n const className = opts?.className || '';\n const mode = opts?.mode || 'vertical';\n return {\n 'ax-chart-legend': true,\n [className]: !!className,\n [`ax-legend-${mode}`]: true,\n };\n });\n\n // Track if the legend is interactive\n protected isInteractive = computed(() => this.options()?.interactive !== false);\n\n // Compute the items to display from the chart\n protected displayItems = computed(() => {\n
|
|
1
|
+
{"version":3,"file":"acorex-charts-chart-legend.mjs","sources":["../../../../packages/charts/chart-legend/src/lib/chart-legend.component.ts","../../../../packages/charts/chart-legend/src/lib/chart-legend.component.html","../../../../packages/charts/chart-legend/src/acorex-charts-chart-legend.ts"],"sourcesContent":["import { CommonModule } from '@angular/common';\nimport { Component, ElementRef, ViewEncapsulation, computed, input, output, signal, viewChild } from '@angular/core';\nimport { AXChartLegendCompatible, AXChartLegendItem, AXChartLegendOptions } from './chart-legend.type';\n\n@Component({\n selector: 'ax-chart-legend',\n templateUrl: './chart-legend.component.html',\n styleUrls: ['./chart-legend.component.css'],\n imports: [CommonModule],\n\n encapsulation: ViewEncapsulation.None,\n})\nexport class AXChartLegendComponent {\n /**\n * Chart component instance\n * Must implement AXChartLegendCompatible interface\n */\n chart = input.required<AXChartLegendCompatible>();\n\n /**\n * Configuration options for the legend\n */\n options = input<AXChartLegendOptions>({});\n\n /**\n * Event emitted when a legend item is clicked\n * Returns the item that was clicked\n */\n itemClick = output<AXChartLegendItem>();\n\n /**\n * Event emitted when the mouse enters a legend item\n */\n itemMouseEnter = output<AXChartLegendItem>();\n\n /**\n * Event emitted when the mouse leaves a legend item\n */\n itemMouseLeave = output<AXChartLegendItem>();\n\n /**\n * Reference to legend container for measuring dimensions\n */\n legendContainer = viewChild<ElementRef<HTMLDivElement>>('legendContainer');\n\n private readonly interactionVersion = signal(0);\n\n // Computed values for the template\n protected showValues = computed(() => this.options()?.showValues !== false);\n protected showPercentage = computed(() => this.options()?.showPercentage !== false);\n protected containerClass = computed(() => {\n const opts = this.options();\n const className = opts?.className || '';\n const mode = opts?.mode || 'vertical';\n return {\n 'ax-chart-legend': true,\n [className]: !!className,\n [`ax-legend-${mode}`]: true,\n };\n });\n\n // Track if the legend is interactive\n protected isInteractive = computed(() => this.options()?.interactive !== false);\n\n // Compute the items to display from the chart\n protected displayItems = computed(() => {\n const chart = this.chart();\n chart.legendStateVersion?.();\n this.interactionVersion();\n return chart.getLegendItems();\n });\n\n /**\n * Handle clicks on legend items\n */\n protected onItemClick(item: AXChartLegendItem): void {\n const chartInstance = this.chart();\n\n if (this.isInteractive()) {\n chartInstance.toggleSegment(item.id);\n this.interactionVersion.update((version) => version + 1);\n }\n\n const refreshedItem = this.displayItems().find((legendItem) => legendItem.id === item.id) ?? item;\n this.itemClick.emit(refreshedItem);\n }\n\n /**\n * Handle mouse enter on legend items\n */\n protected onItemMouseEnter(item: AXChartLegendItem): void {\n this.itemMouseEnter.emit(item);\n this.chart().highlightSegment(item.id);\n }\n\n /**\n * Handle mouse leave on legend items\n */\n protected onItemMouseLeave(item: AXChartLegendItem): void {\n this.itemMouseLeave.emit(item);\n this.chart().highlightSegment(null);\n }\n\n protected hasValidPercentage(value: number | undefined): boolean {\n return value != null && !Number.isNaN(value);\n }\n\n /**\n * Get legend container dimensions\n */\n getDimensions(): { width: number; height: number } {\n if (!this.legendContainer()?.nativeElement) {\n return { width: 0, height: 0 };\n }\n\n return {\n width: this.legendContainer().nativeElement.offsetWidth,\n height: this.legendContainer().nativeElement.offsetHeight,\n };\n }\n}\n","<div #legendContainer [ngClass]=\"containerClass()\">\n @for (item of displayItems(); track item.id) {\n <div class=\"ax-legend-item\" [class.ax-legend-item-hidden]=\"item.hidden\" (click)=\"onItemClick(item)\"\n (mouseenter)=\"onItemMouseEnter(item)\" (mouseleave)=\"onItemMouseLeave(item)\">\n <span class=\"ax-legend-color\" [style.background-color]=\"item.color\"></span>\n <span class=\"ax-legend-name\">{{ item.name }}</span>\n @if (showValues()) {\n <span class=\"ax-legend-value\">{{ item.value | number: '1.0-2' }}</span>\n }\n @if (showPercentage() && hasValidPercentage(item.percentage)) {\n <span class=\"ax-legend-percentage\">{{ item.percentage | number: '1.0-2' }}%</span>\n }\n </div>\n }\n</div>","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as i1 from '@angular/common';
|
|
2
2
|
import { CommonModule } from '@angular/common';
|
|
3
3
|
import * as i0 from '@angular/core';
|
|
4
|
-
import { inject, NgZone, input, viewChild,
|
|
4
|
+
import { inject, NgZone, input, viewChild, effect, ViewEncapsulation, Component } from '@angular/core';
|
|
5
5
|
|
|
6
6
|
class AXChartTooltipComponent {
|
|
7
7
|
ngZone = inject(NgZone);
|
|
@@ -30,9 +30,10 @@ class AXChartTooltipComponent {
|
|
|
30
30
|
tooltipWidth = 0;
|
|
31
31
|
tooltipHeight = 0;
|
|
32
32
|
constructor() {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
effect(() => {
|
|
34
|
+
if (this.visible() && this.data()) {
|
|
35
|
+
this.updateTooltipDimensions();
|
|
36
|
+
}
|
|
36
37
|
});
|
|
37
38
|
}
|
|
38
39
|
// Helpers to support color as string | string[]
|
|
@@ -101,13 +102,13 @@ class AXChartTooltipComponent {
|
|
|
101
102
|
};
|
|
102
103
|
}
|
|
103
104
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXChartTooltipComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
104
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXChartTooltipComponent, isStandalone: true, selector: "ax-chart-tooltip", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null }, visible: { classPropertyName: "visible", publicName: "visible", isSignal: true, isRequired: false, transformFunction: null }, showPercentage: { classPropertyName: "showPercentage", publicName: "showPercentage", isSignal: true, isRequired: false, transformFunction: null }, style: { classPropertyName: "style", publicName: "style", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "ax-chart-tooltip-host" }, viewQueries: [{ propertyName: "tooltipContainer", first: true, predicate: ["tooltipContainer"], descendants: true, isSignal: true }], ngImport: i0, template: "@if (visible() && data()) {\n <div\n #tooltipContainer\n class=\"chart-tooltip chart-tooltip-visible\"\n [style.
|
|
105
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXChartTooltipComponent, isStandalone: true, selector: "ax-chart-tooltip", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null }, visible: { classPropertyName: "visible", publicName: "visible", isSignal: true, isRequired: false, transformFunction: null }, showPercentage: { classPropertyName: "showPercentage", publicName: "showPercentage", isSignal: true, isRequired: false, transformFunction: null }, style: { classPropertyName: "style", publicName: "style", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "ax-chart-tooltip-host" }, viewQueries: [{ propertyName: "tooltipContainer", first: true, predicate: ["tooltipContainer"], descendants: true, isSignal: true }], ngImport: i0, template: "@if (visible() && data()) {\n <div\n #tooltipContainer\n class=\"chart-tooltip chart-tooltip-visible\"\n [style.left.px]=\"position().x\"\n [style.top.px]=\"position().y\"\n [ngStyle]=\"style()\"\n aria-hidden=\"false\"\n >\n <div class=\"chart-tooltip-content\">\n <div class=\"chart-tooltip-body\">\n @if (!isTitleArray()) {\n <div class=\"chart-tooltip-title-row\">\n @if (singleColor()) {\n <div class=\"chart-tooltip-color\" [style.background-color]=\"singleColor()!\"></div>\n }\n <div class=\"chart-tooltip-title\">\n {{ data()!.title }}\n </div>\n </div>\n } @else {\n <div class=\"chart-tooltip-title-list\">\n @for (t of titleList(); let i = $index; track $index) {\n <div class=\"chart-tooltip-title-row\">\n @if (colorAt(i)) {\n <div class=\"chart-tooltip-color\" [style.background-color]=\"colorAt(i)!\"></div>\n }\n <div class=\"chart-tooltip-title\">\n {{ t }}\n </div>\n </div>\n }\n </div>\n }\n\n <div class=\"chart-tooltip-value-row\">\n <div class=\"chart-tooltip-value\">{{ formattedValue() }}</div>\n @if (showPercentage() && data()!.percentage) {\n <div class=\"chart-tooltip-percentage\">\n {{ data()!.percentage }}\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n}\n", styles: ["@layer properties;@layer components{ax-chart-tooltip.ax-chart-tooltip-host{pointer-events:none;position:absolute;top:calc(var(--spacing, .25rem) * 0);left:calc(var(--spacing, .25rem) * 0);z-index:10;width:calc(var(--spacing, .25rem) * 0);height:calc(var(--spacing, .25rem) * 0);overflow:visible;--ax-comp-chart-tooltip-bg-color: 23, 23, 23;--ax-comp-chart-tooltip-text-color: 245, 245, 245}.chart-tooltip{pointer-events:none;visibility:hidden;position:absolute;z-index:1000;width:max-content;max-width:250px;border-radius:var(--radius-md, .375rem);border-style:var(--tw-border-style);border-width:1px;border-color:color-mix(in srgb,#fff 10%,transparent);padding-inline:calc(var(--spacing, .25rem) * 3);padding-block:calc(var(--spacing, .25rem) * 2);font-size:.8rem;opacity:0%;--tw-backdrop-blur: blur(var(--blur-sm, 8px));-webkit-backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);transition-property:opacity;transition-timing-function:var(--tw-ease, var(--default-transition-timing-function, cubic-bezier(.4, 0, .2, 1)));transition-duration:var(--tw-duration, var(--default-transition-duration, .15s));--tw-duration: .15s;transition-duration:.15s;--tw-ease: var(--ease-in, cubic-bezier(.4, 0, 1, 1));transition-timing-function:var(--ease-in, cubic-bezier(.4, 0, 1, 1));background-color:rgba(var(--ax-comp-chart-tooltip-bg-color),.96);color:rgba(var(--ax-comp-chart-tooltip-text-color));box-shadow:0 10px 15px -3px #00000059,0 4px 6px -2px #0003}@supports (color: color-mix(in lab,red,red)){.chart-tooltip{border-color:color-mix(in oklab,var(--color-white, #fff) 10%,transparent)}}.chart-tooltip-visible{visibility:visible;opacity:100%}.chart-tooltip-content{display:flex;align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 2)}.chart-tooltip-body{display:flex;flex-direction:column;overflow:hidden;text-overflow:ellipsis}.chart-tooltip-title-row{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 1.5);padding-bottom:calc(var(--spacing, .25rem) * 2)}.chart-tooltip-title-list .chart-tooltip-title-row{padding-bottom:calc(var(--spacing, .25rem) * 1)}.chart-tooltip-color{width:calc(var(--spacing, .25rem) * 2.5);height:calc(var(--spacing, .25rem) * 2.5);flex-shrink:0;border-radius:2px}.chart-tooltip-title{overflow:hidden;--tw-leading: 1.2;line-height:1.2;--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);text-overflow:ellipsis;white-space:nowrap}.chart-tooltip-value-row{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 2);white-space:nowrap}.chart-tooltip-value{flex-grow:1;--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500)}.chart-tooltip-percentage{flex-shrink:0;border-radius:calc(infinity * 1px);padding-inline:calc(var(--spacing, .25rem) * 1.5);padding-block:calc(var(--spacing, .25rem) * .5);font-size:.7rem;--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500);background-color:rgba(var(--ax-comp-chart-tooltip-text-color))}@supports (color: color-mix(in lab,red,red)){.chart-tooltip-percentage{background-color:color-mix(in srgb,rgba(var(--ax-comp-chart-tooltip-text-color)) 20%,transparent)}}}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-backdrop-blur{syntax: \"*\"; inherits: false;}@property --tw-backdrop-brightness{syntax: \"*\"; inherits: false;}@property --tw-backdrop-contrast{syntax: \"*\"; inherits: false;}@property --tw-backdrop-grayscale{syntax: \"*\"; inherits: false;}@property --tw-backdrop-hue-rotate{syntax: \"*\"; inherits: false;}@property --tw-backdrop-invert{syntax: \"*\"; inherits: false;}@property --tw-backdrop-opacity{syntax: \"*\"; inherits: false;}@property --tw-backdrop-saturate{syntax: \"*\"; inherits: false;}@property --tw-backdrop-sepia{syntax: \"*\"; inherits: false;}@property --tw-duration{syntax: \"*\"; inherits: false;}@property --tw-ease{syntax: \"*\"; inherits: false;}@property --tw-leading{syntax: \"*\"; inherits: false;}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style: solid;--tw-backdrop-blur: initial;--tw-backdrop-brightness: initial;--tw-backdrop-contrast: initial;--tw-backdrop-grayscale: initial;--tw-backdrop-hue-rotate: initial;--tw-backdrop-invert: initial;--tw-backdrop-opacity: initial;--tw-backdrop-saturate: initial;--tw-backdrop-sepia: initial;--tw-duration: initial;--tw-ease: initial;--tw-leading: initial;--tw-font-weight: initial}}}\n/*! tailwindcss v4.1.16 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }], encapsulation: i0.ViewEncapsulation.None });
|
|
105
106
|
}
|
|
106
107
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXChartTooltipComponent, decorators: [{
|
|
107
108
|
type: Component,
|
|
108
|
-
args: [{ selector: 'ax-chart-tooltip', imports: [CommonModule], encapsulation: ViewEncapsulation.None,
|
|
109
|
+
args: [{ selector: 'ax-chart-tooltip', imports: [CommonModule], encapsulation: ViewEncapsulation.None, host: {
|
|
109
110
|
class: 'ax-chart-tooltip-host',
|
|
110
|
-
}, template: "@if (visible() && data()) {\n <div\n #tooltipContainer\n class=\"chart-tooltip chart-tooltip-visible\"\n [style.
|
|
111
|
+
}, template: "@if (visible() && data()) {\n <div\n #tooltipContainer\n class=\"chart-tooltip chart-tooltip-visible\"\n [style.left.px]=\"position().x\"\n [style.top.px]=\"position().y\"\n [ngStyle]=\"style()\"\n aria-hidden=\"false\"\n >\n <div class=\"chart-tooltip-content\">\n <div class=\"chart-tooltip-body\">\n @if (!isTitleArray()) {\n <div class=\"chart-tooltip-title-row\">\n @if (singleColor()) {\n <div class=\"chart-tooltip-color\" [style.background-color]=\"singleColor()!\"></div>\n }\n <div class=\"chart-tooltip-title\">\n {{ data()!.title }}\n </div>\n </div>\n } @else {\n <div class=\"chart-tooltip-title-list\">\n @for (t of titleList(); let i = $index; track $index) {\n <div class=\"chart-tooltip-title-row\">\n @if (colorAt(i)) {\n <div class=\"chart-tooltip-color\" [style.background-color]=\"colorAt(i)!\"></div>\n }\n <div class=\"chart-tooltip-title\">\n {{ t }}\n </div>\n </div>\n }\n </div>\n }\n\n <div class=\"chart-tooltip-value-row\">\n <div class=\"chart-tooltip-value\">{{ formattedValue() }}</div>\n @if (showPercentage() && data()!.percentage) {\n <div class=\"chart-tooltip-percentage\">\n {{ data()!.percentage }}\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n}\n", styles: ["@layer properties;@layer components{ax-chart-tooltip.ax-chart-tooltip-host{pointer-events:none;position:absolute;top:calc(var(--spacing, .25rem) * 0);left:calc(var(--spacing, .25rem) * 0);z-index:10;width:calc(var(--spacing, .25rem) * 0);height:calc(var(--spacing, .25rem) * 0);overflow:visible;--ax-comp-chart-tooltip-bg-color: 23, 23, 23;--ax-comp-chart-tooltip-text-color: 245, 245, 245}.chart-tooltip{pointer-events:none;visibility:hidden;position:absolute;z-index:1000;width:max-content;max-width:250px;border-radius:var(--radius-md, .375rem);border-style:var(--tw-border-style);border-width:1px;border-color:color-mix(in srgb,#fff 10%,transparent);padding-inline:calc(var(--spacing, .25rem) * 3);padding-block:calc(var(--spacing, .25rem) * 2);font-size:.8rem;opacity:0%;--tw-backdrop-blur: blur(var(--blur-sm, 8px));-webkit-backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);transition-property:opacity;transition-timing-function:var(--tw-ease, var(--default-transition-timing-function, cubic-bezier(.4, 0, .2, 1)));transition-duration:var(--tw-duration, var(--default-transition-duration, .15s));--tw-duration: .15s;transition-duration:.15s;--tw-ease: var(--ease-in, cubic-bezier(.4, 0, 1, 1));transition-timing-function:var(--ease-in, cubic-bezier(.4, 0, 1, 1));background-color:rgba(var(--ax-comp-chart-tooltip-bg-color),.96);color:rgba(var(--ax-comp-chart-tooltip-text-color));box-shadow:0 10px 15px -3px #00000059,0 4px 6px -2px #0003}@supports (color: color-mix(in lab,red,red)){.chart-tooltip{border-color:color-mix(in oklab,var(--color-white, #fff) 10%,transparent)}}.chart-tooltip-visible{visibility:visible;opacity:100%}.chart-tooltip-content{display:flex;align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 2)}.chart-tooltip-body{display:flex;flex-direction:column;overflow:hidden;text-overflow:ellipsis}.chart-tooltip-title-row{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 1.5);padding-bottom:calc(var(--spacing, .25rem) * 2)}.chart-tooltip-title-list .chart-tooltip-title-row{padding-bottom:calc(var(--spacing, .25rem) * 1)}.chart-tooltip-color{width:calc(var(--spacing, .25rem) * 2.5);height:calc(var(--spacing, .25rem) * 2.5);flex-shrink:0;border-radius:2px}.chart-tooltip-title{overflow:hidden;--tw-leading: 1.2;line-height:1.2;--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);text-overflow:ellipsis;white-space:nowrap}.chart-tooltip-value-row{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 2);white-space:nowrap}.chart-tooltip-value{flex-grow:1;--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500)}.chart-tooltip-percentage{flex-shrink:0;border-radius:calc(infinity * 1px);padding-inline:calc(var(--spacing, .25rem) * 1.5);padding-block:calc(var(--spacing, .25rem) * .5);font-size:.7rem;--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500);background-color:rgba(var(--ax-comp-chart-tooltip-text-color))}@supports (color: color-mix(in lab,red,red)){.chart-tooltip-percentage{background-color:color-mix(in srgb,rgba(var(--ax-comp-chart-tooltip-text-color)) 20%,transparent)}}}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-backdrop-blur{syntax: \"*\"; inherits: false;}@property --tw-backdrop-brightness{syntax: \"*\"; inherits: false;}@property --tw-backdrop-contrast{syntax: \"*\"; inherits: false;}@property --tw-backdrop-grayscale{syntax: \"*\"; inherits: false;}@property --tw-backdrop-hue-rotate{syntax: \"*\"; inherits: false;}@property --tw-backdrop-invert{syntax: \"*\"; inherits: false;}@property --tw-backdrop-opacity{syntax: \"*\"; inherits: false;}@property --tw-backdrop-saturate{syntax: \"*\"; inherits: false;}@property --tw-backdrop-sepia{syntax: \"*\"; inherits: false;}@property --tw-duration{syntax: \"*\"; inherits: false;}@property --tw-ease{syntax: \"*\"; inherits: false;}@property --tw-leading{syntax: \"*\"; inherits: false;}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style: solid;--tw-backdrop-blur: initial;--tw-backdrop-brightness: initial;--tw-backdrop-contrast: initial;--tw-backdrop-grayscale: initial;--tw-backdrop-hue-rotate: initial;--tw-backdrop-invert: initial;--tw-backdrop-opacity: initial;--tw-backdrop-saturate: initial;--tw-backdrop-sepia: initial;--tw-duration: initial;--tw-ease: initial;--tw-leading: initial;--tw-font-weight: initial}}}\n/*! tailwindcss v4.1.16 | MIT License | https://tailwindcss.com */\n"] }]
|
|
111
112
|
}], ctorParameters: () => [], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], position: [{ type: i0.Input, args: [{ isSignal: true, alias: "position", required: false }] }], visible: [{ type: i0.Input, args: [{ isSignal: true, alias: "visible", required: false }] }], showPercentage: [{ type: i0.Input, args: [{ isSignal: true, alias: "showPercentage", required: false }] }], style: [{ type: i0.Input, args: [{ isSignal: true, alias: "style", required: false }] }], tooltipContainer: [{ type: i0.ViewChild, args: ['tooltipContainer', { isSignal: true }] }] } });
|
|
112
113
|
|
|
113
114
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"acorex-charts-chart-tooltip.mjs","sources":["../../../../packages/charts/chart-tooltip/src/lib/chart-tooltip.component.ts","../../../../packages/charts/chart-tooltip/src/lib/chart-tooltip.component.html","../../../../packages/charts/chart-tooltip/src/acorex-charts-chart-tooltip.ts"],"sourcesContent":["import { CommonModule } from '@angular/common';\nimport {
|
|
1
|
+
{"version":3,"file":"acorex-charts-chart-tooltip.mjs","sources":["../../../../packages/charts/chart-tooltip/src/lib/chart-tooltip.component.ts","../../../../packages/charts/chart-tooltip/src/lib/chart-tooltip.component.html","../../../../packages/charts/chart-tooltip/src/acorex-charts-chart-tooltip.ts"],"sourcesContent":["import { CommonModule } from '@angular/common';\nimport { Component, ElementRef, NgZone, ViewEncapsulation, effect, inject, input, viewChild } from '@angular/core';\nimport { AXChartTooltipData } from './chart-tooltip.type';\n\n@Component({\n selector: 'ax-chart-tooltip',\n templateUrl: './chart-tooltip.component.html',\n styleUrls: ['./chart-tooltip.component.css'],\n imports: [CommonModule],\n encapsulation: ViewEncapsulation.None,\n host: {\n class: 'ax-chart-tooltip-host',\n },\n})\nexport class AXChartTooltipComponent {\n private ngZone = inject(NgZone);\n\n data = input<AXChartTooltipData | null>(null);\n position = input<{ x: number; y: number }>({ x: 0, y: 0 });\n visible = input<boolean>(false);\n\n /**\n * Whether to show the tooltip's percentage badge\n */\n showPercentage = input<boolean>(true);\n\n /**\n * Optional custom styling for the tooltip\n */\n style = input<{ [key: string]: string }>({});\n\n /**\n * Reference to tooltip container for measuring dimensions\n */\n tooltipContainer = viewChild<ElementRef<HTMLDivElement>>('tooltipContainer');\n\n // Tooltip dimensions\n protected tooltipWidth = 0;\n protected tooltipHeight = 0;\n\n constructor() {\n effect(() => {\n if (this.visible() && this.data()) {\n this.updateTooltipDimensions();\n }\n });\n }\n\n // Helpers to support color as string | string[]\n protected isColorArray(): boolean {\n const color = this.data()?.color as unknown;\n return Array.isArray(color);\n }\n\n protected colorList(): string[] {\n const color = this.data()?.color as unknown;\n return Array.isArray(color) ? (color as string[]) : [];\n }\n\n protected singleColor(): string | null {\n const color = this.data()?.color as unknown;\n return typeof color === 'string' ? (color as string) : null;\n }\n\n protected isTitleArray(): boolean {\n const t = this.data()?.title as unknown;\n return Array.isArray(t);\n }\n\n protected titleList(): string[] {\n const t = this.data()?.title as unknown;\n return Array.isArray(t) ? (t as string[]) : [];\n }\n\n protected colorAt(index: number): string | null {\n const c = this.data()?.color as unknown;\n if (Array.isArray(c)) {\n return (c as string[])[index] ?? null;\n }\n return typeof c === 'string' ? (c as string) : null;\n }\n\n protected formattedValue(): string {\n const v = this.data()?.value;\n if (v == null) return '';\n if (typeof v === 'number') return v.toLocaleString();\n const num = Number(v);\n return isNaN(num) ? v : num.toLocaleString();\n }\n\n /**\n * Updates tooltip dimensions after it's rendered\n */\n protected updateTooltipDimensions(): void {\n if (!this.visible()) {\n return;\n }\n\n this.ngZone.runOutsideAngular(() => {\n requestAnimationFrame(() => {\n const tooltipEl = this.tooltipContainer()?.nativeElement;\n if (!tooltipEl) {\n return;\n }\n\n this.tooltipWidth = tooltipEl.offsetWidth;\n this.tooltipHeight = tooltipEl.offsetHeight;\n });\n });\n }\n\n /**\n * Get adjusted tooltip position\n * Exposes properties for parent components to query tooltip dimensions\n */\n getDimensions(): { width: number; height: number } {\n return {\n width: this.tooltipWidth,\n height: this.tooltipHeight,\n };\n }\n}\n","@if (visible() && data()) {\n <div\n #tooltipContainer\n class=\"chart-tooltip chart-tooltip-visible\"\n [style.left.px]=\"position().x\"\n [style.top.px]=\"position().y\"\n [ngStyle]=\"style()\"\n aria-hidden=\"false\"\n >\n <div class=\"chart-tooltip-content\">\n <div class=\"chart-tooltip-body\">\n @if (!isTitleArray()) {\n <div class=\"chart-tooltip-title-row\">\n @if (singleColor()) {\n <div class=\"chart-tooltip-color\" [style.background-color]=\"singleColor()!\"></div>\n }\n <div class=\"chart-tooltip-title\">\n {{ data()!.title }}\n </div>\n </div>\n } @else {\n <div class=\"chart-tooltip-title-list\">\n @for (t of titleList(); let i = $index; track $index) {\n <div class=\"chart-tooltip-title-row\">\n @if (colorAt(i)) {\n <div class=\"chart-tooltip-color\" [style.background-color]=\"colorAt(i)!\"></div>\n }\n <div class=\"chart-tooltip-title\">\n {{ t }}\n </div>\n </div>\n }\n </div>\n }\n\n <div class=\"chart-tooltip-value-row\">\n <div class=\"chart-tooltip-value\">{{ formattedValue() }}</div>\n @if (showPercentage() && data()!.percentage) {\n <div class=\"chart-tooltip-percentage\">\n {{ data()!.percentage }}\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -63,6 +63,9 @@ class AXDonutChartComponent extends AXChartComponent {
|
|
|
63
63
|
pieData = [];
|
|
64
64
|
// State management
|
|
65
65
|
hiddenSegments = new Set();
|
|
66
|
+
_legendStateVersion = signal(0, /* @ts-ignore */
|
|
67
|
+
...(ngDevMode ? [{ debugName: "_legendStateVersion" }] : /* istanbul ignore next */ []));
|
|
68
|
+
legendStateVersion = this._legendStateVersion.asReadonly();
|
|
66
69
|
_initialized = signal(false, /* @ts-ignore */
|
|
67
70
|
...(ngDevMode ? [{ debugName: "_initialized" }] : /* istanbul ignore next */ []));
|
|
68
71
|
_rendered = signal(false, /* @ts-ignore */
|
|
@@ -143,10 +146,14 @@ class AXDonutChartComponent extends AXChartComponent {
|
|
|
143
146
|
untracked(() => {
|
|
144
147
|
if (this._rendered()) {
|
|
145
148
|
this.updateChart();
|
|
149
|
+
this.bumpLegendState();
|
|
146
150
|
}
|
|
147
151
|
});
|
|
148
152
|
}, /* @ts-ignore */
|
|
149
153
|
...(ngDevMode ? [{ debugName: "dataChangeEffect" }] : /* istanbul ignore next */ []));
|
|
154
|
+
bumpLegendState() {
|
|
155
|
+
this._legendStateVersion.update((version) => version + 1);
|
|
156
|
+
}
|
|
150
157
|
/**
|
|
151
158
|
* Highlights a specific segment by ID
|
|
152
159
|
* @param id The segment ID to highlight, or null to clear highlight
|
|
@@ -251,6 +258,7 @@ class AXDonutChartComponent extends AXChartComponent {
|
|
|
251
258
|
this.hiddenSegments.add(id);
|
|
252
259
|
this.updateChart();
|
|
253
260
|
}
|
|
261
|
+
this.bumpLegendState();
|
|
254
262
|
return !this.isSegmentHidden(id);
|
|
255
263
|
}
|
|
256
264
|
ngOnDestroy() {
|
|
@@ -369,10 +377,19 @@ class AXDonutChartComponent extends AXChartComponent {
|
|
|
369
377
|
const svg = this.createSvgWithFilters(container, width, height);
|
|
370
378
|
// Create main chart group
|
|
371
379
|
this.svg = svg.append('g').attr('transform', `translate(${width / 2}, ${height / 2})`);
|
|
380
|
+
const { innerRadius } = this.getDonutRadii(width, height);
|
|
372
381
|
// Create donut segments
|
|
373
382
|
this.createDonutSegments(width, height, visibleData, layoutTotal);
|
|
374
383
|
// Add total in center
|
|
375
|
-
this.addCenterDisplay(displayTotal);
|
|
384
|
+
this.addCenterDisplay(displayTotal, innerRadius);
|
|
385
|
+
}
|
|
386
|
+
getDonutRadii(chartWidth, chartHeight) {
|
|
387
|
+
const maxRadius = Math.min(chartWidth, chartHeight) / 2;
|
|
388
|
+
const radius = Math.max(0, maxRadius - this.CHART_INSET);
|
|
389
|
+
const donutWidthPercent = this.effectiveOptions().donutWidth / 100;
|
|
390
|
+
const innerRadius = radius * (1 - donutWidthPercent);
|
|
391
|
+
const outerRadius = radius * 0.95;
|
|
392
|
+
return { innerRadius, outerRadius, radius };
|
|
376
393
|
}
|
|
377
394
|
/**
|
|
378
395
|
* Create SVG element with filter definitions for shadows
|
|
@@ -413,13 +430,7 @@ class AXDonutChartComponent extends AXChartComponent {
|
|
|
413
430
|
.value((d) => this.getSegmentLayoutValue(d.value))
|
|
414
431
|
.sort(null)
|
|
415
432
|
.padAngle(0.02);
|
|
416
|
-
|
|
417
|
-
const maxRadius = Math.min(chartWidth, chartHeight) / 2;
|
|
418
|
-
const radius = Math.max(0, maxRadius - this.CHART_INSET);
|
|
419
|
-
// Calculate inner radius based on donutWidth percentage
|
|
420
|
-
const donutWidthPercent = this.effectiveOptions().donutWidth / 100;
|
|
421
|
-
const innerRadius = radius * (1 - donutWidthPercent);
|
|
422
|
-
const outerRadius = radius * 0.95;
|
|
433
|
+
const { innerRadius, outerRadius } = this.getDonutRadii(chartWidth, chartHeight);
|
|
423
434
|
const ringWidth = outerRadius - innerRadius;
|
|
424
435
|
const arc = this.d3
|
|
425
436
|
.arc()
|
|
@@ -705,44 +716,79 @@ class AXDonutChartComponent extends AXChartComponent {
|
|
|
705
716
|
return;
|
|
706
717
|
}
|
|
707
718
|
this._tooltipRafId = null;
|
|
708
|
-
const containerRect = containerEl.getBoundingClientRect();
|
|
709
719
|
const tooltipRect = tooltipEl ? tooltipEl.getBoundingClientRect() : null;
|
|
710
|
-
const pos = computeTooltipPosition(
|
|
720
|
+
const pos = computeTooltipPosition(containerEl, tooltipRect, coords.x, coords.y, this.TOOLTIP_GAP);
|
|
711
721
|
this._tooltipPosition.set(pos);
|
|
712
722
|
});
|
|
713
723
|
}
|
|
724
|
+
cancelTooltipPosition() {
|
|
725
|
+
if (this._tooltipRafId != null) {
|
|
726
|
+
cancelAnimationFrame(this._tooltipRafId);
|
|
727
|
+
this._tooltipRafId = null;
|
|
728
|
+
}
|
|
729
|
+
this._pendingTooltipCoords = null;
|
|
730
|
+
}
|
|
714
731
|
/**
|
|
715
|
-
* Adds center display with total value
|
|
732
|
+
* Adds center display with total value, scaled to fit the donut hole.
|
|
716
733
|
*/
|
|
717
|
-
addCenterDisplay(displayTotal) {
|
|
718
|
-
if (!this.svg)
|
|
734
|
+
addCenterDisplay(displayTotal, innerRadius) {
|
|
735
|
+
if (!this.svg || innerRadius <= 0)
|
|
719
736
|
return;
|
|
720
|
-
const
|
|
721
|
-
|
|
722
|
-
const
|
|
723
|
-
const
|
|
724
|
-
|
|
737
|
+
const valueText = displayTotal.toLocaleString();
|
|
738
|
+
const labelText = this.effectiveOptions().totalLabel || 'Total';
|
|
739
|
+
const { valueFontSize, labelFontSize, displayLabel } = this.calculateCenterTextSizes(valueText, labelText, innerRadius);
|
|
740
|
+
const labelLineHeight = labelFontSize * 1.3;
|
|
741
|
+
const valueY = -(labelLineHeight / 2);
|
|
725
742
|
const totalDisplay = this.svg
|
|
726
743
|
.append('g')
|
|
727
744
|
.attr('class', 'ax-donut-chart-total-display')
|
|
728
745
|
.attr('text-anchor', 'middle');
|
|
729
|
-
// Add total value
|
|
730
746
|
totalDisplay
|
|
731
747
|
.append('text')
|
|
732
748
|
.attr('class', 'ax-donut-chart-total-value')
|
|
733
|
-
.
|
|
749
|
+
.attr('y', valueY)
|
|
750
|
+
.attr('dominant-baseline', 'middle')
|
|
751
|
+
.style('font-size', `${valueFontSize}px`)
|
|
734
752
|
.style('font-weight', '600')
|
|
735
753
|
.style('fill', 'rgb(var(--ax-comp-donut-chart-value-color))')
|
|
736
|
-
.text(
|
|
737
|
-
// Add label
|
|
754
|
+
.text(valueText);
|
|
738
755
|
totalDisplay
|
|
739
756
|
.append('text')
|
|
740
757
|
.attr('class', 'ax-donut-chart-total-label')
|
|
741
|
-
.attr('
|
|
742
|
-
.
|
|
758
|
+
.attr('y', valueY + valueFontSize * 0.55 + labelLineHeight / 2)
|
|
759
|
+
.attr('dominant-baseline', 'middle')
|
|
760
|
+
.style('font-size', `${labelFontSize}px`)
|
|
743
761
|
.style('fill', 'rgb(var(--ax-comp-donut-chart-value-color))')
|
|
744
762
|
.style('opacity', '0.8')
|
|
745
|
-
.text(
|
|
763
|
+
.text(displayLabel);
|
|
764
|
+
}
|
|
765
|
+
calculateCenterTextSizes(valueText, labelText, innerRadius) {
|
|
766
|
+
const availableDiameter = innerRadius * 2;
|
|
767
|
+
const availableWidth = availableDiameter * 0.82;
|
|
768
|
+
const availableHeight = availableDiameter * 0.78;
|
|
769
|
+
const MIN_VALUE_FONT = 9;
|
|
770
|
+
const MAX_VALUE_FONT = innerRadius * 0.42;
|
|
771
|
+
let valueFontSize = Math.min(innerRadius * 0.34, MAX_VALUE_FONT);
|
|
772
|
+
while (valueFontSize > MIN_VALUE_FONT && !this.doesTextFit(valueText, valueFontSize, availableWidth)) {
|
|
773
|
+
valueFontSize -= 0.5;
|
|
774
|
+
}
|
|
775
|
+
valueFontSize = Math.max(MIN_VALUE_FONT, Math.round(valueFontSize * 2) / 2);
|
|
776
|
+
let labelFontSize = Math.max(8, Math.round(valueFontSize * 0.42 * 2) / 2);
|
|
777
|
+
const labelLineHeight = labelFontSize * 1.3;
|
|
778
|
+
const totalHeight = valueFontSize + labelLineHeight;
|
|
779
|
+
if (totalHeight > availableHeight) {
|
|
780
|
+
const scale = availableHeight / totalHeight;
|
|
781
|
+
valueFontSize = Math.max(MIN_VALUE_FONT, Math.round(valueFontSize * scale * 2) / 2);
|
|
782
|
+
labelFontSize = Math.max(8, Math.round(labelFontSize * scale * 2) / 2);
|
|
783
|
+
}
|
|
784
|
+
while (labelFontSize > 8 && !this.doesTextFit(labelText, labelFontSize, availableWidth)) {
|
|
785
|
+
labelFontSize -= 0.5;
|
|
786
|
+
}
|
|
787
|
+
labelFontSize = Math.max(8, Math.round(labelFontSize * 2) / 2);
|
|
788
|
+
const displayLabel = this.doesTextFit(labelText, labelFontSize, availableWidth)
|
|
789
|
+
? labelText
|
|
790
|
+
: this.truncateTextToFit(labelText, labelFontSize, availableWidth);
|
|
791
|
+
return { valueFontSize, labelFontSize, displayLabel };
|
|
746
792
|
}
|
|
747
793
|
/**
|
|
748
794
|
* Handles chart rendering errors
|
|
@@ -757,11 +803,7 @@ class AXDonutChartComponent extends AXChartComponent {
|
|
|
757
803
|
* Cleans up chart resources
|
|
758
804
|
*/
|
|
759
805
|
cleanupChart() {
|
|
760
|
-
|
|
761
|
-
cancelAnimationFrame(this._tooltipRafId);
|
|
762
|
-
this._tooltipRafId = null;
|
|
763
|
-
}
|
|
764
|
-
this._pendingTooltipCoords = null;
|
|
806
|
+
this.cancelTooltipPosition();
|
|
765
807
|
const container = this.chartContainerEl()?.nativeElement;
|
|
766
808
|
if (container) {
|
|
767
809
|
this.d3
|
|
@@ -776,7 +818,6 @@ class AXDonutChartComponent extends AXChartComponent {
|
|
|
776
818
|
this._currentlyHighlightedSegment.set(null);
|
|
777
819
|
}
|
|
778
820
|
// ===== Helper utilities for modularity and maintainability =====
|
|
779
|
-
// computeTooltipPosition moved to shared chart utils
|
|
780
821
|
/**
|
|
781
822
|
* Gets an accessibility label describing the donut chart for screen readers
|
|
782
823
|
* @returns Descriptive string for screen readers
|
|
@@ -827,11 +868,11 @@ class AXDonutChartComponent extends AXChartComponent {
|
|
|
827
868
|
return (this.getSegmentLayoutValue(segmentValue) / layoutTotal) * 100;
|
|
828
869
|
}
|
|
829
870
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXDonutChartComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
830
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "22.0.8", type: AXDonutChartComponent, isStandalone: true, selector: "ax-donut-chart", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { segmentClick: "segmentClick", segmentHover: "segmentHover" }, viewQueries: [{ propertyName: "chartContainerEl", first: true, predicate: ["chartContainer"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"ax-donut-chart\" #chartContainer role=\"img\" [attr.aria-label]=\"getAccessibilityLabel()\">\n <!-- Tooltip component -->\n <ax-chart-tooltip\n [visible]=\"tooltipVisible()\"\n [position]=\"tooltipPosition()\"\n [data]=\"tooltipData()\"\n [showPercentage]=\"true\"\n ></ax-chart-tooltip>\n</div>\n", styles: ["@
|
|
871
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "22.0.8", type: AXDonutChartComponent, isStandalone: true, selector: "ax-donut-chart", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { segmentClick: "segmentClick", segmentHover: "segmentHover" }, viewQueries: [{ propertyName: "chartContainerEl", first: true, predicate: ["chartContainer"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"ax-donut-chart\" #chartContainer role=\"img\" [attr.aria-label]=\"getAccessibilityLabel()\">\n <!-- Tooltip component -->\n <ax-chart-tooltip\n [visible]=\"tooltipVisible()\"\n [position]=\"tooltipPosition()\"\n [data]=\"tooltipData()\"\n [showPercentage]=\"true\"\n ></ax-chart-tooltip>\n</div>\n", styles: ["@layer properties;@layer components{.ax-chart-empty{pointer-events:none;position:absolute;inset:calc(var(--spacing, .25rem) * 0);z-index:1;box-sizing:border-box;display:flex;align-items:center;justify-content:center;padding:calc(var(--spacing, .25rem) * 4);color:rgba(var(--ax-sys-color-on-lightest-surface))}.ax-chart-empty__card{box-sizing:border-box;max-width:300px;border-radius:var(--radius-lg, .5rem);padding:calc(var(--spacing, .25rem) * 6);text-align:center;width:80%;border:1px solid rgba(var(--ax-sys-color-border-surface));background-color:rgba(var(--ax-sys-color-lightest-surface));color:rgba(var(--ax-sys-color-on-lightest-surface))}.ax-chart-empty__icon{margin-bottom:calc(var(--spacing, .25rem) * 3);opacity:60%}.ax-chart-empty__title{margin-bottom:calc(var(--spacing, .25rem) * 2);font-size:var(--text-base, 1rem);line-height:var(--tw-leading, var(--text-base--line-height, 1.5 ));--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);color:rgba(var(--ax-sys-color-on-lightest-surface))}.ax-chart-empty__help{font-size:.8rem;opacity:60%;color:rgba(var(--ax-sys-color-on-lightest-surface))}}@layer components{ax-donut-chart{box-sizing:border-box;display:block;height:100%;min-height:calc(var(--spacing, .25rem) * 0);width:100%;--ax-comp-donut-chart-bg-color: 0, 0, 0, 0;--ax-comp-donut-chart-data-labels-color: var(--ax-sys-color-on-lightest-surface);--ax-comp-donut-chart-value-color: var(--ax-sys-color-on-lightest-surface)}ax-donut-chart .ax-donut-chart{position:relative;box-sizing:border-box;height:100%;min-height:calc(var(--spacing, .25rem) * 0);width:100%;overflow:hidden;border-radius:var(--radius-lg, .5rem);padding:clamp(.5rem,1.2vw,.875rem);background-color:rgba(var(--ax-comp-donut-chart-bg-color))}ax-donut-chart .ax-donut-chart svg{display:block;height:100%;max-height:100%;width:100%;max-width:100%;overflow:hidden}ax-donut-chart .ax-donut-chart svg g:has(text){font-family:inherit}}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-font-weight: initial}}}\n/*! tailwindcss v4.1.16 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "component", type: AXChartTooltipComponent, selector: "ax-chart-tooltip", inputs: ["data", "position", "visible", "showPercentage", "style"] }], encapsulation: i0.ViewEncapsulation.None });
|
|
831
872
|
}
|
|
832
873
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXDonutChartComponent, decorators: [{
|
|
833
874
|
type: Component,
|
|
834
|
-
args: [{ selector: 'ax-donut-chart', encapsulation: ViewEncapsulation.None, imports: [AXChartTooltipComponent], template: "<div class=\"ax-donut-chart\" #chartContainer role=\"img\" [attr.aria-label]=\"getAccessibilityLabel()\">\n <!-- Tooltip component -->\n <ax-chart-tooltip\n [visible]=\"tooltipVisible()\"\n [position]=\"tooltipPosition()\"\n [data]=\"tooltipData()\"\n [showPercentage]=\"true\"\n ></ax-chart-tooltip>\n</div>\n", styles: ["@
|
|
875
|
+
args: [{ selector: 'ax-donut-chart', encapsulation: ViewEncapsulation.None, imports: [AXChartTooltipComponent], template: "<div class=\"ax-donut-chart\" #chartContainer role=\"img\" [attr.aria-label]=\"getAccessibilityLabel()\">\n <!-- Tooltip component -->\n <ax-chart-tooltip\n [visible]=\"tooltipVisible()\"\n [position]=\"tooltipPosition()\"\n [data]=\"tooltipData()\"\n [showPercentage]=\"true\"\n ></ax-chart-tooltip>\n</div>\n", styles: ["@layer properties;@layer components{.ax-chart-empty{pointer-events:none;position:absolute;inset:calc(var(--spacing, .25rem) * 0);z-index:1;box-sizing:border-box;display:flex;align-items:center;justify-content:center;padding:calc(var(--spacing, .25rem) * 4);color:rgba(var(--ax-sys-color-on-lightest-surface))}.ax-chart-empty__card{box-sizing:border-box;max-width:300px;border-radius:var(--radius-lg, .5rem);padding:calc(var(--spacing, .25rem) * 6);text-align:center;width:80%;border:1px solid rgba(var(--ax-sys-color-border-surface));background-color:rgba(var(--ax-sys-color-lightest-surface));color:rgba(var(--ax-sys-color-on-lightest-surface))}.ax-chart-empty__icon{margin-bottom:calc(var(--spacing, .25rem) * 3);opacity:60%}.ax-chart-empty__title{margin-bottom:calc(var(--spacing, .25rem) * 2);font-size:var(--text-base, 1rem);line-height:var(--tw-leading, var(--text-base--line-height, 1.5 ));--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);color:rgba(var(--ax-sys-color-on-lightest-surface))}.ax-chart-empty__help{font-size:.8rem;opacity:60%;color:rgba(var(--ax-sys-color-on-lightest-surface))}}@layer components{ax-donut-chart{box-sizing:border-box;display:block;height:100%;min-height:calc(var(--spacing, .25rem) * 0);width:100%;--ax-comp-donut-chart-bg-color: 0, 0, 0, 0;--ax-comp-donut-chart-data-labels-color: var(--ax-sys-color-on-lightest-surface);--ax-comp-donut-chart-value-color: var(--ax-sys-color-on-lightest-surface)}ax-donut-chart .ax-donut-chart{position:relative;box-sizing:border-box;height:100%;min-height:calc(var(--spacing, .25rem) * 0);width:100%;overflow:hidden;border-radius:var(--radius-lg, .5rem);padding:clamp(.5rem,1.2vw,.875rem);background-color:rgba(var(--ax-comp-donut-chart-bg-color))}ax-donut-chart .ax-donut-chart svg{display:block;height:100%;max-height:100%;width:100%;max-width:100%;overflow:hidden}ax-donut-chart .ax-donut-chart svg g:has(text){font-family:inherit}}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-font-weight: initial}}}\n/*! tailwindcss v4.1.16 | MIT License | https://tailwindcss.com */\n"] }]
|
|
835
876
|
}], ctorParameters: () => [], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], segmentClick: [{ type: i0.Output, args: ["segmentClick"] }], segmentHover: [{ type: i0.Output, args: ["segmentHover"] }], chartContainerEl: [{ type: i0.ViewChild, args: ['chartContainer', { isSignal: true }] }] } });
|
|
836
877
|
|
|
837
878
|
/**
|