@acorex/charts 20.6.31 → 20.6.33
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 +2 -2
- package/fesm2022/acorex-charts-bar-chart.mjs.map +1 -1
- package/fesm2022/acorex-charts-donut-chart.mjs +2 -2
- package/fesm2022/acorex-charts-donut-chart.mjs.map +1 -1
- package/fesm2022/acorex-charts-funnel-chart.mjs +135 -44
- package/fesm2022/acorex-charts-funnel-chart.mjs.map +1 -1
- package/fesm2022/acorex-charts-gauge-chart.mjs +2 -2
- package/fesm2022/acorex-charts-gauge-chart.mjs.map +1 -1
- package/fesm2022/acorex-charts-heatmap-chart.mjs +131 -25
- package/fesm2022/acorex-charts-heatmap-chart.mjs.map +1 -1
- package/fesm2022/acorex-charts-line-chart.mjs +2 -2
- package/fesm2022/acorex-charts-line-chart.mjs.map +1 -1
- package/funnel-chart/index.d.ts +21 -4
- package/heatmap-chart/index.d.ts +21 -0
- package/package.json +5 -5
|
@@ -1,19 +1,18 @@
|
|
|
1
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
|
-
color: 'rgb(
|
|
15
|
+
color: 'rgb(var(--ax-sys-color-primary-500))',
|
|
17
16
|
messages: {
|
|
18
17
|
noData: 'No funnel data available',
|
|
19
18
|
noDataIcon: 'fa-light fa-filter-list',
|
|
@@ -25,6 +24,11 @@ const AX_FUNNEL_CHART_CONFIG = new InjectionToken('AX_FUNNEL_CHART_CONFIG', {
|
|
|
25
24
|
});
|
|
26
25
|
|
|
27
26
|
class AXFunnelChartComponent extends AXChartComponent {
|
|
27
|
+
/**
|
|
28
|
+
* Fixed SVG coordinate system; the graphic scales to the container via `width`/`height: 100%` + `viewBox`.
|
|
29
|
+
* Margins and geometry are expressed in these units (same numeric scale as a ~400px reference viewport).
|
|
30
|
+
*/
|
|
31
|
+
static VIEW_BOX_SIZE = 400;
|
|
28
32
|
// Inputs
|
|
29
33
|
data = input([], ...(ngDevMode ? [{ debugName: "data" }] : []));
|
|
30
34
|
options = input({}, ...(ngDevMode ? [{ debugName: "options" }] : []));
|
|
@@ -37,9 +41,6 @@ class AXFunnelChartComponent extends AXChartComponent {
|
|
|
37
41
|
d3;
|
|
38
42
|
_initialized = signal(false, ...(ngDevMode ? [{ debugName: "_initialized" }] : []));
|
|
39
43
|
_rendered = signal(false, ...(ngDevMode ? [{ debugName: "_rendered" }] : []));
|
|
40
|
-
platformService = inject(AXPlatform);
|
|
41
|
-
isRtl = signal(this.platformService.isRtl(), ...(ngDevMode ? [{ debugName: "isRtl" }] : []));
|
|
42
|
-
directionSub;
|
|
43
44
|
// Tooltip Signals
|
|
44
45
|
_tooltipVisible = signal(false, ...(ngDevMode ? [{ debugName: "_tooltipVisible" }] : []));
|
|
45
46
|
_tooltipPosition = signal({ x: 0, y: 0 }, ...(ngDevMode ? [{ debugName: "_tooltipPosition" }] : []));
|
|
@@ -58,14 +59,6 @@ class AXFunnelChartComponent extends AXChartComponent {
|
|
|
58
59
|
afterNextRender(() => {
|
|
59
60
|
this._initialized.set(true);
|
|
60
61
|
this.loadD3();
|
|
61
|
-
this.directionSub = this.platformService.directionChange
|
|
62
|
-
.pipe(map((i) => i.data === 'rtl'))
|
|
63
|
-
.subscribe((isRtl) => {
|
|
64
|
-
this.isRtl.set(isRtl);
|
|
65
|
-
if (this._rendered()) {
|
|
66
|
-
this.updateChart();
|
|
67
|
-
}
|
|
68
|
-
});
|
|
69
62
|
});
|
|
70
63
|
effect(() => {
|
|
71
64
|
// Trigger update on data or option change
|
|
@@ -77,7 +70,6 @@ class AXFunnelChartComponent extends AXChartComponent {
|
|
|
77
70
|
});
|
|
78
71
|
}
|
|
79
72
|
ngOnDestroy() {
|
|
80
|
-
this.directionSub?.unsubscribe();
|
|
81
73
|
this.cleanupChart();
|
|
82
74
|
}
|
|
83
75
|
async loadD3() {
|
|
@@ -103,28 +95,32 @@ class AXFunnelChartComponent extends AXChartComponent {
|
|
|
103
95
|
return;
|
|
104
96
|
}
|
|
105
97
|
const container = this.chartContainerEl().nativeElement;
|
|
106
|
-
const
|
|
107
|
-
const
|
|
98
|
+
const vb = AXFunnelChartComponent.VIEW_BOX_SIZE;
|
|
99
|
+
const width = vb;
|
|
100
|
+
const height = vb;
|
|
108
101
|
const opt = this.effectiveOptions();
|
|
109
102
|
const margin = opt.margin;
|
|
110
|
-
const
|
|
111
|
-
const
|
|
103
|
+
const easing = getEasingFunction(this.d3, opt.animationEasing);
|
|
104
|
+
const resolvedBaseForIntensity = this.resolveCssColor(opt.color ?? 'rgb(99, 102, 241)');
|
|
112
105
|
this.svgElement = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
|
|
113
106
|
const svg = this.d3
|
|
114
107
|
.select(this.svgElement)
|
|
115
108
|
.attr('width', '100%')
|
|
116
109
|
.attr('height', '100%')
|
|
117
110
|
.attr('viewBox', `0 0 ${width} ${height}`)
|
|
118
|
-
.attr('preserveAspectRatio', 'xMidYMid meet')
|
|
111
|
+
.attr('preserveAspectRatio', 'xMidYMid meet')
|
|
112
|
+
.attr('class', 'ax-funnel-svg');
|
|
119
113
|
container.appendChild(this.svgElement);
|
|
120
114
|
const innerWidth = width - margin.left - margin.right;
|
|
121
115
|
const innerHeight = height - margin.top - margin.bottom;
|
|
116
|
+
if (innerWidth < 1 || innerHeight < 1) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
122
119
|
const g = svg.append('g').attr('transform', `translate(${margin.left},${margin.top})`);
|
|
123
120
|
const sliceHeight = innerHeight / data.length;
|
|
124
121
|
const maxValue = data[0].value;
|
|
125
122
|
const minValue = data[data.length - 1]?.value ?? maxValue;
|
|
126
|
-
const
|
|
127
|
-
const resolvedBaseForIntensity = this.resolveCssColor(opt.color ?? 'rgb(99, 102, 241)');
|
|
123
|
+
const showSegmentValues = opt.showSegmentValues !== false;
|
|
128
124
|
data.forEach((d, i) => {
|
|
129
125
|
const topVal = d.value;
|
|
130
126
|
const bottomVal = data[i + 1]?.value ?? d.value * opt.neckWidth;
|
|
@@ -161,27 +157,49 @@ class AXFunnelChartComponent extends AXChartComponent {
|
|
|
161
157
|
.delay(i * 80)
|
|
162
158
|
.ease(easing)
|
|
163
159
|
.style('opacity', 1);
|
|
160
|
+
sliceGroup
|
|
161
|
+
.append('title')
|
|
162
|
+
.text(`${d.name}: ${d.value.toLocaleString()}`);
|
|
164
163
|
if (opt.showLabels) {
|
|
164
|
+
const { cx, cy, width: midW } = this.trapezoidInteriorMetrics(xTop, topW, xBottom, bottomW, yTop, yBottom);
|
|
165
|
+
const { nameSize, valueSize, showValueLine, displayName } = this.computeSegmentLabelTypography(sliceHeight, midW, d.name, showSegmentValues);
|
|
166
|
+
const { primary, secondary } = this.pickOnSliceTextColors(computedColor);
|
|
165
167
|
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
|
-
|
|
168
|
+
const lineGap = Math.max(2, sliceHeight * 0.06);
|
|
169
|
+
if (showValueLine && valueSize > 0) {
|
|
170
|
+
labelGroup
|
|
171
|
+
.append('text')
|
|
172
|
+
.attr('class', 'funnel-label-name')
|
|
173
|
+
.attr('x', cx)
|
|
174
|
+
.attr('y', cy - (valueSize * 0.55 + lineGap * 0.5))
|
|
175
|
+
.attr('text-anchor', 'middle')
|
|
176
|
+
.attr('dominant-baseline', 'middle')
|
|
177
|
+
.style('font-size', `${nameSize}`)
|
|
178
|
+
.style('fill', primary)
|
|
179
|
+
.text(displayName);
|
|
180
|
+
labelGroup
|
|
181
|
+
.append('text')
|
|
182
|
+
.attr('class', 'funnel-label-value')
|
|
183
|
+
.attr('x', cx)
|
|
184
|
+
.attr('y', cy + (nameSize * 0.55 + lineGap * 0.5))
|
|
185
|
+
.attr('text-anchor', 'middle')
|
|
186
|
+
.attr('dominant-baseline', 'middle')
|
|
187
|
+
.style('font-size', `${valueSize}`)
|
|
188
|
+
.style('fill', secondary)
|
|
189
|
+
.text(d.value.toLocaleString());
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
labelGroup
|
|
193
|
+
.append('text')
|
|
194
|
+
.attr('class', 'funnel-label-name funnel-label-name--single')
|
|
195
|
+
.attr('x', cx)
|
|
196
|
+
.attr('y', cy)
|
|
197
|
+
.attr('text-anchor', 'middle')
|
|
198
|
+
.attr('dominant-baseline', 'middle')
|
|
199
|
+
.style('font-size', `${nameSize}`)
|
|
200
|
+
.style('fill', primary)
|
|
201
|
+
.text(displayName);
|
|
202
|
+
}
|
|
185
203
|
labelGroup
|
|
186
204
|
.transition()
|
|
187
205
|
.duration(600)
|
|
@@ -190,6 +208,79 @@ class AXFunnelChartComponent extends AXChartComponent {
|
|
|
190
208
|
}
|
|
191
209
|
});
|
|
192
210
|
}
|
|
211
|
+
trapezoidInteriorMetrics(xTop, topW, xBottom, bottomW, yTop, yBottom) {
|
|
212
|
+
const cy = (yTop + yBottom) / 2;
|
|
213
|
+
const denom = yBottom - yTop || 1;
|
|
214
|
+
const t = (cy - yTop) / denom;
|
|
215
|
+
const xL = xTop + t * (xBottom - xTop);
|
|
216
|
+
const xR = xTop + topW + t * (xBottom + bottomW - (xTop + topW));
|
|
217
|
+
return { cx: (xL + xR) / 2, cy, width: Math.max(0, xR - xL) };
|
|
218
|
+
}
|
|
219
|
+
computeSegmentLabelTypography(sliceHeight, segmentInnerWidth, name, wantValue) {
|
|
220
|
+
const charFactor = 0.52;
|
|
221
|
+
const minFont = 6.5;
|
|
222
|
+
const maxName = 15;
|
|
223
|
+
const innerW = Math.max(segmentInnerWidth, 8);
|
|
224
|
+
let showValueLine = wantValue && sliceHeight >= 17 && innerW >= 38;
|
|
225
|
+
const fitNameOnly = () => {
|
|
226
|
+
const raw = Math.min(maxName + 2, sliceHeight * 0.42, innerW / Math.max(name.length * charFactor, 2.5));
|
|
227
|
+
return Math.max(minFont, raw);
|
|
228
|
+
};
|
|
229
|
+
const fitBoth = () => {
|
|
230
|
+
const vBudget = sliceHeight * 0.76;
|
|
231
|
+
let nameSize = Math.min(maxName, vBudget / 2.45, innerW / Math.max(name.length * charFactor, 2.5));
|
|
232
|
+
nameSize = Math.max(minFont, nameSize);
|
|
233
|
+
let valueSize = Math.max(minFont, Math.min(nameSize * 0.88, vBudget / 2.45));
|
|
234
|
+
const stackH = nameSize * 1.18 + valueSize * 1.08 + sliceHeight * 0.05;
|
|
235
|
+
if (stackH > sliceHeight * 0.88) {
|
|
236
|
+
const scale = (sliceHeight * 0.88) / stackH;
|
|
237
|
+
nameSize = Math.max(minFont, nameSize * scale);
|
|
238
|
+
valueSize = Math.max(minFont, valueSize * scale);
|
|
239
|
+
}
|
|
240
|
+
return { nameSize, valueSize };
|
|
241
|
+
};
|
|
242
|
+
let nameSize;
|
|
243
|
+
let valueSize = 0;
|
|
244
|
+
if (showValueLine) {
|
|
245
|
+
const both = fitBoth();
|
|
246
|
+
nameSize = both.nameSize;
|
|
247
|
+
valueSize = both.valueSize;
|
|
248
|
+
if (nameSize * 1.2 + valueSize * 1.05 > sliceHeight * 0.9) {
|
|
249
|
+
showValueLine = false;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
if (!showValueLine) {
|
|
253
|
+
nameSize = fitNameOnly();
|
|
254
|
+
}
|
|
255
|
+
const maxChars = Math.max(2, Math.floor(innerW / (nameSize * charFactor)));
|
|
256
|
+
const displayName = this.truncateLabel(name, maxChars);
|
|
257
|
+
return { nameSize, valueSize, showValueLine, displayName };
|
|
258
|
+
}
|
|
259
|
+
truncateLabel(name, maxChars) {
|
|
260
|
+
if (name.length <= maxChars)
|
|
261
|
+
return name;
|
|
262
|
+
if (maxChars <= 1)
|
|
263
|
+
return '…';
|
|
264
|
+
return `${name.slice(0, maxChars - 1)}…`;
|
|
265
|
+
}
|
|
266
|
+
pickOnSliceTextColors(sliceColorCss) {
|
|
267
|
+
const resolved = this.resolveCssColor(sliceColorCss);
|
|
268
|
+
const c = this.d3.color(resolved);
|
|
269
|
+
if (!c) {
|
|
270
|
+
return { primary: 'rgba(255,255,255,0.95)', secondary: 'rgba(255,255,255,0.78)' };
|
|
271
|
+
}
|
|
272
|
+
const rgb = this.d3.rgb(c);
|
|
273
|
+
const a = Math.max(0, Math.min(1, rgb.opacity));
|
|
274
|
+
// Blend slice color over white (typical card/surface) so low-alpha intensity ramps read correctly.
|
|
275
|
+
const br = (rgb.r / 255) * a + (1 - a);
|
|
276
|
+
const bg = (rgb.g / 255) * a + (1 - a);
|
|
277
|
+
const bb = (rgb.b / 255) * a + (1 - a);
|
|
278
|
+
const lum = 0.2126 * br + 0.7152 * bg + 0.0722 * bb;
|
|
279
|
+
if (lum > 0.62) {
|
|
280
|
+
return { primary: 'rgba(15,23,42,0.92)', secondary: 'rgba(15,23,42,0.72)' };
|
|
281
|
+
}
|
|
282
|
+
return { primary: 'rgba(255,255,255,0.96)', secondary: 'rgba(255,255,255,0.78)' };
|
|
283
|
+
}
|
|
193
284
|
resolveSliceColor(item, index, opt, minValue, maxValue, resolvedBaseRgb) {
|
|
194
285
|
if (item.color)
|
|
195
286
|
return this.resolveCssColor(item.color);
|
|
@@ -261,11 +352,11 @@ class AXFunnelChartComponent extends AXChartComponent {
|
|
|
261
352
|
}
|
|
262
353
|
}
|
|
263
354
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: AXFunnelChartComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
264
|
-
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:
|
|
355
|
+
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:0;box-sizing:border-box;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:0;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%;min-height:0;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 });
|
|
265
356
|
}
|
|
266
357
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: AXFunnelChartComponent, decorators: [{
|
|
267
358
|
type: Component,
|
|
268
|
-
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:
|
|
359
|
+
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:0;box-sizing:border-box;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:0;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%;min-height:0;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"] }]
|
|
269
360
|
}], ctorParameters: () => [] });
|
|
270
361
|
|
|
271
362
|
/**
|