@acorex/charts 20.6.16 → 20.6.18
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/bar-chart/index.d.ts +2 -0
- package/donut-chart/index.d.ts +1 -0
- package/fesm2022/acorex-charts-bar-chart.mjs +12 -8
- package/fesm2022/acorex-charts-bar-chart.mjs.map +1 -1
- package/fesm2022/acorex-charts-donut-chart.mjs +13 -5
- package/fesm2022/acorex-charts-donut-chart.mjs.map +1 -1
- package/fesm2022/acorex-charts-funnel-chart.mjs +207 -0
- package/fesm2022/acorex-charts-funnel-chart.mjs.map +1 -0
- package/fesm2022/acorex-charts-gauge-chart.mjs +132 -70
- package/fesm2022/acorex-charts-gauge-chart.mjs.map +1 -1
- package/fesm2022/acorex-charts-heatmap-chart.mjs +181 -0
- package/fesm2022/acorex-charts-heatmap-chart.mjs.map +1 -0
- package/fesm2022/acorex-charts-line-chart.mjs +12 -14
- package/fesm2022/acorex-charts-line-chart.mjs.map +1 -1
- package/funnel-chart/README.md +3 -0
- package/funnel-chart/index.d.ts +90 -0
- package/gauge-chart/index.d.ts +12 -0
- package/heatmap-chart/README.md +3 -0
- package/heatmap-chart/index.d.ts +92 -0
- package/line-chart/index.d.ts +1 -0
- package/package.json +12 -4
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import { AXChartComponent, getEasingFunction, computeTooltipPosition } from '@acorex/charts';
|
|
2
|
+
import { AXChartTooltipComponent } from '@acorex/charts/chart-tooltip';
|
|
3
|
+
import * as i0 from '@angular/core';
|
|
4
|
+
import { InjectionToken, input, viewChild, signal, inject, computed, afterNextRender, effect, ChangeDetectionStrategy, ViewEncapsulation, Component } from '@angular/core';
|
|
5
|
+
|
|
6
|
+
const AXFunnelChartDefaultConfig = {
|
|
7
|
+
margin: { top: 20, right: 160, bottom: 20, left: 160 },
|
|
8
|
+
neckWidth: 0.3,
|
|
9
|
+
showLabels: true,
|
|
10
|
+
showTooltip: true,
|
|
11
|
+
animationDuration: 1000,
|
|
12
|
+
animationEasing: 'cubic-out',
|
|
13
|
+
// Modern Blue Palette
|
|
14
|
+
colors: ['#1e1b4b', '#312e81', '#3730a3', '#4338ca', '#4f46e5', '#6366f1', '#818cf8'],
|
|
15
|
+
messages: {
|
|
16
|
+
noData: 'No funnel data available',
|
|
17
|
+
noDataIcon: 'fa-light fa-filter-list',
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
const AX_FUNNEL_CHART_CONFIG = new InjectionToken('AX_FUNNEL_CHART_CONFIG', {
|
|
21
|
+
providedIn: 'root',
|
|
22
|
+
factory: () => AXFunnelChartDefaultConfig,
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
class AXFunnelChartComponent extends AXChartComponent {
|
|
26
|
+
// Inputs
|
|
27
|
+
data = input([], ...(ngDevMode ? [{ debugName: "data" }] : []));
|
|
28
|
+
options = input({}, ...(ngDevMode ? [{ debugName: "options" }] : []));
|
|
29
|
+
chartContainerEl = viewChild.required('chartContainer');
|
|
30
|
+
// SVG State
|
|
31
|
+
svgElement = null;
|
|
32
|
+
d3;
|
|
33
|
+
_initialized = signal(false, ...(ngDevMode ? [{ debugName: "_initialized" }] : []));
|
|
34
|
+
_rendered = signal(false, ...(ngDevMode ? [{ debugName: "_rendered" }] : []));
|
|
35
|
+
// Tooltip Signals
|
|
36
|
+
_tooltipVisible = signal(false, ...(ngDevMode ? [{ debugName: "_tooltipVisible" }] : []));
|
|
37
|
+
_tooltipPosition = signal({ x: 0, y: 0 }, ...(ngDevMode ? [{ debugName: "_tooltipPosition" }] : []));
|
|
38
|
+
_tooltipData = signal({ title: '', value: '' }, ...(ngDevMode ? [{ debugName: "_tooltipData" }] : []));
|
|
39
|
+
_tooltipRafId = null;
|
|
40
|
+
tooltipVisible = this._tooltipVisible.asReadonly();
|
|
41
|
+
tooltipPosition = this._tooltipPosition.asReadonly();
|
|
42
|
+
tooltipData = this._tooltipData.asReadonly();
|
|
43
|
+
configToken = inject(AX_FUNNEL_CHART_CONFIG);
|
|
44
|
+
effectiveOptions = computed(() => ({
|
|
45
|
+
...this.configToken,
|
|
46
|
+
...this.options(),
|
|
47
|
+
}), ...(ngDevMode ? [{ debugName: "effectiveOptions" }] : []));
|
|
48
|
+
constructor() {
|
|
49
|
+
super();
|
|
50
|
+
afterNextRender(() => {
|
|
51
|
+
this._initialized.set(true);
|
|
52
|
+
this.loadD3();
|
|
53
|
+
});
|
|
54
|
+
effect(() => {
|
|
55
|
+
// Trigger update on data or option change
|
|
56
|
+
this.data();
|
|
57
|
+
this.effectiveOptions();
|
|
58
|
+
if (this._rendered()) {
|
|
59
|
+
this.updateChart();
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
ngOnDestroy() {
|
|
64
|
+
this.cleanupChart();
|
|
65
|
+
}
|
|
66
|
+
async loadD3() {
|
|
67
|
+
if (this.d3)
|
|
68
|
+
return;
|
|
69
|
+
try {
|
|
70
|
+
this.d3 = await import('d3');
|
|
71
|
+
if (this._initialized() && this.chartContainerEl()) {
|
|
72
|
+
this.createChart();
|
|
73
|
+
this._rendered.set(true);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
console.error('AXFunnelChart: Failed to load D3.js', error);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
createChart() {
|
|
81
|
+
if (this.svgElement)
|
|
82
|
+
this.svgElement.remove();
|
|
83
|
+
const data = [...this.data()].sort((a, b) => b.value - a.value);
|
|
84
|
+
if (!data.length)
|
|
85
|
+
return;
|
|
86
|
+
const container = this.chartContainerEl().nativeElement;
|
|
87
|
+
const width = container.clientWidth;
|
|
88
|
+
const height = container.clientHeight;
|
|
89
|
+
const opt = this.effectiveOptions();
|
|
90
|
+
const margin = opt.margin;
|
|
91
|
+
this.svgElement = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
|
|
92
|
+
const svg = this.d3
|
|
93
|
+
.select(this.svgElement)
|
|
94
|
+
.attr('width', '100%')
|
|
95
|
+
.attr('height', '100%')
|
|
96
|
+
.attr('viewBox', `0 0 ${width} ${height}`)
|
|
97
|
+
.attr('preserveAspectRatio', 'xMidYMid meet');
|
|
98
|
+
container.appendChild(this.svgElement);
|
|
99
|
+
const innerWidth = width - margin.left - margin.right;
|
|
100
|
+
const innerHeight = height - margin.top - margin.bottom;
|
|
101
|
+
const g = svg.append('g').attr('transform', `translate(${margin.left},${margin.top})`);
|
|
102
|
+
const colorScale = this.d3.scaleOrdinal().range(opt.colors);
|
|
103
|
+
const sliceHeight = innerHeight / data.length;
|
|
104
|
+
const maxValue = data[0].value;
|
|
105
|
+
const easing = getEasingFunction(this.d3, opt.animationEasing);
|
|
106
|
+
data.forEach((d, i) => {
|
|
107
|
+
const topVal = d.value;
|
|
108
|
+
const bottomVal = data[i + 1]?.value ?? d.value * opt.neckWidth;
|
|
109
|
+
const topW = (topVal / maxValue) * innerWidth;
|
|
110
|
+
const bottomW = (bottomVal / maxValue) * innerWidth;
|
|
111
|
+
const xTop = (innerWidth - topW) / 2;
|
|
112
|
+
const xBottom = (innerWidth - bottomW) / 2;
|
|
113
|
+
const yTop = i * sliceHeight;
|
|
114
|
+
const yBottom = (i + 1) * sliceHeight;
|
|
115
|
+
const pathData = `M ${xTop},${yTop} L ${xTop + topW},${yTop} L ${xBottom + bottomW},${yBottom} L ${xBottom},${yBottom} Z`;
|
|
116
|
+
const sliceGroup = g.append('g').attr('class', 'funnel-slice-container');
|
|
117
|
+
const path = sliceGroup
|
|
118
|
+
.append('path')
|
|
119
|
+
.attr('class', 'funnel-slice')
|
|
120
|
+
.attr('d', pathData)
|
|
121
|
+
.attr('fill', d.color ?? colorScale(i.toString()))
|
|
122
|
+
.style('opacity', 0)
|
|
123
|
+
.on('mouseenter', (event) => {
|
|
124
|
+
svg.classed('is-dimmed', true);
|
|
125
|
+
this.d3.select(event.currentTarget).classed('is-active', true);
|
|
126
|
+
this.showTooltip(event, d);
|
|
127
|
+
})
|
|
128
|
+
.on('mousemove', (event) => this.updateTooltipPosition(event))
|
|
129
|
+
.on('mouseleave', (event) => {
|
|
130
|
+
svg.classed('is-dimmed', false);
|
|
131
|
+
this.d3.select(event.currentTarget).classed('is-active', false);
|
|
132
|
+
this.hideTooltip();
|
|
133
|
+
});
|
|
134
|
+
path
|
|
135
|
+
.transition()
|
|
136
|
+
.duration(opt.animationDuration)
|
|
137
|
+
.delay(i * 80)
|
|
138
|
+
.ease(easing)
|
|
139
|
+
.style('opacity', 1);
|
|
140
|
+
if (opt.showLabels) {
|
|
141
|
+
const labelGroup = sliceGroup.append('g').attr('class', 'funnel-label-group').style('opacity', 0);
|
|
142
|
+
labelGroup
|
|
143
|
+
.append('text')
|
|
144
|
+
.attr('class', 'funnel-label-name')
|
|
145
|
+
.attr('x', innerWidth / 2 + topW / 2 + 25)
|
|
146
|
+
.attr('y', yTop + sliceHeight / 2 - 5)
|
|
147
|
+
.text(d.name);
|
|
148
|
+
labelGroup
|
|
149
|
+
.append('text')
|
|
150
|
+
.attr('class', 'funnel-label-value')
|
|
151
|
+
.attr('x', innerWidth / 2 + topW / 2 + 25)
|
|
152
|
+
.attr('y', yTop + sliceHeight / 2 + 15)
|
|
153
|
+
.text(d.value.toLocaleString());
|
|
154
|
+
labelGroup
|
|
155
|
+
.transition()
|
|
156
|
+
.duration(600)
|
|
157
|
+
.delay(400 + i * 80)
|
|
158
|
+
.style('opacity', 1);
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
updateChart() {
|
|
163
|
+
this.createChart();
|
|
164
|
+
}
|
|
165
|
+
showTooltip(event, item) {
|
|
166
|
+
if (!this.effectiveOptions().showTooltip)
|
|
167
|
+
return;
|
|
168
|
+
this._tooltipData.set({ title: item.name, value: item.value.toLocaleString(), color: item.color });
|
|
169
|
+
this._tooltipVisible.set(true);
|
|
170
|
+
this.updateTooltipPosition(event);
|
|
171
|
+
}
|
|
172
|
+
updateTooltipPosition(event) {
|
|
173
|
+
if (this._tooltipRafId)
|
|
174
|
+
cancelAnimationFrame(this._tooltipRafId);
|
|
175
|
+
this._tooltipRafId = requestAnimationFrame(() => {
|
|
176
|
+
const containerEl = this.chartContainerEl().nativeElement;
|
|
177
|
+
const rect = containerEl.getBoundingClientRect();
|
|
178
|
+
const tooltipEl = containerEl.querySelector('.chart-tooltip');
|
|
179
|
+
const tooltipRect = tooltipEl?.getBoundingClientRect() ?? null;
|
|
180
|
+
this._tooltipPosition.set(computeTooltipPosition(rect, tooltipRect, event.clientX + 10, event.clientY - 10, 10));
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
hideTooltip() {
|
|
184
|
+
this._tooltipVisible.set(false);
|
|
185
|
+
}
|
|
186
|
+
cleanupChart() {
|
|
187
|
+
if (this._tooltipRafId)
|
|
188
|
+
cancelAnimationFrame(this._tooltipRafId);
|
|
189
|
+
if (this.svgElement) {
|
|
190
|
+
this.svgElement.remove();
|
|
191
|
+
this.svgElement = null;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: AXFunnelChartComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
195
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "20.3.3", type: AXFunnelChartComponent, isStandalone: true, selector: "ax-funnel-chart", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "chartContainerEl", first: true, predicate: ["chartContainer"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"ax-funnel-chart\" role=\"img\" #chartContainer></div>\n\n<ax-chart-tooltip [data]=\"tooltipData()\" [position]=\"tooltipPosition()\" [visible]=\"tooltipVisible()\">\n</ax-chart-tooltip>\n", styles: ["ax-funnel-chart{display:block;width:100%;height:100%;min-height:350px;--ax-comp-funnel-bg: 0, 0, 0, 0;--ax-comp-funnel-text: var(--ax-sys-color-on-surface);--ax-comp-funnel-label-secondary: var(--ax-sys-color-on-surface-variant);--ax-comp-funnel-slice-opacity: .9;--ax-comp-funnel-dim-opacity: .25}ax-funnel-chart .ax-funnel-chart{position:relative;width:100%;height:100%;overflow:hidden;background-color:rgba(var(--ax-comp-funnel-bg))}ax-funnel-chart .ax-funnel-chart svg{display:block;width:100%;height:100%;overflow:visible}ax-funnel-chart .ax-funnel-chart svg .funnel-slice{cursor:pointer;opacity:var(--ax-comp-funnel-slice-opacity);transition:opacity .3s cubic-bezier(.4,0,.2,1)}ax-funnel-chart .ax-funnel-chart svg .funnel-slice.is-active{opacity:1;filter:saturate(1.2)}ax-funnel-chart .ax-funnel-chart svg .funnel-label-group{pointer-events:none}ax-funnel-chart .ax-funnel-chart svg .funnel-label-group .funnel-label-name{font-size:12px;font-weight:700;fill:rgb(var(--ax-comp-funnel-text));text-transform:uppercase;letter-spacing:.05em}ax-funnel-chart .ax-funnel-chart svg .funnel-label-group .funnel-label-value{font-size:13px;fill:rgb(var(--ax-comp-funnel-label-secondary));font-variant-numeric:tabular-nums;font-weight:500}ax-funnel-chart .ax-funnel-chart svg.is-dimmed .funnel-slice:not(.is-active){opacity:var(--ax-comp-funnel-dim-opacity)}\n"], dependencies: [{ kind: "component", type: AXChartTooltipComponent, selector: "ax-chart-tooltip", inputs: ["data", "position", "visible", "showPercentage", "style"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
196
|
+
}
|
|
197
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: AXFunnelChartComponent, decorators: [{
|
|
198
|
+
type: Component,
|
|
199
|
+
args: [{ selector: 'ax-funnel-chart', encapsulation: ViewEncapsulation.None, imports: [AXChartTooltipComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"ax-funnel-chart\" role=\"img\" #chartContainer></div>\n\n<ax-chart-tooltip [data]=\"tooltipData()\" [position]=\"tooltipPosition()\" [visible]=\"tooltipVisible()\">\n</ax-chart-tooltip>\n", styles: ["ax-funnel-chart{display:block;width:100%;height:100%;min-height:350px;--ax-comp-funnel-bg: 0, 0, 0, 0;--ax-comp-funnel-text: var(--ax-sys-color-on-surface);--ax-comp-funnel-label-secondary: var(--ax-sys-color-on-surface-variant);--ax-comp-funnel-slice-opacity: .9;--ax-comp-funnel-dim-opacity: .25}ax-funnel-chart .ax-funnel-chart{position:relative;width:100%;height:100%;overflow:hidden;background-color:rgba(var(--ax-comp-funnel-bg))}ax-funnel-chart .ax-funnel-chart svg{display:block;width:100%;height:100%;overflow:visible}ax-funnel-chart .ax-funnel-chart svg .funnel-slice{cursor:pointer;opacity:var(--ax-comp-funnel-slice-opacity);transition:opacity .3s cubic-bezier(.4,0,.2,1)}ax-funnel-chart .ax-funnel-chart svg .funnel-slice.is-active{opacity:1;filter:saturate(1.2)}ax-funnel-chart .ax-funnel-chart svg .funnel-label-group{pointer-events:none}ax-funnel-chart .ax-funnel-chart svg .funnel-label-group .funnel-label-name{font-size:12px;font-weight:700;fill:rgb(var(--ax-comp-funnel-text));text-transform:uppercase;letter-spacing:.05em}ax-funnel-chart .ax-funnel-chart svg .funnel-label-group .funnel-label-value{font-size:13px;fill:rgb(var(--ax-comp-funnel-label-secondary));font-variant-numeric:tabular-nums;font-weight:500}ax-funnel-chart .ax-funnel-chart svg.is-dimmed .funnel-slice:not(.is-active){opacity:var(--ax-comp-funnel-dim-opacity)}\n"] }]
|
|
200
|
+
}], ctorParameters: () => [] });
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Generated bundle index. Do not edit.
|
|
204
|
+
*/
|
|
205
|
+
|
|
206
|
+
export { AXFunnelChartComponent, AXFunnelChartDefaultConfig, AX_FUNNEL_CHART_CONFIG };
|
|
207
|
+
//# sourceMappingURL=acorex-charts-funnel-chart.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"acorex-charts-funnel-chart.mjs","sources":["../tmp-esm2022/funnel-chart/lib/funnel-chart.config.js","../tmp-esm2022/funnel-chart/lib/funnel-chart.component.js","../tmp-esm2022/funnel-chart/acorex-charts-funnel-chart.js"],"sourcesContent":["import { InjectionToken } from '@angular/core';\nexport const AXFunnelChartDefaultConfig = {\n margin: { top: 20, right: 160, bottom: 20, left: 160 },\n neckWidth: 0.3,\n showLabels: true,\n showTooltip: true,\n animationDuration: 1000,\n animationEasing: 'cubic-out',\n // Modern Blue Palette\n colors: ['#1e1b4b', '#312e81', '#3730a3', '#4338ca', '#4f46e5', '#6366f1', '#818cf8'],\n messages: {\n noData: 'No funnel data available',\n noDataIcon: 'fa-light fa-filter-list',\n },\n};\nexport const AX_FUNNEL_CHART_CONFIG = new InjectionToken('AX_FUNNEL_CHART_CONFIG', {\n providedIn: 'root',\n factory: () => AXFunnelChartDefaultConfig,\n});\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZnVubmVsLWNoYXJ0LmNvbmZpZy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3BhY2thZ2VzL2NoYXJ0cy9mdW5uZWwtY2hhcnQvc3JjL2xpYi9mdW5uZWwtY2hhcnQuY29uZmlnLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFHL0MsTUFBTSxDQUFDLE1BQU0sMEJBQTBCLEdBQXdCO0lBQzdELE1BQU0sRUFBRSxFQUFFLEdBQUcsRUFBRSxFQUFFLEVBQUUsS0FBSyxFQUFFLEdBQUcsRUFBRSxNQUFNLEVBQUUsRUFBRSxFQUFFLElBQUksRUFBRSxHQUFHLEVBQUU7SUFDdEQsU0FBUyxFQUFFLEdBQUc7SUFDZCxVQUFVLEVBQUUsSUFBSTtJQUNoQixXQUFXLEVBQUUsSUFBSTtJQUNqQixpQkFBaUIsRUFBRSxJQUFJO0lBQ3ZCLGVBQWUsRUFBRSxXQUFXO0lBQzVCLHNCQUFzQjtJQUN0QixNQUFNLEVBQUUsQ0FBQyxTQUFTLEVBQUUsU0FBUyxFQUFFLFNBQVMsRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFLFNBQVMsRUFBRSxTQUFTLENBQUM7SUFDckYsUUFBUSxFQUFFO1FBQ1IsTUFBTSxFQUFFLDBCQUEwQjtRQUNsQyxVQUFVLEVBQUUseUJBQXlCO0tBQ3RDO0NBQ0YsQ0FBQztBQUVGLE1BQU0sQ0FBQyxNQUFNLHNCQUFzQixHQUFHLElBQUksY0FBYyxDQUFzQix3QkFBd0IsRUFBRTtJQUN0RyxVQUFVLEVBQUUsTUFBTTtJQUNsQixPQUFPLEVBQUUsR0FBRyxFQUFFLENBQUMsMEJBQTBCO0NBQzFDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEluamVjdGlvblRva2VuIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBBWEZ1bm5lbENoYXJ0T3B0aW9uIH0gZnJvbSAnLi9mdW5uZWwtY2hhcnQudHlwZSc7XG5cbmV4cG9ydCBjb25zdCBBWEZ1bm5lbENoYXJ0RGVmYXVsdENvbmZpZzogQVhGdW5uZWxDaGFydE9wdGlvbiA9IHtcbiAgbWFyZ2luOiB7IHRvcDogMjAsIHJpZ2h0OiAxNjAsIGJvdHRvbTogMjAsIGxlZnQ6IDE2MCB9LFxuICBuZWNrV2lkdGg6IDAuMyxcbiAgc2hvd0xhYmVsczogdHJ1ZSxcbiAgc2hvd1Rvb2x0aXA6IHRydWUsXG4gIGFuaW1hdGlvbkR1cmF0aW9uOiAxMDAwLFxuICBhbmltYXRpb25FYXNpbmc6ICdjdWJpYy1vdXQnLFxuICAvLyBNb2Rlcm4gQmx1ZSBQYWxldHRlXG4gIGNvbG9yczogWycjMWUxYjRiJywgJyMzMTJlODEnLCAnIzM3MzBhMycsICcjNDMzOGNhJywgJyM0ZjQ2ZTUnLCAnIzYzNjZmMScsICcjODE4Y2Y4J10sXG4gIG1lc3NhZ2VzOiB7XG4gICAgbm9EYXRhOiAnTm8gZnVubmVsIGRhdGEgYXZhaWxhYmxlJyxcbiAgICBub0RhdGFJY29uOiAnZmEtbGlnaHQgZmEtZmlsdGVyLWxpc3QnLFxuICB9LFxufTtcblxuZXhwb3J0IGNvbnN0IEFYX0ZVTk5FTF9DSEFSVF9DT05GSUcgPSBuZXcgSW5qZWN0aW9uVG9rZW48QVhGdW5uZWxDaGFydE9wdGlvbj4oJ0FYX0ZVTk5FTF9DSEFSVF9DT05GSUcnLCB7XG4gIHByb3ZpZGVkSW46ICdyb290JyxcbiAgZmFjdG9yeTogKCkgPT4gQVhGdW5uZWxDaGFydERlZmF1bHRDb25maWcsXG59KTtcbiJdfQ==","import { AXChartComponent, computeTooltipPosition, getEasingFunction } from '@acorex/charts';\nimport { AXChartTooltipComponent } from '@acorex/charts/chart-tooltip';\nimport { ChangeDetectionStrategy, Component, ViewEncapsulation, afterNextRender, computed, effect, inject, input, signal, viewChild, } from '@angular/core';\nimport { AX_FUNNEL_CHART_CONFIG } from './funnel-chart.config';\nimport * as i0 from \"@angular/core\";\nexport class AXFunnelChartComponent extends AXChartComponent {\n // Inputs\n data = input([], ...(ngDevMode ? [{ debugName: \"data\" }] : []));\n options = input({}, ...(ngDevMode ? [{ debugName: \"options\" }] : []));\n chartContainerEl = viewChild.required('chartContainer');\n // SVG State\n svgElement = null;\n d3;\n _initialized = signal(false, ...(ngDevMode ? [{ debugName: \"_initialized\" }] : []));\n _rendered = signal(false, ...(ngDevMode ? [{ debugName: \"_rendered\" }] : []));\n // Tooltip Signals\n _tooltipVisible = signal(false, ...(ngDevMode ? [{ debugName: \"_tooltipVisible\" }] : []));\n _tooltipPosition = signal({ x: 0, y: 0 }, ...(ngDevMode ? [{ debugName: \"_tooltipPosition\" }] : []));\n _tooltipData = signal({ title: '', value: '' }, ...(ngDevMode ? [{ debugName: \"_tooltipData\" }] : []));\n _tooltipRafId = null;\n tooltipVisible = this._tooltipVisible.asReadonly();\n tooltipPosition = this._tooltipPosition.asReadonly();\n tooltipData = this._tooltipData.asReadonly();\n configToken = inject(AX_FUNNEL_CHART_CONFIG);\n effectiveOptions = computed(() => ({\n ...this.configToken,\n ...this.options(),\n }), ...(ngDevMode ? [{ debugName: \"effectiveOptions\" }] : []));\n constructor() {\n super();\n afterNextRender(() => {\n this._initialized.set(true);\n this.loadD3();\n });\n effect(() => {\n // Trigger update on data or option change\n this.data();\n this.effectiveOptions();\n if (this._rendered()) {\n this.updateChart();\n }\n });\n }\n ngOnDestroy() {\n this.cleanupChart();\n }\n async loadD3() {\n if (this.d3)\n return;\n try {\n this.d3 = await import('d3');\n if (this._initialized() && this.chartContainerEl()) {\n this.createChart();\n this._rendered.set(true);\n }\n }\n catch (error) {\n console.error('AXFunnelChart: Failed to load D3.js', error);\n }\n }\n createChart() {\n if (this.svgElement)\n this.svgElement.remove();\n const data = [...this.data()].sort((a, b) => b.value - a.value);\n if (!data.length)\n return;\n const container = this.chartContainerEl().nativeElement;\n const width = container.clientWidth;\n const height = container.clientHeight;\n const opt = this.effectiveOptions();\n const margin = opt.margin;\n this.svgElement = document.createElementNS('http://www.w3.org/2000/svg', 'svg');\n const svg = this.d3\n .select(this.svgElement)\n .attr('width', '100%')\n .attr('height', '100%')\n .attr('viewBox', `0 0 ${width} ${height}`)\n .attr('preserveAspectRatio', 'xMidYMid meet');\n container.appendChild(this.svgElement);\n const innerWidth = width - margin.left - margin.right;\n const innerHeight = height - margin.top - margin.bottom;\n const g = svg.append('g').attr('transform', `translate(${margin.left},${margin.top})`);\n const colorScale = this.d3.scaleOrdinal().range(opt.colors);\n const sliceHeight = innerHeight / data.length;\n const maxValue = data[0].value;\n const easing = getEasingFunction(this.d3, opt.animationEasing);\n data.forEach((d, i) => {\n const topVal = d.value;\n const bottomVal = data[i + 1]?.value ?? d.value * opt.neckWidth;\n const topW = (topVal / maxValue) * innerWidth;\n const bottomW = (bottomVal / maxValue) * innerWidth;\n const xTop = (innerWidth - topW) / 2;\n const xBottom = (innerWidth - bottomW) / 2;\n const yTop = i * sliceHeight;\n const yBottom = (i + 1) * sliceHeight;\n const pathData = `M ${xTop},${yTop} L ${xTop + topW},${yTop} L ${xBottom + bottomW},${yBottom} L ${xBottom},${yBottom} Z`;\n const sliceGroup = g.append('g').attr('class', 'funnel-slice-container');\n const path = sliceGroup\n .append('path')\n .attr('class', 'funnel-slice')\n .attr('d', pathData)\n .attr('fill', d.color ?? colorScale(i.toString()))\n .style('opacity', 0)\n .on('mouseenter', (event) => {\n svg.classed('is-dimmed', true);\n this.d3.select(event.currentTarget).classed('is-active', true);\n this.showTooltip(event, d);\n })\n .on('mousemove', (event) => this.updateTooltipPosition(event))\n .on('mouseleave', (event) => {\n svg.classed('is-dimmed', false);\n this.d3.select(event.currentTarget).classed('is-active', false);\n this.hideTooltip();\n });\n path\n .transition()\n .duration(opt.animationDuration)\n .delay(i * 80)\n .ease(easing)\n .style('opacity', 1);\n if (opt.showLabels) {\n const labelGroup = sliceGroup.append('g').attr('class', 'funnel-label-group').style('opacity', 0);\n labelGroup\n .append('text')\n .attr('class', 'funnel-label-name')\n .attr('x', innerWidth / 2 + topW / 2 + 25)\n .attr('y', yTop + sliceHeight / 2 - 5)\n .text(d.name);\n labelGroup\n .append('text')\n .attr('class', 'funnel-label-value')\n .attr('x', innerWidth / 2 + topW / 2 + 25)\n .attr('y', yTop + sliceHeight / 2 + 15)\n .text(d.value.toLocaleString());\n labelGroup\n .transition()\n .duration(600)\n .delay(400 + i * 80)\n .style('opacity', 1);\n }\n });\n }\n updateChart() {\n this.createChart();\n }\n showTooltip(event, item) {\n if (!this.effectiveOptions().showTooltip)\n return;\n this._tooltipData.set({ title: item.name, value: item.value.toLocaleString(), color: item.color });\n this._tooltipVisible.set(true);\n this.updateTooltipPosition(event);\n }\n updateTooltipPosition(event) {\n if (this._tooltipRafId)\n cancelAnimationFrame(this._tooltipRafId);\n this._tooltipRafId = requestAnimationFrame(() => {\n const containerEl = this.chartContainerEl().nativeElement;\n const rect = containerEl.getBoundingClientRect();\n const tooltipEl = containerEl.querySelector('.chart-tooltip');\n const tooltipRect = tooltipEl?.getBoundingClientRect() ?? null;\n this._tooltipPosition.set(computeTooltipPosition(rect, tooltipRect, event.clientX + 10, event.clientY - 10, 10));\n });\n }\n hideTooltip() {\n this._tooltipVisible.set(false);\n }\n cleanupChart() {\n if (this._tooltipRafId)\n cancelAnimationFrame(this._tooltipRafId);\n if (this.svgElement) {\n this.svgElement.remove();\n this.svgElement = null;\n }\n }\n static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: \"12.0.0\", version: \"20.3.3\", ngImport: i0, type: AXFunnelChartComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });\n static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: \"17.2.0\", version: \"20.3.3\", type: AXFunnelChartComponent, isStandalone: true, selector: \"ax-funnel-chart\", inputs: { data: { classPropertyName: \"data\", publicName: \"data\", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: \"options\", publicName: \"options\", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: \"chartContainerEl\", first: true, predicate: [\"chartContainer\"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: \"<div class=\\\"ax-funnel-chart\\\" role=\\\"img\\\" #chartContainer></div>\\n\\n<ax-chart-tooltip [data]=\\\"tooltipData()\\\" [position]=\\\"tooltipPosition()\\\" [visible]=\\\"tooltipVisible()\\\">\\n</ax-chart-tooltip>\\n\", styles: [\"ax-funnel-chart{display:block;width:100%;height:100%;min-height:350px;--ax-comp-funnel-bg: 0, 0, 0, 0;--ax-comp-funnel-text: var(--ax-sys-color-on-surface);--ax-comp-funnel-label-secondary: var(--ax-sys-color-on-surface-variant);--ax-comp-funnel-slice-opacity: .9;--ax-comp-funnel-dim-opacity: .25}ax-funnel-chart .ax-funnel-chart{position:relative;width:100%;height:100%;overflow:hidden;background-color:rgba(var(--ax-comp-funnel-bg))}ax-funnel-chart .ax-funnel-chart svg{display:block;width:100%;height:100%;overflow:visible}ax-funnel-chart .ax-funnel-chart svg .funnel-slice{cursor:pointer;opacity:var(--ax-comp-funnel-slice-opacity);transition:opacity .3s cubic-bezier(.4,0,.2,1)}ax-funnel-chart .ax-funnel-chart svg .funnel-slice.is-active{opacity:1;filter:saturate(1.2)}ax-funnel-chart .ax-funnel-chart svg .funnel-label-group{pointer-events:none}ax-funnel-chart .ax-funnel-chart svg .funnel-label-group .funnel-label-name{font-size:12px;font-weight:700;fill:rgb(var(--ax-comp-funnel-text));text-transform:uppercase;letter-spacing:.05em}ax-funnel-chart .ax-funnel-chart svg .funnel-label-group .funnel-label-value{font-size:13px;fill:rgb(var(--ax-comp-funnel-label-secondary));font-variant-numeric:tabular-nums;font-weight:500}ax-funnel-chart .ax-funnel-chart svg.is-dimmed .funnel-slice:not(.is-active){opacity:var(--ax-comp-funnel-dim-opacity)}\\n\"], dependencies: [{ kind: \"component\", type: AXChartTooltipComponent, selector: \"ax-chart-tooltip\", inputs: [\"data\", \"position\", \"visible\", \"showPercentage\", \"style\"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });\n}\ni0.ɵɵngDeclareClassMetadata({ minVersion: \"12.0.0\", version: \"20.3.3\", ngImport: i0, type: AXFunnelChartComponent, decorators: [{\n type: Component,\n args: [{ selector: 'ax-funnel-chart', encapsulation: ViewEncapsulation.None, imports: [AXChartTooltipComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: \"<div class=\\\"ax-funnel-chart\\\" role=\\\"img\\\" #chartContainer></div>\\n\\n<ax-chart-tooltip [data]=\\\"tooltipData()\\\" [position]=\\\"tooltipPosition()\\\" [visible]=\\\"tooltipVisible()\\\">\\n</ax-chart-tooltip>\\n\", styles: [\"ax-funnel-chart{display:block;width:100%;height:100%;min-height:350px;--ax-comp-funnel-bg: 0, 0, 0, 0;--ax-comp-funnel-text: var(--ax-sys-color-on-surface);--ax-comp-funnel-label-secondary: var(--ax-sys-color-on-surface-variant);--ax-comp-funnel-slice-opacity: .9;--ax-comp-funnel-dim-opacity: .25}ax-funnel-chart .ax-funnel-chart{position:relative;width:100%;height:100%;overflow:hidden;background-color:rgba(var(--ax-comp-funnel-bg))}ax-funnel-chart .ax-funnel-chart svg{display:block;width:100%;height:100%;overflow:visible}ax-funnel-chart .ax-funnel-chart svg .funnel-slice{cursor:pointer;opacity:var(--ax-comp-funnel-slice-opacity);transition:opacity .3s cubic-bezier(.4,0,.2,1)}ax-funnel-chart .ax-funnel-chart svg .funnel-slice.is-active{opacity:1;filter:saturate(1.2)}ax-funnel-chart .ax-funnel-chart svg .funnel-label-group{pointer-events:none}ax-funnel-chart .ax-funnel-chart svg .funnel-label-group .funnel-label-name{font-size:12px;font-weight:700;fill:rgb(var(--ax-comp-funnel-text));text-transform:uppercase;letter-spacing:.05em}ax-funnel-chart .ax-funnel-chart svg .funnel-label-group .funnel-label-value{font-size:13px;fill:rgb(var(--ax-comp-funnel-label-secondary));font-variant-numeric:tabular-nums;font-weight:500}ax-funnel-chart .ax-funnel-chart svg.is-dimmed .funnel-slice:not(.is-active){opacity:var(--ax-comp-funnel-dim-opacity)}\\n\"] }]\n }], ctorParameters: () => [] });\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZnVubmVsLWNoYXJ0LmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3BhY2thZ2VzL2NoYXJ0cy9mdW5uZWwtY2hhcnQvc3JjL2xpYi9mdW5uZWwtY2hhcnQuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vcGFja2FnZXMvY2hhcnRzL2Z1bm5lbC1jaGFydC9zcmMvbGliL2Z1bm5lbC1jaGFydC5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsZ0JBQWdCLEVBQXdCLHNCQUFzQixFQUFFLGlCQUFpQixFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDbkgsT0FBTyxFQUFFLHVCQUF1QixFQUFzQixNQUFNLDhCQUE4QixDQUFDO0FBQzNGLE9BQU8sRUFDTCx1QkFBdUIsRUFDdkIsU0FBUyxFQUdULGlCQUFpQixFQUNqQixlQUFlLEVBQ2YsUUFBUSxFQUNSLE1BQU0sRUFDTixNQUFNLEVBQ04sS0FBSyxFQUNMLE1BQU0sRUFDTixTQUFTLEdBQ1YsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLHNCQUFzQixFQUFFLE1BQU0sdUJBQXVCLENBQUM7O0FBVy9ELE1BQU0sT0FBTyxzQkFBdUIsU0FBUSxnQkFBZ0I7SUFDMUQsU0FBUztJQUNULElBQUksR0FBRyxLQUFLLENBQWlCLEVBQUUsZ0RBQUMsQ0FBQztJQUNqQyxPQUFPLEdBQUcsS0FBSyxDQUFzQixFQUFFLG1EQUFDLENBQUM7SUFFeEIsZ0JBQWdCLEdBQUcsU0FBUyxDQUFDLFFBQVEsQ0FBNkIsZ0JBQWdCLENBQUMsQ0FBQztJQUVyRyxZQUFZO0lBQ0osVUFBVSxHQUF5QixJQUFJLENBQUM7SUFDdEMsRUFBRSxDQUF1QjtJQUMzQixZQUFZLEdBQUcsTUFBTSxDQUFDLEtBQUssd0RBQUMsQ0FBQztJQUM3QixTQUFTLEdBQUcsTUFBTSxDQUFDLEtBQUsscURBQUMsQ0FBQztJQUVsQyxrQkFB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LEVBQUUsS0FBSyxDQUFDLE9BQU8sR0FBRyxFQUFFLEVBQUUsS0FBSyxDQUFDLE9BQU8sR0FBRyxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUNuSCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFTyxXQUFXO1FBQ2pCLElBQUksQ0FBQyxlQUFlLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ2xDLENBQUM7SUFFTSxZQUFZO1FBQ2pCLElBQUksSUFBSSxDQUFDLGFBQWE7WUFBRSxvQkFBb0IsQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLENBQUM7UUFDakUsSUFBSSxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7WUFDcEIsSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUN6QixJQUFJLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQztRQUN6QixDQUFDO0lBQ0gsQ0FBQzt1R0FwTVUsc0JBQXNCOzJGQUF0QixzQkFBc0IscWVDM0JuQywwTUFJQSxvNENEb0JZLHVCQUF1Qjs7MkZBR3RCLHNCQUFzQjtrQkFSbEMsU0FBUzsrQkFDRSxpQkFBaUIsaUJBR1osaUJBQWlCLENBQUMsSUFBSSxXQUM1QixDQUFDLHVCQUF1QixDQUFDLG1CQUNqQix1QkFBdUIsQ0FBQyxNQUFNIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQVhDaGFydENvbXBvbmVudCwgQVhDaGFydENvbXBvbmVudEJhc2UsIGNvbXB1dGVUb29sdGlwUG9zaXRpb24sIGdldEVhc2luZ0Z1bmN0aW9uIH0gZnJvbSAnQGFjb3JleC9jaGFydHMnO1xuaW1wb3J0IHsgQVhDaGFydFRvb2x0aXBDb21wb25lbnQsIEFYQ2hhcnRUb29sdGlwRGF0YSB9IGZyb20gJ0BhY29yZXgvY2hhcnRzL2NoYXJ0LXRvb2x0aXAnO1xuaW1wb3J0IHtcbiAgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXG4gIENvbXBvbmVudCxcbiAgRWxlbWVudFJlZixcbiAgT25EZXN0cm95LFxuICBWaWV3RW5jYXBzdWxhdGlvbixcbiAgYWZ0ZXJOZXh0UmVuZGVyLFxuICBjb21wdXRlZCxcbiAgZWZmZWN0LFxuICBpbmplY3QsXG4gIGlucHV0LFxuICBzaWduYWwsXG4gIHZpZXdDaGlsZCxcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBBWF9GVU5ORUxfQ0hBUlRfQ09ORklHIH0gZnJvbSAnLi9mdW5uZWwtY2hhcnQuY29uZmlnJztcbmltcG9ydCB7IEFYRnVubmVsQ2hhcnRPcHRpb24sIEFYRnVubmVsRGF0YSB9IGZyb20gJy4vZnVubmVsLWNoYXJ0LnR5cGUnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdheC1mdW5uZWwtY2hhcnQnLFxuICB0ZW1wbGF0ZVVybDogJy4vZnVubmVsLWNoYXJ0LmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmxzOiBbJy4vZnVubmVsLWNoYXJ0LmNvbXBvbmVudC5zY3NzJ10sXG4gIGVuY2Fwc3VsYXRpb246IFZpZXdFbmNhcHN1bGF0aW9uLk5vbmUsXG4gIGltcG9ydHM6IFtBWENoYXJ0VG9vbHRpcENvbXBvbmVudF0sXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxufSlcbmV4cG9ydCBjbGFzcyBBWEZ1bm5lbENoYXJ0Q29tcG9uZW50IGV4dGVuZHMgQVhDaGFydENvbXBvbmVudCBpbXBsZW1lbnRzIE9uRGVzdHJveSwgQVhDaGFydENvbXBvbmVudEJhc2Uge1xuICAvLyBJbnB1dHNcbiAgZGF0YSA9IGlucHV0PEFYRnVubmVsRGF0YVtdPihbXSk7XG4gIG9wdGlvbnMgPSBpbnB1dDxBWEZ1bm5lbENoYXJ0T3B0aW9uPih7fSk7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBjaGFydENvbnRhaW5lckVsID0gdmlld0NoaWxkLnJlcXVpcmVkPEVsZW1lbnRSZWY8SFRNTERpdkVsZW1lbnQ+PignY2hhcnRDb250YWluZXInKTtcblxuICAvLyBTVkcgU3RhdGVcbiAgcHJpdmF0ZSBzdmdFbGVtZW50OiBTVkdTVkdFbGVtZW50IHwgbnVsbCA9IG51bGw7XG4gIHByb3RlY3RlZCBkMyE6IHR5cGVvZiBpbXBvcnQoJ2QzJyk7XG4gIHByaXZhdGUgX2luaXRpYWxpemVkID0gc2lnbmFsKGZhbHNlKTtcbiAgcHJpdmF0ZSBfcmVuZGVyZWQgPSBzaWduYWwoZmFsc2UpO1xuXG4gIC8vIFRvb2x0aXAgU2lnbmFsc1xuICBwcml2YXRlIF90b29sdGlwVmlzaWJsZSA9IHNpZ25hbChmYWxzZSk7XG4gIHByaXZhdGUgX3Rvb2x0aXBQb3NpdGlvbiA9IHNpZ25hbCh7IHg6IDAsIHk6IDAgfSk7XG4gIHByaXZhdGUgX3Rvb2x0aXBEYXRhID0gc2lnbmFsPEFYQ2hhcnRUb29sdGlwRGF0YT4oeyB0aXRsZTogJycsIHZhbHVlOiAnJyB9KTtcbiAgcHJpdmF0ZSBfdG9vbHRpcFJhZklkOiBudW1iZXIgfCBudWxsID0gbnVsbDtcblxuICBwcm90ZWN0ZWQgdG9vbHRpcFZpc2libGUgPSB0aGlzLl90b29sdGlwVmlzaWJsZS5hc1JlYWRvbmx5KCk7XG4gIHByb3RlY3RlZCB0b29sdGlwUG9zaXRpb24gPSB0aGlzLl90b29sdGlwUG9zaXRpb24uYXNSZWFkb25seSgpO1xuICBwcm90ZWN0ZWQgdG9vbHRpcERhdGEgPSB0aGlzLl90b29sdGlwRGF0YS5hc1JlYWRvbmx5KCk7XG5cbiAgcHJpdmF0ZSBjb25maWdUb2tlbiA9IGluamVjdChBWF9GVU5ORUxfQ0hBUlRfQ09ORklHKTtcblxuICBwcm90ZWN0ZWQgZWZmZWN0aXZlT3B0aW9ucyA9IGNvbXB1dGVkKCgpID0+ICh7XG4gICAgLi4udGhpcy5jb25maWdUb2tlbixcbiAgICAuLi50aGlzLm9wdGlvbnMoKSxcbiAgfSkpO1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKCk7XG5cbiAgICBhZnRlck5leHRSZW5kZXIoKCkgPT4ge1xuICAgICAgdGhpcy5faW5pdGlhbGl6ZWQuc2V0KHRydWUpO1xuICAgICAgdGhpcy5sb2FkRDMoKTtcbiAgICB9KTtcblxuICAgIGVmZmVjdCgoKSA9PiB7XG4gICAgICAvLyBUcmlnZ2VyIHVwZGF0ZSBvbiBkYXRhIG9yIG9wdGlvbiBjaGFuZ2VcbiAgICAgIHRoaXMuZGF0YSgpO1xuICAgICAgdGhpcy5lZmZlY3RpdmVPcHRpb25zKCk7XG4gICAgICBpZiAodGhpcy5fcmVuZGVyZWQoKSkge1xuICAgICAgICB0aGlzLnVwZGF0ZUNoYXJ0KCk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICB0aGlzLmNsZWFudXBDaGFydCgpO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGxvYWREMygpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAodGhpcy5kMykgcmV0dXJuO1xuICAgIHRyeSB7XG4gICAgICB0aGlzLmQzID0gYXdhaXQgaW1wb3J0KCdkMycpO1xuICAgICAgaWYgKHRoaXMuX2luaXRpYWxpemVkKCkgJiYgdGhpcy5jaGFydENvbnRhaW5lckVsKCkpIHtcbiAgICAgICAgdGhpcy5jcmVhdGVDaGFydCgpO1xuICAgICAgICB0aGlzLl9yZW5kZXJlZC5zZXQodHJ1ZSk7XG4gICAgICB9XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoJ0FYRnVubmVsQ2hhcnQ6IEZhaWxlZCB0byBsb2FkIEQzLmpzJywgZXJyb3IpO1xuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBjcmVhdGVDaGFydCgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5zdmdFbGVtZW50KSB0aGlzLnN2Z0VsZW1lbnQucmVtb3ZlKCk7XG5cbiAgICBjb25zdCBkYXRhID0gWy4uLnRoaXMuZGF0YSgpXS5zb3J0KChhLCBiKSA9PiBiLnZhbHVlIC0gYS52YWx1ZSk7XG4gICAgaWYgKCFkYXRhLmxlbmd0aCkgcmV0dXJuO1xuXG4gICAgY29uc3QgY29udGFpbmVyID0gdGhpcy5jaGFydENvbnRhaW5lckVsKCkubmF0aXZlRWxlbWVudDtcbiAgICBjb25zdCB3aWR0aCA9IGNvbnRhaW5lci5jbGllbnRXaWR0aDtcbiAgICBjb25zdCBoZWlnaHQgPSBjb250YWluZXIuY2xpZW50SGVpZ2h0O1xuICAgIGNvbnN0IG9wdCA9IHRoaXMuZWZmZWN0aXZlT3B0aW9ucygpO1xuICAgIGNvbnN0IG1hcmdpbiA9IG9wdC5tYXJnaW47XG5cbiAgICB0aGlzLnN2Z0VsZW1lbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50TlMoJ2h0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnJywgJ3N2ZycpO1xuICAgIGNvbnN0IHN2ZyA9IHRoaXMuZDNcbiAgICAgIC5zZWxlY3QodGhpcy5zdmdFbGVtZW50KVxuICAgICAgLmF0dHIoJ3dpZHRoJywgJzEwMCUnKVxuICAgICAgLmF0dHIoJ2hlaWdodCcsICcxMDAlJylcbiAgICAgIC5hdHRyKCd2aWV3Qm94JywgYDAgMCAke3dpZHRofSAke2hlaWdodH1gKVxuICAgICAgLmF0dHIoJ3ByZXNlcnZlQXNwZWN0UmF0aW8nLCAneE1pZFlNaWQgbWVldCcpO1xuXG4gICAgY29udGFpbmVyLmFwcGVuZENoaWxkKHRoaXMuc3ZnRWxlbWVudCk7XG5cbiAgICBjb25zdCBpbm5lcldpZHRoID0gd2lkdGggLSBtYXJnaW4ubGVmdCAtIG1hcmdpbi5yaWdodDtcbiAgICBjb25zdCBpbm5lckhlaWdodCA9IGhlaWdodCAtIG1hcmdpbi50b3AgLSBtYXJnaW4uYm90dG9tO1xuXG4gICAgY29uc3QgZyA9IHN2Zy5hcHBlbmQoJ2cnKS5hdHRyKCd0cmFuc2Zvcm0nLCBgdHJhbnNsYXRlKCR7bWFyZ2luLmxlZnR9LCR7bWFyZ2luLnRvcH0pYCk7XG5cbiAgICBjb25zdCBjb2xvclNjYWxlID0gdGhpcy5kMy5zY2FsZU9yZGluYWw8c3RyaW5nPigpLnJhbmdlKG9wdC5jb2xvcnMpO1xuICAgIGNvbnN0IHNsaWNlSGVpZ2h0ID0gaW5uZXJIZWlnaHQgLyBkYXRhLmxlbmd0aDtcbiAgICBjb25zdCBtYXhWYWx1ZSA9IGRhdGFbMF0udmFsdWU7XG4gICAgY29uc3QgZWFzaW5nID0gZ2V0RWFzaW5nRnVuY3Rpb24odGhpcy5kMywgb3B0LmFuaW1hdGlvbkVhc2luZyk7XG5cbiAgICBkYXRhLmZvckVhY2goKGQsIGkpID0+IHtcbiAgICAgIGNvbnN0IHRvcFZhbCA9IGQudmFsdWU7XG4gICAgICBjb25zdCBib3R0b21WYWwgPSBkYXRhW2kgKyAxXT8udmFsdWUgPz8gZC52YWx1ZSAqIG9wdC5uZWNrV2lkdGg7XG5cbiAgICAgIGNvbnN0IHRvcFcgPSAodG9wVmFsIC8gbWF4VmFsdWUpICogaW5uZXJXaWR0aDtcbiAgICAgIGNvbnN0IGJvdHRvbVcgPSAoYm90dG9tVmFsIC8gbWF4VmFsdWUpICogaW5uZXJXaWR0aDtcblxuICAgICAgY29uc3QgeFRvcCA9IChpbm5lcldpZHRoIC0gdG9wVykgLyAyO1xuICAgICAgY29uc3QgeEJvdHRvbSA9IChpbm5lcldpZHRoIC0gYm90dG9tVykgLyAyO1xuICAgICAgY29uc3QgeVRvcCA9IGkgKiBzbGljZUhlaWdodDtcbiAgICAgIGNvbnN0IHlCb3R0b20gPSAoaSArIDEpICogc2xpY2VIZWlnaHQ7XG5cbiAgICAgIGNvbnN0IHBhdGhEYXRhID0gYE0gJHt4VG9wfSwke3lUb3B9IEwgJHt4VG9wICsgdG9wV30sJHt5VG9wfSBMICR7eEJvdHRvbSArIGJvdHRvbVd9LCR7eUJvdHRvbX0gTCAke3hCb3R0b219LCR7eUJvdHRvbX0gWmA7XG5cbiAgICAgIGNvbnN0IHNsaWNlR3JvdXAgPSBnLmFwcGVuZCgnZycpLmF0dHIoJ2NsYXNzJywgJ2Z1bm5lbC1zbGljZS1jb250YWluZXInKTtcblxuICAgICAgY29uc3QgcGF0aCA9IHNsaWNlR3JvdXBcbiAgICAgICAgLmFwcGVuZCgncGF0aCcpXG4gICAgICAgIC5hdHRyKCdjbGFzcycsICdmdW5uZWwtc2xpY2UnKVxuICAgICAgICAuYXR0cignZCcsIHBhdGhEYXRhKVxuICAgICAgICAuYXR0cignZmlsbCcsIGQuY29sb3IgPz8gY29sb3JTY2FsZShpLnRvU3RyaW5nKCkpKVxuICAgICAgICAuc3R5bGUoJ29wYWNpdHknLCAwKVxuICAgICAgICAub24oJ21vdXNlZW50ZXInLCAoZXZlbnQpID0+IHtcbiAgICAgICAgICBzdmcuY2xhc3NlZCgnaXMtZGltbWVkJywgdHJ1ZSk7XG4gICAgICAgICAgdGhpcy5kMy5zZWxlY3QoZXZlbnQuY3VycmVudFRhcmdldCkuY2xhc3NlZCgnaXMtYWN0aXZlJywgdHJ1ZSk7XG4gICAgICAgICAgdGhpcy5zaG93VG9vbHRpcChldmVudCwgZCk7XG4gICAgICAgIH0pXG4gICAgICAgIC5vbignbW91c2Vtb3ZlJywgKGV2ZW50KSA9PiB0aGlzLnVwZGF0ZVRvb2x0aXBQb3NpdGlvbihldmVudCkpXG4gICAgICAgIC5vbignbW91c2VsZWF2ZScsIChldmVudCkgPT4ge1xuICAgICAgICAgIHN2Zy5jbGFzc2VkKCdpcy1kaW1tZWQnLCBmYWxzZSk7XG4gICAgICAgICAgdGhpcy5kMy5zZWxlY3QoZXZlbnQuY3VycmVudFRhcmdldCkuY2xhc3NlZCgnaXMtYWN0aXZlJywgZmFsc2UpO1xuICAgICAgICAgIHRoaXMuaGlkZVRvb2x0aXAoKTtcbiAgICAgICAgfSk7XG5cbiAgICAgIHBhdGhcbiAgICAgICAgLnRyYW5zaXRpb24oKVxuICAgICAgICAuZHVyYXRpb24ob3B0LmFuaW1hdGlvbkR1cmF0aW9uKVxuICAgICAgICAuZGVsYXkoaSAqIDgwKVxuICAgICAgICAuZWFzZShlYXNpbmcpXG4gICAgICAgIC5zdHlsZSgnb3BhY2l0eScsIDEpO1xuXG4gICAgICBpZiAob3B0LnNob3dMYWJlbHMpIHtcbiAgICAgICAgY29uc3QgbGFiZWxHcm91cCA9IHNsaWNlR3JvdXAuYXBwZW5kKCdnJykuYXR0cignY2xhc3MnLCAnZnVubmVsLWxhYmVsLWdyb3VwJykuc3R5bGUoJ29wYWNpdHknLCAwKTtcblxuICAgICAgICBsYWJlbEdyb3VwXG4gICAgICAgICAgLmFwcGVuZCgndGV4dCcpXG4gICAgICAgICAgLmF0dHIoJ2NsYXNzJywgJ2Z1bm5lbC1sYWJlbC1uYW1lJylcbiAgICAgICAgICAuYXR0cigneCcsIGlubmVyV2lkdGggLyAyICsgdG9wVyAvIDIgKyAyNSlcbiAgICAgICAgICAuYXR0cigneScsIHlUb3AgKyBzbGljZUhlaWdodCAvIDIgLSA1KVxuICAgICAgICAgIC50ZXh0KGQubmFtZSk7XG5cbiAgICAgICAgbGFiZWxHcm91cFxuICAgICAgICAgIC5hcHBlbmQoJ3RleHQnKVxuICAgICAgICAgIC5hdHRyKCdjbGFzcycsICdmdW5uZWwtbGFiZWwtdmFsdWUnKVxuICAgICAgICAgIC5hdHRyKCd4JywgaW5uZXJXaWR0aCAvIDIgKyB0b3BXIC8gMiArIDI1KVxuICAgICAgICAgIC5hdHRyKCd5JywgeVRvcCArIHNsaWNlSGVpZ2h0IC8gMiArIDE1KVxuICAgICAgICAgIC50ZXh0KGQudmFsdWUudG9Mb2NhbGVTdHJpbmcoKSk7XG5cbiAgICAgICAgbGFiZWxHcm91cFxuICAgICAgICAgIC50cmFuc2l0aW9uKClcbiAgICAgICAgICAuZHVyYXRpb24oNjAwKVxuICAgICAgICAgIC5kZWxheSg0MDAgKyBpICogODApXG4gICAgICAgICAgLnN0eWxlKCdvcGFjaXR5JywgMSk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICBwdWJsaWMgdXBkYXRlQ2hhcnQoKTogdm9pZCB7XG4gICAgdGhpcy5jcmVhdGVDaGFydCgpO1xuICB9XG5cbiAgcHJpdmF0ZSBzaG93VG9vbHRpcChldmVudDogTW91c2VFdmVudCwgaXRlbTogQVhGdW5uZWxEYXRhKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLmVmZmVjdGl2ZU9wdGlvbnMoKS5zaG93VG9vbHRpcCkgcmV0dXJuO1xuICAgIHRoaXMuX3Rvb2x0aXBEYXRhLnNldCh7IHRpdGxlOiBpdGVtLm5hbWUsIHZhbHVlOiBpdGVtLnZhbHVlLnRvTG9jYWxlU3RyaW5nKCksIGNvbG9yOiBpdGVtLmNvbG9yIH0pO1xuICAgIHRoaXMuX3Rvb2x0aXBWaXNpYmxlLnNldCh0cnVlKTtcbiAgICB0aGlzLnVwZGF0ZVRvb2x0aXBQb3NpdGlvbihldmVudCk7XG4gIH1cblxuICBwcml2YXRlIHVwZGF0ZVRvb2x0aXBQb3NpdGlvbihldmVudDogTW91c2VFdmVudCk6IHZvaWQge1xuICAgIGlmICh0aGlzLl90b29sdGlwUmFmSWQpIGNhbmNlbEFuaW1hdGlvbkZyYW1lKHRoaXMuX3Rvb2x0aXBSYWZJZCk7XG4gICAgdGhpcy5fdG9vbHRpcFJhZklkID0gcmVxdWVzdEFuaW1hdGlvbkZyYW1lKCgpID0+IHtcbiAgICAgIGNvbnN0IGNvbnRhaW5lckVsID0gdGhpcy5jaGFydENvbnRhaW5lckVsKCkubmF0aXZlRWxlbWVudDtcbiAgICAgIGNvbnN0IHJlY3QgPSBjb250YWluZXJFbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgIGNvbnN0IHRvb2x0aXBFbCA9IGNvbnRhaW5lckVsLnF1ZXJ5U2VsZWN0b3IoJy5jaGFydC10b29sdGlwJykgYXMgSFRNTEVsZW1lbnQ7XG4gICAgICBjb25zdCB0b29sdGlwUmVjdCA9IHRvb2x0aXBFbD8uZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkgPz8gbnVsbDtcbiAgICAgIHRoaXMuX3Rvb2x0aXBQb3NpdGlvbi5zZXQoY29tcHV0ZVRvb2x0aXBQb3NpdGlvbihyZWN0LCB0b29sdGlwUmVjdCwgZXZlbnQuY2xpZW50WCArIDEwLCBldmVudC5jbGllbnRZIC0gMTAsIDEwKSk7XG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIGhpZGVUb29sdGlwKCk6IHZvaWQge1xuICAgIHRoaXMuX3Rvb2x0aXBWaXNpYmxlLnNldChmYWxzZSk7XG4gIH1cblxuICBwdWJsaWMgY2xlYW51cENoYXJ0KCk6IHZvaWQge1xuICAgIGlmICh0aGlzLl90b29sdGlwUmFmSWQpIGNhbmNlbEFuaW1hdGlvbkZyYW1lKHRoaXMuX3Rvb2x0aXBSYWZJZCk7XG4gICAgaWYgKHRoaXMuc3ZnRWxlbWVudCkge1xuICAgICAgdGhpcy5zdmdFbGVtZW50LnJlbW92ZSgpO1xuICAgICAgdGhpcy5zdmdFbGVtZW50ID0gbnVsbDtcbiAgICB9XG4gIH1cbn1cbiIsIjxkaXYgY2xhc3M9XCJheC1mdW5uZWwtY2hhcnRcIiByb2xlPVwiaW1nXCIgI2NoYXJ0Q29udGFpbmVyPjwvZGl2PlxuXG48YXgtY2hhcnQtdG9vbHRpcCBbZGF0YV09XCJ0b29sdGlwRGF0YSgpXCIgW3Bvc2l0aW9uXT1cInRvb2x0aXBQb3NpdGlvbigpXCIgW3Zpc2libGVdPVwidG9vbHRpcFZpc2libGUoKVwiPlxuPC9heC1jaGFydC10b29sdGlwPlxuIl19","/**\n * Generated bundle index. Do not edit.\n */\nexport * from './index';\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWNvcmV4LWNoYXJ0cy1mdW5uZWwtY2hhcnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wYWNrYWdlcy9jaGFydHMvZnVubmVsLWNoYXJ0L3NyYy9hY29yZXgtY2hhcnRzLWZ1bm5lbC1jaGFydC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7R0FFRztBQUVILGNBQWMsU0FBUyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBHZW5lcmF0ZWQgYnVuZGxlIGluZGV4LiBEbyBub3QgZWRpdC5cbiAqL1xuXG5leHBvcnQgKiBmcm9tICcuL2luZGV4JztcbiJdfQ=="],"names":[],"mappings":"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"}
|
|
@@ -81,6 +81,10 @@ class AXGaugeChartComponent extends AXChartComponent {
|
|
|
81
81
|
HALF_CIRCLE_RADIANS = Math.PI;
|
|
82
82
|
QUARTER_CIRCLE_RADIANS = Math.PI / 2;
|
|
83
83
|
DEGREES_PER_RADIAN = 180 / Math.PI;
|
|
84
|
+
CHART_EDGE_PADDING = 12;
|
|
85
|
+
TICK_LABEL_CHAR_WIDTH_RATIO = 0.62;
|
|
86
|
+
TICK_LABEL_SIDE_PADDING = 6;
|
|
87
|
+
LABEL_TICK_CLEARANCE = 4;
|
|
84
88
|
constructor() {
|
|
85
89
|
super();
|
|
86
90
|
// Dynamically load D3 and initialize the chart when the component is ready
|
|
@@ -165,29 +169,36 @@ class AXGaugeChartComponent extends AXChartComponent {
|
|
|
165
169
|
// Calculate margin as percentage of size (5-8% with reasonable bounds)
|
|
166
170
|
const marginRatio = 0.08;
|
|
167
171
|
const margin = Math.max(5, Math.min(size * marginRatio, 30));
|
|
168
|
-
|
|
169
|
-
const
|
|
172
|
+
const tickCount = this.getTickCount(size);
|
|
173
|
+
const tickFontPx = this.getTickFontSize(size);
|
|
174
|
+
const maxTickLabelWidth = this.estimateMaxTickLabelWidth(tickCount, minValue, maxValue, tickFontPx);
|
|
175
|
+
const tickLength = Math.max(4, Math.min((size / 2) * 0.12, 14));
|
|
176
|
+
// Keep labels closer to the gauge arc while preserving readability.
|
|
177
|
+
const labelGap = Math.max(6, Math.min((size / 2) * 0.06, 14));
|
|
178
|
+
const labelOffsetFromTickEnd = labelGap + tickFontPx * 0.35;
|
|
179
|
+
const tickLabelSpace = tickLength + labelOffsetFromTickEnd + tickFontPx;
|
|
170
180
|
const totalVerticalSpace = size / 2 + tickLabelSpace;
|
|
171
|
-
//
|
|
172
|
-
|
|
173
|
-
const estimatedTickFontSize = Math.max(14, Math.min(18, Math.floor(size / 35)));
|
|
174
|
-
const horizontalPadding = Math.max(20, estimatedTickFontSize * 1.5);
|
|
181
|
+
// Labels at edge ticks use start/end anchors, so they can extend by near full width.
|
|
182
|
+
const horizontalPadding = Math.max(18, maxTickLabelWidth + 8);
|
|
175
183
|
const totalWidth = size + horizontalPadding * 2;
|
|
184
|
+
const viewBoxWidth = totalWidth + this.CHART_EDGE_PADDING * 2;
|
|
185
|
+
const viewBoxHeight = totalVerticalSpace + this.CHART_EDGE_PADDING * 2;
|
|
176
186
|
// Set up SVG with responsive viewBox that accounts for overflow
|
|
177
187
|
const svg = this.d3
|
|
178
188
|
.select(this.svgElement)
|
|
179
189
|
.attr('width', '100%')
|
|
180
190
|
.attr('height', '100%')
|
|
181
|
-
.attr('viewBox', `0 0 ${
|
|
191
|
+
.attr('viewBox', `0 0 ${viewBoxWidth} ${viewBoxHeight}`)
|
|
182
192
|
.attr('preserveAspectRatio', 'xMidYMid meet');
|
|
183
193
|
// Create a group for the chart centered horizontally with padding, positioned to show only the top half
|
|
184
194
|
const chartGroup = svg
|
|
185
195
|
.append('g')
|
|
186
|
-
.attr('transform', `translate(${size / 2 + horizontalPadding}, ${size / 2 - margin})`);
|
|
196
|
+
.attr('transform', `translate(${size / 2 + horizontalPadding + this.CHART_EDGE_PADDING}, ${size / 2 - margin + this.CHART_EDGE_PADDING})`);
|
|
187
197
|
// Define gauge parameters
|
|
188
198
|
const radius = size / 2 - margin;
|
|
189
|
-
const desiredGaugeWidth = typeof gaugeWidth === 'number' && !Number.isNaN(gaugeWidth) ? gaugeWidth :
|
|
190
|
-
|
|
199
|
+
const desiredGaugeWidth = typeof gaugeWidth === 'number' && !Number.isNaN(gaugeWidth) ? gaugeWidth : 30;
|
|
200
|
+
// Respect explicit gaugeWidth in px with sane absolute bounds.
|
|
201
|
+
const clampedGaugeWidth = Math.max(6, Math.min(desiredGaugeWidth, radius * 0.7));
|
|
191
202
|
const innerRadius = radius - clampedGaugeWidth;
|
|
192
203
|
const outerRadius = radius;
|
|
193
204
|
// Create gradient definitions
|
|
@@ -199,7 +210,7 @@ class AXGaugeChartComponent extends AXChartComponent {
|
|
|
199
210
|
this.drawThresholds(chartGroup, innerRadius, outerRadius, minValue, maxValue, thresholds, cornerRadius);
|
|
200
211
|
}
|
|
201
212
|
// Draw tick marks
|
|
202
|
-
this.drawTicks(chartGroup, outerRadius, minValue, maxValue, size);
|
|
213
|
+
this.drawTicks(chartGroup, outerRadius, minValue, maxValue, size, tickCount, tickFontPx);
|
|
203
214
|
// Draw the dial/needle with animation
|
|
204
215
|
this.drawDial(chartGroup, radius, this.value(), minValue, maxValue, animationDuration);
|
|
205
216
|
// Draw the value display (after the dial so it's on top)
|
|
@@ -485,79 +496,130 @@ class AXGaugeChartComponent extends AXChartComponent {
|
|
|
485
496
|
/**
|
|
486
497
|
* Draws tick marks and labels around the gauge
|
|
487
498
|
*/
|
|
488
|
-
drawTicks(chartGroup, radius, minValue, maxValue, size) {
|
|
489
|
-
// Dynamically choose tick count based on chart size (reduced for better spacing)
|
|
490
|
-
let tickCount = 5;
|
|
491
|
-
if (size < 200)
|
|
492
|
-
tickCount = 3; // Very small: only show min, mid, max
|
|
493
|
-
else if (size < 300)
|
|
494
|
-
tickCount = 4;
|
|
495
|
-
else if (size < 400)
|
|
496
|
-
tickCount = 5;
|
|
497
|
-
else if (size > 520)
|
|
498
|
-
tickCount = 7;
|
|
499
|
-
// Scale tick length and label offset proportionally to size
|
|
499
|
+
drawTicks(chartGroup, radius, minValue, maxValue, size, tickCount, tickFontPx) {
|
|
500
500
|
const tickLength = Math.max(4, Math.min(radius * 0.12, 14));
|
|
501
|
-
|
|
502
|
-
const labelOffset = Math.max(22, Math.min(radius * 0.28, 45));
|
|
503
|
-
// Create a group for the ticks
|
|
501
|
+
const baseLabelOffset = this.getBaseLabelOffset(radius, tickLength, tickFontPx);
|
|
504
502
|
const tickGroup = chartGroup.append('g').attr('class', 'ticks');
|
|
505
|
-
// Generate tick values
|
|
506
503
|
const tickValues = [];
|
|
507
504
|
const step = (maxValue - minValue) / (tickCount - 1);
|
|
508
505
|
for (let i = 0; i < tickCount; i++) {
|
|
509
506
|
tickValues.push(minValue + i * step);
|
|
510
507
|
}
|
|
511
|
-
|
|
512
|
-
tickValues.forEach((tick) => {
|
|
513
|
-
// Calculate angle for this tick
|
|
508
|
+
const tickMetrics = tickValues.map((tick) => {
|
|
514
509
|
const angle = this.scaleValueToAngle(tick, minValue, maxValue);
|
|
515
|
-
const radians = angle - this.QUARTER_CIRCLE_RADIANS;
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
// Draw tick line
|
|
510
|
+
const radians = angle - this.QUARTER_CIRCLE_RADIANS;
|
|
511
|
+
return {
|
|
512
|
+
radians,
|
|
513
|
+
cos: Math.cos(radians),
|
|
514
|
+
sin: Math.sin(radians),
|
|
515
|
+
label: this.formatTickValue(tick, minValue, maxValue),
|
|
516
|
+
};
|
|
517
|
+
});
|
|
518
|
+
tickMetrics.forEach((metric) => {
|
|
525
519
|
tickGroup
|
|
526
520
|
.append('line')
|
|
527
|
-
.attr('x1',
|
|
528
|
-
.attr('y1',
|
|
529
|
-
.attr('x2',
|
|
530
|
-
.attr('y2',
|
|
521
|
+
.attr('x1', metric.cos * (radius + 5))
|
|
522
|
+
.attr('y1', metric.sin * (radius + 5))
|
|
523
|
+
.attr('x2', metric.cos * (radius + tickLength))
|
|
524
|
+
.attr('y2', metric.sin * (radius + tickLength))
|
|
531
525
|
.attr('stroke', 'rgba(var(--ax-comp-gauge-chart-text-color), 0.5)')
|
|
532
526
|
.attr('stroke-width', 2);
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
527
|
+
});
|
|
528
|
+
const textSelection = tickGroup
|
|
529
|
+
.selectAll('text.gauge-tick-label')
|
|
530
|
+
.data(tickMetrics)
|
|
531
|
+
.enter()
|
|
532
|
+
.append('text')
|
|
533
|
+
.attr('class', 'gauge-tick-label')
|
|
534
|
+
.attr('x', 0)
|
|
535
|
+
.attr('y', 0)
|
|
536
|
+
.attr('fill', 'rgba(var(--ax-comp-gauge-chart-text-color), 0.7)')
|
|
537
|
+
.style('font-size', `${tickFontPx}px`)
|
|
538
|
+
.text((d) => d.label);
|
|
539
|
+
textSelection.each((d, index, nodes) => {
|
|
540
|
+
const node = nodes[index];
|
|
541
|
+
let bboxWidth = this.estimateLabelWidth(d.label, tickFontPx);
|
|
542
|
+
let bboxHeight = tickFontPx;
|
|
543
|
+
try {
|
|
544
|
+
const bbox = node.getBBox();
|
|
545
|
+
if (bbox.width > 0)
|
|
546
|
+
bboxWidth = bbox.width;
|
|
547
|
+
if (bbox.height > 0)
|
|
548
|
+
bboxHeight = bbox.height;
|
|
545
549
|
}
|
|
546
|
-
|
|
547
|
-
//
|
|
548
|
-
formattedValue = formatLargeNumber(Math.round(tick));
|
|
550
|
+
catch {
|
|
551
|
+
// Keep fallback estimates.
|
|
549
552
|
}
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
.text(formattedValue);
|
|
553
|
+
const anchor = this.getTickLabelAnchor(d.cos);
|
|
554
|
+
const nearEdgeExtent = this.getNearEdgeProjection(anchor, d.cos, d.sin, bboxWidth, bboxHeight);
|
|
555
|
+
const requiredOffset = tickLength + this.LABEL_TICK_CLEARANCE + nearEdgeExtent;
|
|
556
|
+
const effectiveLabelOffset = Math.max(baseLabelOffset, requiredOffset);
|
|
557
|
+
const nudge = tickFontPx * 0.1;
|
|
558
|
+
const x = d.cos * (radius + effectiveLabelOffset) + (anchor === 'start' ? nudge : anchor === 'end' ? -nudge : 0);
|
|
559
|
+
const y = d.sin * (radius + effectiveLabelOffset);
|
|
560
|
+
this.d3.select(node).attr('x', x).attr('y', y).attr('text-anchor', anchor).attr('dominant-baseline', 'middle');
|
|
559
561
|
});
|
|
560
562
|
}
|
|
563
|
+
getTickCount(size) {
|
|
564
|
+
if (size < 200)
|
|
565
|
+
return 3;
|
|
566
|
+
if (size < 300)
|
|
567
|
+
return 4;
|
|
568
|
+
if (size < 400)
|
|
569
|
+
return 5;
|
|
570
|
+
if (size > 520)
|
|
571
|
+
return 7;
|
|
572
|
+
return 5;
|
|
573
|
+
}
|
|
574
|
+
getTickFontSize(size) {
|
|
575
|
+
return Math.max(14, Math.min(18, Math.floor(size / 35)));
|
|
576
|
+
}
|
|
577
|
+
getBaseLabelOffset(radius, tickLength, tickFontPx) {
|
|
578
|
+
const labelGap = Math.max(6, Math.min(radius * 0.06, 14));
|
|
579
|
+
return tickLength + labelGap + tickFontPx * 0.2;
|
|
580
|
+
}
|
|
581
|
+
getTickLabelAnchor(cosValue) {
|
|
582
|
+
if (cosValue > 0.35)
|
|
583
|
+
return 'start';
|
|
584
|
+
if (cosValue < -0.35)
|
|
585
|
+
return 'end';
|
|
586
|
+
return 'middle';
|
|
587
|
+
}
|
|
588
|
+
getNearEdgeProjection(anchor, cosValue, sinValue, bboxWidth, bboxHeight) {
|
|
589
|
+
const absCos = Math.abs(cosValue);
|
|
590
|
+
const absSin = Math.abs(sinValue);
|
|
591
|
+
const halfHeightProjection = absSin * (bboxHeight / 2);
|
|
592
|
+
// For start/end anchored labels on edge ticks, the nearest side is close to the anchor point.
|
|
593
|
+
if (anchor === 'start' || anchor === 'end') {
|
|
594
|
+
return halfHeightProjection + absCos * this.TICK_LABEL_SIDE_PADDING;
|
|
595
|
+
}
|
|
596
|
+
// For centered labels, nearest side includes half text width projection.
|
|
597
|
+
return absCos * (bboxWidth / 2) + halfHeightProjection;
|
|
598
|
+
}
|
|
599
|
+
formatTickValue(tick, minValue, maxValue) {
|
|
600
|
+
const valueRange = maxValue - minValue;
|
|
601
|
+
if (valueRange <= 10) {
|
|
602
|
+
return tick.toFixed(2).replace(/\.?0+$/, '');
|
|
603
|
+
}
|
|
604
|
+
if (valueRange < 1000) {
|
|
605
|
+
return tick % 1 === 0 ? tick.toString() : tick.toFixed(1);
|
|
606
|
+
}
|
|
607
|
+
return formatLargeNumber(Math.round(tick));
|
|
608
|
+
}
|
|
609
|
+
estimateLabelWidth(label, tickFontPx) {
|
|
610
|
+
return label.length * tickFontPx * this.TICK_LABEL_CHAR_WIDTH_RATIO + this.TICK_LABEL_SIDE_PADDING;
|
|
611
|
+
}
|
|
612
|
+
estimateMaxTickLabelWidth(tickCount, minValue, maxValue, tickFontPx) {
|
|
613
|
+
if (tickCount <= 1)
|
|
614
|
+
return tickFontPx;
|
|
615
|
+
const step = (maxValue - minValue) / (tickCount - 1);
|
|
616
|
+
let maxChars = 0;
|
|
617
|
+
for (let i = 0; i < tickCount; i++) {
|
|
618
|
+
const label = this.formatTickValue(minValue + i * step, minValue, maxValue);
|
|
619
|
+
maxChars = Math.max(maxChars, label.length);
|
|
620
|
+
}
|
|
621
|
+
return maxChars * tickFontPx * this.TICK_LABEL_CHAR_WIDTH_RATIO + this.TICK_LABEL_SIDE_PADDING;
|
|
622
|
+
}
|
|
561
623
|
/**
|
|
562
624
|
* Draws the value and label text in the center
|
|
563
625
|
*/
|
|
@@ -672,11 +734,11 @@ class AXGaugeChartComponent extends AXChartComponent {
|
|
|
672
734
|
return radians * this.DEGREES_PER_RADIAN;
|
|
673
735
|
}
|
|
674
736
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: AXGaugeChartComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
675
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "20.3.3", type: AXGaugeChartComponent, isStandalone: true, selector: "ax-gauge-chart", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "chartContainerEl", first: true, predicate: ["chartContainer"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"ax-gauge-chart\" role=\"img\" #chartContainer></div>\n<ax-chart-tooltip [data]=\"tooltipData()\" [position]=\"tooltipPosition()\" [visible]=\"tooltipVisible()\"></ax-chart-tooltip>\n", styles: ["ax-gauge-chart{display:block;width:100%;height:100%;min-height:
|
|
737
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "20.3.3", type: AXGaugeChartComponent, isStandalone: true, selector: "ax-gauge-chart", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "chartContainerEl", first: true, predicate: ["chartContainer"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"ax-gauge-chart\" role=\"img\" #chartContainer></div>\n<ax-chart-tooltip [data]=\"tooltipData()\" [position]=\"tooltipPosition()\" [visible]=\"tooltipVisible()\"></ax-chart-tooltip>\n", styles: ["ax-gauge-chart{display:block;width:100%;height:100%;min-height:clamp(220px,38vw,360px);--ax-comp-gauge-chart-bg-color: 0, 0, 0, 0;--ax-comp-gauge-chart-text-color: var(--ax-sys-color-on-lightest-surface);--ax-comp-gauge-chart-track-color: var(--ax-sys-color-dark-surface);--ax-comp-gauge-chart-needle-color: var(--ax-sys-color-primary-500)}ax-gauge-chart .ax-gauge-chart{position:relative;width:100%;height:100%;box-sizing:border-box;padding:clamp(.5rem,1.2vw,.875rem);overflow:hidden;color:rgb(var(--ax-comp-gauge-chart-text-color));background-color:rgba(var(--ax-comp-gauge-chart-bg-color));border-radius:.5rem}ax-gauge-chart .ax-gauge-chart svg{display:block;width:100%;height:100%;max-width:100%;max-height:100%;overflow:hidden}ax-gauge-chart .ax-gauge-chart svg g:has(text){font-family:inherit}ax-gauge-chart .ax-gauge-chart-no-data-message{display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;padding:1rem;width:100%;height:100%;color:rgb(var(--ax-comp-gauge-chart-text-color));background-color:rgb(var(--ax-comp-gauge-chart-bg-color))}ax-gauge-chart .ax-gauge-chart-no-data-icon{margin-bottom:.75rem;color:rgba(var(--ax-comp-gauge-chart-text-color),.6)}ax-gauge-chart .ax-gauge-chart-no-data-text{font-weight:600;color:rgb(var(--ax-comp-gauge-chart-text-color))}\n"], dependencies: [{ kind: "component", type: AXChartTooltipComponent, selector: "ax-chart-tooltip", inputs: ["data", "position", "visible", "showPercentage", "style"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
676
738
|
}
|
|
677
739
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: AXGaugeChartComponent, decorators: [{
|
|
678
740
|
type: Component,
|
|
679
|
-
args: [{ selector: 'ax-gauge-chart', encapsulation: ViewEncapsulation.None, imports: [AXChartTooltipComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"ax-gauge-chart\" role=\"img\" #chartContainer></div>\n<ax-chart-tooltip [data]=\"tooltipData()\" [position]=\"tooltipPosition()\" [visible]=\"tooltipVisible()\"></ax-chart-tooltip>\n", styles: ["ax-gauge-chart{display:block;width:100%;height:100%;min-height:
|
|
741
|
+
args: [{ selector: 'ax-gauge-chart', encapsulation: ViewEncapsulation.None, imports: [AXChartTooltipComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"ax-gauge-chart\" role=\"img\" #chartContainer></div>\n<ax-chart-tooltip [data]=\"tooltipData()\" [position]=\"tooltipPosition()\" [visible]=\"tooltipVisible()\"></ax-chart-tooltip>\n", styles: ["ax-gauge-chart{display:block;width:100%;height:100%;min-height:clamp(220px,38vw,360px);--ax-comp-gauge-chart-bg-color: 0, 0, 0, 0;--ax-comp-gauge-chart-text-color: var(--ax-sys-color-on-lightest-surface);--ax-comp-gauge-chart-track-color: var(--ax-sys-color-dark-surface);--ax-comp-gauge-chart-needle-color: var(--ax-sys-color-primary-500)}ax-gauge-chart .ax-gauge-chart{position:relative;width:100%;height:100%;box-sizing:border-box;padding:clamp(.5rem,1.2vw,.875rem);overflow:hidden;color:rgb(var(--ax-comp-gauge-chart-text-color));background-color:rgba(var(--ax-comp-gauge-chart-bg-color));border-radius:.5rem}ax-gauge-chart .ax-gauge-chart svg{display:block;width:100%;height:100%;max-width:100%;max-height:100%;overflow:hidden}ax-gauge-chart .ax-gauge-chart svg g:has(text){font-family:inherit}ax-gauge-chart .ax-gauge-chart-no-data-message{display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;padding:1rem;width:100%;height:100%;color:rgb(var(--ax-comp-gauge-chart-text-color));background-color:rgb(var(--ax-comp-gauge-chart-bg-color))}ax-gauge-chart .ax-gauge-chart-no-data-icon{margin-bottom:.75rem;color:rgba(var(--ax-comp-gauge-chart-text-color),.6)}ax-gauge-chart .ax-gauge-chart-no-data-text{font-weight:600;color:rgb(var(--ax-comp-gauge-chart-text-color))}\n"] }]
|
|
680
742
|
}], ctorParameters: () => [] });
|
|
681
743
|
|
|
682
744
|
/**
|