@acorex/charts 20.6.30 → 20.6.32
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-funnel-chart.mjs +184 -66
- package/fesm2022/acorex-charts-funnel-chart.mjs.map +1 -1
- package/fesm2022/acorex-charts-heatmap-chart.mjs +30 -24
- package/fesm2022/acorex-charts-heatmap-chart.mjs.map +1 -1
- package/fesm2022/acorex-charts.mjs +25 -1
- package/fesm2022/acorex-charts.mjs.map +1 -1
- package/funnel-chart/index.d.ts +39 -10
- package/heatmap-chart/index.d.ts +24 -8
- package/index.d.ts +8 -1
- package/package.json +8 -8
|
@@ -1,20 +1,18 @@
|
|
|
1
|
-
import { AXChartComponent, getEasingFunction, computeTooltipPosition } from '@acorex/charts';
|
|
1
|
+
import { AXChartComponent, getEasingFunction, resolveCssColorInContext, computeTooltipPosition } from '@acorex/charts';
|
|
2
2
|
import { AXChartTooltipComponent } from '@acorex/charts/chart-tooltip';
|
|
3
|
-
import { AXPlatform } from '@acorex/core/platform';
|
|
4
3
|
import * as i0 from '@angular/core';
|
|
5
4
|
import { InjectionToken, input, output, viewChild, signal, inject, computed, afterNextRender, effect, ChangeDetectionStrategy, ViewEncapsulation, Component } from '@angular/core';
|
|
6
|
-
import { map } from 'rxjs';
|
|
7
5
|
|
|
8
6
|
const AXFunnelChartDefaultConfig = {
|
|
9
|
-
margin: { top:
|
|
7
|
+
margin: { top: 16, right: 16, bottom: 16, left: 16 },
|
|
10
8
|
neckWidth: 0.3,
|
|
11
9
|
showLabels: true,
|
|
10
|
+
showSegmentValues: true,
|
|
12
11
|
labelOffset: 24,
|
|
13
12
|
showTooltip: true,
|
|
14
13
|
animationDuration: 1000,
|
|
15
14
|
animationEasing: 'cubic-out',
|
|
16
|
-
|
|
17
|
-
endColor: 'rgb(var(--ax-sys-color-primary-950))',
|
|
15
|
+
color: 'rgb(var(--ax-sys-color-primary-500))',
|
|
18
16
|
messages: {
|
|
19
17
|
noData: 'No funnel data available',
|
|
20
18
|
noDataIcon: 'fa-light fa-filter-list',
|
|
@@ -38,9 +36,8 @@ class AXFunnelChartComponent extends AXChartComponent {
|
|
|
38
36
|
d3;
|
|
39
37
|
_initialized = signal(false, ...(ngDevMode ? [{ debugName: "_initialized" }] : []));
|
|
40
38
|
_rendered = signal(false, ...(ngDevMode ? [{ debugName: "_rendered" }] : []));
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
directionSub;
|
|
39
|
+
resizeObserver = null;
|
|
40
|
+
resizeDebounceId = null;
|
|
44
41
|
// Tooltip Signals
|
|
45
42
|
_tooltipVisible = signal(false, ...(ngDevMode ? [{ debugName: "_tooltipVisible" }] : []));
|
|
46
43
|
_tooltipPosition = signal({ x: 0, y: 0 }, ...(ngDevMode ? [{ debugName: "_tooltipPosition" }] : []));
|
|
@@ -59,14 +56,7 @@ class AXFunnelChartComponent extends AXChartComponent {
|
|
|
59
56
|
afterNextRender(() => {
|
|
60
57
|
this._initialized.set(true);
|
|
61
58
|
this.loadD3();
|
|
62
|
-
this.
|
|
63
|
-
.pipe(map((i) => i.data === 'rtl'))
|
|
64
|
-
.subscribe((isRtl) => {
|
|
65
|
-
this.isRtl.set(isRtl);
|
|
66
|
-
if (this._rendered()) {
|
|
67
|
-
this.updateChart();
|
|
68
|
-
}
|
|
69
|
-
});
|
|
59
|
+
this.attachResizeObserver();
|
|
70
60
|
});
|
|
71
61
|
effect(() => {
|
|
72
62
|
// Trigger update on data or option change
|
|
@@ -78,9 +68,34 @@ class AXFunnelChartComponent extends AXChartComponent {
|
|
|
78
68
|
});
|
|
79
69
|
}
|
|
80
70
|
ngOnDestroy() {
|
|
81
|
-
this.
|
|
71
|
+
this.detachResizeObserver();
|
|
82
72
|
this.cleanupChart();
|
|
83
73
|
}
|
|
74
|
+
attachResizeObserver() {
|
|
75
|
+
if (typeof ResizeObserver === 'undefined')
|
|
76
|
+
return;
|
|
77
|
+
const el = this.chartContainerEl().nativeElement;
|
|
78
|
+
this.resizeObserver = new ResizeObserver(() => {
|
|
79
|
+
if (this.resizeDebounceId !== null) {
|
|
80
|
+
clearTimeout(this.resizeDebounceId);
|
|
81
|
+
}
|
|
82
|
+
this.resizeDebounceId = window.setTimeout(() => {
|
|
83
|
+
this.resizeDebounceId = null;
|
|
84
|
+
if (this._rendered() && this.d3) {
|
|
85
|
+
this.updateChart();
|
|
86
|
+
}
|
|
87
|
+
}, 80);
|
|
88
|
+
});
|
|
89
|
+
this.resizeObserver.observe(el);
|
|
90
|
+
}
|
|
91
|
+
detachResizeObserver() {
|
|
92
|
+
this.resizeObserver?.disconnect();
|
|
93
|
+
this.resizeObserver = null;
|
|
94
|
+
if (this.resizeDebounceId !== null) {
|
|
95
|
+
clearTimeout(this.resizeDebounceId);
|
|
96
|
+
this.resizeDebounceId = null;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
84
99
|
async loadD3() {
|
|
85
100
|
if (this.d3)
|
|
86
101
|
return;
|
|
@@ -104,27 +119,34 @@ class AXFunnelChartComponent extends AXChartComponent {
|
|
|
104
119
|
return;
|
|
105
120
|
}
|
|
106
121
|
const container = this.chartContainerEl().nativeElement;
|
|
107
|
-
const width = container.clientWidth;
|
|
108
|
-
const height = container.clientHeight;
|
|
122
|
+
const width = Math.max(0, container.clientWidth);
|
|
123
|
+
const height = Math.max(0, container.clientHeight);
|
|
124
|
+
if (width < 2 || height < 2) {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
109
127
|
const opt = this.effectiveOptions();
|
|
110
128
|
const margin = opt.margin;
|
|
111
|
-
const
|
|
112
|
-
const
|
|
129
|
+
const easing = getEasingFunction(this.d3, opt.animationEasing);
|
|
130
|
+
const resolvedBaseForIntensity = this.resolveCssColor(opt.color ?? 'rgb(99, 102, 241)');
|
|
113
131
|
this.svgElement = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
|
|
114
132
|
const svg = this.d3
|
|
115
133
|
.select(this.svgElement)
|
|
116
134
|
.attr('width', '100%')
|
|
117
135
|
.attr('height', '100%')
|
|
118
136
|
.attr('viewBox', `0 0 ${width} ${height}`)
|
|
119
|
-
.attr('preserveAspectRatio', 'xMidYMid meet')
|
|
137
|
+
.attr('preserveAspectRatio', 'xMidYMid meet')
|
|
138
|
+
.attr('class', 'ax-funnel-svg');
|
|
120
139
|
container.appendChild(this.svgElement);
|
|
121
140
|
const innerWidth = width - margin.left - margin.right;
|
|
122
141
|
const innerHeight = height - margin.top - margin.bottom;
|
|
142
|
+
if (innerWidth < 2 || innerHeight < 2) {
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
123
145
|
const g = svg.append('g').attr('transform', `translate(${margin.left},${margin.top})`);
|
|
124
146
|
const sliceHeight = innerHeight / data.length;
|
|
125
147
|
const maxValue = data[0].value;
|
|
126
148
|
const minValue = data[data.length - 1]?.value ?? maxValue;
|
|
127
|
-
const
|
|
149
|
+
const showSegmentValues = opt.showSegmentValues !== false;
|
|
128
150
|
data.forEach((d, i) => {
|
|
129
151
|
const topVal = d.value;
|
|
130
152
|
const bottomVal = data[i + 1]?.value ?? d.value * opt.neckWidth;
|
|
@@ -136,7 +158,7 @@ class AXFunnelChartComponent extends AXChartComponent {
|
|
|
136
158
|
const yBottom = (i + 1) * sliceHeight;
|
|
137
159
|
const pathData = `M ${xTop},${yTop} L ${xTop + topW},${yTop} L ${xBottom + bottomW},${yBottom} L ${xBottom},${yBottom} Z`;
|
|
138
160
|
const sliceGroup = g.append('g').attr('class', 'funnel-slice-container');
|
|
139
|
-
const computedColor = this.resolveSliceColor(d, i, opt, minValue, maxValue);
|
|
161
|
+
const computedColor = this.resolveSliceColor(d, i, opt, minValue, maxValue, resolvedBaseForIntensity);
|
|
140
162
|
const path = sliceGroup
|
|
141
163
|
.append('path')
|
|
142
164
|
.attr('class', 'funnel-slice')
|
|
@@ -161,27 +183,49 @@ class AXFunnelChartComponent extends AXChartComponent {
|
|
|
161
183
|
.delay(i * 80)
|
|
162
184
|
.ease(easing)
|
|
163
185
|
.style('opacity', 1);
|
|
186
|
+
sliceGroup
|
|
187
|
+
.append('title')
|
|
188
|
+
.text(`${d.name}: ${d.value.toLocaleString()}`);
|
|
164
189
|
if (opt.showLabels) {
|
|
190
|
+
const { cx, cy, width: midW } = this.trapezoidInteriorMetrics(xTop, topW, xBottom, bottomW, yTop, yBottom);
|
|
191
|
+
const { nameSize, valueSize, showValueLine, displayName } = this.computeSegmentLabelTypography(sliceHeight, midW, d.name, showSegmentValues);
|
|
192
|
+
const { primary, secondary } = this.pickOnSliceTextColors(computedColor);
|
|
165
193
|
const labelGroup = sliceGroup.append('g').attr('class', 'funnel-label-group').style('opacity', 0);
|
|
166
|
-
const
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
194
|
+
const lineGap = Math.max(2, sliceHeight * 0.06);
|
|
195
|
+
if (showValueLine && valueSize > 0) {
|
|
196
|
+
labelGroup
|
|
197
|
+
.append('text')
|
|
198
|
+
.attr('class', 'funnel-label-name')
|
|
199
|
+
.attr('x', cx)
|
|
200
|
+
.attr('y', cy - (valueSize * 0.55 + lineGap * 0.5))
|
|
201
|
+
.attr('text-anchor', 'middle')
|
|
202
|
+
.attr('dominant-baseline', 'middle')
|
|
203
|
+
.style('font-size', `${nameSize}px`)
|
|
204
|
+
.style('fill', primary)
|
|
205
|
+
.text(displayName);
|
|
206
|
+
labelGroup
|
|
207
|
+
.append('text')
|
|
208
|
+
.attr('class', 'funnel-label-value')
|
|
209
|
+
.attr('x', cx)
|
|
210
|
+
.attr('y', cy + (nameSize * 0.55 + lineGap * 0.5))
|
|
211
|
+
.attr('text-anchor', 'middle')
|
|
212
|
+
.attr('dominant-baseline', 'middle')
|
|
213
|
+
.style('font-size', `${valueSize}px`)
|
|
214
|
+
.style('fill', secondary)
|
|
215
|
+
.text(d.value.toLocaleString());
|
|
216
|
+
}
|
|
217
|
+
else {
|
|
218
|
+
labelGroup
|
|
219
|
+
.append('text')
|
|
220
|
+
.attr('class', 'funnel-label-name funnel-label-name--single')
|
|
221
|
+
.attr('x', cx)
|
|
222
|
+
.attr('y', cy)
|
|
223
|
+
.attr('text-anchor', 'middle')
|
|
224
|
+
.attr('dominant-baseline', 'middle')
|
|
225
|
+
.style('font-size', `${nameSize}px`)
|
|
226
|
+
.style('fill', primary)
|
|
227
|
+
.text(displayName);
|
|
228
|
+
}
|
|
185
229
|
labelGroup
|
|
186
230
|
.transition()
|
|
187
231
|
.duration(600)
|
|
@@ -190,23 +234,106 @@ class AXFunnelChartComponent extends AXChartComponent {
|
|
|
190
234
|
}
|
|
191
235
|
});
|
|
192
236
|
}
|
|
193
|
-
|
|
237
|
+
trapezoidInteriorMetrics(xTop, topW, xBottom, bottomW, yTop, yBottom) {
|
|
238
|
+
const cy = (yTop + yBottom) / 2;
|
|
239
|
+
const denom = yBottom - yTop || 1;
|
|
240
|
+
const t = (cy - yTop) / denom;
|
|
241
|
+
const xL = xTop + t * (xBottom - xTop);
|
|
242
|
+
const xR = xTop + topW + t * (xBottom + bottomW - (xTop + topW));
|
|
243
|
+
return { cx: (xL + xR) / 2, cy, width: Math.max(0, xR - xL) };
|
|
244
|
+
}
|
|
245
|
+
computeSegmentLabelTypography(sliceHeight, segmentInnerWidth, name, wantValue) {
|
|
246
|
+
const charFactor = 0.52;
|
|
247
|
+
const minFont = 6.5;
|
|
248
|
+
const maxName = 15;
|
|
249
|
+
const innerW = Math.max(segmentInnerWidth, 8);
|
|
250
|
+
let showValueLine = wantValue && sliceHeight >= 17 && innerW >= 38;
|
|
251
|
+
const fitNameOnly = () => {
|
|
252
|
+
const raw = Math.min(maxName + 2, sliceHeight * 0.42, innerW / Math.max(name.length * charFactor, 2.5));
|
|
253
|
+
return Math.max(minFont, raw);
|
|
254
|
+
};
|
|
255
|
+
const fitBoth = () => {
|
|
256
|
+
const vBudget = sliceHeight * 0.76;
|
|
257
|
+
let nameSize = Math.min(maxName, vBudget / 2.45, innerW / Math.max(name.length * charFactor, 2.5));
|
|
258
|
+
nameSize = Math.max(minFont, nameSize);
|
|
259
|
+
let valueSize = Math.max(minFont, Math.min(nameSize * 0.88, vBudget / 2.45));
|
|
260
|
+
const stackH = nameSize * 1.18 + valueSize * 1.08 + sliceHeight * 0.05;
|
|
261
|
+
if (stackH > sliceHeight * 0.88) {
|
|
262
|
+
const scale = (sliceHeight * 0.88) / stackH;
|
|
263
|
+
nameSize = Math.max(minFont, nameSize * scale);
|
|
264
|
+
valueSize = Math.max(minFont, valueSize * scale);
|
|
265
|
+
}
|
|
266
|
+
return { nameSize, valueSize };
|
|
267
|
+
};
|
|
268
|
+
let nameSize;
|
|
269
|
+
let valueSize = 0;
|
|
270
|
+
if (showValueLine) {
|
|
271
|
+
const both = fitBoth();
|
|
272
|
+
nameSize = both.nameSize;
|
|
273
|
+
valueSize = both.valueSize;
|
|
274
|
+
if (nameSize * 1.2 + valueSize * 1.05 > sliceHeight * 0.9) {
|
|
275
|
+
showValueLine = false;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
if (!showValueLine) {
|
|
279
|
+
nameSize = fitNameOnly();
|
|
280
|
+
}
|
|
281
|
+
const maxChars = Math.max(2, Math.floor(innerW / (nameSize * charFactor)));
|
|
282
|
+
const displayName = this.truncateLabel(name, maxChars);
|
|
283
|
+
return { nameSize, valueSize, showValueLine, displayName };
|
|
284
|
+
}
|
|
285
|
+
truncateLabel(name, maxChars) {
|
|
286
|
+
if (name.length <= maxChars)
|
|
287
|
+
return name;
|
|
288
|
+
if (maxChars <= 1)
|
|
289
|
+
return '…';
|
|
290
|
+
return `${name.slice(0, maxChars - 1)}…`;
|
|
291
|
+
}
|
|
292
|
+
pickOnSliceTextColors(sliceColorCss) {
|
|
293
|
+
const resolved = this.resolveCssColor(sliceColorCss);
|
|
294
|
+
const c = this.d3.color(resolved);
|
|
295
|
+
if (!c) {
|
|
296
|
+
return { primary: 'rgba(255,255,255,0.95)', secondary: 'rgba(255,255,255,0.78)' };
|
|
297
|
+
}
|
|
298
|
+
const rgb = this.d3.rgb(c);
|
|
299
|
+
const a = Math.max(0, Math.min(1, rgb.opacity));
|
|
300
|
+
// Blend slice color over white (typical card/surface) so low-alpha intensity ramps read correctly.
|
|
301
|
+
const br = (rgb.r / 255) * a + (1 - a);
|
|
302
|
+
const bg = (rgb.g / 255) * a + (1 - a);
|
|
303
|
+
const bb = (rgb.b / 255) * a + (1 - a);
|
|
304
|
+
const lum = 0.2126 * br + 0.7152 * bg + 0.0722 * bb;
|
|
305
|
+
if (lum > 0.62) {
|
|
306
|
+
return { primary: 'rgba(15,23,42,0.92)', secondary: 'rgba(15,23,42,0.72)' };
|
|
307
|
+
}
|
|
308
|
+
return { primary: 'rgba(255,255,255,0.96)', secondary: 'rgba(255,255,255,0.78)' };
|
|
309
|
+
}
|
|
310
|
+
resolveSliceColor(item, index, opt, minValue, maxValue, resolvedBaseRgb) {
|
|
194
311
|
if (item.color)
|
|
195
|
-
return item.color;
|
|
312
|
+
return this.resolveCssColor(item.color);
|
|
196
313
|
const palette = opt.colors?.filter(Boolean) ?? [];
|
|
197
314
|
if (palette.length > 0) {
|
|
198
315
|
const key = String(item.id ?? item.name ?? index);
|
|
199
316
|
const idx = this.hashStringToUint32(key) % palette.length;
|
|
200
|
-
|
|
317
|
+
const raw = palette[idx] ?? opt.color ?? 'rgb(99, 102, 241)';
|
|
318
|
+
return this.resolveCssColor(raw);
|
|
201
319
|
}
|
|
202
|
-
const
|
|
203
|
-
const
|
|
204
|
-
const
|
|
205
|
-
const
|
|
206
|
-
const
|
|
207
|
-
|
|
320
|
+
const rangeMin = opt.valueRange?.min ?? minValue;
|
|
321
|
+
const rangeMax = opt.valueRange?.max ?? maxValue;
|
|
322
|
+
const span = rangeMax - rangeMin;
|
|
323
|
+
const t = span === 0 ? 1 : (item.value - rangeMin) / span;
|
|
324
|
+
const clamped = Math.max(0, Math.min(1, t));
|
|
325
|
+
return this.applyIntensityToResolvedRgb(resolvedBaseRgb, clamped);
|
|
326
|
+
}
|
|
327
|
+
/** `resolvedRgb` must be a computed `rgb()` / `rgba()` string (e.g. from {@link resolveCssColor}). */
|
|
328
|
+
applyIntensityToResolvedRgb(resolvedRgb, t) {
|
|
208
329
|
const clamped = Math.max(0, Math.min(1, t));
|
|
209
|
-
|
|
330
|
+
const parsed = this.d3.color(resolvedRgb);
|
|
331
|
+
if (!parsed)
|
|
332
|
+
return resolvedRgb;
|
|
333
|
+
const rgb = this.d3.rgb(parsed);
|
|
334
|
+
const minOpacity = 0.12;
|
|
335
|
+
const opacity = minOpacity + clamped * (1 - minOpacity);
|
|
336
|
+
return `rgba(${Math.round(rgb.r)},${Math.round(rgb.g)},${Math.round(rgb.b)},${opacity})`;
|
|
210
337
|
}
|
|
211
338
|
hashStringToUint32(input) {
|
|
212
339
|
let hash = 5381;
|
|
@@ -216,16 +343,7 @@ class AXFunnelChartComponent extends AXChartComponent {
|
|
|
216
343
|
return hash >>> 0;
|
|
217
344
|
}
|
|
218
345
|
resolveCssColor(color) {
|
|
219
|
-
|
|
220
|
-
const probe = document.createElement('span');
|
|
221
|
-
probe.style.color = color;
|
|
222
|
-
probe.style.position = 'absolute';
|
|
223
|
-
probe.style.left = '-9999px';
|
|
224
|
-
probe.style.top = '-9999px';
|
|
225
|
-
container.appendChild(probe);
|
|
226
|
-
const computed = getComputedStyle(probe).color;
|
|
227
|
-
probe.remove();
|
|
228
|
-
return computed || color;
|
|
346
|
+
return resolveCssColorInContext(this.chartContainerEl().nativeElement, color);
|
|
229
347
|
}
|
|
230
348
|
updateChart() {
|
|
231
349
|
this.createChart();
|
|
@@ -260,11 +378,11 @@ class AXFunnelChartComponent extends AXChartComponent {
|
|
|
260
378
|
}
|
|
261
379
|
}
|
|
262
380
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: AXFunnelChartComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
263
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.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 } }, outputs: { segmentClick: "segmentClick" }, viewQueries: [{ propertyName: "chartContainerEl", first: true, predicate: ["chartContainer"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"ax-funnel-chart-container\" role=\"img\" #chartContainer>\n @if (data()?.length === 0) {\n <div class=\"ax-funnel-no-data\">\n <i [class]=\"effectiveOptions().messages?.noDataIcon\"></i>\n <p class=\"ax-funnel-no-data-text\">{{ effectiveOptions().messages?.noData }}</p>\n </div>\n }\n</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:
|
|
381
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.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 } }, outputs: { segmentClick: "segmentClick" }, viewQueries: [{ propertyName: "chartContainerEl", first: true, predicate: ["chartContainer"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"ax-funnel-chart-container\" role=\"img\" #chartContainer>\n @if (data()?.length === 0) {\n <div class=\"ax-funnel-no-data\">\n <i [class]=\"effectiveOptions().messages?.noDataIcon\"></i>\n <p class=\"ax-funnel-no-data-text\">{{ effectiveOptions().messages?.noData }}</p>\n </div>\n }\n</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:clamp(220px,42vmin,520px);container-type:size;--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: 1;--ax-comp-funnel-dim-opacity: .22;--ax-comp-funnel-slice-stroke: rgba(255, 255, 255, .14);--ax-comp-funnel-slice-shadow: 0 10px 28px rgba(15, 23, 42, .12)}ax-funnel-chart .ax-funnel-chart-container{position:relative;width:100%;height:100%;min-height:inherit;overflow:hidden;border-radius:clamp(10px,2cqw,20px);background-color:rgba(var(--ax-comp-funnel-bg));padding:clamp(.5rem,2cqw,1.25rem);box-sizing:border-box}ax-funnel-chart .ax-funnel-chart-container svg{display:block;width:100%;height:100%;overflow:visible}ax-funnel-chart .ax-funnel-chart-container svg .funnel-slice{cursor:pointer;opacity:var(--ax-comp-funnel-slice-opacity);stroke:var(--ax-comp-funnel-slice-stroke);stroke-width:1;vector-effect:non-scaling-stroke;filter:drop-shadow(var(--ax-comp-funnel-slice-shadow));transition:filter .28s cubic-bezier(.4,0,.2,1),opacity .28s cubic-bezier(.4,0,.2,1)}ax-funnel-chart .ax-funnel-chart-container svg .funnel-slice.is-active{opacity:1;filter:drop-shadow(var(--ax-comp-funnel-slice-shadow)) saturate(1.08) brightness(1.03)}ax-funnel-chart .ax-funnel-chart-container svg .funnel-label-group{pointer-events:none;font-family:inherit;font-synthesis:none;text-rendering:geometricPrecision}ax-funnel-chart .ax-funnel-chart-container svg .funnel-label-group .funnel-label-name{font-weight:650;letter-spacing:.02em}ax-funnel-chart .ax-funnel-chart-container svg .funnel-label-group .funnel-label-name--single{font-weight:680;letter-spacing:.015em}ax-funnel-chart .ax-funnel-chart-container svg .funnel-label-group .funnel-label-value{font-weight:560;font-variant-numeric:tabular-nums;letter-spacing:.01em}ax-funnel-chart .ax-funnel-chart-container svg.is-dimmed .funnel-slice:not(.is-active){opacity:var(--ax-comp-funnel-dim-opacity)}ax-funnel-chart .ax-funnel-no-data{position:absolute;top:0;right:0;bottom:0;left:0;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;color:rgba(var(--ax-comp-funnel-text),.6)}ax-funnel-chart .ax-funnel-no-data i{font-size:clamp(1.5rem,4cqw,2rem);margin-bottom:.5rem}ax-funnel-chart .ax-funnel-no-data .ax-funnel-no-data-text{font-size:clamp(.875rem,2.5cqw,1rem)}\n"], dependencies: [{ kind: "component", type: AXChartTooltipComponent, selector: "ax-chart-tooltip", inputs: ["data", "position", "visible", "showPercentage", "style"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
264
382
|
}
|
|
265
383
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: AXFunnelChartComponent, decorators: [{
|
|
266
384
|
type: Component,
|
|
267
|
-
args: [{ selector: 'ax-funnel-chart', encapsulation: ViewEncapsulation.None, imports: [AXChartTooltipComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"ax-funnel-chart-container\" role=\"img\" #chartContainer>\n @if (data()?.length === 0) {\n <div class=\"ax-funnel-no-data\">\n <i [class]=\"effectiveOptions().messages?.noDataIcon\"></i>\n <p class=\"ax-funnel-no-data-text\">{{ effectiveOptions().messages?.noData }}</p>\n </div>\n }\n</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:
|
|
385
|
+
args: [{ selector: 'ax-funnel-chart', encapsulation: ViewEncapsulation.None, imports: [AXChartTooltipComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"ax-funnel-chart-container\" role=\"img\" #chartContainer>\n @if (data()?.length === 0) {\n <div class=\"ax-funnel-no-data\">\n <i [class]=\"effectiveOptions().messages?.noDataIcon\"></i>\n <p class=\"ax-funnel-no-data-text\">{{ effectiveOptions().messages?.noData }}</p>\n </div>\n }\n</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:clamp(220px,42vmin,520px);container-type:size;--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: 1;--ax-comp-funnel-dim-opacity: .22;--ax-comp-funnel-slice-stroke: rgba(255, 255, 255, .14);--ax-comp-funnel-slice-shadow: 0 10px 28px rgba(15, 23, 42, .12)}ax-funnel-chart .ax-funnel-chart-container{position:relative;width:100%;height:100%;min-height:inherit;overflow:hidden;border-radius:clamp(10px,2cqw,20px);background-color:rgba(var(--ax-comp-funnel-bg));padding:clamp(.5rem,2cqw,1.25rem);box-sizing:border-box}ax-funnel-chart .ax-funnel-chart-container svg{display:block;width:100%;height:100%;overflow:visible}ax-funnel-chart .ax-funnel-chart-container svg .funnel-slice{cursor:pointer;opacity:var(--ax-comp-funnel-slice-opacity);stroke:var(--ax-comp-funnel-slice-stroke);stroke-width:1;vector-effect:non-scaling-stroke;filter:drop-shadow(var(--ax-comp-funnel-slice-shadow));transition:filter .28s cubic-bezier(.4,0,.2,1),opacity .28s cubic-bezier(.4,0,.2,1)}ax-funnel-chart .ax-funnel-chart-container svg .funnel-slice.is-active{opacity:1;filter:drop-shadow(var(--ax-comp-funnel-slice-shadow)) saturate(1.08) brightness(1.03)}ax-funnel-chart .ax-funnel-chart-container svg .funnel-label-group{pointer-events:none;font-family:inherit;font-synthesis:none;text-rendering:geometricPrecision}ax-funnel-chart .ax-funnel-chart-container svg .funnel-label-group .funnel-label-name{font-weight:650;letter-spacing:.02em}ax-funnel-chart .ax-funnel-chart-container svg .funnel-label-group .funnel-label-name--single{font-weight:680;letter-spacing:.015em}ax-funnel-chart .ax-funnel-chart-container svg .funnel-label-group .funnel-label-value{font-weight:560;font-variant-numeric:tabular-nums;letter-spacing:.01em}ax-funnel-chart .ax-funnel-chart-container svg.is-dimmed .funnel-slice:not(.is-active){opacity:var(--ax-comp-funnel-dim-opacity)}ax-funnel-chart .ax-funnel-no-data{position:absolute;top:0;right:0;bottom:0;left:0;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;color:rgba(var(--ax-comp-funnel-text),.6)}ax-funnel-chart .ax-funnel-no-data i{font-size:clamp(1.5rem,4cqw,2rem);margin-bottom:.5rem}ax-funnel-chart .ax-funnel-no-data .ax-funnel-no-data-text{font-size:clamp(.875rem,2.5cqw,1rem)}\n"] }]
|
|
268
386
|
}], ctorParameters: () => [] });
|
|
269
387
|
|
|
270
388
|
/**
|