apexcharts 8.2.0 → 8.3.1
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/README.md +7 -7
- package/dist/apexcharts.common.js +2 -2
- package/dist/apexcharts.core.js +19793 -19713
- package/dist/apexcharts.core.min.js +2 -2
- package/dist/apexcharts.css +38 -8
- package/dist/apexcharts.esm.js +1882 -1625
- package/dist/apexcharts.full.js +22044 -21634
- package/dist/apexcharts.full.min.js +2 -2
- package/dist/apexcharts.js +21414 -21124
- package/dist/apexcharts.min.js +2 -2
- package/dist/apexcharts.ssr.common.js +2 -2
- package/dist/apexcharts.ssr.esm.js +21413 -21123
- package/dist/area.common.js +2 -2
- package/dist/area.esm.js +91 -40
- package/dist/bar.common.js +2 -2
- package/dist/bar.esm.js +478 -406
- package/dist/bar.js +2 -2
- package/dist/boxPlot.common.js +2 -2
- package/dist/boxPlot.esm.js +409 -334
- package/dist/bubble.common.js +2 -2
- package/dist/bubble.esm.js +91 -40
- package/dist/candlestick.common.js +2 -2
- package/dist/candlestick.esm.js +409 -334
- package/dist/candlestick.js +2 -2
- package/dist/column.common.js +2 -2
- package/dist/column.esm.js +478 -406
- package/dist/core.common.js +2 -2
- package/dist/core.esm.js +19793 -19713
- package/dist/donut.common.js +2 -2
- package/dist/donut.esm.js +3 -9
- package/dist/dumbbell.common.js +2 -2
- package/dist/dumbbell.esm.js +478 -406
- package/dist/features/all.common.js +2 -2
- package/dist/features/all.esm.js +442 -324
- package/dist/features/annotations.common.js +2 -2
- package/dist/features/annotations.esm.js +65 -48
- package/dist/features/annotations.js +2 -2
- package/dist/features/context-menu.common.js +1 -1
- package/dist/features/context-menu.esm.js +1 -1
- package/dist/features/context-menu.js +1 -1
- package/dist/features/drilldown.common.js +2 -2
- package/dist/features/drilldown.esm.js +4 -2
- package/dist/features/drilldown.js +2 -2
- package/dist/features/dumbbell.common.js +1 -1
- package/dist/features/dumbbell.esm.js +1 -1
- package/dist/features/dumbbell.js +1 -1
- package/dist/features/exports.common.js +2 -2
- package/dist/features/exports.esm.js +10 -4
- package/dist/features/exports.js +2 -2
- package/dist/features/facet.common.js +1 -1
- package/dist/features/facet.esm.js +1 -1
- package/dist/features/facet.js +1 -1
- package/dist/features/highlight-filter.common.js +2 -2
- package/dist/features/highlight-filter.esm.js +14 -9
- package/dist/features/highlight-filter.js +2 -2
- package/dist/features/history.common.js +1 -1
- package/dist/features/history.esm.js +1 -1
- package/dist/features/history.js +1 -1
- package/dist/features/ink.common.js +1 -1
- package/dist/features/ink.esm.js +1 -1
- package/dist/features/ink.js +1 -1
- package/dist/features/keyboard.common.js +2 -2
- package/dist/features/keyboard.esm.js +97 -145
- package/dist/features/keyboard.js +2 -2
- package/dist/features/legend.common.js +2 -2
- package/dist/features/legend.esm.js +64 -44
- package/dist/features/legend.js +2 -2
- package/dist/features/link.common.js +1 -1
- package/dist/features/link.esm.js +1 -1
- package/dist/features/link.js +1 -1
- package/dist/features/marks.common.js +1 -1
- package/dist/features/marks.esm.js +1 -1
- package/dist/features/marks.js +1 -1
- package/dist/features/measure.common.js +1 -1
- package/dist/features/measure.esm.js +1 -1
- package/dist/features/measure.js +1 -1
- package/dist/features/morph.common.js +2 -2
- package/dist/features/morph.esm.js +9 -5
- package/dist/features/morph.js +2 -2
- package/dist/features/perspectives.common.js +2 -2
- package/dist/features/perspectives.esm.js +4 -1
- package/dist/features/perspectives.js +2 -2
- package/dist/features/raincloud.common.js +2 -2
- package/dist/features/raincloud.esm.js +26 -27
- package/dist/features/raincloud.js +2 -2
- package/dist/features/renderer-canvas.common.js +2 -2
- package/dist/features/renderer-canvas.esm.js +2 -1
- package/dist/features/renderer-canvas.js +2 -2
- package/dist/features/stats.common.js +2 -2
- package/dist/features/stats.esm.js +52 -59
- package/dist/features/stats.js +2 -2
- package/dist/features/storyboard.common.js +2 -2
- package/dist/features/storyboard.esm.js +4 -1
- package/dist/features/storyboard.js +2 -2
- package/dist/features/streamgraph.common.js +2 -2
- package/dist/features/streamgraph.esm.js +48 -14
- package/dist/features/streamgraph.js +2 -2
- package/dist/features/toolbar.common.js +2 -2
- package/dist/features/toolbar.esm.js +148 -18
- package/dist/features/toolbar.js +2 -2
- package/dist/features/trellis.common.js +2 -2
- package/dist/features/trellis.esm.js +150 -63
- package/dist/features/trellis.js +2 -2
- package/dist/features/waterfall.common.js +1 -1
- package/dist/features/waterfall.esm.js +1 -1
- package/dist/features/waterfall.js +1 -1
- package/dist/features/weave.common.js +2 -2
- package/dist/features/weave.esm.js +13 -12
- package/dist/features/weave.js +2 -2
- package/dist/full.common.js +2 -2
- package/dist/full.esm.js +1068 -842
- package/dist/heatmap.common.js +2 -2
- package/dist/heatmap.esm.js +3 -17
- package/dist/heatmap.js +2 -2
- package/dist/histogram.common.js +2 -2
- package/dist/histogram.esm.js +529 -464
- package/dist/icicle.common.js +2 -2
- package/dist/icicle.esm.js +80 -46
- package/dist/icicle.js +2 -2
- package/dist/line.common.js +2 -2
- package/dist/line.esm.js +91 -40
- package/dist/line.js +2 -2
- package/dist/locales/en.json +2 -1
- package/dist/locales/ro.json +3 -2
- package/dist/pictograms.common.js +1 -1
- package/dist/pictograms.esm.js +1 -1
- package/dist/pictograms.js +1 -1
- package/dist/pie.common.js +2 -2
- package/dist/pie.esm.js +3 -9
- package/dist/pie.js +2 -2
- package/dist/polarArea.common.js +2 -2
- package/dist/polarArea.esm.js +3 -9
- package/dist/radar.common.js +2 -2
- package/dist/radar.esm.js +5 -4
- package/dist/radar.js +2 -2
- package/dist/radialBar.common.js +2 -2
- package/dist/radialBar.esm.js +5 -12
- package/dist/radialBar.js +2 -2
- package/dist/raincloud.common.js +2 -2
- package/dist/raincloud.esm.js +97 -52
- package/dist/rangeArea.common.js +2 -2
- package/dist/rangeArea.esm.js +91 -40
- package/dist/rangeBar.common.js +2 -2
- package/dist/rangeBar.esm.js +478 -406
- package/dist/scatter.common.js +2 -2
- package/dist/scatter.esm.js +91 -40
- package/dist/streamgraph.common.js +2 -2
- package/dist/streamgraph.esm.js +138 -53
- package/dist/sunburst.common.js +2 -2
- package/dist/sunburst.esm.js +116 -94
- package/dist/sunburst.js +2 -2
- package/dist/treemap.common.js +2 -2
- package/dist/treemap.esm.js +138 -104
- package/dist/treemap.js +2 -2
- package/dist/unit-shapes.common.js +1 -1
- package/dist/unit-shapes.esm.js +1 -1
- package/dist/unit-shapes.js +1 -1
- package/dist/unit.common.js +2 -2
- package/dist/unit.esm.js +280 -202
- package/dist/unit.js +2 -2
- package/dist/violin.common.js +2 -2
- package/dist/violin.esm.js +72 -26
- package/dist/violin.js +2 -2
- package/dist/waterfall.common.js +2 -2
- package/dist/waterfall.esm.js +477 -405
- package/package.json +1 -1
- package/src/apexcharts.js +40 -59
- package/src/assets/apexcharts.css +38 -8
- package/src/charts/Bar.js +62 -55
- package/src/charts/BarStacked.js +80 -88
- package/src/charts/BoxCandleStick.js +28 -31
- package/src/charts/Icicle.js +68 -47
- package/src/charts/Line.js +118 -42
- package/src/charts/Pie.js +2 -8
- package/src/charts/Radar.js +5 -7
- package/src/charts/Radial.js +2 -6
- package/src/charts/RangeBar.js +47 -43
- package/src/charts/Sunburst.js +101 -98
- package/src/charts/Treemap.js +150 -88
- package/src/charts/Unit.js +368 -250
- package/src/charts/Violin.js +48 -30
- package/src/charts/common/Breadcrumb.js +2 -2
- package/src/charts/common/Hierarchy.js +32 -11
- package/src/charts/common/Jitter.js +32 -7
- package/src/charts/common/Stats.js +30 -23
- package/src/charts/common/bar/DataLabels.js +76 -81
- package/src/charts/common/bar/Helpers.js +43 -7
- package/src/charts/common/line/Helpers.js +12 -15
- package/src/charts/common/partition/NodeTooltip.js +29 -7
- package/src/charts/common/partition/Partition.js +33 -1
- package/src/charts/common/treemap/Helpers.js +3 -11
- package/src/charts/common/treemap/Nested.js +2 -3
- package/src/features/raincloud.js +16 -10
- package/src/features/stats.js +67 -62
- package/src/locales/en.json +2 -1
- package/src/locales/ro.json +3 -2
- package/src/modules/Animations.js +102 -95
- package/src/modules/AxisMapping.js +47 -12
- package/src/modules/Core.js +4 -0
- package/src/modules/CoreUtils.js +18 -42
- package/src/modules/Data.js +23 -24
- package/src/modules/DataLabels.js +6 -6
- package/src/modules/Exports.js +12 -5
- package/src/modules/Fill.js +17 -8
- package/src/modules/Filters.js +50 -50
- package/src/modules/Graphics.js +69 -51
- package/src/modules/Markers.js +3 -1
- package/src/modules/MorphTypeChange.js +13 -7
- package/src/modules/Range.js +44 -29
- package/src/modules/RendererController.js +17 -3
- package/src/modules/Scales.js +32 -9
- package/src/modules/Series.js +41 -19
- package/src/modules/Theme.js +1 -1
- package/src/modules/Toolbar.js +3 -2
- package/src/modules/UnitMarkRegistry.js +0 -5
- package/src/modules/ZoomPanSelection.js +123 -2
- package/src/modules/accessibility/KeyboardNavigation.js +114 -186
- package/src/modules/animations/Easing.js +2 -1
- package/src/modules/animations/LengthTransition.js +22 -2
- package/src/modules/annotations/Helpers.js +68 -52
- package/src/modules/axes/Grid.js +21 -7
- package/src/modules/axes/YAxis.js +8 -9
- package/src/modules/dimensions/Dimensions.js +9 -3
- package/src/modules/dimensions/Grid.js +2 -2
- package/src/modules/dimensions/XAxis.js +2 -5
- package/src/modules/drilldown/Breadcrumb.js +5 -2
- package/src/modules/helpers/Destroy.js +1 -1
- package/src/modules/helpers/UpdateHelpers.js +33 -15
- package/src/modules/highlightFilter/HighlightFilter.js +8 -9
- package/src/modules/highlightFilter/TreemapPart.js +2 -2
- package/src/modules/legend/HeatmapGradientLegend.js +76 -45
- package/src/modules/legend/Helpers.js +8 -1
- package/src/modules/legend/Legend.js +11 -12
- package/src/modules/license/LicenseEnforcer.js +5 -0
- package/src/modules/settings/Defaults.js +28 -56
- package/src/modules/settings/Globals.js +5 -0
- package/src/modules/settings/Options.js +7 -7
- package/src/modules/settings/TypeAliases.js +33 -16
- package/src/modules/streamgraph/StreamLabels.js +1 -0
- package/src/modules/tooltip/Labels.js +73 -76
- package/src/modules/tooltip/Marker.js +25 -21
- package/src/modules/tooltip/Position.js +88 -51
- package/src/modules/tooltip/Tooltip.js +242 -255
- package/src/modules/tooltip/Utils.js +71 -130
- package/src/modules/tooltip/constants.js +5 -5
- package/src/modules/trellis/Trellis.js +6 -0
- package/src/modules/trellis/TrellisChrome.js +18 -7
- package/src/modules/trellis/TrellisSync.js +2 -0
- package/src/modules/trellis/TrellisTooltip.js +2 -11
- package/src/modules/weave/WeaveHost.js +18 -12
- package/src/renderers/canvas/CanvasGraphics.js +1 -0
- package/src/ssr/DOMShim.js +10 -0
- package/src/svg/SVGFilter.js +26 -17
- package/src/types/internal.d.ts +9 -3
- package/src/utils/Utils.js +0 -14
- package/types/apexcharts.d.ts +33 -12
package/dist/full.esm.js
CHANGED
|
@@ -50,7 +50,7 @@ var __async = (__this, __arguments, generator) => {
|
|
|
50
50
|
});
|
|
51
51
|
};
|
|
52
52
|
/*!
|
|
53
|
-
* ApexCharts v8.
|
|
53
|
+
* ApexCharts v8.3.1
|
|
54
54
|
* (c) 2018-2026 ApexCharts
|
|
55
55
|
*/
|
|
56
56
|
import ApexCharts$1 from "apexcharts";
|
|
@@ -62,6 +62,285 @@ const getChartClass = ApexCharts.__apex_ChartFactory_getChartClass;
|
|
|
62
62
|
const Fill = ApexCharts.__apex_Fill;
|
|
63
63
|
const Graphics = ApexCharts.__apex_Graphics;
|
|
64
64
|
const Series = ApexCharts.__apex_Series;
|
|
65
|
+
const Animations = ApexCharts.__apex_Animations;
|
|
66
|
+
const prefersReducedMotion = ApexCharts.__apex_Animations_prefersReducedMotion;
|
|
67
|
+
const BrowserAPIs = ApexCharts.__apex_BrowserAPIs_BrowserAPIs;
|
|
68
|
+
const Environment = ApexCharts.__apex_Environment_Environment;
|
|
69
|
+
const resolveEasing = ApexCharts.__apex_Easing_resolveEasing;
|
|
70
|
+
const parsePath = ApexCharts.__apex_PathMorphing_parsePath;
|
|
71
|
+
const arrayToPath = ApexCharts.__apex_PathMorphing_arrayToPath;
|
|
72
|
+
function buildUnionEntries(join, oldN) {
|
|
73
|
+
const exitSet = new Set(join.exits);
|
|
74
|
+
const entries = [];
|
|
75
|
+
let oi = 0;
|
|
76
|
+
for (let nj = 0; nj < join.toOld.length; nj++) {
|
|
77
|
+
const oj = join.toOld[nj];
|
|
78
|
+
if (oj !== -1) {
|
|
79
|
+
while (oi < oj) {
|
|
80
|
+
if (exitSet.has(oi)) entries.push({ oldJ: oi, newJ: -1 });
|
|
81
|
+
oi++;
|
|
82
|
+
}
|
|
83
|
+
entries.push({ oldJ: oj, newJ: nj });
|
|
84
|
+
oi = oj + 1;
|
|
85
|
+
} else {
|
|
86
|
+
entries.push({ oldJ: -1, newJ: nj });
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
while (oi < oldN) {
|
|
90
|
+
if (exitSet.has(oi)) entries.push({ oldJ: oi, newJ: -1 });
|
|
91
|
+
oi++;
|
|
92
|
+
}
|
|
93
|
+
return entries;
|
|
94
|
+
}
|
|
95
|
+
function analyzeSeriesPath(d, expectedAnchors, isArea) {
|
|
96
|
+
if (!d || typeof d !== "string") return null;
|
|
97
|
+
const cmds = parsePath(d);
|
|
98
|
+
if (!cmds.length || cmds[0][0] !== "M") return null;
|
|
99
|
+
for (let i2 = 1; i2 < cmds.length; i2++) {
|
|
100
|
+
if (cmds[i2][0] === "M") return null;
|
|
101
|
+
}
|
|
102
|
+
let body = cmds;
|
|
103
|
+
let closing = null;
|
|
104
|
+
if (isArea) {
|
|
105
|
+
if (cmds.length < 5) return null;
|
|
106
|
+
closing = cmds.slice(-3);
|
|
107
|
+
body = cmds.slice(0, -3);
|
|
108
|
+
if (closing[2][0] !== "Z") return null;
|
|
109
|
+
if (closing[1][0] !== "L") return null;
|
|
110
|
+
if (closing[0][0] !== "L" && closing[0][0] !== "C") return null;
|
|
111
|
+
} else if (cmds[cmds.length - 1][0] === "Z") {
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
if (body.length !== expectedAnchors || body.length < 2) return null;
|
|
115
|
+
const segType = body[1][0];
|
|
116
|
+
if (segType !== "L" && segType !== "C") return null;
|
|
117
|
+
for (let i2 = 2; i2 < body.length; i2++) {
|
|
118
|
+
if (body[i2][0] !== segType) return null;
|
|
119
|
+
}
|
|
120
|
+
const anchors = body.map(
|
|
121
|
+
(c) => c[0] === "C" ? [Number(c[5]), Number(c[6])] : [Number(c[1]), Number(c[2])]
|
|
122
|
+
);
|
|
123
|
+
for (const a2 of anchors) {
|
|
124
|
+
if (!isFinite(a2[0]) || !isFinite(a2[1])) return null;
|
|
125
|
+
}
|
|
126
|
+
return { body, closing, segType, anchors };
|
|
127
|
+
}
|
|
128
|
+
function lerpPt(a2, b, t2) {
|
|
129
|
+
return [a2[0] + (b[0] - a2[0]) * t2, a2[1] + (b[1] - a2[1]) * t2];
|
|
130
|
+
}
|
|
131
|
+
function splitCubic(s2, cmd, t2) {
|
|
132
|
+
const p0 = s2;
|
|
133
|
+
const p1 = [cmd[1], cmd[2]];
|
|
134
|
+
const p2 = [cmd[3], cmd[4]];
|
|
135
|
+
const p3 = [cmd[5], cmd[6]];
|
|
136
|
+
const p01 = lerpPt(p0, p1, t2);
|
|
137
|
+
const p12 = lerpPt(p1, p2, t2);
|
|
138
|
+
const p23 = lerpPt(p2, p3, t2);
|
|
139
|
+
const p012 = lerpPt(p01, p12, t2);
|
|
140
|
+
const p123 = lerpPt(p12, p23, t2);
|
|
141
|
+
const mid = lerpPt(p012, p123, t2);
|
|
142
|
+
return {
|
|
143
|
+
first: ["C", p01[0], p01[1], p012[0], p012[1], mid[0], mid[1]],
|
|
144
|
+
second: ["C", p123[0], p123[1], p23[0], p23[1], p3[0], p3[1]],
|
|
145
|
+
mid
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
function splitLine(s2, cmd, t2) {
|
|
149
|
+
const e2 = [cmd[1], cmd[2]];
|
|
150
|
+
const mid = lerpPt(s2, e2, t2);
|
|
151
|
+
return {
|
|
152
|
+
first: ["L", mid[0], mid[1]],
|
|
153
|
+
second: ["L", e2[0], e2[1]],
|
|
154
|
+
mid
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
function expandPath(analysis, ownIdx) {
|
|
158
|
+
const { body, closing, segType, anchors } = analysis;
|
|
159
|
+
const n2 = anchors.length;
|
|
160
|
+
const m = ownIdx.length;
|
|
161
|
+
const degen = (p) => segType === "C" ? ["C", p[0], p[1], p[0], p[1], p[0], p[1]] : ["L", p[0], p[1]];
|
|
162
|
+
const out = [["M", anchors[0][0], anchors[0][1]]];
|
|
163
|
+
let firstOwn = 0;
|
|
164
|
+
while (firstOwn < m && ownIdx[firstOwn] !== 0) firstOwn++;
|
|
165
|
+
for (let q2 = 1; q2 <= firstOwn; q2++) out.push(degen(anchors[0]));
|
|
166
|
+
let entry = firstOwn + 1;
|
|
167
|
+
for (let s2 = 0; s2 < n2 - 1; s2++) {
|
|
168
|
+
let interior = 0;
|
|
169
|
+
while (entry + interior < m && ownIdx[entry + interior] === -1) interior++;
|
|
170
|
+
const cmd = body[s2 + 1];
|
|
171
|
+
if (!interior) {
|
|
172
|
+
out.push(cmd.slice());
|
|
173
|
+
} else {
|
|
174
|
+
const totalParts = interior + 1;
|
|
175
|
+
let start = anchors[s2];
|
|
176
|
+
let rest = cmd;
|
|
177
|
+
for (let q2 = 0; q2 < interior; q2++) {
|
|
178
|
+
const t2 = 1 / (totalParts - q2);
|
|
179
|
+
const sp = segType === "C" ? splitCubic(start, rest, t2) : splitLine(start, rest, t2);
|
|
180
|
+
out.push(sp.first);
|
|
181
|
+
start = sp.mid;
|
|
182
|
+
rest = sp.second;
|
|
183
|
+
}
|
|
184
|
+
out.push(rest);
|
|
185
|
+
}
|
|
186
|
+
entry += interior + 1;
|
|
187
|
+
}
|
|
188
|
+
while (entry < m) {
|
|
189
|
+
out.push(degen(anchors[n2 - 1]));
|
|
190
|
+
entry++;
|
|
191
|
+
}
|
|
192
|
+
if (closing) closing.forEach((c) => out.push(c.slice()));
|
|
193
|
+
return out;
|
|
194
|
+
}
|
|
195
|
+
function reconcilePathPair(fromD, toD, entries, oldN, newN, isArea) {
|
|
196
|
+
const fromAnalysis = analyzeSeriesPath(fromD, oldN, isArea);
|
|
197
|
+
if (!fromAnalysis) return null;
|
|
198
|
+
const toAnalysis = analyzeSeriesPath(toD, newN, isArea);
|
|
199
|
+
if (!toAnalysis) return null;
|
|
200
|
+
if (fromAnalysis.segType !== toAnalysis.segType) return null;
|
|
201
|
+
if ((fromAnalysis.closing || toAnalysis.closing) && (!fromAnalysis.closing || !toAnalysis.closing || fromAnalysis.closing[0][0] !== toAnalysis.closing[0][0])) {
|
|
202
|
+
return null;
|
|
203
|
+
}
|
|
204
|
+
const fromOwn = entries.map((e2) => e2.oldJ);
|
|
205
|
+
const toOwn = entries.map((e2) => e2.newJ);
|
|
206
|
+
return {
|
|
207
|
+
from: arrayToPath(expandPath(fromAnalysis, fromOwn)),
|
|
208
|
+
toInterp: arrayToPath(expandPath(toAnalysis, toOwn))
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
function lengthTransitionEnabled(w) {
|
|
212
|
+
var _a;
|
|
213
|
+
const anim = w.config.chart.animations;
|
|
214
|
+
if (!anim || anim.enabled === false) return false;
|
|
215
|
+
if (!anim.dynamicAnimation || anim.dynamicAnimation.enabled === false) {
|
|
216
|
+
return false;
|
|
217
|
+
}
|
|
218
|
+
const largeThreshold = (_a = anim.largeDatasetThreshold) != null ? _a : 0;
|
|
219
|
+
if (largeThreshold > 0 && w.globals.dataPoints > largeThreshold) return false;
|
|
220
|
+
return !!(Environment.isBrowser() && w.globals.dataChanged && w.globals.shouldAnimate);
|
|
221
|
+
}
|
|
222
|
+
function datumKey(w, realIndex, j2) {
|
|
223
|
+
var _a, _b, _c, _d;
|
|
224
|
+
if ((_a = w.axisFlags) == null ? void 0 : _a.isXNumeric) {
|
|
225
|
+
const sx = (_c = (_b = w.seriesData) == null ? void 0 : _b.seriesX) == null ? void 0 : _c[realIndex];
|
|
226
|
+
if (sx && sx.length && sx[j2] != null) return "x:" + sx[j2];
|
|
227
|
+
}
|
|
228
|
+
const lbl = (_d = w.globals.labels) == null ? void 0 : _d[j2];
|
|
229
|
+
if (lbl != null && String(lbl) !== "") {
|
|
230
|
+
return "c:" + (Array.isArray(lbl) ? lbl.join(" ") : String(lbl));
|
|
231
|
+
}
|
|
232
|
+
return "j:" + j2;
|
|
233
|
+
}
|
|
234
|
+
function frameDatumKey(frame, realIndex, j2) {
|
|
235
|
+
var _a, _b;
|
|
236
|
+
if (frame.isXNumeric) {
|
|
237
|
+
const sx = (_a = frame.seriesX) == null ? void 0 : _a[realIndex];
|
|
238
|
+
if (sx && sx.length && sx[j2] != null) return "x:" + sx[j2];
|
|
239
|
+
}
|
|
240
|
+
const lbl = (_b = frame.labels) == null ? void 0 : _b[j2];
|
|
241
|
+
if (lbl != null && String(lbl) !== "") {
|
|
242
|
+
return "c:" + (Array.isArray(lbl) ? lbl.join(" ") : String(lbl));
|
|
243
|
+
}
|
|
244
|
+
return "j:" + j2;
|
|
245
|
+
}
|
|
246
|
+
function joinKeys(oldKeys, newKeys) {
|
|
247
|
+
const oldIndex = /* @__PURE__ */ new Map();
|
|
248
|
+
oldKeys.forEach((k2, i2) => {
|
|
249
|
+
if (!oldIndex.has(k2)) oldIndex.set(k2, i2);
|
|
250
|
+
});
|
|
251
|
+
const toOld = new Array(newKeys.length);
|
|
252
|
+
const usedOld = /* @__PURE__ */ new Set();
|
|
253
|
+
let prev = -1;
|
|
254
|
+
let ordered = true;
|
|
255
|
+
let identity = oldKeys.length === newKeys.length;
|
|
256
|
+
newKeys.forEach((k2, i2) => {
|
|
257
|
+
const oi = oldIndex.has(k2) && !usedOld.has(oldIndex.get(k2)) ? oldIndex.get(k2) : -1;
|
|
258
|
+
toOld[i2] = oi;
|
|
259
|
+
if (oi !== -1) {
|
|
260
|
+
usedOld.add(oi);
|
|
261
|
+
if (oi < prev) ordered = false;
|
|
262
|
+
prev = oi;
|
|
263
|
+
}
|
|
264
|
+
if (oi !== i2) identity = false;
|
|
265
|
+
});
|
|
266
|
+
const exits = [];
|
|
267
|
+
for (let i2 = 0; i2 < oldKeys.length; i2++) {
|
|
268
|
+
if (!usedOld.has(i2)) exits.push(i2);
|
|
269
|
+
}
|
|
270
|
+
return { toOld, exits, ordered, changed: !identity };
|
|
271
|
+
}
|
|
272
|
+
function uniquifyKeys(keys) {
|
|
273
|
+
const seen = /* @__PURE__ */ new Map();
|
|
274
|
+
return keys.map((k2) => {
|
|
275
|
+
const count = seen.get(k2) || 0;
|
|
276
|
+
seen.set(k2, count + 1);
|
|
277
|
+
return count === 0 ? k2 : `${k2}#${count}`;
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
function seriesKeys(w, realIndex, n2 = ((_a) => (_a = w.seriesData.series[realIndex]) == null ? void 0 : _a.length)() | 0) {
|
|
281
|
+
return uniquifyKeys(
|
|
282
|
+
Array.from({ length: n2 }, (_2, j2) => datumKey(w, realIndex, j2))
|
|
283
|
+
);
|
|
284
|
+
}
|
|
285
|
+
function seriesJoin(w, realIndex, includeIdentity = false, allowReorder = false) {
|
|
286
|
+
var _a, _b;
|
|
287
|
+
if (!lengthTransitionEnabled(w)) return null;
|
|
288
|
+
const frame = w.globals.prevStreamFrame;
|
|
289
|
+
if (!frame) return null;
|
|
290
|
+
const oldY = (_a = frame.seriesY) == null ? void 0 : _a[realIndex];
|
|
291
|
+
const newY = (_b = w.seriesData.series) == null ? void 0 : _b[realIndex];
|
|
292
|
+
if (!Array.isArray(oldY) || !Array.isArray(newY)) return null;
|
|
293
|
+
if (!oldY.length || !newY.length) return null;
|
|
294
|
+
const oldKeys = uniquifyKeys(
|
|
295
|
+
oldY.map((_2, j2) => frameDatumKey(frame, realIndex, j2))
|
|
296
|
+
);
|
|
297
|
+
const newKeys = seriesKeys(w, realIndex);
|
|
298
|
+
const join = joinKeys(oldKeys, newKeys);
|
|
299
|
+
if (!join.ordered && !allowReorder) return null;
|
|
300
|
+
if (!join.changed && !includeIdentity) return null;
|
|
301
|
+
return { join, oldKeys, newKeys };
|
|
302
|
+
}
|
|
303
|
+
function morphEasing(w) {
|
|
304
|
+
var _a, _b;
|
|
305
|
+
const anim = w.config.chart.animations;
|
|
306
|
+
return resolveEasing((_b = (_a = anim.dynamicAnimation) == null ? void 0 : _a.easing) != null ? _b : anim.easing);
|
|
307
|
+
}
|
|
308
|
+
function reconcileSeriesPaths(w, { type, realIndex, pathFromLine, pathFromArea, linePaths, areaPaths }) {
|
|
309
|
+
var _a, _b;
|
|
310
|
+
const sj = seriesJoin(w, realIndex);
|
|
311
|
+
if (!sj) return null;
|
|
312
|
+
const { join, oldKeys, newKeys } = sj;
|
|
313
|
+
const frame = w.globals.prevStreamFrame;
|
|
314
|
+
if (!frame) return null;
|
|
315
|
+
const oldY = (_a = frame.seriesY) == null ? void 0 : _a[realIndex];
|
|
316
|
+
const newY = (_b = w.seriesData.series) == null ? void 0 : _b[realIndex];
|
|
317
|
+
if (oldY.length < 2 || newY.length < 2) return null;
|
|
318
|
+
if (oldY.some((v) => v === null) || newY.some((v) => v === null)) return null;
|
|
319
|
+
const entries = buildUnionEntries(join, oldKeys.length);
|
|
320
|
+
const out = {};
|
|
321
|
+
if (Array.isArray(linePaths) && linePaths.length === 1 && pathFromLine) {
|
|
322
|
+
out.line = reconcilePathPair(
|
|
323
|
+
pathFromLine,
|
|
324
|
+
linePaths[0],
|
|
325
|
+
entries,
|
|
326
|
+
oldKeys.length,
|
|
327
|
+
newKeys.length,
|
|
328
|
+
false
|
|
329
|
+
);
|
|
330
|
+
}
|
|
331
|
+
if (type === "area" && Array.isArray(areaPaths) && areaPaths.length === 1 && pathFromArea) {
|
|
332
|
+
out.area = reconcilePathPair(
|
|
333
|
+
pathFromArea,
|
|
334
|
+
areaPaths[0],
|
|
335
|
+
entries,
|
|
336
|
+
oldKeys.length,
|
|
337
|
+
newKeys.length,
|
|
338
|
+
true
|
|
339
|
+
);
|
|
340
|
+
}
|
|
341
|
+
if (!out.line && !out.area) return null;
|
|
342
|
+
return out;
|
|
343
|
+
}
|
|
65
344
|
const Utils = ApexCharts.__apex_Utils;
|
|
66
345
|
const tangents = (points) => {
|
|
67
346
|
const m = finiteDifferences(points);
|
|
@@ -173,9 +452,20 @@ function finiteDifferences(points) {
|
|
|
173
452
|
m[i2] = d;
|
|
174
453
|
return m;
|
|
175
454
|
}
|
|
455
|
+
function jitterExtent(pool, w) {
|
|
456
|
+
let lo = Infinity;
|
|
457
|
+
let hi = -Infinity;
|
|
458
|
+
pool.slice(0, w.seriesData.series.length).flat(2).forEach((v) => {
|
|
459
|
+
if (v === +v) {
|
|
460
|
+
if (v < lo) lo = v;
|
|
461
|
+
if (v > hi) hi = v;
|
|
462
|
+
}
|
|
463
|
+
});
|
|
464
|
+
return [lo, hi];
|
|
465
|
+
}
|
|
176
466
|
function buildJitterGroups({
|
|
177
|
-
w,
|
|
178
467
|
points,
|
|
468
|
+
extent,
|
|
179
469
|
seedA,
|
|
180
470
|
seedB,
|
|
181
471
|
center,
|
|
@@ -186,6 +476,7 @@ function buildJitterGroups({
|
|
|
186
476
|
clampAt,
|
|
187
477
|
sideSign
|
|
188
478
|
}) {
|
|
479
|
+
var _a, _b;
|
|
189
480
|
const opts = options;
|
|
190
481
|
if (!opts || opts.show === false) return [];
|
|
191
482
|
if (!points || !points.length) return [];
|
|
@@ -199,8 +490,8 @@ function buildJitterGroups({
|
|
|
199
490
|
const scale = opts.colorScale;
|
|
200
491
|
const useScale = scale && Array.isArray(scale.colors) && scale.colors.length > 0;
|
|
201
492
|
const steps = useScale ? Math.max(2, scale.steps || 24) : 1;
|
|
202
|
-
const sMin =
|
|
203
|
-
const sMax =
|
|
493
|
+
const sMin = (_a = scale == null ? void 0 : scale.min) != null ? _a : extent[0];
|
|
494
|
+
const sMax = (_b = scale == null ? void 0 : scale.max) != null ? _b : extent[1];
|
|
204
495
|
const span = sMax - sMin || 1;
|
|
205
496
|
const buckets = useScale ? new Array(steps).fill("") : [""];
|
|
206
497
|
for (let k2 = 0; k2 < points.length; k2 += stride) {
|
|
@@ -286,7 +577,7 @@ function renderJitter({
|
|
|
286
577
|
elSeries.add(elPointsWrap);
|
|
287
578
|
}
|
|
288
579
|
function darkenColor(color, amount) {
|
|
289
|
-
const rgb = Utils.
|
|
580
|
+
const rgb = Utils.parseColor(color) || Utils.parseColor(Utils.resolveColor(color));
|
|
290
581
|
if (!rgb) return color;
|
|
291
582
|
const f = Math.max(0, 1 - amount);
|
|
292
583
|
return `rgb(${Math.round(rgb[0] * f)},${Math.round(rgb[1] * f)},${Math.round(rgb[2] * f)})`;
|
|
@@ -343,6 +634,7 @@ class Violin extends BarBase {
|
|
|
343
634
|
const fill = new Fill(this.w);
|
|
344
635
|
this.violinOptions = w.config.plotOptions.violin;
|
|
345
636
|
this.pointsOptions = this.violinOptions.points;
|
|
637
|
+
this.jx = jitterExtent(w.violinData.seriesViolinPoints, w);
|
|
346
638
|
this.boxOptions = this.violinOptions.box || {};
|
|
347
639
|
this.cloudSign = crossSign(this.violinOptions.side);
|
|
348
640
|
this.rainSign = this.pointsOptions.show === false ? 0 : crossSign(this.pointsOptions.position);
|
|
@@ -357,7 +649,7 @@ class Violin extends BarBase {
|
|
|
357
649
|
series = this.coreUtils.getLogSeries(series);
|
|
358
650
|
this.series = series;
|
|
359
651
|
this.yRatio = this.coreUtils.getLogYRatios(this.yRatio);
|
|
360
|
-
this.barHelpers.initVariables(series);
|
|
652
|
+
this.barHelpers.initVariables(series, seriesIndex);
|
|
361
653
|
const ret = graphics.group({
|
|
362
654
|
class: "apexcharts-violin-series apexcharts-plot-series"
|
|
363
655
|
});
|
|
@@ -504,7 +796,8 @@ class Violin extends BarBase {
|
|
|
504
796
|
elDataLabelsWrap,
|
|
505
797
|
visibleSeries: this.visibleI,
|
|
506
798
|
type: "violin",
|
|
507
|
-
classes: "apexcharts-raincloud-box"
|
|
799
|
+
classes: "apexcharts-raincloud-box",
|
|
800
|
+
noLabel: true
|
|
508
801
|
});
|
|
509
802
|
});
|
|
510
803
|
}
|
|
@@ -541,11 +834,16 @@ class Violin extends BarBase {
|
|
|
541
834
|
var _a, _b, _c, _d, _e, _f, _g;
|
|
542
835
|
const w = this.w;
|
|
543
836
|
const { realIndex, j: j2, translationsIndex } = indexes;
|
|
544
|
-
const yRatio = this.yRatio[translationsIndex];
|
|
837
|
+
const yRatio = this.yRatio[translationsIndex] * (this.isReversed ? -1 : 1);
|
|
838
|
+
let barXPosition = x2 + barWidth * this.visibleI;
|
|
545
839
|
if (w.axisFlags.isXNumeric) {
|
|
546
|
-
|
|
840
|
+
({ x: x2, barXPosition } = this.getBarXForNumericXAxis({
|
|
841
|
+
x: x2,
|
|
842
|
+
barWidth,
|
|
843
|
+
realIndex,
|
|
844
|
+
j: j2
|
|
845
|
+
}));
|
|
547
846
|
}
|
|
548
|
-
const barXPosition = x2 + barWidth * this.visibleI;
|
|
549
847
|
const center = barXPosition + barWidth / 2;
|
|
550
848
|
const halfExtent = barWidth / 2;
|
|
551
849
|
const density = this.getDensity(realIndex, j2);
|
|
@@ -574,7 +872,7 @@ class Violin extends BarBase {
|
|
|
574
872
|
if (morphFrom) {
|
|
575
873
|
pathFrom = morphFrom;
|
|
576
874
|
} else if (w.globals.previousPaths.length > 0) {
|
|
577
|
-
pathFrom = this.
|
|
875
|
+
pathFrom = this._prevBody(realIndex, j2, pathTo);
|
|
578
876
|
}
|
|
579
877
|
if (pathFrom == null) {
|
|
580
878
|
pathFrom = this.buildBodyPath({
|
|
@@ -613,7 +911,7 @@ class Violin extends BarBase {
|
|
|
613
911
|
alongFn,
|
|
614
912
|
vertical: true
|
|
615
913
|
}),
|
|
616
|
-
alongRepresentative: alongFn((_g =
|
|
914
|
+
alongRepresentative: alongFn((_g = w.seriesData.series[realIndex][j2]) != null ? _g : 0)
|
|
617
915
|
};
|
|
618
916
|
}
|
|
619
917
|
/** @param {{indexes: any, y: any, yDivision: any, barHeight: any, zeroW: any}} opts */
|
|
@@ -621,7 +919,7 @@ class Violin extends BarBase {
|
|
|
621
919
|
var _a, _b, _c, _d, _e, _f, _g;
|
|
622
920
|
const w = this.w;
|
|
623
921
|
const { realIndex, j: j2 } = indexes;
|
|
624
|
-
const yRatio = this.invertedYRatio;
|
|
922
|
+
const yRatio = this.invertedYRatio * (this.isReversed ? -1 : 1);
|
|
625
923
|
const barYPosition = y + barHeight * this.visibleI;
|
|
626
924
|
const center = barYPosition + barHeight / 2;
|
|
627
925
|
const halfExtent = barHeight / 2;
|
|
@@ -651,7 +949,7 @@ class Violin extends BarBase {
|
|
|
651
949
|
if (morphFrom) {
|
|
652
950
|
pathFrom = morphFrom;
|
|
653
951
|
} else if (w.globals.previousPaths.length > 0) {
|
|
654
|
-
pathFrom = this.
|
|
952
|
+
pathFrom = this._prevBody(realIndex, j2, pathTo);
|
|
655
953
|
}
|
|
656
954
|
if (pathFrom == null) {
|
|
657
955
|
pathFrom = this.buildBodyPath({
|
|
@@ -688,7 +986,7 @@ class Violin extends BarBase {
|
|
|
688
986
|
alongFn,
|
|
689
987
|
vertical: false
|
|
690
988
|
}),
|
|
691
|
-
alongRepresentative: alongFn((_g =
|
|
989
|
+
alongRepresentative: alongFn((_g = w.seriesData.series[realIndex][j2]) != null ? _g : 0)
|
|
692
990
|
};
|
|
693
991
|
}
|
|
694
992
|
/**
|
|
@@ -779,6 +1077,23 @@ class Violin extends BarBase {
|
|
|
779
1077
|
leftPts.reverse();
|
|
780
1078
|
return this.smoothSegment(rightPts, vertical, false) + this.smoothSegment(leftPts, vertical, true) + "z";
|
|
781
1079
|
}
|
|
1080
|
+
/**
|
|
1081
|
+
* The survivor's previous body when it can morph to `pathTo`, else null so
|
|
1082
|
+
* the violin regrows from its centreline (a changed density node count
|
|
1083
|
+
* cannot tween, and bar corner reconciliation does not apply here).
|
|
1084
|
+
*
|
|
1085
|
+
* @param {number} realIndex
|
|
1086
|
+
* @param {number} j
|
|
1087
|
+
* @param {string} pathTo
|
|
1088
|
+
* @returns {string | null}
|
|
1089
|
+
*/
|
|
1090
|
+
_prevBody(realIndex, j2, pathTo) {
|
|
1091
|
+
var _a, _b;
|
|
1092
|
+
const d = (_b = (_a = this._prevKeyedPaths(realIndex)) == null ? void 0 : _a.get(
|
|
1093
|
+
datumKey(this.w, realIndex, j2)
|
|
1094
|
+
)) == null ? void 0 : _b.d;
|
|
1095
|
+
return d && Violin.pathCommandCount(d) === Violin.pathCommandCount(pathTo) ? d : null;
|
|
1096
|
+
}
|
|
782
1097
|
/**
|
|
783
1098
|
* Build the five-number box sub-paths for one category — the raincloud
|
|
784
1099
|
* "umbrella", or a violin box overlay. Two sub-paths so each can carry its
|
|
@@ -796,7 +1111,7 @@ class Violin extends BarBase {
|
|
|
796
1111
|
* @returns {{pathTo:string, pathFrom:string, filled:boolean}[] | null}
|
|
797
1112
|
*/
|
|
798
1113
|
buildBoxSubPaths({ realIndex, j: j2, boxCenter, boxHalfPx, alongFn, vertical }) {
|
|
799
|
-
var _a, _b;
|
|
1114
|
+
var _a, _b, _c;
|
|
800
1115
|
const w = this.w;
|
|
801
1116
|
if (!this.boxShown || boxHalfPx <= 0) return null;
|
|
802
1117
|
const summary = (_a = w.violinData.seriesViolinSummary[realIndex]) == null ? void 0 : _a[j2];
|
|
@@ -821,22 +1136,17 @@ class Violin extends BarBase {
|
|
|
821
1136
|
};
|
|
822
1137
|
const full = build2(capHalf, boxHalfPx);
|
|
823
1138
|
const collapsed = build2(0, 0);
|
|
824
|
-
const
|
|
825
|
-
|
|
826
|
-
if (w.globals.previousPaths.length > 0) {
|
|
827
|
-
pathFrom = this.getPreviousPath(realIndex, j2, pathTo);
|
|
828
|
-
}
|
|
829
|
-
return pathFrom == null ? collapsedFrom : pathFrom;
|
|
830
|
-
};
|
|
1139
|
+
const keyed = w.globals.previousPaths.length ? this._prevKeyedPaths(realIndex) : null;
|
|
1140
|
+
const prevBox = ((_c = keyed == null ? void 0 : keyed.get(datumKey(w, realIndex, j2))) == null ? void 0 : _c.box) || [];
|
|
831
1141
|
return [
|
|
832
1142
|
{
|
|
833
1143
|
pathTo: full.whiskers,
|
|
834
|
-
pathFrom:
|
|
1144
|
+
pathFrom: prevBox[0] || collapsed.whiskers,
|
|
835
1145
|
filled: false
|
|
836
1146
|
},
|
|
837
1147
|
{
|
|
838
1148
|
pathTo: full.box,
|
|
839
|
-
pathFrom:
|
|
1149
|
+
pathFrom: prevBox[1] || collapsed.box,
|
|
840
1150
|
filled: true
|
|
841
1151
|
}
|
|
842
1152
|
];
|
|
@@ -912,8 +1222,11 @@ class Violin extends BarBase {
|
|
|
912
1222
|
const scatterCenter = offsetLane ? rainCenter : this.cloudSign !== 0 ? cloudBase : center;
|
|
913
1223
|
const scatterHalf = offsetLane ? rainHalfPx : this.cloudSign !== 0 ? cloudMaxPx : halfExtent;
|
|
914
1224
|
return buildJitterGroups({
|
|
915
|
-
w: this.w,
|
|
916
1225
|
points: (_a = this.w.violinData.seriesViolinPoints[realIndex]) == null ? void 0 : _a[j2],
|
|
1226
|
+
extent: (
|
|
1227
|
+
/** @type {number[]} */
|
|
1228
|
+
this.jx
|
|
1229
|
+
),
|
|
917
1230
|
seedA: realIndex,
|
|
918
1231
|
seedB: j2,
|
|
919
1232
|
center: scatterCenter,
|
|
@@ -1707,10 +2020,6 @@ function getUnitMark(name) {
|
|
|
1707
2020
|
if (!name) return null;
|
|
1708
2021
|
return getMarks()[name] || null;
|
|
1709
2022
|
}
|
|
1710
|
-
const Environment = ApexCharts.__apex_Environment_Environment;
|
|
1711
|
-
const BrowserAPIs = ApexCharts.__apex_BrowserAPIs_BrowserAPIs;
|
|
1712
|
-
const Animations = ApexCharts.__apex_Animations;
|
|
1713
|
-
const prefersReducedMotion = ApexCharts.__apex_Animations_prefersReducedMotion;
|
|
1714
2023
|
function drawOuterLabel(w, spec) {
|
|
1715
2024
|
const {
|
|
1716
2025
|
lines,
|
|
@@ -1813,6 +2122,15 @@ function spaceOutLabels(items, minGap, maxY, minY) {
|
|
|
1813
2122
|
}
|
|
1814
2123
|
}
|
|
1815
2124
|
const GOLDEN_ANGLE = Math.PI * (3 - Math.sqrt(5));
|
|
2125
|
+
const uniqueId = (seen, id) => {
|
|
2126
|
+
const n2 = (seen.get(id) || 0) + 1;
|
|
2127
|
+
seen.set(id, n2);
|
|
2128
|
+
return n2 > 1 ? id + "#" + n2 : id;
|
|
2129
|
+
};
|
|
2130
|
+
const toNum = (v) => {
|
|
2131
|
+
if (typeof v === "string") v = parseFloat(v);
|
|
2132
|
+
return typeof v === "number" && isFinite(v) ? v : null;
|
|
2133
|
+
};
|
|
1816
2134
|
function easeOutCubic(t2) {
|
|
1817
2135
|
return 1 - Math.pow(1 - t2, 3);
|
|
1818
2136
|
}
|
|
@@ -1858,6 +2176,9 @@ class Unit {
|
|
|
1858
2176
|
const w = this.w;
|
|
1859
2177
|
const graphics = new Graphics(w, this.ctx);
|
|
1860
2178
|
const ret = graphics.group({ class: "apexcharts-unit" });
|
|
2179
|
+
BrowserAPIs.cancelAnimationFrame(w.globals.unitGatherRAF || 0);
|
|
2180
|
+
BrowserAPIs.cancelAnimationFrame(w.globals.unitExitRAF || 0);
|
|
2181
|
+
w.globals.unitGatherRAF = w.globals.unitExitRAF = null;
|
|
1861
2182
|
if (w.globals.noData || !Array.isArray(series) || series.length === 0) {
|
|
1862
2183
|
return ret;
|
|
1863
2184
|
}
|
|
@@ -1867,15 +2188,16 @@ class Unit {
|
|
|
1867
2188
|
const flow = transition === "flow";
|
|
1868
2189
|
const identity = transition === "identity";
|
|
1869
2190
|
const unitValue = opts.unitValue > 0 ? opts.unitValue : 1;
|
|
2191
|
+
const gridSplit = layout === "grid" && !!(opts.grid && opts.grid.split);
|
|
1870
2192
|
let counts = series.map((v) => {
|
|
1871
2193
|
const n2 = Math.abs(Utils.parseNumber(v)) / unitValue;
|
|
1872
|
-
return n2 > 0 ? Math.max(1, Math.round(n2)) : 0;
|
|
2194
|
+
return gridSplit ? n2 : n2 > 0 ? Math.max(1, Math.round(n2)) : 0;
|
|
1873
2195
|
});
|
|
1874
|
-
|
|
2196
|
+
if (!gridSplit && layout !== "scatter") {
|
|
2197
|
+
counts = this._applyMaxUnits(counts, opts.maxUnits);
|
|
2198
|
+
}
|
|
1875
2199
|
const total = counts.reduce((a2, b) => a2 + b, 0);
|
|
1876
2200
|
const clusters = layout === "packed" ? this._layoutPacked(counts, opts) : layout === "columns" ? this._layoutColumns(counts, opts) : layout === "grid" ? this._layoutGrid(counts, opts) : layout === "scatter" ? this._layoutScatter(opts) : layout === "arc" ? this._layoutArc(counts, opts) : layout === "custom" ? this._layoutCustom(counts, opts) : this._layoutGrouped(counts, opts);
|
|
1877
|
-
const gridSplit = layout === "grid" && !!(opts.grid && opts.grid.split);
|
|
1878
|
-
if (gridSplit) this._drawGridTrack(ret, graphics, opts);
|
|
1879
2201
|
if (layout === "scatter") this._drawScatterAxes(ret, graphics);
|
|
1880
2202
|
const dotR = this._lastDotR;
|
|
1881
2203
|
const animate = this._shouldAnimate();
|
|
@@ -1906,7 +2228,49 @@ class Unit {
|
|
|
1906
2228
|
const unitData = w.seriesData.unitData || [];
|
|
1907
2229
|
const sizeStats = this._bubbleStats(unitData, opts, dotR);
|
|
1908
2230
|
let gIndex = 0;
|
|
1909
|
-
|
|
2231
|
+
const seen = /* @__PURE__ */ new Map();
|
|
2232
|
+
const track = gridSplit && this._gridTrack && this._gridTrack.cells || [];
|
|
2233
|
+
const trackG = graphics.group({ class: "apexcharts-unit-track" });
|
|
2234
|
+
if (track.length) ret.add(trackG);
|
|
2235
|
+
const trackFill = opts.grid && opts.grid.trackColor || "rgba(128,128,128,0.14)";
|
|
2236
|
+
const trackSpec = this._baseSpec({ shape: opts.shape === "square" && "square" }, dotR);
|
|
2237
|
+
const perTile = track.length / Math.max(1, clusters.length);
|
|
2238
|
+
const live = this.ctx && this.ctx._unitSprings;
|
|
2239
|
+
const glide = (node, spec, x2, y, key, r2, at, pair) => {
|
|
2240
|
+
const from = prev && prev.get(key);
|
|
2241
|
+
const s2 = live && live.get(key);
|
|
2242
|
+
const still = from && from.x === x2 && from.y === y && from.r === r2 && (!s2 || s2.x.value === x2 && s2.y.value === y);
|
|
2243
|
+
nextPrev.set(key, { x: x2, y, fill: trackFill, r: r2, spec });
|
|
2244
|
+
if (prev && animate && !pieceTakeover && !still) {
|
|
2245
|
+
const cx0 = from ? from.x : x2;
|
|
2246
|
+
const cy0 = from ? from.y : y;
|
|
2247
|
+
node.style.opacity = from ? "1" : "0";
|
|
2248
|
+
this._place(node, spec, cx0, cy0);
|
|
2249
|
+
animDots.splice(at, 0, {
|
|
2250
|
+
node,
|
|
2251
|
+
spec,
|
|
2252
|
+
x: x2,
|
|
2253
|
+
y,
|
|
2254
|
+
cx0,
|
|
2255
|
+
cy0,
|
|
2256
|
+
key,
|
|
2257
|
+
r0: from && from.r != null ? from.r : r2,
|
|
2258
|
+
r1: r2,
|
|
2259
|
+
delay: 0,
|
|
2260
|
+
isEnter: !from,
|
|
2261
|
+
pair
|
|
2262
|
+
});
|
|
2263
|
+
} else {
|
|
2264
|
+
this._place(node, spec, x2, y);
|
|
2265
|
+
}
|
|
2266
|
+
};
|
|
2267
|
+
const ride2 = (k2, pair) => {
|
|
2268
|
+
const el = this._drawDot(graphics, opts, dotR, trackFill, -1, 0, trackSpec);
|
|
2269
|
+
el.node.classList.add("apexcharts-unit-track-cell");
|
|
2270
|
+
trackG.add(el);
|
|
2271
|
+
glide(el.node, trackSpec, track[k2].x, track[k2].y, "trk:" + k2, dotR, animDots.length, pair);
|
|
2272
|
+
};
|
|
2273
|
+
clusters.forEach((cluster, ci) => {
|
|
1910
2274
|
const color = w.globals.colors[cluster.i] || w.globals.colors[0] || "#008FFB";
|
|
1911
2275
|
const elSeries = graphics.group({
|
|
1912
2276
|
class: "apexcharts-series",
|
|
@@ -1918,7 +2282,9 @@ class Unit {
|
|
|
1918
2282
|
});
|
|
1919
2283
|
const burstCount = cluster.dots.length;
|
|
1920
2284
|
const catData = unitData[cluster.i];
|
|
2285
|
+
const at = animDots.length;
|
|
1921
2286
|
cluster.dots.forEach((d, jj) => {
|
|
2287
|
+
if (track.length) ride2(ci * perTile + jj, true);
|
|
1922
2288
|
const j2 = d.j != null ? d.j : jj;
|
|
1923
2289
|
const datum = catData ? catData[j2] : void 0;
|
|
1924
2290
|
const dotFill = datum && typeof datum === "object" && datum.fillColor ? datum.fillColor : color;
|
|
@@ -1929,7 +2295,7 @@ class Unit {
|
|
|
1929
2295
|
let key;
|
|
1930
2296
|
if (identity) {
|
|
1931
2297
|
const id = datum && typeof datum === "object" ? datum.id != null ? datum.id : datum.name : void 0;
|
|
1932
|
-
key = id != null ? `id:${id}` : `g:${gIndex}`;
|
|
2298
|
+
key = id != null ? `id:${uniqueId(seen, String(id))}` : `g:${gIndex}`;
|
|
1933
2299
|
} else if (flow) {
|
|
1934
2300
|
key = String(gIndex);
|
|
1935
2301
|
} else if (d.slot != null) {
|
|
@@ -1949,8 +2315,9 @@ class Unit {
|
|
|
1949
2315
|
const anchor = from || (morphActive ? morph.getInitialSlotFor(cluster.i, j2, burstCount) : null);
|
|
1950
2316
|
const enter = opts.gather && opts.gather.enter || "burst";
|
|
1951
2317
|
const inPlace = gridSplit || enter === "fade" || enter === "rise";
|
|
1952
|
-
const
|
|
1953
|
-
const
|
|
2318
|
+
const start = anchor || gridSplit && prev && prev.get("trk:" + d.slot);
|
|
2319
|
+
const cx0 = start ? start.x : inPlace ? d.x : cluster.cx;
|
|
2320
|
+
const cy0 = start ? start.y : enter === "rise" && !gridSplit ? d.y + 14 : inPlace ? d.y : cluster.cy;
|
|
1954
2321
|
el.node.style.opacity = anchor ? "1" : "0";
|
|
1955
2322
|
this._place(el.node, spec, cx0, cy0);
|
|
1956
2323
|
animDots.push({
|
|
@@ -1980,9 +2347,16 @@ class Unit {
|
|
|
1980
2347
|
this._place(el.node, spec, d.x, d.y);
|
|
1981
2348
|
}
|
|
1982
2349
|
});
|
|
2350
|
+
for (let k2 = cluster.dots.length; k2 < perTile; k2++) ride2(ci * perTile + k2, false);
|
|
1983
2351
|
if ((layout === "grouped" || layout === "columns" || gridSplit) && opts.clusterLabels && opts.clusterLabels.show && counts[cluster.i] > 0) {
|
|
1984
2352
|
const labelTotal = gridSplit ? this._gridDenom : total;
|
|
1985
|
-
this._drawClusterLabel(elSeries, cluster, counts[cluster.i], labelTotal, opts, color);
|
|
2353
|
+
const t2 = this._drawClusterLabel(elSeries, cluster, counts[cluster.i], labelTotal, opts, color);
|
|
2354
|
+
if (t2 && gridSplit) {
|
|
2355
|
+
const spec = { pk: PK_CORNER, hx: 0, hy: 0, r: 0 };
|
|
2356
|
+
const lx = +(t2.getAttribute("x") || 0);
|
|
2357
|
+
const ly = +(t2.getAttribute("y") || 0);
|
|
2358
|
+
glide(t2, spec, lx, ly, "lbl:" + cluster.i, 0, at, animDots.length > at);
|
|
2359
|
+
}
|
|
1986
2360
|
}
|
|
1987
2361
|
ret.add(elSeries);
|
|
1988
2362
|
});
|
|
@@ -2017,9 +2391,13 @@ class Unit {
|
|
|
2017
2391
|
const total = counts.reduce((a2, b) => a2 + b, 0);
|
|
2018
2392
|
if (!maxUnits || maxUnits <= 0 || total <= maxUnits) return counts;
|
|
2019
2393
|
const scale = maxUnits / total;
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2394
|
+
const ctx = this.ctx || {};
|
|
2395
|
+
if (!ctx._unitCapWarned) {
|
|
2396
|
+
ctx._unitCapWarned = true;
|
|
2397
|
+
console.warn(
|
|
2398
|
+
`[ApexCharts] unit chart: ${total} dots exceeds maxUnits (${maxUnits}); counts were scaled down proportionally. Raise plotOptions.unit.maxUnits or use plotOptions.unit.unitValue to represent more units per dot.`
|
|
2399
|
+
);
|
|
2400
|
+
}
|
|
2023
2401
|
return counts.map((c) => c > 0 ? Math.max(1, Math.round(c * scale)) : 0);
|
|
2024
2402
|
}
|
|
2025
2403
|
/**
|
|
@@ -2129,7 +2507,8 @@ class Unit {
|
|
|
2129
2507
|
*
|
|
2130
2508
|
* `id` is the datum's own id/name where the per-unit object form supplies
|
|
2131
2509
|
* one, so a provider can address a specific unit ("Texas", "employee 41")
|
|
2132
|
-
* rather than a positional slot. It falls back to `"<category>:<index>"
|
|
2510
|
+
* rather than a positional slot. It falls back to `"<category>:<index>"`, and
|
|
2511
|
+
* a repeated one is suffixed (`"Alex#2"`).
|
|
2133
2512
|
*
|
|
2134
2513
|
* @param {number[]} counts
|
|
2135
2514
|
* @param {number} dotR the radius the engine would use, so a provider that
|
|
@@ -2141,13 +2520,17 @@ class Unit {
|
|
|
2141
2520
|
const unitData = w.seriesData.unitData || [];
|
|
2142
2521
|
const names = w.seriesData.seriesNames || [];
|
|
2143
2522
|
const objects = [];
|
|
2523
|
+
const seen = /* @__PURE__ */ new Map();
|
|
2144
2524
|
let index = 0;
|
|
2145
2525
|
counts.forEach((n2, i2) => {
|
|
2146
2526
|
var _a;
|
|
2147
2527
|
const catData = unitData[i2];
|
|
2148
2528
|
for (let j2 = 0; j2 < n2; j2++) {
|
|
2149
2529
|
const datum = catData ? catData[j2] : void 0;
|
|
2150
|
-
const id =
|
|
2530
|
+
const id = uniqueId(
|
|
2531
|
+
seen,
|
|
2532
|
+
datum && typeof datum === "object" && (datum.id != null || datum.name != null) ? String(datum.id != null ? datum.id : datum.name) : `${i2}:${j2}`
|
|
2533
|
+
);
|
|
2151
2534
|
objects.push({
|
|
2152
2535
|
id,
|
|
2153
2536
|
index,
|
|
@@ -2331,11 +2714,18 @@ class Unit {
|
|
|
2331
2714
|
const pad = Math.min(gw, gh) * 0.04;
|
|
2332
2715
|
const boxW = Math.max(1e-6, b.maxX - b.minX);
|
|
2333
2716
|
const boxH = Math.max(1e-6, b.maxY - b.minY);
|
|
2334
|
-
const
|
|
2335
|
-
const
|
|
2717
|
+
const fit = (inset) => Math.max(4, Math.min((gw - 2 * pad - inset) / boxW, (gh - 2 * pad - inset) / boxH));
|
|
2718
|
+
const seat = (r2) => fit(2 * this._arcAllocate(total, r2 * innerRatio, r2, span, opts).dotR);
|
|
2719
|
+
let hi = fit(0);
|
|
2720
|
+
let r1 = seat(hi);
|
|
2721
|
+
for (let k2 = 0; k2 < 6; k2++) {
|
|
2722
|
+
const m = (r1 + hi) / 2;
|
|
2723
|
+
if (m <= seat(m)) r1 = m;
|
|
2724
|
+
else hi = m;
|
|
2725
|
+
}
|
|
2336
2726
|
const cx = gw / 2 - (b.minX + b.maxX) / 2 * r1;
|
|
2337
2727
|
const cy = gh / 2 - (b.minY + b.maxY) / 2 * r1;
|
|
2338
|
-
const alloc = this._arcAllocate(total,
|
|
2728
|
+
const alloc = this._arcAllocate(total, r1 * innerRatio, r1, span, opts);
|
|
2339
2729
|
this._lastDotR = alloc.dotR;
|
|
2340
2730
|
const seats = [];
|
|
2341
2731
|
for (let r2 = 0; r2 < alloc.R; r2++) {
|
|
@@ -2619,7 +3009,7 @@ class Unit {
|
|
|
2619
3009
|
* value over a denominator (`grid.max`, else the largest count so the leader
|
|
2620
3010
|
* fills its tile and every other tile stays proportionally full - no empty
|
|
2621
3011
|
* tiles for arbitrary data). The unfilled cells are drawn as a faint TRACK
|
|
2622
|
-
* backdrop (
|
|
3012
|
+
* backdrop (drawn by draw()) so each tile reads as a part-to-whole "of N".
|
|
2623
3013
|
* Only VISIBLE (non-zero) categories claim a tile, so a legend hide drops the
|
|
2624
3014
|
* tile and the rest re-flow. Each filled cell is keyed by a physical
|
|
2625
3015
|
* `tile*cells + localCell` slot, so a value change grows/shrinks a tile's fill
|
|
@@ -2637,7 +3027,7 @@ class Unit {
|
|
|
2637
3027
|
const rowsPerTile = Math.max(1, Math.ceil(cellsPerTile / cols));
|
|
2638
3028
|
const visible = counts.map((_2, i2) => i2).filter((i2) => counts[i2] > 0);
|
|
2639
3029
|
const K2 = Math.max(1, visible.length);
|
|
2640
|
-
const denom = gcfg.max > 0 ? gcfg.max : Math.max(
|
|
3030
|
+
const denom = gcfg.max > 0 ? gcfg.max : Math.max(...counts) || 1;
|
|
2641
3031
|
const tileCols = Math.max(
|
|
2642
3032
|
1,
|
|
2643
3033
|
Math.round(gcfg.tileColumns > 0 ? gcfg.tileColumns : Math.ceil(Math.sqrt(K2)))
|
|
@@ -2702,40 +3092,6 @@ class Unit {
|
|
|
2702
3092
|
this._gridTrack = { cells: track };
|
|
2703
3093
|
return clusters;
|
|
2704
3094
|
}
|
|
2705
|
-
/**
|
|
2706
|
-
* Draw the faint "track" backdrop for the small-multiple grid: every cell of
|
|
2707
|
-
* every tile's full lattice, so the filled (coloured) cells drawn on top read
|
|
2708
|
-
* as a fraction of the whole. Static (redrawn each render, never animated);
|
|
2709
|
-
* painted BEHIND the series groups. `grid.trackColor` overrides the default
|
|
2710
|
-
* theme-neutral grey.
|
|
2711
|
-
* @param {any} ret @param {Graphics} graphics @param {any} opts
|
|
2712
|
-
*/
|
|
2713
|
-
_drawGridTrack(ret, graphics, opts) {
|
|
2714
|
-
const track = this._gridTrack;
|
|
2715
|
-
if (!track || !track.cells || !track.cells.length) return;
|
|
2716
|
-
const r2 = this._lastDotR;
|
|
2717
|
-
const gcfg = opts.grid || {};
|
|
2718
|
-
const trackColor = gcfg.trackColor || "rgba(128,128,128,0.14)";
|
|
2719
|
-
const g = graphics.group({ class: "apexcharts-unit-track" });
|
|
2720
|
-
track.cells.forEach((c) => {
|
|
2721
|
-
let el;
|
|
2722
|
-
if (opts.shape === "square") {
|
|
2723
|
-
const side = r2 * 2;
|
|
2724
|
-
el = graphics.drawRect(0, 0, side, side, opts.borderRadius || 0, trackColor, 1, 0, "none");
|
|
2725
|
-
el.node.setAttribute("fill", trackColor);
|
|
2726
|
-
el.node.setAttribute("x", String(c.x - r2));
|
|
2727
|
-
el.node.setAttribute("y", String(c.y - r2));
|
|
2728
|
-
} else {
|
|
2729
|
-
el = graphics.drawCircle(r2, { fill: trackColor, "stroke-width": 0, stroke: "none" });
|
|
2730
|
-
el.node.setAttribute("fill", trackColor);
|
|
2731
|
-
el.node.setAttribute("cx", String(c.x));
|
|
2732
|
-
el.node.setAttribute("cy", String(c.y));
|
|
2733
|
-
}
|
|
2734
|
-
el.node.classList.add("apexcharts-unit-track-cell");
|
|
2735
|
-
g.add(el);
|
|
2736
|
-
});
|
|
2737
|
-
ret.add(g);
|
|
2738
|
-
}
|
|
2739
3095
|
/**
|
|
2740
3096
|
* Scatter / beeswarm layout: position every unit on a real numeric X value
|
|
2741
3097
|
* axis by its own value (`_unitValueOf`), laned by category on Y. Within a
|
|
@@ -2750,11 +3106,14 @@ class Unit {
|
|
|
2750
3106
|
_layoutScatter(opts) {
|
|
2751
3107
|
const w = this.w;
|
|
2752
3108
|
const scfg = opts.scatter || {};
|
|
2753
|
-
|
|
2754
|
-
|
|
3109
|
+
const unitData = w.seriesData.unitData || [];
|
|
3110
|
+
const lens = unitData.map((c) => c ? c.length : 0);
|
|
3111
|
+
const caps = this._applyMaxUnits(lens, opts.maxUnits);
|
|
3112
|
+
const keep = (ci, j2) => Math.floor((j2 + 1) * caps[ci] / lens[ci]) > Math.floor(j2 * caps[ci] / lens[ci]);
|
|
3113
|
+
if (scfg.y === "value") return this._layoutScatter2D(opts, keep);
|
|
3114
|
+
if (scfg.orientation === "vertical") return this._layoutScatterVertical(opts, keep);
|
|
2755
3115
|
const gw = w.layout.gridWidth;
|
|
2756
3116
|
const gh = w.layout.gridHeight;
|
|
2757
|
-
const unitData = w.seriesData.unitData || [];
|
|
2758
3117
|
const names = w.seriesData.seriesNames || [];
|
|
2759
3118
|
const valueOf2 = (d) => this._unitValueOf(d);
|
|
2760
3119
|
const sizeStats = this._scatterSizeStats(scfg, unitData);
|
|
@@ -2779,11 +3138,13 @@ class Unit {
|
|
|
2779
3138
|
vmax = 1;
|
|
2780
3139
|
}
|
|
2781
3140
|
const tickAmount = Math.max(2, Math.round(scfg.tickAmount > 0 ? scfg.tickAmount : 5));
|
|
2782
|
-
const domain = this._scatterValueDomain(scfg, vmin, vmax, tickAmount);
|
|
3141
|
+
const domain = this._scatterValueDomain(scfg.xMin, scfg.xMax, vmin, vmax, tickAmount);
|
|
2783
3142
|
const xMin = domain.min;
|
|
2784
3143
|
const xMax = domain.max;
|
|
2785
3144
|
const xSpan = xMax - xMin || 1;
|
|
2786
|
-
const
|
|
3145
|
+
const font = { fontFamily: w.config.chart.fontFamily, fontWeight: 600 };
|
|
3146
|
+
const laneName = (i2) => names[i2] || `series-${i2 + 1}`;
|
|
3147
|
+
const laneW = scfg.laneLabelWidth != null ? Math.max(0, scfg.laneLabelWidth) : Kv > 1 ? Math.min(gw / 3, measureLabelWidth(w, visible.map(laneName), font) + 14) : 8;
|
|
2787
3148
|
const bottomGutter = 30 + (scfg.xTitle ? 20 : 0);
|
|
2788
3149
|
const plotL = laneW;
|
|
2789
3150
|
const plotR = gw - 8;
|
|
@@ -2817,19 +3178,24 @@ class Unit {
|
|
|
2817
3178
|
const maxR = sizeStats ? sizeStats.rMax : r2;
|
|
2818
3179
|
visible.forEach((ci, slot) => {
|
|
2819
3180
|
const cy = laneCy(slot);
|
|
2820
|
-
|
|
2821
|
-
const
|
|
2822
|
-
|
|
3181
|
+
let name = laneName(ci);
|
|
3182
|
+
const wid = laneW > 12 ? measureLabelWidth(w, [name], font) : 0;
|
|
3183
|
+
if (wid > laneW - 14 && wid) {
|
|
3184
|
+
name = name.slice(0, Math.max(1, Math.floor(name.length * (laneW - 14) / wid) - 1)) + "…";
|
|
3185
|
+
}
|
|
3186
|
+
lanes2.push({ i: ci, cy, name });
|
|
3187
|
+
const pts = [];
|
|
3188
|
+
(unitData[ci] || []).forEach((d, j2) => {
|
|
2823
3189
|
const v = valueOf2(d);
|
|
2824
|
-
|
|
3190
|
+
if (!isNum(v) || !keep(ci, j2)) return;
|
|
3191
|
+
const p = { j: j2, px: plotX(v), y: cy };
|
|
2825
3192
|
if (sizeStats) p.r = this._scatterRadius(d, sizeStats, r2);
|
|
2826
|
-
|
|
3193
|
+
pts.push(p);
|
|
2827
3194
|
});
|
|
2828
3195
|
if (jitter) {
|
|
2829
3196
|
const halfLane = Math.max(maxR, laneH / 2 - maxR);
|
|
2830
|
-
pts.forEach((p
|
|
2831
|
-
|
|
2832
|
-
p.y = cy + (t2 * 2 - 1) * halfLane;
|
|
3197
|
+
pts.forEach((p) => {
|
|
3198
|
+
p.y = cy + (hash01(ci * 7919 + p.j) * 2 - 1) * halfLane;
|
|
2833
3199
|
});
|
|
2834
3200
|
} else {
|
|
2835
3201
|
this._beeswarm(pts, cy, r2, step, maxR);
|
|
@@ -2839,7 +3205,7 @@ class Unit {
|
|
|
2839
3205
|
cx: (plotL + plotR) / 2,
|
|
2840
3206
|
cy,
|
|
2841
3207
|
outerR: laneH / 2,
|
|
2842
|
-
dots: pts.map((p) => ({ x: p.px, y: p.y, r: p.r }))
|
|
3208
|
+
dots: pts.map((p) => ({ x: p.px, y: p.y, r: p.r, j: p.j }))
|
|
2843
3209
|
});
|
|
2844
3210
|
});
|
|
2845
3211
|
const ticks = domain.ticks;
|
|
@@ -2866,9 +3232,9 @@ class Unit {
|
|
|
2866
3232
|
* dots horizontally off each column's centre line. The value-axis config keys
|
|
2867
3233
|
* (`xMin`/`xMax`/`xTitle`/`xFormatter`/`tickAmount`) still describe the value
|
|
2868
3234
|
* axis (now Y), so flipping `orientation` keeps the same value settings.
|
|
2869
|
-
* @param {any} opts
|
|
3235
|
+
* @param {any} opts @param {(ci:number, j:number) => boolean} keep
|
|
2870
3236
|
*/
|
|
2871
|
-
_layoutScatterVertical(opts) {
|
|
3237
|
+
_layoutScatterVertical(opts, keep) {
|
|
2872
3238
|
const w = this.w;
|
|
2873
3239
|
const scfg = opts.scatter || {};
|
|
2874
3240
|
const gw = w.layout.gridWidth;
|
|
@@ -2898,7 +3264,7 @@ class Unit {
|
|
|
2898
3264
|
vmax = 1;
|
|
2899
3265
|
}
|
|
2900
3266
|
const tickAmount = Math.max(2, Math.round(scfg.tickAmount > 0 ? scfg.tickAmount : 5));
|
|
2901
|
-
const domain = this._scatterValueDomain(scfg, vmin, vmax, tickAmount);
|
|
3267
|
+
const domain = this._scatterValueDomain(scfg.xMin, scfg.xMax, vmin, vmax, tickAmount);
|
|
2902
3268
|
const vMin = domain.min;
|
|
2903
3269
|
const vMax = domain.max;
|
|
2904
3270
|
const vSpan = vMax - vMin || 1;
|
|
@@ -2937,18 +3303,18 @@ class Unit {
|
|
|
2937
3303
|
visible.forEach((ci, slot) => {
|
|
2938
3304
|
const cx = laneCx(slot);
|
|
2939
3305
|
lanes2.push({ i: ci, cx, name: names[ci] || `series-${ci + 1}` });
|
|
2940
|
-
const
|
|
2941
|
-
|
|
3306
|
+
const pts = [];
|
|
3307
|
+
(unitData[ci] || []).forEach((d, j2) => {
|
|
2942
3308
|
const v = valueOf2(d);
|
|
2943
|
-
|
|
3309
|
+
if (!isNum(v) || !keep(ci, j2)) return;
|
|
3310
|
+
const p = { j: j2, py: plotY(v), x: cx };
|
|
2944
3311
|
if (sizeStats) p.r = this._scatterRadius(d, sizeStats, r2);
|
|
2945
|
-
|
|
3312
|
+
pts.push(p);
|
|
2946
3313
|
});
|
|
2947
3314
|
if (jitter) {
|
|
2948
3315
|
const halfLane = Math.max(maxR, laneW / 2 - maxR);
|
|
2949
|
-
pts.forEach((p
|
|
2950
|
-
|
|
2951
|
-
p.x = cx + (t2 * 2 - 1) * halfLane;
|
|
3316
|
+
pts.forEach((p) => {
|
|
3317
|
+
p.x = cx + (hash01(ci * 7919 + p.j) * 2 - 1) * halfLane;
|
|
2952
3318
|
});
|
|
2953
3319
|
} else {
|
|
2954
3320
|
this._beeswarm(pts, cx, r2, step, maxR, true);
|
|
@@ -2958,7 +3324,7 @@ class Unit {
|
|
|
2958
3324
|
cx,
|
|
2959
3325
|
cy: (plotT + plotB) / 2,
|
|
2960
3326
|
outerR: laneW / 2,
|
|
2961
|
-
dots: pts.map((p) => ({ x: p.x, y: p.py, r: p.r }))
|
|
3327
|
+
dots: pts.map((p) => ({ x: p.x, y: p.py, r: p.r, j: p.j }))
|
|
2962
3328
|
});
|
|
2963
3329
|
});
|
|
2964
3330
|
const ticks = domain.ticks;
|
|
@@ -2987,17 +3353,17 @@ class Unit {
|
|
|
2987
3353
|
* per category). With `scatter.sizeRange` set, each dot is a BUBBLE scaled (by
|
|
2988
3354
|
* area) from its `sizeField` (default 'z'). Needs the object form with numeric
|
|
2989
3355
|
* `x` + `y`.
|
|
2990
|
-
* @param {any} opts
|
|
3356
|
+
* @param {any} opts @param {(ci:number, j:number) => boolean} keep
|
|
2991
3357
|
*/
|
|
2992
|
-
_layoutScatter2D(opts) {
|
|
3358
|
+
_layoutScatter2D(opts, keep) {
|
|
2993
3359
|
const w = this.w;
|
|
2994
3360
|
const gw = w.layout.gridWidth;
|
|
2995
3361
|
const gh = w.layout.gridHeight;
|
|
2996
3362
|
const scfg = opts.scatter || {};
|
|
2997
3363
|
const unitData = w.seriesData.unitData || [];
|
|
2998
|
-
const isNum = (v) =>
|
|
2999
|
-
const xOf = (d) => d && typeof d === "object" ? d.x : null;
|
|
3000
|
-
const yOf = (d) => d && typeof d === "object" ? d.y != null ? d.y : d.value : null;
|
|
3364
|
+
const isNum = (v) => v != null;
|
|
3365
|
+
const xOf = (d) => d && typeof d === "object" ? toNum(d.x) : null;
|
|
3366
|
+
const yOf = (d) => d && typeof d === "object" ? toNum(d.y != null ? d.y : d.value) : null;
|
|
3001
3367
|
const visible = unitData.map((_2, i2) => i2).filter(
|
|
3002
3368
|
(i2) => (unitData[i2] || []).some((d) => isNum(xOf(d)) && isNum(yOf(d)))
|
|
3003
3369
|
);
|
|
@@ -3023,22 +3389,24 @@ class Unit {
|
|
|
3023
3389
|
ymn = 0;
|
|
3024
3390
|
ymx = 1;
|
|
3025
3391
|
}
|
|
3026
|
-
const
|
|
3027
|
-
|
|
3028
|
-
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
|
|
3392
|
+
const dx = this._scatterValueDomain(
|
|
3393
|
+
scfg.xMin,
|
|
3394
|
+
scfg.xMax,
|
|
3395
|
+
xmn,
|
|
3396
|
+
xmx,
|
|
3397
|
+
Math.max(2, Math.round(scfg.tickAmount > 0 ? scfg.tickAmount : 5))
|
|
3032
3398
|
);
|
|
3033
|
-
const
|
|
3034
|
-
scfg.yMin
|
|
3035
|
-
scfg.yMax
|
|
3036
|
-
|
|
3399
|
+
const dy = this._scatterValueDomain(
|
|
3400
|
+
scfg.yMin,
|
|
3401
|
+
scfg.yMax,
|
|
3402
|
+
ymn,
|
|
3403
|
+
ymx,
|
|
3404
|
+
Math.max(2, Math.round(scfg.yTickAmount > 0 ? scfg.yTickAmount : 5))
|
|
3037
3405
|
);
|
|
3038
|
-
const xMin =
|
|
3039
|
-
const xMax =
|
|
3040
|
-
const yMin =
|
|
3041
|
-
const yMax =
|
|
3406
|
+
const xMin = dx.min;
|
|
3407
|
+
const xMax = dx.max;
|
|
3408
|
+
const yMin = dy.min;
|
|
3409
|
+
const yMax = dy.max;
|
|
3042
3410
|
const xSpan = xMax - xMin || 1;
|
|
3043
3411
|
const ySpan = yMax - yMin || 1;
|
|
3044
3412
|
const leftGutter = 46 + (scfg.yTitle ? 18 : 0);
|
|
@@ -3056,15 +3424,17 @@ class Unit {
|
|
|
3056
3424
|
this._lastDotR = baseR;
|
|
3057
3425
|
const clusters = [];
|
|
3058
3426
|
visible.forEach((ci) => {
|
|
3059
|
-
const
|
|
3060
|
-
|
|
3427
|
+
const dots = [];
|
|
3428
|
+
(unitData[ci] || []).forEach((d, j2) => {
|
|
3061
3429
|
const x2 = xOf(d);
|
|
3062
3430
|
const y = yOf(d);
|
|
3063
|
-
return
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
|
|
3067
|
-
|
|
3431
|
+
if (x2 == null || y == null || !keep(ci, j2)) return;
|
|
3432
|
+
dots.push({
|
|
3433
|
+
x: plotX(x2),
|
|
3434
|
+
y: plotY(y),
|
|
3435
|
+
r: sizeStats ? this._scatterRadius(d, sizeStats, baseR) : void 0,
|
|
3436
|
+
j: j2
|
|
3437
|
+
});
|
|
3068
3438
|
});
|
|
3069
3439
|
clusters.push({
|
|
3070
3440
|
i: ci,
|
|
@@ -3074,18 +3444,6 @@ class Unit {
|
|
|
3074
3444
|
dots
|
|
3075
3445
|
});
|
|
3076
3446
|
});
|
|
3077
|
-
const mkTicks = (lo, hi, span, spacing, pinned, n2) => {
|
|
3078
|
-
const out = [];
|
|
3079
|
-
if (pinned) {
|
|
3080
|
-
for (let k2 = 0; k2 < n2; k2++) out.push(lo + span * k2 / (n2 - 1));
|
|
3081
|
-
} else {
|
|
3082
|
-
const sp = spacing || span / Math.max(1, n2 - 1);
|
|
3083
|
-
for (let v = lo; v <= hi + sp * 0.5; v += sp) {
|
|
3084
|
-
out.push(Math.abs(v) < sp * 1e-9 ? 0 : v);
|
|
3085
|
-
}
|
|
3086
|
-
}
|
|
3087
|
-
return out;
|
|
3088
|
-
};
|
|
3089
3447
|
this._scatterAxis = {
|
|
3090
3448
|
mode: "2d",
|
|
3091
3449
|
plotL,
|
|
@@ -3094,22 +3452,8 @@ class Unit {
|
|
|
3094
3452
|
plotB,
|
|
3095
3453
|
plotX,
|
|
3096
3454
|
plotY,
|
|
3097
|
-
xTicks:
|
|
3098
|
-
|
|
3099
|
-
xMax,
|
|
3100
|
-
xSpan,
|
|
3101
|
-
nx.spacing,
|
|
3102
|
-
scfg.xMin != null || scfg.xMax != null,
|
|
3103
|
-
xTicksN
|
|
3104
|
-
),
|
|
3105
|
-
yTicks: mkTicks(
|
|
3106
|
-
yMin,
|
|
3107
|
-
yMax,
|
|
3108
|
-
ySpan,
|
|
3109
|
-
ny.spacing,
|
|
3110
|
-
scfg.yMin != null || scfg.yMax != null,
|
|
3111
|
-
yTicksN
|
|
3112
|
-
),
|
|
3455
|
+
xTicks: dx.ticks,
|
|
3456
|
+
yTicks: dy.ticks,
|
|
3113
3457
|
xTitle: scfg.xTitle,
|
|
3114
3458
|
yTitle: scfg.yTitle,
|
|
3115
3459
|
xFormatter: typeof scfg.xFormatter === "function" ? scfg.xFormatter : null,
|
|
@@ -3216,32 +3560,43 @@ class Unit {
|
|
|
3216
3560
|
});
|
|
3217
3561
|
}
|
|
3218
3562
|
/**
|
|
3219
|
-
* Value-axis domain + ticks for a
|
|
3563
|
+
* Value-axis domain + ticks for a scatter axis. The domain ALWAYS contains
|
|
3220
3564
|
* every datum: a swarm that clips a dot outside the plot box is a bug, so an
|
|
3221
|
-
* explicit `
|
|
3565
|
+
* explicit `lo`/`hi` only FRAMES the axis and is extended by whole
|
|
3222
3566
|
* tick-steps whenever the data would otherwise overflow. Orientation-agnostic:
|
|
3223
3567
|
* the same value axis is X for a horizontal swarm and Y for a vertical one.
|
|
3224
|
-
* @param {
|
|
3568
|
+
* @param {number|undefined} lo pinned minimum @param {number|undefined} hi
|
|
3569
|
+
* pinned maximum
|
|
3225
3570
|
* @param {number} vmin data minimum @param {number} vmax data maximum
|
|
3226
3571
|
* @param {number} tickAmount desired tick count
|
|
3227
3572
|
* @returns {{ min:number, max:number, ticks:number[] }}
|
|
3228
3573
|
*/
|
|
3229
|
-
_scatterValueDomain(
|
|
3574
|
+
_scatterValueDomain(lo, hi, vmin, vmax, tickAmount) {
|
|
3230
3575
|
const buildTicks = (min, max, spacing2) => {
|
|
3231
3576
|
const ticks = [];
|
|
3232
|
-
for (let v = min; v <= max + spacing2 * 0.5; v
|
|
3577
|
+
for (let k2 = 0, v = min; v <= max + spacing2 * 0.5; v = min + ++k2 * spacing2) {
|
|
3233
3578
|
ticks.push(Math.abs(v) < spacing2 * 1e-9 ? 0 : v);
|
|
3234
3579
|
}
|
|
3235
3580
|
return ticks;
|
|
3236
3581
|
};
|
|
3237
|
-
if (
|
|
3238
|
-
let min =
|
|
3239
|
-
|
|
3240
|
-
|
|
3241
|
-
|
|
3582
|
+
if (lo != null || hi != null) {
|
|
3583
|
+
let min = (
|
|
3584
|
+
/** @type {number} */
|
|
3585
|
+
lo != null ? lo : hi
|
|
3586
|
+
);
|
|
3587
|
+
let max = (
|
|
3588
|
+
/** @type {number} */
|
|
3589
|
+
hi != null ? hi : lo
|
|
3590
|
+
);
|
|
3591
|
+
const spacing2 = max > min ? (max - min) / Math.max(1, tickAmount - 1) : this._niceScale(Math.min(min, vmin), Math.max(max, vmax), tickAmount).spacing;
|
|
3242
3592
|
if (vmin < min) min -= Math.ceil((min - vmin) / spacing2) * spacing2;
|
|
3243
3593
|
if (vmax > max) max += Math.ceil((vmax - max) / spacing2) * spacing2;
|
|
3244
|
-
|
|
3594
|
+
if (!(max > min)) max = min + spacing2;
|
|
3595
|
+
if ((max - min) / spacing2 <= 2 * tickAmount) {
|
|
3596
|
+
return { min, max, ticks: buildTicks(min, max, spacing2) };
|
|
3597
|
+
}
|
|
3598
|
+
vmin = min;
|
|
3599
|
+
vmax = max;
|
|
3245
3600
|
}
|
|
3246
3601
|
const nice = this._niceScale(vmin, vmax, tickAmount);
|
|
3247
3602
|
const spacing = nice.spacing || (nice.max - nice.min) / Math.max(1, tickAmount - 1);
|
|
@@ -3332,13 +3687,13 @@ class Unit {
|
|
|
3332
3687
|
ax.yTicks.forEach((v) => {
|
|
3333
3688
|
const y = ax.plotY(v);
|
|
3334
3689
|
if (ax.gridlines) line(ax.plotL, y, ax.plotR, y, gridColor);
|
|
3335
|
-
const label2 = ax.yFormatter ? String(ax.yFormatter(v)) : this._formatTick(v);
|
|
3690
|
+
const label2 = ax.yFormatter ? String(ax.yFormatter(v)) : this._formatTick(v, ax.yTicks);
|
|
3336
3691
|
text(label2, ax.plotL - 8, y, "end", labelColor, 11, 400, "apexcharts-unit-tick");
|
|
3337
3692
|
});
|
|
3338
3693
|
ax.xTicks.forEach((v) => {
|
|
3339
3694
|
const x2 = ax.plotX(v);
|
|
3340
3695
|
if (ax.gridlines) line(x2, ax.plotT, x2, ax.plotB, gridColor);
|
|
3341
|
-
const label2 = ax.xFormatter ? String(ax.xFormatter(v)) : this._formatTick(v);
|
|
3696
|
+
const label2 = ax.xFormatter ? String(ax.xFormatter(v)) : this._formatTick(v, ax.xTicks);
|
|
3342
3697
|
text(label2, x2, ax.plotB + 14, "middle", labelColor, 11, 400, "apexcharts-unit-tick");
|
|
3343
3698
|
});
|
|
3344
3699
|
line(ax.plotL, ax.plotB, ax.plotR, ax.plotB, axisColor);
|
|
@@ -3378,7 +3733,7 @@ class Unit {
|
|
|
3378
3733
|
ax.ticks.forEach((v) => {
|
|
3379
3734
|
const y = ax.plotY(v);
|
|
3380
3735
|
if (ax.gridlines) line(ax.plotL, y, ax.plotR, y, gridColor);
|
|
3381
|
-
const label2 = ax.formatter ? String(ax.formatter(v)) : this._formatTick(v);
|
|
3736
|
+
const label2 = ax.formatter ? String(ax.formatter(v)) : this._formatTick(v, ax.ticks);
|
|
3382
3737
|
text(label2, ax.plotL - 8, y, "end", labelColor, 11, 400, "apexcharts-unit-tick");
|
|
3383
3738
|
});
|
|
3384
3739
|
line(ax.plotL, ax.plotT, ax.plotL, ax.plotB, axisColor);
|
|
@@ -3408,7 +3763,7 @@ class Unit {
|
|
|
3408
3763
|
ax.ticks.forEach((v, idx) => {
|
|
3409
3764
|
const x2 = ax.plotX(v);
|
|
3410
3765
|
if (ax.gridlines) line(x2, ax.plotT, x2, ax.plotB, gridColor);
|
|
3411
|
-
const label2 = ax.formatter ? String(ax.formatter(v)) : this._formatTick(v);
|
|
3766
|
+
const label2 = ax.formatter ? String(ax.formatter(v)) : this._formatTick(v, ax.ticks);
|
|
3412
3767
|
const anchor = idx === 0 ? "start" : idx === ax.ticks.length - 1 ? "end" : "middle";
|
|
3413
3768
|
text(label2, x2, ax.plotB + 14, anchor, labelColor, 11, 400, "apexcharts-unit-tick");
|
|
3414
3769
|
});
|
|
@@ -3434,17 +3789,19 @@ class Unit {
|
|
|
3434
3789
|
ret.add(g);
|
|
3435
3790
|
}
|
|
3436
3791
|
/**
|
|
3437
|
-
* Compact tick-value formatting: integers as-is, otherwise trimmed to
|
|
3438
|
-
*
|
|
3439
|
-
* @param {number} v @
|
|
3792
|
+
* Compact tick-value formatting: integers as-is, otherwise trimmed to enough
|
|
3793
|
+
* decimals to tell neighbouring ticks apart; large magnitudes get a k/M suffix.
|
|
3794
|
+
* @param {number} v @param {number[]} ticks the axis ticks (their step sets
|
|
3795
|
+
* the decimals) @returns {string}
|
|
3440
3796
|
*/
|
|
3441
|
-
_formatTick(v) {
|
|
3797
|
+
_formatTick(v, ticks) {
|
|
3442
3798
|
if (!isFinite(v)) return "";
|
|
3443
3799
|
const a2 = Math.abs(v);
|
|
3444
3800
|
if (a2 >= 1e6) return `${+(v / 1e6).toFixed(1)}M`;
|
|
3445
3801
|
if (a2 >= 1e4) return `${+(v / 1e3).toFixed(1)}k`;
|
|
3446
3802
|
if (Number.isInteger(v)) return String(v);
|
|
3447
|
-
|
|
3803
|
+
const step = Math.abs(ticks[1] - ticks[0]) || 1;
|
|
3804
|
+
return String(+v.toFixed(Math.min(20, Math.max(2, 1 - Math.floor(Math.log10(step))))));
|
|
3448
3805
|
}
|
|
3449
3806
|
/**
|
|
3450
3807
|
* Distribute `total` whole cells across `counts` in proportion to each value,
|
|
@@ -3509,17 +3866,12 @@ class Unit {
|
|
|
3509
3866
|
return !!(sbv && sbv.enabled && opts.shape !== "image" && opts.shape !== "square");
|
|
3510
3867
|
}
|
|
3511
3868
|
/**
|
|
3512
|
-
* This datum's numeric value for sizing / tooltip: the number
|
|
3513
|
-
* object's `value` / `y`. Null when there is
|
|
3869
|
+
* This datum's numeric value for sizing / tooltip: the number (or numeric
|
|
3870
|
+
* string) itself, or an object's `value` / `y`. Null when there is none.
|
|
3514
3871
|
* @param {any} d @returns {number | null}
|
|
3515
3872
|
*/
|
|
3516
3873
|
_unitValueOf(d) {
|
|
3517
|
-
|
|
3518
|
-
if (d && typeof d === "object") {
|
|
3519
|
-
const v = d.value != null ? d.value : d.y;
|
|
3520
|
-
return typeof v === "number" ? v : null;
|
|
3521
|
-
}
|
|
3522
|
-
return null;
|
|
3874
|
+
return toNum(d && typeof d === "object" ? d.value != null ? d.value : d.y : d);
|
|
3523
3875
|
}
|
|
3524
3876
|
/**
|
|
3525
3877
|
* Radius for one bubble given the value stats. Default 'area' scaling makes
|
|
@@ -3661,8 +4013,9 @@ class Unit {
|
|
|
3661
4013
|
*
|
|
3662
4014
|
* @param {SVGElement} node @param {UnitMarkSpec} spec
|
|
3663
4015
|
* @param {number} x @param {number} y
|
|
4016
|
+
* @param {number} [k] scale against the spec's size, while a size tweens
|
|
3664
4017
|
*/
|
|
3665
|
-
_place(node, spec, x2, y) {
|
|
4018
|
+
_place(node, spec, x2, y, k2 = 1) {
|
|
3666
4019
|
const s2 = (
|
|
3667
4020
|
/** @type {any} */
|
|
3668
4021
|
spec
|
|
@@ -3670,16 +4023,31 @@ class Unit {
|
|
|
3670
4023
|
if (s2.pk === PK_GLYPH) {
|
|
3671
4024
|
node.setAttribute(
|
|
3672
4025
|
"transform",
|
|
3673
|
-
"translate(" + (x2 - s2.ox) + "," + (y - s2.oy) + s2.tail
|
|
4026
|
+
"translate(" + (x2 - s2.ox * k2) + "," + (y - s2.oy * k2) + (k2 === 1 ? s2.tail : ") scale(" + s2.s * k2 + ")")
|
|
3674
4027
|
);
|
|
3675
4028
|
} else if (s2.pk === PK_CORNER) {
|
|
3676
|
-
node.setAttribute("x", String(x2 - s2.hx));
|
|
3677
|
-
node.setAttribute("y", String(y - s2.hy));
|
|
4029
|
+
node.setAttribute("x", String(x2 - s2.hx * k2));
|
|
4030
|
+
node.setAttribute("y", String(y - s2.hy * k2));
|
|
3678
4031
|
} else {
|
|
3679
4032
|
node.setAttribute("cx", String(x2));
|
|
3680
4033
|
node.setAttribute("cy", String(y));
|
|
3681
4034
|
}
|
|
3682
4035
|
}
|
|
4036
|
+
/**
|
|
4037
|
+
* Size one mark at `k` times its spec's size (a glyph scales in `_place`).
|
|
4038
|
+
* @param {SVGElement} node @param {UnitMarkSpec} spec @param {number} k
|
|
4039
|
+
*/
|
|
4040
|
+
_size(node, spec, k2) {
|
|
4041
|
+
const s2 = (
|
|
4042
|
+
/** @type {any} */
|
|
4043
|
+
spec
|
|
4044
|
+
);
|
|
4045
|
+
if (s2.pk === PK_CIRCLE) node.setAttribute("r", String(s2.r * k2));
|
|
4046
|
+
else if (s2.pk === PK_CORNER) {
|
|
4047
|
+
node.setAttribute("width", String(2 * s2.hx * k2));
|
|
4048
|
+
node.setAttribute("height", String(2 * s2.hy * k2));
|
|
4049
|
+
}
|
|
4050
|
+
}
|
|
3683
4051
|
/**
|
|
3684
4052
|
* The spec for the chart-wide shape (no pictogram, no per-mark radius).
|
|
3685
4053
|
* @param {any} opts @param {number} [r]
|
|
@@ -3738,7 +4106,7 @@ class Unit {
|
|
|
3738
4106
|
*/
|
|
3739
4107
|
_glyphSpec(mark, dotR, pcfg) {
|
|
3740
4108
|
const qr = Math.round(dotR * 10) / 10;
|
|
3741
|
-
const key = mark.name +
|
|
4109
|
+
const key = mark.name + mark.path + mark.viewBox + mark.fillRule + qr;
|
|
3742
4110
|
const hit = this._specCache.get(key);
|
|
3743
4111
|
if (hit) return hit;
|
|
3744
4112
|
const vb = mark.viewBox || [0, 0, 100, 100];
|
|
@@ -3787,9 +4155,9 @@ class Unit {
|
|
|
3787
4155
|
* Draw one dot (circle, square, or image icon) with the category fill +
|
|
3788
4156
|
* stroke, tagged so the shared non-axis tooltip and hover reuse work.
|
|
3789
4157
|
* @param {Graphics} graphics @param {any} opts @param {number} dotR
|
|
3790
|
-
* @param {string} color @param {number} i @param {number} j
|
|
3791
|
-
*
|
|
3792
|
-
*
|
|
4158
|
+
* @param {string} color @param {number} i @param {number} j (i < 0: an exit
|
|
4159
|
+
* ghost, left untagged so tooltips and morph capture skip it)
|
|
4160
|
+
* @param {UnitMarkSpec} spec this mark's resolved spec
|
|
3793
4161
|
* @returns {any}
|
|
3794
4162
|
*/
|
|
3795
4163
|
_drawDot(graphics, opts, dotR, color, i2, j2, spec) {
|
|
@@ -3798,7 +4166,7 @@ class Unit {
|
|
|
3798
4166
|
const strokeColor = Array.isArray(w.globals.stroke.colors) ? w.globals.stroke.colors[i2] || "none" : "none";
|
|
3799
4167
|
const fillOpacity = typeof w.config.fill.opacity === "number" ? w.config.fill.opacity : 1;
|
|
3800
4168
|
let el;
|
|
3801
|
-
if (spec
|
|
4169
|
+
if (spec.pk === PK_GLYPH) {
|
|
3802
4170
|
el = w.dom.Paper.path(spec.d);
|
|
3803
4171
|
el.node.setAttribute("fill", color);
|
|
3804
4172
|
if (spec.fillRule === "evenodd") {
|
|
@@ -3806,7 +4174,7 @@ class Unit {
|
|
|
3806
4174
|
}
|
|
3807
4175
|
if (fillOpacity < 1) el.node.setAttribute("fill-opacity", String(fillOpacity));
|
|
3808
4176
|
el.node.setAttribute("data:r", String(spec.r));
|
|
3809
|
-
} else if (opts.shape === "image" && opts.image && opts.image.src) {
|
|
4177
|
+
} else if (spec.pk === PK_CORNER && opts.shape === "image" && opts.image && opts.image.src) {
|
|
3810
4178
|
const iw = opts.image.width || 20;
|
|
3811
4179
|
const ih = opts.image.height || 20;
|
|
3812
4180
|
el = w.dom.Paper.image(opts.image.src);
|
|
@@ -3816,7 +4184,7 @@ class Unit {
|
|
|
3816
4184
|
if (opts.image.tint) {
|
|
3817
4185
|
el.node.setAttribute("filter", `url(#${this._tintFilter(color)})`);
|
|
3818
4186
|
}
|
|
3819
|
-
} else if (
|
|
4187
|
+
} else if (spec.pk === PK_CORNER) {
|
|
3820
4188
|
const side = dotR * 2;
|
|
3821
4189
|
el = graphics.drawRect(0, 0, side, side, opts.borderRadius || 0, color, 1, strokeW, strokeColor);
|
|
3822
4190
|
el.node.setAttribute("fill", color);
|
|
@@ -3830,9 +4198,11 @@ class Unit {
|
|
|
3830
4198
|
el.node.setAttribute("fill", color);
|
|
3831
4199
|
if (fillOpacity < 1) el.node.setAttribute("fill-opacity", String(fillOpacity));
|
|
3832
4200
|
}
|
|
3833
|
-
|
|
3834
|
-
|
|
3835
|
-
|
|
4201
|
+
if (i2 >= 0) {
|
|
4202
|
+
el.node.classList.add("apexcharts-unit-area");
|
|
4203
|
+
el.node.setAttribute("i", String(i2));
|
|
4204
|
+
el.node.setAttribute("j", String(j2));
|
|
4205
|
+
}
|
|
3836
4206
|
return el;
|
|
3837
4207
|
}
|
|
3838
4208
|
/**
|
|
@@ -3846,10 +4216,12 @@ class Unit {
|
|
|
3846
4216
|
_tintFilter(color) {
|
|
3847
4217
|
const w = this.w;
|
|
3848
4218
|
const NS = "http://www.w3.org/2000/svg";
|
|
3849
|
-
const
|
|
3850
|
-
|
|
4219
|
+
const tints = this._tints || (this._tints = /* @__PURE__ */ new Map());
|
|
4220
|
+
let id = tints.get(color);
|
|
4221
|
+
if (id) return id;
|
|
4222
|
+
id = `apexcharts-unit-tint-${w.globals.chartID}-${tints.size}`;
|
|
4223
|
+
tints.set(color, id);
|
|
3851
4224
|
const svg = w.dom.Paper.node;
|
|
3852
|
-
if (svg.querySelector(`#${id}`)) return id;
|
|
3853
4225
|
let defs = svg.querySelector("defs");
|
|
3854
4226
|
if (!defs) {
|
|
3855
4227
|
defs = BrowserAPIs.createElementNS(NS, "defs");
|
|
@@ -3972,6 +4344,14 @@ class Unit {
|
|
|
3972
4344
|
}
|
|
3973
4345
|
if (this.ctx) this.ctx._unitSprings = springs;
|
|
3974
4346
|
}
|
|
4347
|
+
/**
|
|
4348
|
+
* True once a loop's node no longer belongs to this chart's live SVG.
|
|
4349
|
+
* @param {Element} node @returns {boolean}
|
|
4350
|
+
*/
|
|
4351
|
+
_stale(node) {
|
|
4352
|
+
const P = this.w.dom.Paper;
|
|
4353
|
+
return !!this.w.globals.isDestroyed || !P || !P.node.contains(node);
|
|
4354
|
+
}
|
|
3975
4355
|
/**
|
|
3976
4356
|
* One rAF loop that tweens every dot from its start (cx0/cy0 - either the
|
|
3977
4357
|
* cluster centre on first mount / for entering dots, or its previous slot on
|
|
@@ -3994,8 +4374,8 @@ class Unit {
|
|
|
3994
4374
|
const speed = Math.max(1, w.config.chart.animations.speed || 800);
|
|
3995
4375
|
const maxDelay = Math.min(speed * 0.6, 450);
|
|
3996
4376
|
const n2 = dots.length;
|
|
3997
|
-
for (let k2 =
|
|
3998
|
-
dots[k2].delay = n2 > 1 ? k2 / (n2 - 1) * maxDelay : 0;
|
|
4377
|
+
for (let k2 = n2; k2--; ) {
|
|
4378
|
+
dots[k2].delay = dots[k2].pair ? dots[k2 + 1].delay : n2 > 1 ? k2 / (n2 - 1) * maxDelay : 0;
|
|
3999
4379
|
}
|
|
4000
4380
|
const gcfg = opts.gather || {};
|
|
4001
4381
|
const motion = gcfg.motion || "auto";
|
|
@@ -4004,8 +4384,9 @@ class Unit {
|
|
|
4004
4384
|
else if (this.ctx) this.ctx._unitSprings = null;
|
|
4005
4385
|
for (let k2 = 0; k2 < n2; k2++) {
|
|
4006
4386
|
const d = dots[k2];
|
|
4007
|
-
if (d.
|
|
4008
|
-
d.node.
|
|
4387
|
+
if (d.r0 !== d.r1) {
|
|
4388
|
+
this._size(d.node, d.spec, d.r0 / d.r1);
|
|
4389
|
+
this._place(d.node, d.spec, d.cx0, d.cy0, d.r0 / d.r1);
|
|
4009
4390
|
}
|
|
4010
4391
|
}
|
|
4011
4392
|
for (let k2 = 0; k2 < n2; k2++) {
|
|
@@ -4016,16 +4397,11 @@ class Unit {
|
|
|
4016
4397
|
}
|
|
4017
4398
|
}
|
|
4018
4399
|
const easePos = gcfg.easing === "outBack" ? easeOutBack(typeof gcfg.overshoot === "number" ? gcfg.overshoot : 1.70158) : gcfg.easing === "inOutCubic" ? easeInOutCubic : easeOutCubic;
|
|
4019
|
-
if (this.w.globals.unitGatherRAF != null) {
|
|
4020
|
-
BrowserAPIs.cancelAnimationFrame(this.w.globals.unitGatherRAF);
|
|
4021
|
-
this.w.globals.unitGatherRAF = null;
|
|
4022
|
-
}
|
|
4023
4400
|
const start = performance.now();
|
|
4024
4401
|
let last = start;
|
|
4025
4402
|
const stepFn = (now) => {
|
|
4026
|
-
if (this.
|
|
4403
|
+
if (this._stale(dots[0].node)) {
|
|
4027
4404
|
this.w.globals.unitGatherRAF = null;
|
|
4028
|
-
this.w.globals.animationEnded = true;
|
|
4029
4405
|
return;
|
|
4030
4406
|
}
|
|
4031
4407
|
const dt = Math.min(MAX_FRAME_STEP, Math.max(0, (now - last) / 1e3));
|
|
@@ -4053,7 +4429,12 @@ class Unit {
|
|
|
4053
4429
|
cx = d.cx0 + (d.x - d.cx0) * e2;
|
|
4054
4430
|
cy = d.cy0 + (d.y - d.cy0) * e2;
|
|
4055
4431
|
}
|
|
4056
|
-
|
|
4432
|
+
let sk = 1;
|
|
4433
|
+
if (d.r0 !== d.r1) {
|
|
4434
|
+
sk = (d.r0 + (d.r1 - d.r0) * ec) / d.r1;
|
|
4435
|
+
this._size(d.node, d.spec, sk);
|
|
4436
|
+
}
|
|
4437
|
+
this._place(d.node, d.spec, cx, cy, sk);
|
|
4057
4438
|
if (d.isEnter) d.node.style.opacity = String(Math.min(1, t2 * 2.5));
|
|
4058
4439
|
if (d._c0 && d._c1) {
|
|
4059
4440
|
const cr = Math.round(d._c0[0] + (d._c1[0] - d._c0[0]) * ec);
|
|
@@ -4061,9 +4442,6 @@ class Unit {
|
|
|
4061
4442
|
const cb = Math.round(d._c0[2] + (d._c1[2] - d._c0[2]) * ec);
|
|
4062
4443
|
d.node.setAttribute("fill", `rgb(${cr},${cg},${cb})`);
|
|
4063
4444
|
}
|
|
4064
|
-
if (d.spec.pk === PK_CIRCLE && d.r0 != null && d.r1 != null && d.r0 !== d.r1) {
|
|
4065
|
-
d.node.setAttribute("r", String(d.r0 + (d.r1 - d.r0) * ec));
|
|
4066
|
-
}
|
|
4067
4445
|
if (t2 < 1) done = false;
|
|
4068
4446
|
}
|
|
4069
4447
|
if (done) {
|
|
@@ -4071,8 +4449,9 @@ class Unit {
|
|
|
4071
4449
|
const d = dots[k2];
|
|
4072
4450
|
d.node.style.opacity = "";
|
|
4073
4451
|
if (d._c1 && d.fill1) d.node.setAttribute("fill", d.fill1);
|
|
4074
|
-
if (d.
|
|
4075
|
-
d.node
|
|
4452
|
+
if (d.r0 !== d.r1) {
|
|
4453
|
+
this._size(d.node, d.spec, 1);
|
|
4454
|
+
this._place(d.node, d.spec, d.x, d.y);
|
|
4076
4455
|
}
|
|
4077
4456
|
}
|
|
4078
4457
|
this.w.globals.unitGatherRAF = null;
|
|
@@ -4095,7 +4474,7 @@ class Unit {
|
|
|
4095
4474
|
const cap = Math.max(0, opts.maxUnits || 5e3);
|
|
4096
4475
|
const exits = [];
|
|
4097
4476
|
for (const [key, slot] of prev) {
|
|
4098
|
-
if (!nextPrev.has(key)) {
|
|
4477
|
+
if (!nextPrev.has(key) && key[0] !== "l") {
|
|
4099
4478
|
exits.push(slot);
|
|
4100
4479
|
if (exits.length >= cap) break;
|
|
4101
4480
|
}
|
|
@@ -4122,7 +4501,7 @@ class Unit {
|
|
|
4122
4501
|
exits.forEach((slot) => {
|
|
4123
4502
|
const r2 = slot.r != null ? slot.r : dotR;
|
|
4124
4503
|
const spec = slot.spec || this._baseSpec(opts, r2);
|
|
4125
|
-
const el = this._drawDot(graphics, opts, r2, slot.fill,
|
|
4504
|
+
const el = this._drawDot(graphics, opts, r2, slot.fill, -1, 0, spec);
|
|
4126
4505
|
el.node.classList.add("apexcharts-unit-exit");
|
|
4127
4506
|
this._place(el.node, spec, slot.x, slot.y);
|
|
4128
4507
|
group2.add(el);
|
|
@@ -4133,13 +4512,9 @@ class Unit {
|
|
|
4133
4512
|
return;
|
|
4134
4513
|
}
|
|
4135
4514
|
const speed = Math.max(1, w.config.chart.animations.speed || 800);
|
|
4136
|
-
if (this.w.globals.unitExitRAF != null) {
|
|
4137
|
-
BrowserAPIs.cancelAnimationFrame(this.w.globals.unitExitRAF);
|
|
4138
|
-
this.w.globals.unitExitRAF = null;
|
|
4139
|
-
}
|
|
4140
4515
|
const start = performance.now();
|
|
4141
4516
|
const stepFn = (now) => {
|
|
4142
|
-
if (this.
|
|
4517
|
+
if (this._stale(group2.node)) {
|
|
4143
4518
|
this.w.globals.unitExitRAF = null;
|
|
4144
4519
|
return;
|
|
4145
4520
|
}
|
|
@@ -4210,7 +4585,8 @@ ${percent2.toFixed(1)}%`;
|
|
|
4210
4585
|
if (!lines.length) return 0;
|
|
4211
4586
|
const width = measureLabelWidth(w, lines, {
|
|
4212
4587
|
fontSize: cfg.fontSize,
|
|
4213
|
-
fontFamily: cfg.fontFamily || w.config.chart.fontFamily
|
|
4588
|
+
fontFamily: cfg.fontFamily || w.config.chart.fontFamily,
|
|
4589
|
+
fontWeight: cfg.fontWeight
|
|
4214
4590
|
});
|
|
4215
4591
|
const gap = conn.gap != null ? conn.gap : 8;
|
|
4216
4592
|
const length = conn.length != null ? conn.length : 22;
|
|
@@ -4347,6 +4723,7 @@ ${percent2.toFixed(1)}%`;
|
|
|
4347
4723
|
* the blob in either direction.
|
|
4348
4724
|
* @param {any} elSeries @param {{ i:number, cx:number, cy:number, outerR:number, flat?:boolean }} cluster
|
|
4349
4725
|
* @param {number} value @param {number} total @param {any} opts @param {string} color
|
|
4726
|
+
* @returns {SVGElement|undefined}
|
|
4350
4727
|
*/
|
|
4351
4728
|
_drawClusterLabel(elSeries, cluster, value, total, opts, color) {
|
|
4352
4729
|
const w = this.w;
|
|
@@ -4404,6 +4781,10 @@ ${percent2.toFixed(1)}%`;
|
|
|
4404
4781
|
textEl.textContent = str;
|
|
4405
4782
|
}
|
|
4406
4783
|
elSeries.node.appendChild(textEl);
|
|
4784
|
+
return (
|
|
4785
|
+
/** @type {any} */
|
|
4786
|
+
textEl
|
|
4787
|
+
);
|
|
4407
4788
|
}
|
|
4408
4789
|
}
|
|
4409
4790
|
ApexCharts__default.use({
|
|
@@ -4506,26 +4887,33 @@ function drilldownById(w, id) {
|
|
|
4506
4887
|
const list = dd && Array.isArray(dd.series) ? dd.series : [];
|
|
4507
4888
|
return list.find((s2) => s2 && s2.id === id);
|
|
4508
4889
|
}
|
|
4509
|
-
function
|
|
4890
|
+
function segment(name, seen) {
|
|
4891
|
+
var _a;
|
|
4892
|
+
const n2 = String(name).replace(/\//g, "%2F");
|
|
4893
|
+
const o2 = ((_a = seen.get(n2)) != null ? _a : -1) + 1;
|
|
4894
|
+
seen.set(n2, o2);
|
|
4895
|
+
return `${o2}:${n2}`;
|
|
4896
|
+
}
|
|
4897
|
+
function toNode(w, d, i2, paletteFromParent, parentKey, seenIds = null, opts = {}, seen = /* @__PURE__ */ new Map()) {
|
|
4510
4898
|
var _a, _b, _c;
|
|
4511
4899
|
const isObj = d && typeof d === "object";
|
|
4512
4900
|
const name = isObj ? (_b = (_a = d.x) != null ? _a : d.name) != null ? _b : "" : "";
|
|
4513
|
-
const
|
|
4901
|
+
const raw = isObj ? (_c = d.y) != null ? _c : d.value : d;
|
|
4902
|
+
const value = raw == null || raw === "" ? NaN : Number(raw);
|
|
4514
4903
|
const node = {
|
|
4515
4904
|
name: String(name),
|
|
4516
4905
|
value: isNaN(value) ? null : value,
|
|
4517
4906
|
color: isObj && d.color ? d.color : void 0,
|
|
4518
|
-
|
|
4519
|
-
// siblings stay distinct). Update animations morph matched keys in place.
|
|
4520
|
-
_key: `${parentKey}/${i2}:${name}`
|
|
4907
|
+
_key: `${parentKey}/${segment(name, seen)}`
|
|
4521
4908
|
};
|
|
4522
4909
|
if (paletteFromParent && !node.color) {
|
|
4523
4910
|
node.color = paletteFromParent[i2 % paletteFromParent.length];
|
|
4524
4911
|
}
|
|
4525
4912
|
if (opts.keepDatum) node._datum = d;
|
|
4913
|
+
const kids = /* @__PURE__ */ new Map();
|
|
4526
4914
|
if (isObj && Array.isArray(d.children) && d.children.length) {
|
|
4527
4915
|
node.children = d.children.map(
|
|
4528
|
-
(c, j2) => toNode(w, c, j2, null, node._key, seenIds, opts)
|
|
4916
|
+
(c, j2) => toNode(w, c, j2, null, node._key, seenIds, opts, kids)
|
|
4529
4917
|
);
|
|
4530
4918
|
} else if (isObj && d.drilldown != null && opts.expandDrilldown !== false) {
|
|
4531
4919
|
const visited = seenIds || /* @__PURE__ */ new Set();
|
|
@@ -4536,7 +4924,7 @@ function toNode(w, d, i2, paletteFromParent, parentKey, seenIds = null, opts = {
|
|
|
4536
4924
|
nextSeen.add(d.drilldown);
|
|
4537
4925
|
const palette = Array.isArray(dd.colors) ? dd.colors : null;
|
|
4538
4926
|
node.children = dd.data.map(
|
|
4539
|
-
(c, j2) => toNode(w, c, j2, palette, node._key, nextSeen, opts)
|
|
4927
|
+
(c, j2) => toNode(w, c, j2, palette, node._key, nextSeen, opts, kids)
|
|
4540
4928
|
);
|
|
4541
4929
|
}
|
|
4542
4930
|
}
|
|
@@ -4551,8 +4939,9 @@ function buildHierarchy(w, opts = {}) {
|
|
|
4551
4939
|
const first = cfgSeries && cfgSeries[0];
|
|
4552
4940
|
const data = first && Array.isArray(first.data) ? first.data : cfgSeries;
|
|
4553
4941
|
if (!Array.isArray(data)) return [];
|
|
4942
|
+
const seen = /* @__PURE__ */ new Map();
|
|
4554
4943
|
return data.map(
|
|
4555
|
-
(d, i2) => toNode(w, d, i2, null, "", null, opts)
|
|
4944
|
+
(d, i2) => toNode(w, d, i2, null, "", null, opts, seen)
|
|
4556
4945
|
);
|
|
4557
4946
|
}
|
|
4558
4947
|
function fillValues(node) {
|
|
@@ -4706,7 +5095,7 @@ function renderBreadcrumb(w, opts) {
|
|
|
4706
5095
|
text.setAttribute("class", "apexcharts-breadcrumb-label");
|
|
4707
5096
|
text.textContent = String(label2);
|
|
4708
5097
|
btn.appendChild(text);
|
|
4709
|
-
btn.addEventListener("click", () => opts.onNavigate(i2, crumb));
|
|
5098
|
+
btn.addEventListener("click", (e2) => opts.onNavigate(i2, crumb, e2));
|
|
4710
5099
|
nav.appendChild(btn);
|
|
4711
5100
|
});
|
|
4712
5101
|
elWrap.appendChild(nav);
|
|
@@ -4826,6 +5215,15 @@ function resolveFocus(node, current, roots) {
|
|
|
4826
5215
|
if (next === current) return { changed: false, focus: current };
|
|
4827
5216
|
return { changed: true, focus: next };
|
|
4828
5217
|
}
|
|
5218
|
+
function focusByKey(key, nodesAll, roots) {
|
|
5219
|
+
var _a;
|
|
5220
|
+
const f = key && nodesAll.find((n2) => n2._key === key);
|
|
5221
|
+
return f && ((_a = f.children) == null ? void 0 : _a.length) && !(roots.length === 1 && f === roots[0]) ? f : null;
|
|
5222
|
+
}
|
|
5223
|
+
function setZoomCursor(chart, node) {
|
|
5224
|
+
if (!Environment.isBrowser() || chart.cfg.zoomOnClick === false) return;
|
|
5225
|
+
node._el.node.style.cursor = resolveFocus(node, chart._focus, chart._roots).changed ? "pointer" : "default";
|
|
5226
|
+
}
|
|
4829
5227
|
function parseSize(size, max, fallbackRatio = 0) {
|
|
4830
5228
|
if (typeof size === "number") return size;
|
|
4831
5229
|
const s2 = String(size).trim();
|
|
@@ -4860,6 +5258,7 @@ function colorPass(node, color, tint, out) {
|
|
|
4860
5258
|
}
|
|
4861
5259
|
}
|
|
4862
5260
|
}
|
|
5261
|
+
const escapeHtml$1 = (s2) => String(s2).replace(/[&<>"']/g, (c) => `&#${c.charCodeAt(0)};`);
|
|
4863
5262
|
class NodeTooltip {
|
|
4864
5263
|
/**
|
|
4865
5264
|
* @param {any} w
|
|
@@ -4897,14 +5296,29 @@ class NodeTooltip {
|
|
|
4897
5296
|
* @param {any} node
|
|
4898
5297
|
*/
|
|
4899
5298
|
show(e2, node) {
|
|
5299
|
+
var _a;
|
|
4900
5300
|
const t2 = this._tip();
|
|
4901
5301
|
if (!t2) return;
|
|
4902
5302
|
const w = this.w;
|
|
4903
5303
|
const pctTotal = (node.value / this.total * 100).toFixed(1);
|
|
4904
5304
|
const parentVal = node._parent ? node._parent.value : this.total;
|
|
4905
5305
|
const pctParent = parentVal > 0 ? (node.value / parentVal * 100).toFixed(1) : pctTotal;
|
|
4906
|
-
const
|
|
4907
|
-
|
|
5306
|
+
const ty = w.config.tooltip.y;
|
|
5307
|
+
const fmt = (_a = Array.isArray(ty) ? ty[0] : ty) == null ? void 0 : _a.formatter;
|
|
5308
|
+
const val = fmt ? fmt(node.value, { seriesIndex: 0, dataPointIndex: -1, w, node }) : +node.value.toPrecision(12);
|
|
5309
|
+
t2.innerHTML = `<div class="apexcharts-tooltip-series-group apexcharts-active" style="display:flex"><span class="apexcharts-tooltip-marker"></span><div class="apexcharts-tooltip-text"><div class="apexcharts-tooltip-y-group"><span class="apexcharts-tooltip-text-y-label">${escapeHtml$1(node.name)}: </span><span class="apexcharts-tooltip-text-y-value">${val} (${pctParent}% of parent, ${pctTotal}% of total)</span></div></div></div>`;
|
|
5310
|
+
const group2 = (
|
|
5311
|
+
/** @type {HTMLElement} */
|
|
5312
|
+
t2.firstChild
|
|
5313
|
+
);
|
|
5314
|
+
const marker = (
|
|
5315
|
+
/** @type {HTMLElement} */
|
|
5316
|
+
group2.firstChild
|
|
5317
|
+
);
|
|
5318
|
+
marker.style.backgroundColor = node._color;
|
|
5319
|
+
if (w.config.tooltip.fillSeriesColor) {
|
|
5320
|
+
group2.style.backgroundColor = node._color;
|
|
5321
|
+
}
|
|
4908
5322
|
t2.classList.add("apexcharts-active");
|
|
4909
5323
|
t2.style.opacity = "1";
|
|
4910
5324
|
this.position(e2);
|
|
@@ -4992,14 +5406,19 @@ class SunburstChart {
|
|
|
4992
5406
|
this.centerY = gh / 2 + (this.cfg.offsetY || 0);
|
|
4993
5407
|
this.maxRadius = Math.min(gw, gh) / 2.05 - this.strokeWidth - (!w.config.chart.sparkline.enabled ? w.config.chart.dropShadow.blur : 0);
|
|
4994
5408
|
if (this.maxRadius < 5) return g;
|
|
4995
|
-
this._roots =
|
|
5409
|
+
this._roots = buildHierarchy(w);
|
|
4996
5410
|
if (!this._roots.length) return g;
|
|
4997
|
-
this._roots.forEach(
|
|
5411
|
+
this._roots.forEach(fillValues);
|
|
4998
5412
|
this._validateStrict();
|
|
4999
5413
|
this._nodesAll = [];
|
|
5000
5414
|
const colors = w.globals.colors || [];
|
|
5001
5415
|
this._roots.forEach((r2, i2) => {
|
|
5002
|
-
|
|
5416
|
+
colorPass(
|
|
5417
|
+
r2,
|
|
5418
|
+
r2.color || colors[i2 % colors.length] || "#008FFB",
|
|
5419
|
+
this.cfg.tint,
|
|
5420
|
+
this._nodesAll
|
|
5421
|
+
);
|
|
5003
5422
|
});
|
|
5004
5423
|
this.total = this._roots.reduce((s2, r2) => s2 + Math.max(0, r2.value), 0) || 1;
|
|
5005
5424
|
this._tooltip.total = this.total;
|
|
@@ -5007,13 +5426,17 @@ class SunburstChart {
|
|
|
5007
5426
|
this._labelsG = graphics.group({ class: "apexcharts-sunburst-labels" });
|
|
5008
5427
|
g.add(this._ringsG);
|
|
5009
5428
|
g.add(this._labelsG);
|
|
5010
|
-
this._focus =
|
|
5429
|
+
this._focus = focusByKey(
|
|
5430
|
+
w.globals.sunburstFocusKey,
|
|
5431
|
+
this._nodesAll,
|
|
5432
|
+
this._roots
|
|
5433
|
+
);
|
|
5011
5434
|
this._relayout(this._focus);
|
|
5012
5435
|
const anims = w.config.chart.animations;
|
|
5013
5436
|
let mode = "none";
|
|
5014
5437
|
if (anims.enabled) {
|
|
5015
5438
|
if (w.globals.dataChanged) {
|
|
5016
|
-
if (
|
|
5439
|
+
if (w.globals.shouldAnimate !== false) mode = "update";
|
|
5017
5440
|
} else if (!w.globals.resized) {
|
|
5018
5441
|
mode = "intro";
|
|
5019
5442
|
}
|
|
@@ -5023,22 +5446,6 @@ class SunburstChart {
|
|
|
5023
5446
|
return g;
|
|
5024
5447
|
}
|
|
5025
5448
|
// ------------------------------------------------------------------ data
|
|
5026
|
-
/**
|
|
5027
|
-
* Resolve the config into root nodes `{ name, value, color?, children? }`.
|
|
5028
|
-
* Each datum may carry `children` (native) or `drilldown: '<id>'` (adapter).
|
|
5029
|
-
* Shared with the treemap - see charts/common/Hierarchy.
|
|
5030
|
-
* @returns {any[]}
|
|
5031
|
-
*/
|
|
5032
|
-
_buildHierarchy() {
|
|
5033
|
-
return buildHierarchy(this.w);
|
|
5034
|
-
}
|
|
5035
|
-
/**
|
|
5036
|
-
* Fill a parent's value from its children when missing.
|
|
5037
|
-
* @param {any} node
|
|
5038
|
-
*/
|
|
5039
|
-
_fillValues(node) {
|
|
5040
|
-
fillValues(node);
|
|
5041
|
-
}
|
|
5042
5449
|
/**
|
|
5043
5450
|
* With `partition: 'strict'`, warn (once) when a parent's value does not
|
|
5044
5451
|
* match the sum of its children. The angles are still normalized to fill the
|
|
@@ -5052,22 +5459,13 @@ class SunburstChart {
|
|
|
5052
5459
|
remedy: "Angles are normalized to fill the wedge."
|
|
5053
5460
|
});
|
|
5054
5461
|
}
|
|
5055
|
-
/**
|
|
5056
|
-
* Assign a colour to every node (explicit `color` wins, else the parent's
|
|
5057
|
-
* colour tinted lighter). Done once so zoom preserves colours.
|
|
5058
|
-
* Shared with the icicle - see charts/common/partition/Tint.
|
|
5059
|
-
* @param {any} node
|
|
5060
|
-
* @param {string} color
|
|
5061
|
-
*/
|
|
5062
|
-
_colorPass(node, color) {
|
|
5063
|
-
colorPass(node, color, this.cfg.tint, this._nodesAll);
|
|
5064
|
-
}
|
|
5065
5462
|
// ---------------------------------------------------------------- layout
|
|
5066
5463
|
/**
|
|
5067
5464
|
* Recompute visibility + angles + radii for a focus node (null = whole tree).
|
|
5068
5465
|
* @param {any} focus
|
|
5069
5466
|
*/
|
|
5070
5467
|
_relayout(focus) {
|
|
5468
|
+
this.w.globals.sunburstFocusKey = focus && focus._key;
|
|
5071
5469
|
this._focusMaxDepth = placeTree({
|
|
5072
5470
|
roots: this._roots,
|
|
5073
5471
|
nodesAll: this._nodesAll,
|
|
@@ -5108,14 +5506,15 @@ class SunburstChart {
|
|
|
5108
5506
|
* @param {'intro'|'zoom'|'update'|'none'} mode
|
|
5109
5507
|
*/
|
|
5110
5508
|
_applyLayout(mode) {
|
|
5111
|
-
var _a;
|
|
5509
|
+
var _a, _b, _c;
|
|
5112
5510
|
const w = this.w;
|
|
5113
5511
|
const anims = w.config.chart.animations;
|
|
5114
|
-
const
|
|
5512
|
+
const dyn = anims.dynamicAnimation;
|
|
5513
|
+
const dur = !anims.enabled || mode === "none" ? 0 : mode === "intro" ? (_a = anims.speed) != null ? _a : 500 : dyn.enabled ? (_b = dyn.speed) != null ? _b : 350 : 0;
|
|
5115
5514
|
const gen = ++this._zoomGen;
|
|
5116
5515
|
const morph = (
|
|
5117
5516
|
/** @type {any} */
|
|
5118
|
-
(
|
|
5517
|
+
(_c = this.ctx) == null ? void 0 : _c.morphTypeChange
|
|
5119
5518
|
);
|
|
5120
5519
|
const morphActive = !!morph && typeof morph.isActive === "function" && morph.isActive() && typeof morph.getInitialPathAt === "function";
|
|
5121
5520
|
const morphDur = morphActive ? morph.getSpeed() : 0;
|
|
@@ -5124,6 +5523,11 @@ class SunburstChart {
|
|
|
5124
5523
|
/** @type {any} */
|
|
5125
5524
|
this.ctx._sunburstPrevGeoms
|
|
5126
5525
|
) : null;
|
|
5526
|
+
const geo = (n2) => n2._cur || { a0: n2._t0, a1: n2._t1, iR: n2._iR, oR: n2._oR };
|
|
5527
|
+
const pinch = (c) => {
|
|
5528
|
+
const m = (c.a0 + c.a1) / 2;
|
|
5529
|
+
return { a0: m, a1: m, iR: c.iR, oR: c.iR };
|
|
5530
|
+
};
|
|
5127
5531
|
this._nodesAll.forEach((node) => {
|
|
5128
5532
|
if (node._show) {
|
|
5129
5533
|
const target2 = {
|
|
@@ -5133,36 +5537,55 @@ class SunburstChart {
|
|
|
5133
5537
|
oR: node._oR
|
|
5134
5538
|
};
|
|
5135
5539
|
if (!node._el) node._el = this._createArcEl(node);
|
|
5540
|
+
setZoomCursor(this, node);
|
|
5136
5541
|
const morphFrom = morphActive ? this._morphSourceFor(node) : null;
|
|
5137
5542
|
if (morphFrom && morphDur > 0) {
|
|
5138
5543
|
this._morphArcFrom(node, morphFrom, target2, morphDur, gen);
|
|
5139
5544
|
} else if ((mode === "intro" || morphActive) && dur > 0) {
|
|
5140
5545
|
this._sweepArc(node, target2, morphActive ? morphDur : dur, gen);
|
|
5141
5546
|
} else {
|
|
5142
|
-
|
|
5143
|
-
|
|
5144
|
-
|
|
5145
|
-
from = node._cur;
|
|
5146
|
-
} else if (prev && prev.get(node._key)) {
|
|
5147
|
-
from = prev.get(node._key);
|
|
5148
|
-
} else {
|
|
5149
|
-
const mid = (target2.a0 + target2.a1) / 2;
|
|
5150
|
-
from = { a0: mid, a1: mid, iR: target2.iR, oR: target2.iR };
|
|
5151
|
-
isNew = true;
|
|
5152
|
-
}
|
|
5153
|
-
this._animateArc(node, from, target2, dur, false, isNew, gen);
|
|
5547
|
+
const p = prev && prev.get(node._key);
|
|
5548
|
+
const from = node._cur || (p ? geo(p) : pinch(target2));
|
|
5549
|
+
this._animateArc(node, from, target2, dur, false, !node._cur && !p, gen);
|
|
5154
5550
|
}
|
|
5155
5551
|
} else if (node._el && node._cur) {
|
|
5156
|
-
|
|
5157
|
-
const target2 = { a0: mid, a1: mid, iR: node._cur.iR, oR: node._cur.iR };
|
|
5158
|
-
this._animateArc(node, node._cur, target2, dur, true, false, gen);
|
|
5552
|
+
this._animateArc(node, node._cur, pinch(node._cur), dur, true, false, gen);
|
|
5159
5553
|
}
|
|
5160
5554
|
});
|
|
5555
|
+
if (prev && dur && !morphActive) {
|
|
5556
|
+
const keys = new Set(this._nodesAll.map((n2) => n2._show && n2._key));
|
|
5557
|
+
prev.forEach((p, k2) => {
|
|
5558
|
+
if (keys.has(k2) || !(p._show || p._cur)) return;
|
|
5559
|
+
const el = this._graphics.drawPath({
|
|
5560
|
+
fill: p._color,
|
|
5561
|
+
stroke: this.strokeColor,
|
|
5562
|
+
strokeWidth: this.strokeWidth,
|
|
5563
|
+
classes: "apexcharts-sunburst-arc"
|
|
5564
|
+
});
|
|
5565
|
+
el.node.setAttribute("data:name", p.name);
|
|
5566
|
+
this._ringsG.add(el.attr({ opacity: p._el.attr("opacity") }));
|
|
5567
|
+
const c = geo(p);
|
|
5568
|
+
const g = { _el: el, _color: p._color, name: p.name, _key: k2, _cur: c };
|
|
5569
|
+
this._nodesAll.push(g);
|
|
5570
|
+
this._animateArc(g, c, pinch(c), dur, true, false, gen);
|
|
5571
|
+
});
|
|
5572
|
+
}
|
|
5573
|
+
const end = Math.max(dur, morphDur);
|
|
5574
|
+
if (end) {
|
|
5575
|
+
this._ringsG.animate(end).after(() => {
|
|
5576
|
+
if (this._zoomGen === gen && this._ringsG.node.isConnected)
|
|
5577
|
+
new Animations(
|
|
5578
|
+
w,
|
|
5579
|
+
/** @type {any} */
|
|
5580
|
+
this.ctx
|
|
5581
|
+
).animationCompleted(
|
|
5582
|
+
this._ringsG.node
|
|
5583
|
+
);
|
|
5584
|
+
});
|
|
5585
|
+
} else w.globals.animationEnded = true;
|
|
5161
5586
|
const geoms = /* @__PURE__ */ new Map();
|
|
5162
5587
|
this._nodesAll.forEach((n2) => {
|
|
5163
|
-
if (n2._show)
|
|
5164
|
-
geoms.set(n2._key, { a0: n2._t0, a1: n2._t1, iR: n2._iR, oR: n2._oR });
|
|
5165
|
-
}
|
|
5588
|
+
if (n2._show || n2._cur) geoms.set(n2._key, n2);
|
|
5166
5589
|
});
|
|
5167
5590
|
this.ctx._sunburstPrevGeoms = geoms;
|
|
5168
5591
|
this._renderLabels(dur);
|
|
@@ -5279,11 +5702,9 @@ class SunburstChart {
|
|
|
5279
5702
|
*/
|
|
5280
5703
|
_createArcEl(node) {
|
|
5281
5704
|
const path = this._graphics.drawPath({
|
|
5282
|
-
d: "",
|
|
5283
5705
|
fill: node._color,
|
|
5284
5706
|
stroke: this.strokeColor,
|
|
5285
5707
|
strokeWidth: this.strokeWidth,
|
|
5286
|
-
fillOpacity: 1,
|
|
5287
5708
|
classes: "apexcharts-sunburst-arc"
|
|
5288
5709
|
});
|
|
5289
5710
|
const el = path.node;
|
|
@@ -5295,9 +5716,8 @@ class SunburstChart {
|
|
|
5295
5716
|
String(!(node.children && node.children.length))
|
|
5296
5717
|
);
|
|
5297
5718
|
this._tooltip.attach(el, node);
|
|
5298
|
-
if (Environment.isBrowser()) {
|
|
5719
|
+
if (Environment.isBrowser() && this.cfg.zoomOnClick !== false) {
|
|
5299
5720
|
el.addEventListener("click", () => this._zoomTo(node));
|
|
5300
|
-
el.style.cursor = "pointer";
|
|
5301
5721
|
}
|
|
5302
5722
|
this._ringsG.add(path);
|
|
5303
5723
|
return path;
|
|
@@ -5361,11 +5781,12 @@ class SunburstChart {
|
|
|
5361
5781
|
if (node._t1 - node._t0 < this.cfg.dataLabels.minAngleToShow) return;
|
|
5362
5782
|
this._renderCurvedLabel(node);
|
|
5363
5783
|
});
|
|
5784
|
+
const gen = this._zoomGen;
|
|
5785
|
+
labelsG.attr({ opacity: dur > 0 ? 0 : 1 });
|
|
5364
5786
|
if (dur > 0) {
|
|
5365
|
-
labelsG.
|
|
5366
|
-
|
|
5367
|
-
|
|
5368
|
-
labelsG.attr({ opacity: 1 });
|
|
5787
|
+
labelsG.animate(250, dur).during((p) => {
|
|
5788
|
+
if (this._zoomGen === gen) labelsG.attr({ opacity: p });
|
|
5789
|
+
});
|
|
5369
5790
|
}
|
|
5370
5791
|
}
|
|
5371
5792
|
/**
|
|
@@ -5374,11 +5795,10 @@ class SunburstChart {
|
|
|
5374
5795
|
* @param {any} node
|
|
5375
5796
|
*/
|
|
5376
5797
|
_renderCurvedLabel(node) {
|
|
5377
|
-
if (!Environment.isBrowser()) return;
|
|
5378
5798
|
const style = this.cfg.dataLabels.style;
|
|
5379
5799
|
const w = this.w;
|
|
5380
5800
|
const r2 = (node._iR + node._oR) / 2;
|
|
5381
|
-
const mid = (node._t0 + node._t1) / 2;
|
|
5801
|
+
const mid = ((node._t0 + node._t1) / 2 % 360 + 360) % 360;
|
|
5382
5802
|
const flip = mid > 90 && mid < 270;
|
|
5383
5803
|
const padDeg = Math.min(r2 > 0 ? 4 / r2 * R2D : 0, (node._t1 - node._t0) / 2);
|
|
5384
5804
|
const from = flip ? node._t1 - padDeg : node._t0 + padDeg;
|
|
@@ -5439,17 +5859,13 @@ class SunburstChart {
|
|
|
5439
5859
|
*/
|
|
5440
5860
|
_zoomTo(node) {
|
|
5441
5861
|
if (this.cfg.zoomOnClick === false) return;
|
|
5442
|
-
const next = resolveFocus(node, this._focus);
|
|
5862
|
+
const next = resolveFocus(node, this._focus, this._roots);
|
|
5443
5863
|
if (!next.changed) return;
|
|
5444
5864
|
this._focus = next.focus;
|
|
5445
5865
|
this._relayout(this._focus);
|
|
5446
5866
|
this._applyLayout("zoom");
|
|
5447
5867
|
this._renderBreadcrumb();
|
|
5448
5868
|
}
|
|
5449
|
-
/** Root -> focus chain of nodes. */
|
|
5450
|
-
_focusChain() {
|
|
5451
|
-
return focusChain(this._focus);
|
|
5452
|
-
}
|
|
5453
5869
|
/**
|
|
5454
5870
|
* Minimal self-contained breadcrumb (reuses the shared `.apexcharts-breadcrumb`
|
|
5455
5871
|
* CSS classes, but does NOT depend on the drilldown feature).
|
|
@@ -5469,7 +5885,7 @@ class SunburstChart {
|
|
|
5469
5885
|
nav.style.top = "0px";
|
|
5470
5886
|
nav.style.left = "0px";
|
|
5471
5887
|
const crumbs = [{ name: "All", node: null }].concat(
|
|
5472
|
-
this.
|
|
5888
|
+
focusChain(this._focus).map((n2) => ({ name: n2.name, node: n2 }))
|
|
5473
5889
|
);
|
|
5474
5890
|
crumbs.forEach((crumb, i2) => {
|
|
5475
5891
|
if (i2 > 0) {
|
|
@@ -5511,21 +5927,7 @@ class SunburstChart {
|
|
|
5511
5927
|
}
|
|
5512
5928
|
});
|
|
5513
5929
|
elWrap.appendChild(nav);
|
|
5514
|
-
|
|
5515
|
-
}
|
|
5516
|
-
/**
|
|
5517
|
-
* The breadcrumb is an absolute overlay at top-left, so it can sit on top of
|
|
5518
|
-
* a left-aligned title (or subtitle). After mounting, push it below any chart
|
|
5519
|
-
* chrome it intersects. (Duplicated from drilldown's Breadcrumb on purpose —
|
|
5520
|
-
* sunburst must not import the drilldown feature.)
|
|
5521
|
-
* @param {any} nav
|
|
5522
|
-
*/
|
|
5523
|
-
/**
|
|
5524
|
-
* Shared with the treemap - see charts/common/Breadcrumb.
|
|
5525
|
-
* @param {any} nav
|
|
5526
|
-
*/
|
|
5527
|
-
_avoidChromeOverlap(nav) {
|
|
5528
|
-
avoidChromeOverlap(this.w, nav);
|
|
5930
|
+
avoidChromeOverlap(w, nav);
|
|
5529
5931
|
}
|
|
5530
5932
|
// ------------------------------------------------------------ geometry
|
|
5531
5933
|
/**
|
|
@@ -5626,6 +6028,8 @@ class IcicleChart {
|
|
|
5626
6028
|
this._roots = buildHierarchy(this.w);
|
|
5627
6029
|
if (!this._roots.length) return g;
|
|
5628
6030
|
this._roots.forEach((r2) => fillValues(r2));
|
|
6031
|
+
this._nodesAll = [];
|
|
6032
|
+
this._colorNodes();
|
|
5629
6033
|
sortTree(this._roots, this.cfg.sort);
|
|
5630
6034
|
if (this.cfg.partition === "strict") {
|
|
5631
6035
|
validateStrict(this._roots, {
|
|
@@ -5633,15 +6037,17 @@ class IcicleChart {
|
|
|
5633
6037
|
remedy: "Extents are normalized to fill the parent."
|
|
5634
6038
|
});
|
|
5635
6039
|
}
|
|
5636
|
-
this._nodesAll = [];
|
|
5637
|
-
this._colorNodes();
|
|
5638
6040
|
this.total = this._roots.reduce((s2, r2) => s2 + Math.max(0, r2.value), 0) || 1;
|
|
5639
6041
|
this._tooltip.total = this.total;
|
|
5640
6042
|
this._cellsG = graphics.group({ class: "apexcharts-icicle-cells" });
|
|
5641
6043
|
this._labelsG = graphics.group({ class: "apexcharts-icicle-labels" });
|
|
5642
6044
|
g.add(this._cellsG);
|
|
5643
6045
|
g.add(this._labelsG);
|
|
5644
|
-
this._focus =
|
|
6046
|
+
this._focus = focusByKey(
|
|
6047
|
+
w.globals.icicleFocusKey,
|
|
6048
|
+
this._nodesAll,
|
|
6049
|
+
this._roots
|
|
6050
|
+
);
|
|
5645
6051
|
this._relayout(this._focus);
|
|
5646
6052
|
const anims = w.config.chart.animations;
|
|
5647
6053
|
let mode = "none";
|
|
@@ -5672,7 +6078,7 @@ class IcicleChart {
|
|
|
5672
6078
|
const fallback = colors[0] || "#008FFB";
|
|
5673
6079
|
let level = this._roots;
|
|
5674
6080
|
const trunk = [];
|
|
5675
|
-
while (level.length === 1 && level[0].children && level[0].children.length
|
|
6081
|
+
while (level.length === 1 && level[0].children && level[0].children.length) {
|
|
5676
6082
|
trunk.push(level[0]);
|
|
5677
6083
|
level = level[0].children;
|
|
5678
6084
|
}
|
|
@@ -5704,6 +6110,7 @@ class IcicleChart {
|
|
|
5704
6110
|
* @param {any} focus
|
|
5705
6111
|
*/
|
|
5706
6112
|
_relayout(focus) {
|
|
6113
|
+
this.w.globals.icicleFocusKey = focus && focus._key;
|
|
5707
6114
|
const extent = this._valueExtent();
|
|
5708
6115
|
const maxDepth = this.cfg.maxDepth;
|
|
5709
6116
|
const capLevels = typeof maxDepth === "number" && maxDepth > 0 ? maxDepth : 0;
|
|
@@ -5739,9 +6146,14 @@ class IcicleChart {
|
|
|
5739
6146
|
gap: 1
|
|
5740
6147
|
});
|
|
5741
6148
|
this._nodesAll.forEach((n2) => {
|
|
6149
|
+
n2._sub = false;
|
|
5742
6150
|
if (!n2._show) return;
|
|
5743
6151
|
n2._d0 = scale.near(n2._vDepth);
|
|
5744
6152
|
n2._d1 = farEdge(n2, scale, this._focusMaxDepth, this.cfg.leaf, used);
|
|
6153
|
+
if (n2._t1 - n2._t0 < 0.5) {
|
|
6154
|
+
n2._show = false;
|
|
6155
|
+
n2._sub = true;
|
|
6156
|
+
}
|
|
5745
6157
|
});
|
|
5746
6158
|
}
|
|
5747
6159
|
/**
|
|
@@ -5819,31 +6231,30 @@ class IcicleChart {
|
|
|
5819
6231
|
* @param {'intro'|'zoom'|'update'|'none'} mode
|
|
5820
6232
|
*/
|
|
5821
6233
|
_applyLayout(mode) {
|
|
6234
|
+
var _a, _b;
|
|
5822
6235
|
const w = this.w;
|
|
5823
6236
|
const anims = w.config.chart.animations;
|
|
5824
|
-
const
|
|
6237
|
+
const dyn = anims.dynamicAnimation;
|
|
6238
|
+
const dur = !anims.enabled || mode === "none" ? 0 : mode === "intro" ? (_a = anims.speed) != null ? _a : 500 : dyn.enabled ? (_b = dyn.speed) != null ? _b : 350 : 0;
|
|
5825
6239
|
const gen = ++this._zoomGen;
|
|
5826
|
-
const prev = mode
|
|
6240
|
+
const prev = dur > 0 && mode !== "intro" ? (
|
|
5827
6241
|
/** @type {any} */
|
|
5828
6242
|
this.ctx._iciclePrevGeoms
|
|
5829
6243
|
) : null;
|
|
5830
6244
|
this._nodesAll.forEach((node) => {
|
|
6245
|
+
const was = node._cur || prev && prev.get(node._key) && prev.get(node._key)();
|
|
5831
6246
|
if (node._show) {
|
|
5832
6247
|
const to = this._box(node);
|
|
5833
6248
|
if (!node._el) node._el = this._createCellEl(node);
|
|
5834
6249
|
node._el.node.setAttribute("data:clipped", String(!!node._clipped));
|
|
5835
|
-
this
|
|
6250
|
+
setZoomCursor(this, node);
|
|
5836
6251
|
if (mode === "intro" && dur > 0) {
|
|
5837
6252
|
this._wipeCell(node, to, dur, gen);
|
|
5838
6253
|
return;
|
|
5839
6254
|
}
|
|
5840
|
-
let from;
|
|
6255
|
+
let from = was;
|
|
5841
6256
|
let isNew = false;
|
|
5842
|
-
if (
|
|
5843
|
-
from = node._cur;
|
|
5844
|
-
} else if (prev && prev.get(node._key)) {
|
|
5845
|
-
from = prev.get(node._key);
|
|
5846
|
-
} else {
|
|
6257
|
+
if (!from) {
|
|
5847
6258
|
from = {
|
|
5848
6259
|
x: to.x + to.w / 2,
|
|
5849
6260
|
y: to.y + to.h / 2,
|
|
@@ -5853,6 +6264,9 @@ class IcicleChart {
|
|
|
5853
6264
|
isNew = true;
|
|
5854
6265
|
}
|
|
5855
6266
|
this._animateCell(node, from, to, dur, false, isNew, gen);
|
|
6267
|
+
} else if (node._sub && was && !was.s) {
|
|
6268
|
+
if (!node._el) node._el = this._createCellEl(node);
|
|
6269
|
+
this._animateCell(node, was, this._box(node), dur, true, false, gen);
|
|
5856
6270
|
} else if (node._el && node._cur) {
|
|
5857
6271
|
const c = node._cur;
|
|
5858
6272
|
const collapsed = {
|
|
@@ -5866,7 +6280,9 @@ class IcicleChart {
|
|
|
5866
6280
|
});
|
|
5867
6281
|
const geoms = /* @__PURE__ */ new Map();
|
|
5868
6282
|
this._nodesAll.forEach((n2) => {
|
|
5869
|
-
|
|
6283
|
+
const b = this._box(n2);
|
|
6284
|
+
if (n2._sub) b.s = 1;
|
|
6285
|
+
if (n2._show || n2._sub) geoms.set(n2._key, () => n2._cur || b);
|
|
5870
6286
|
});
|
|
5871
6287
|
this.ctx._iciclePrevGeoms = geoms;
|
|
5872
6288
|
this._renderLabels(dur);
|
|
@@ -5961,7 +6377,7 @@ class IcicleChart {
|
|
|
5961
6377
|
}
|
|
5962
6378
|
el.node.style.display = "";
|
|
5963
6379
|
const startOp = hide ? Number(el.attr("opacity")) || 1 : fadeIn ? 0 : 1;
|
|
5964
|
-
const endOp = hide ? 0 : 1;
|
|
6380
|
+
const endOp = hide && !node._sub ? 0 : 1;
|
|
5965
6381
|
el.attr({ opacity: startOp });
|
|
5966
6382
|
el.animate(dur).during((pos) => {
|
|
5967
6383
|
if (this._zoomGen !== gen) return;
|
|
@@ -6023,11 +6439,12 @@ class IcicleChart {
|
|
|
6023
6439
|
this._renderLabel(node);
|
|
6024
6440
|
if (node._clipped) this._renderMoreMark(node);
|
|
6025
6441
|
});
|
|
6442
|
+
const gen = this._zoomGen;
|
|
6443
|
+
labelsG.attr({ opacity: dur > 0 ? 0 : 1 });
|
|
6026
6444
|
if (dur > 0) {
|
|
6027
|
-
labelsG.
|
|
6028
|
-
|
|
6029
|
-
|
|
6030
|
-
labelsG.attr({ opacity: 1 });
|
|
6445
|
+
labelsG.animate(250, dur).during((p) => {
|
|
6446
|
+
if (this._zoomGen === gen) labelsG.attr({ opacity: p });
|
|
6447
|
+
});
|
|
6031
6448
|
}
|
|
6032
6449
|
}
|
|
6033
6450
|
/**
|
|
@@ -6040,7 +6457,6 @@ class IcicleChart {
|
|
|
6040
6457
|
* @param {any} node
|
|
6041
6458
|
*/
|
|
6042
6459
|
_renderLabel(node) {
|
|
6043
|
-
if (!Environment.isBrowser()) return;
|
|
6044
6460
|
const dl = this.cfg.dataLabels;
|
|
6045
6461
|
const style = dl.style;
|
|
6046
6462
|
const box = this._box(node);
|
|
@@ -6053,7 +6469,7 @@ class IcicleChart {
|
|
|
6053
6469
|
const room = along - 8;
|
|
6054
6470
|
let label2 = node.name;
|
|
6055
6471
|
if (dl.showValue) {
|
|
6056
|
-
const full = `${node.name}: ${node.value}`;
|
|
6472
|
+
const full = `${node.name}: ${+node.value.toPrecision(12)}`;
|
|
6057
6473
|
if (this._fits(full, room, fontPx)) label2 = full;
|
|
6058
6474
|
}
|
|
6059
6475
|
const text = this._truncate(label2, room, fontPx);
|
|
@@ -6102,7 +6518,6 @@ class IcicleChart {
|
|
|
6102
6518
|
* @param {any} node
|
|
6103
6519
|
*/
|
|
6104
6520
|
_renderMoreMark(node) {
|
|
6105
|
-
if (!Environment.isBrowser()) return;
|
|
6106
6521
|
const box = this._box(node);
|
|
6107
6522
|
const along = this._vertical ? box.w : box.h;
|
|
6108
6523
|
if (along < 18) return;
|
|
@@ -6153,18 +6568,6 @@ class IcicleChart {
|
|
|
6153
6568
|
return name.slice(0, maxChars - 1) + "…";
|
|
6154
6569
|
}
|
|
6155
6570
|
// ----------------------------------------------------------------- zoom
|
|
6156
|
-
/**
|
|
6157
|
-
* A cell offers the pointer only while clicking it would change the view.
|
|
6158
|
-
* A leaf under the current focus, or the single root of a one-root tree,
|
|
6159
|
-
* resolves to the focus the reader is already on, and a pointer there
|
|
6160
|
-
* promises a zoom that cannot happen. Asked on every layout, because a zoom
|
|
6161
|
-
* changes the answer for every cell.
|
|
6162
|
-
* @param {any} node
|
|
6163
|
-
*/
|
|
6164
|
-
_setCursor(node) {
|
|
6165
|
-
if (!Environment.isBrowser() || this.cfg.zoomOnClick === false) return;
|
|
6166
|
-
node._el.node.style.cursor = resolveFocus(node, this._focus, this._roots).changed ? "pointer" : "default";
|
|
6167
|
-
}
|
|
6168
6571
|
/**
|
|
6169
6572
|
* Focus a node (zoom in), or zoom out one level when the current focus is
|
|
6170
6573
|
* clicked.
|
|
@@ -6353,24 +6756,18 @@ function observationsOf(d, allowFlatY) {
|
|
|
6353
6756
|
return out.length ? out : null;
|
|
6354
6757
|
}
|
|
6355
6758
|
function derivedStats(w, kind) {
|
|
6356
|
-
|
|
6357
|
-
|
|
6358
|
-
|
|
6759
|
+
const all = w.statsDerived || (w.statsDerived = {});
|
|
6760
|
+
return all[kind] || (all[kind] = /* @__PURE__ */ new Map());
|
|
6761
|
+
}
|
|
6762
|
+
function deriveStat(derived, key, values, opts, fn) {
|
|
6763
|
+
const s2 = JSON.stringify(opts) + values;
|
|
6764
|
+
let hit = derived.get(key);
|
|
6765
|
+
if (!hit || hit.s !== s2) derived.set(key, hit = { s: s2, e: fn(values, opts) });
|
|
6766
|
+
return hit.e;
|
|
6359
6767
|
}
|
|
6360
6768
|
function isDerived(derived, key, value) {
|
|
6361
|
-
const
|
|
6362
|
-
|
|
6363
|
-
return false;
|
|
6364
|
-
}
|
|
6365
|
-
for (let k2 = 0; k2 < value.length; k2++) {
|
|
6366
|
-
const a2 = ours[k2];
|
|
6367
|
-
const b = value[k2];
|
|
6368
|
-
if (a2 === b) continue;
|
|
6369
|
-
if (!Array.isArray(a2) || !Array.isArray(b) || a2[0] !== b[0] || a2[1] !== b[1]) {
|
|
6370
|
-
return false;
|
|
6371
|
-
}
|
|
6372
|
-
}
|
|
6373
|
-
return true;
|
|
6769
|
+
const e2 = (derived.get(key) || {}).e;
|
|
6770
|
+
return !!e2 && JSON.stringify(e2.density || e2.summary) === JSON.stringify(value);
|
|
6374
6771
|
}
|
|
6375
6772
|
function raincloudTransform(ser, w) {
|
|
6376
6773
|
var _a, _b;
|
|
@@ -6395,21 +6792,26 @@ function raincloudTransform(ser, w) {
|
|
|
6395
6792
|
if (!values) return d;
|
|
6396
6793
|
const out = __spreadValues({}, y);
|
|
6397
6794
|
if (needDensity) {
|
|
6398
|
-
const est =
|
|
6399
|
-
|
|
6400
|
-
|
|
6401
|
-
|
|
6795
|
+
const est = deriveStat(
|
|
6796
|
+
ourDensity,
|
|
6797
|
+
key,
|
|
6798
|
+
values,
|
|
6799
|
+
{ bandwidth: kde.bandwidth, resolution: kde.resolution },
|
|
6800
|
+
kernelDensity
|
|
6801
|
+
);
|
|
6402
6802
|
if (!est) return d;
|
|
6403
6803
|
out.density = est.density;
|
|
6404
6804
|
out.points = values;
|
|
6405
|
-
ourDensity.set(key, est.density);
|
|
6406
6805
|
}
|
|
6407
6806
|
if (needSummary) {
|
|
6408
|
-
const est =
|
|
6409
|
-
|
|
6410
|
-
|
|
6411
|
-
|
|
6412
|
-
|
|
6807
|
+
const est = deriveStat(
|
|
6808
|
+
ourSummary,
|
|
6809
|
+
key,
|
|
6810
|
+
values,
|
|
6811
|
+
{ whiskers },
|
|
6812
|
+
fiveNumberSummary
|
|
6813
|
+
);
|
|
6814
|
+
if (est) out.summary = est.summary;
|
|
6413
6815
|
}
|
|
6414
6816
|
touched = true;
|
|
6415
6817
|
return __spreadProps(__spreadValues({}, d), { y: out });
|
|
@@ -6438,7 +6840,9 @@ class Breadcrumb {
|
|
|
6438
6840
|
const w = this.w;
|
|
6439
6841
|
const elWrap = w.dom.elWrap;
|
|
6440
6842
|
if (!elWrap) return;
|
|
6441
|
-
const existing = elWrap.querySelector(
|
|
6843
|
+
const existing = elWrap.querySelector(
|
|
6844
|
+
".apexcharts-breadcrumb[aria-label^=Drill]"
|
|
6845
|
+
);
|
|
6442
6846
|
if (existing && existing.parentNode) {
|
|
6443
6847
|
existing.parentNode.removeChild(existing);
|
|
6444
6848
|
}
|
|
@@ -7869,22 +8273,55 @@ class AxisMapping {
|
|
|
7869
8273
|
return w.globals.minX + px * AxisMapping.xRatio(w);
|
|
7870
8274
|
}
|
|
7871
8275
|
/**
|
|
7872
|
-
*
|
|
7873
|
-
*
|
|
7874
|
-
*
|
|
7875
|
-
*
|
|
7876
|
-
*
|
|
8276
|
+
* The plot area on screen, in client px: its corner is where the plot's
|
|
8277
|
+
* group is translated to (translateX, translateY into the svg), and it is
|
|
8278
|
+
* gridWidth by gridHeight. The one screen-to-plot measurement: the tooltip,
|
|
8279
|
+
* zoom, selection and every other pointer reader map through it, so x and y
|
|
8280
|
+
* cannot disagree under CSS zoom.
|
|
8281
|
+
*
|
|
8282
|
+
* Never the `.apexcharts-grid` group's box: a group measures to the union
|
|
8283
|
+
* of what it happens to draw (fact 2 above). The plot's outline starts a
|
|
8284
|
+
* pixel down (`Grid.drawGridArea`), so unless gridlines or row bands reach
|
|
8285
|
+
* the top edge the box starts a pixel below the plot, and on a numeric-x bar
|
|
8286
|
+
* chart the horizontal gridlines run `barPadForNumericAxis` out past both
|
|
8287
|
+
* sides.
|
|
8288
|
+
*
|
|
8289
|
+
* `zoom` is the CSS zoom of any container the chart sits in (screen px per
|
|
8290
|
+
* plot px): the measured svg width over `svgWidth`, the unscaled width it
|
|
8291
|
+
* was drawn at. A distance measured on screen from this corner is divided
|
|
8292
|
+
* by it to land in plot px, the space the series are laid out and painted in.
|
|
8293
|
+
* With nothing mounted to measure, screen px are taken as svg px.
|
|
8294
|
+
*
|
|
8295
|
+
* @param {import('../types/internal').ChartStateW} w
|
|
8296
|
+
* @returns {{ left: number, top: number, width: number, height: number, zoom: number }}
|
|
8297
|
+
*/
|
|
8298
|
+
static plotRect(w) {
|
|
8299
|
+
var _a, _b, _c;
|
|
8300
|
+
const svg = ((_a = w.dom.Paper) == null ? void 0 : _a.node) || ((_b = w.dom.baseEl) == null ? void 0 : _b.querySelector(".apexcharts-svg"));
|
|
8301
|
+
const box = ((_c = svg || w.dom.elWrap) == null ? void 0 : _c.getBoundingClientRect()) || {
|
|
8302
|
+
left: 0,
|
|
8303
|
+
top: 0,
|
|
8304
|
+
width: 0
|
|
8305
|
+
};
|
|
8306
|
+
const zoom = (svg && w.globals.svgWidth ? box.width / w.globals.svgWidth : 1) || 1;
|
|
8307
|
+
return {
|
|
8308
|
+
left: box.left + w.layout.translateX * zoom,
|
|
8309
|
+
top: box.top + w.layout.translateY * zoom,
|
|
8310
|
+
width: w.layout.gridWidth * zoom,
|
|
8311
|
+
height: w.layout.gridHeight * zoom,
|
|
8312
|
+
zoom
|
|
8313
|
+
};
|
|
8314
|
+
}
|
|
8315
|
+
/**
|
|
8316
|
+
* Client (screen) x -> pixels from the plot origin of {@link plotRect}.
|
|
8317
|
+
* Pass the rect when the caller has already measured it.
|
|
7877
8318
|
* @param {import('../types/internal').ChartStateW} w
|
|
7878
8319
|
* @param {number} screenX
|
|
8320
|
+
* @param {{ left: number, zoom: number }} [plot]
|
|
7879
8321
|
* @returns {number}
|
|
7880
8322
|
*/
|
|
7881
|
-
static screenXToPlotPx(w, screenX) {
|
|
7882
|
-
|
|
7883
|
-
const svg = baseEl && baseEl.querySelector(".apexcharts-svg");
|
|
7884
|
-
if (!svg) return screenX - w.layout.translateX;
|
|
7885
|
-
const svgRect = svg.getBoundingClientRect();
|
|
7886
|
-
const zoom = w.globals.svgWidth ? svgRect.width / w.globals.svgWidth : 1;
|
|
7887
|
-
return (screenX - svgRect.left) / (zoom || 1) - w.layout.translateX;
|
|
8323
|
+
static screenXToPlotPx(w, screenX, plot = AxisMapping.plotRect(w)) {
|
|
8324
|
+
return (screenX - plot.left) / plot.zoom;
|
|
7888
8325
|
}
|
|
7889
8326
|
}
|
|
7890
8327
|
const VPAD = 3;
|
|
@@ -8077,7 +8514,8 @@ class StreamLabels {
|
|
|
8077
8514
|
text: name,
|
|
8078
8515
|
maxWidth: span,
|
|
8079
8516
|
fontSize: `${px}px`,
|
|
8080
|
-
fontFamily
|
|
8517
|
+
fontFamily,
|
|
8518
|
+
fontWeight
|
|
8081
8519
|
});
|
|
8082
8520
|
if (!text || text === "...") continue;
|
|
8083
8521
|
const drawnWidth = text === name ? rect.width : rect.width * (text.length / name.length);
|
|
@@ -8928,7 +9366,8 @@ class RendererController {
|
|
|
8928
9366
|
this._activate(desired, this._instances[desired]);
|
|
8929
9367
|
return this._activeKind;
|
|
8930
9368
|
}
|
|
8931
|
-
if (mode === desired) {
|
|
9369
|
+
if (mode === desired && !this._warned) {
|
|
9370
|
+
this._warned = 1;
|
|
8932
9371
|
warnMissingFeature(
|
|
8933
9372
|
`\`chart.renderer: '${desired}'\``,
|
|
8934
9373
|
`renderer-${desired}`,
|
|
@@ -8937,11 +9376,17 @@ class RendererController {
|
|
|
8937
9376
|
}
|
|
8938
9377
|
);
|
|
8939
9378
|
}
|
|
8940
|
-
} else if (mode === "canvas" && hasCanvasUnsupportedFeature(this.w)) {
|
|
9379
|
+
} else if (mode === "canvas" && !this._warned && hasCanvasUnsupportedFeature(this.w)) {
|
|
9380
|
+
this._warned = 1;
|
|
8941
9381
|
console.warn(
|
|
8942
9382
|
`[apexcharts] renderer:"canvas" requested but this chart uses a feature the canvas renderer does not render yet (gradient/pattern/image fill or a state color-matrix filter); falling back to SVG.`
|
|
8943
9383
|
);
|
|
8944
9384
|
}
|
|
9385
|
+
const prev = this._instances[this._activeKind];
|
|
9386
|
+
if (prev) {
|
|
9387
|
+
prev.destroy();
|
|
9388
|
+
delete this._instances[this._activeKind];
|
|
9389
|
+
}
|
|
8945
9390
|
this._activate("svg", this.svg);
|
|
8946
9391
|
return this._activeKind;
|
|
8947
9392
|
}
|
|
@@ -10058,9 +10503,11 @@ class HeatmapGradientLegend {
|
|
|
10058
10503
|
this._min = 0;
|
|
10059
10504
|
this._max = 0;
|
|
10060
10505
|
this._geom = null;
|
|
10506
|
+
this._grad = null;
|
|
10061
10507
|
this._bandHitEls = [];
|
|
10062
10508
|
this._activeBandIndex = -1;
|
|
10063
10509
|
this._targetEl = null;
|
|
10510
|
+
this.panelsW = null;
|
|
10064
10511
|
this._onCellEnter = this._onCellEnter.bind(this);
|
|
10065
10512
|
this._onCellLeave = this._onCellLeave.bind(this);
|
|
10066
10513
|
this._onBandEnter = this._onBandEnter.bind(this);
|
|
@@ -10175,15 +10622,8 @@ class HeatmapGradientLegend {
|
|
|
10175
10622
|
linearGrad.setAttribute("x2", "1");
|
|
10176
10623
|
linearGrad.setAttribute("y2", "0");
|
|
10177
10624
|
}
|
|
10178
|
-
|
|
10179
|
-
|
|
10180
|
-
this._max = max;
|
|
10181
|
-
stops.forEach((s2) => {
|
|
10182
|
-
const stopEl = BrowserAPIs.createElementNS(SVG_NS, "stop");
|
|
10183
|
-
stopEl.setAttribute("offset", `${(s2.percent * 100).toFixed(2)}%`);
|
|
10184
|
-
stopEl.setAttribute("stop-color", s2.color);
|
|
10185
|
-
linearGrad.appendChild(stopEl);
|
|
10186
|
-
});
|
|
10625
|
+
this._grad = linearGrad;
|
|
10626
|
+
const { min, max, bands } = this._paintStops();
|
|
10187
10627
|
defs.appendChild(linearGrad);
|
|
10188
10628
|
svg.appendChild(defs);
|
|
10189
10629
|
const rect = BrowserAPIs.createElementNS(SVG_NS, "rect");
|
|
@@ -10392,6 +10832,7 @@ class HeatmapGradientLegend {
|
|
|
10392
10832
|
*/
|
|
10393
10833
|
repositionToPlot() {
|
|
10394
10834
|
var _a, _b;
|
|
10835
|
+
if (this._grad) this._paintStops();
|
|
10395
10836
|
if (!Environment.isBrowser()) return;
|
|
10396
10837
|
if (this._targetEl) return;
|
|
10397
10838
|
const w = this.w;
|
|
@@ -10526,14 +10967,25 @@ class HeatmapGradientLegend {
|
|
|
10526
10967
|
if (idx < 0 || idx === this._activeBandIndex) return;
|
|
10527
10968
|
this._activeBandIndex = idx;
|
|
10528
10969
|
(_d = (_c = (_b = this.ctx) == null ? void 0 : _b.events) == null ? void 0 : _c.fireEvent) == null ? void 0 : _d.call(_c, "legendHover", [this.ctx, idx, w]);
|
|
10529
|
-
|
|
10970
|
+
this._highlightRange(idx, "highlight");
|
|
10530
10971
|
}
|
|
10531
10972
|
/** Leaving a band clears the highlight. */
|
|
10532
10973
|
_onBandLeave() {
|
|
10533
10974
|
if (this._activeBandIndex < 0) return;
|
|
10534
10975
|
const idx = this._activeBandIndex;
|
|
10535
10976
|
this._activeBandIndex = -1;
|
|
10536
|
-
|
|
10977
|
+
this._highlightRange(idx, "reset");
|
|
10978
|
+
}
|
|
10979
|
+
/**
|
|
10980
|
+
* A shared trellis strip sets `panelsW` so a band reaches every panel.
|
|
10981
|
+
* @param {number} idx
|
|
10982
|
+
* @param {'highlight'|'reset'} action
|
|
10983
|
+
*/
|
|
10984
|
+
_highlightRange(idx, action) {
|
|
10985
|
+
var _a;
|
|
10986
|
+
(((_a = this.panelsW) == null ? void 0 : _a.call(this)) || [this.w]).forEach(
|
|
10987
|
+
(w) => new Series(w).highlightRangeInSeries(idx, action)
|
|
10988
|
+
);
|
|
10537
10989
|
}
|
|
10538
10990
|
_attachHoverListeners() {
|
|
10539
10991
|
var _a, _b;
|
|
@@ -10555,10 +11007,10 @@ class HeatmapGradientLegend {
|
|
|
10555
11007
|
*/
|
|
10556
11008
|
_onCellEnter(...args) {
|
|
10557
11009
|
var _a, _b, _c;
|
|
10558
|
-
const w = this.w;
|
|
10559
11010
|
if (!this.arrowEl) return;
|
|
10560
11011
|
const opts = args[args.length - 1];
|
|
10561
11012
|
if (!opts || typeof opts !== "object") return;
|
|
11013
|
+
const w = opts.w || this.w;
|
|
10562
11014
|
const i2 = opts.seriesIndex;
|
|
10563
11015
|
const j2 = opts.dataPointIndex;
|
|
10564
11016
|
if (typeof i2 !== "number" || typeof j2 !== "number") return;
|
|
@@ -10670,6 +11122,21 @@ class HeatmapGradientLegend {
|
|
|
10670
11122
|
polygon.setAttribute("pointer-events", "none");
|
|
10671
11123
|
return polygon;
|
|
10672
11124
|
}
|
|
11125
|
+
/** (Re)write the strip's stops; returns `_computeStops()`. */
|
|
11126
|
+
_paintStops() {
|
|
11127
|
+
const r2 = this._computeStops();
|
|
11128
|
+
const grad = this._grad;
|
|
11129
|
+
this._min = r2.min;
|
|
11130
|
+
this._max = r2.max;
|
|
11131
|
+
grad.innerHTML = "";
|
|
11132
|
+
r2.stops.forEach((s2) => {
|
|
11133
|
+
const stopEl = BrowserAPIs.createElementNS(SVG_NS, "stop");
|
|
11134
|
+
stopEl.setAttribute("offset", `${(s2.percent * 100).toFixed(2)}%`);
|
|
11135
|
+
stopEl.setAttribute("stop-color", s2.color);
|
|
11136
|
+
grad.appendChild(stopEl);
|
|
11137
|
+
});
|
|
11138
|
+
return r2;
|
|
11139
|
+
}
|
|
10673
11140
|
/**
|
|
10674
11141
|
* Build gradient stops + return effective min/max.
|
|
10675
11142
|
* - If `colorScale.ranges` is set, stops are placed at each range boundary
|
|
@@ -10711,7 +11178,8 @@ class HeatmapGradientLegend {
|
|
|
10711
11178
|
if (!Number.isFinite(dataMax)) dataMax = 0;
|
|
10712
11179
|
let min = dataMin;
|
|
10713
11180
|
let max = dataMax;
|
|
10714
|
-
|
|
11181
|
+
const csWindow = typeof cs.min !== "undefined" && typeof cs.max !== "undefined" && cs.max > cs.min;
|
|
11182
|
+
if (csWindow) {
|
|
10715
11183
|
min = cs.min;
|
|
10716
11184
|
max = cs.max;
|
|
10717
11185
|
} else {
|
|
@@ -10742,34 +11210,30 @@ class HeatmapGradientLegend {
|
|
|
10742
11210
|
} else {
|
|
10743
11211
|
const baseColor = w.globals.colors[0] || "#008FFB";
|
|
10744
11212
|
const utils = new Utils();
|
|
10745
|
-
const
|
|
11213
|
+
const type = w.config.chart.type;
|
|
11214
|
+
const plot = w.config.plotOptions[type] || {};
|
|
10746
11215
|
const shadeIntensity = (_b = plot.shadeIntensity) != null ? _b : 0.5;
|
|
10747
|
-
const
|
|
11216
|
+
const g = (
|
|
10748
11217
|
/** @type {any} */
|
|
10749
|
-
w.globals
|
|
11218
|
+
w.globals
|
|
10750
11219
|
);
|
|
11220
|
+
const hasNegs = g.hasNegs;
|
|
11221
|
+
const yExt = type === "heatmap" && !plot.distributed && !csWindow && g.maxY >= g.minY;
|
|
11222
|
+
const hi = yExt ? g.maxY : max;
|
|
11223
|
+
const total = Math.abs(hi) + Math.abs(yExt ? cs.min < g.minY ? cs.min : g.minY : min);
|
|
11224
|
+
const k2 = shadeIntensity * 1.25;
|
|
10751
11225
|
const n2 = Math.max(2, cfg.stops || 16);
|
|
10752
11226
|
for (let s2 = 0; s2 < n2; s2++) {
|
|
10753
11227
|
const t2 = s2 / (n2 - 1);
|
|
10754
|
-
const
|
|
10755
|
-
const
|
|
10756
|
-
|
|
10757
|
-
|
|
10758
|
-
|
|
10759
|
-
|
|
10760
|
-
|
|
10761
|
-
|
|
10762
|
-
|
|
10763
|
-
}
|
|
10764
|
-
} else {
|
|
10765
|
-
colorShadePercent = 1 - percent_v / 100;
|
|
10766
|
-
}
|
|
10767
|
-
if (colorShadePercent > 1) colorShadePercent = 1;
|
|
10768
|
-
if (colorShadePercent < -1) colorShadePercent = -1;
|
|
10769
|
-
const shaded = plot.enableShades ? utils.shadeColor(
|
|
10770
|
-
w.config.theme.mode === "dark" ? colorShadePercent * -1 : colorShadePercent,
|
|
10771
|
-
baseColor
|
|
10772
|
-
) : baseColor;
|
|
11228
|
+
const p = total === 0 ? 0 : Math.min(min + t2 * (max - min), hi) / total;
|
|
11229
|
+
const c = Math.max(
|
|
11230
|
+
-1,
|
|
11231
|
+
Math.min(
|
|
11232
|
+
1,
|
|
11233
|
+
hasNegs ? plot.reverseNegativeShade ? (p < 0 ? p : 1 - p) * k2 : p <= 0 ? 1 - (1 + p) * shadeIntensity : (1 - p) * shadeIntensity : (1 - p) * (type === "treemap" ? k2 : 1)
|
|
11234
|
+
)
|
|
11235
|
+
);
|
|
11236
|
+
const shaded = plot.enableShades ? utils.shadeColor(w.config.theme.mode === "dark" ? -c : c, baseColor) : baseColor;
|
|
10773
11237
|
stops.push({ percent: t2, color: shaded });
|
|
10774
11238
|
}
|
|
10775
11239
|
}
|
|
@@ -10794,6 +11258,7 @@ class TrellisChrome {
|
|
|
10794
11258
|
this.elBreadcrumb = null;
|
|
10795
11259
|
this.gradientLegend = null;
|
|
10796
11260
|
this._gradPending = null;
|
|
11261
|
+
this._gradWire = null;
|
|
10797
11262
|
}
|
|
10798
11263
|
/**
|
|
10799
11264
|
* The per-cell facet header. Built with the cell, before the panel mounts,
|
|
@@ -11024,17 +11489,20 @@ class TrellisChrome {
|
|
|
11024
11489
|
const legend = new HeatmapGradientLegend(chart.w, chart.ctx);
|
|
11025
11490
|
legend.draw(slot);
|
|
11026
11491
|
this.gradientLegend = legend;
|
|
11027
|
-
t2.panels.
|
|
11492
|
+
legend.panelsW = () => t2.panels.filter((p) => p.chart).map((p) => (
|
|
11493
|
+
/** @type {any} */
|
|
11494
|
+
p.chart.w
|
|
11495
|
+
));
|
|
11496
|
+
const wire = (_2, p) => {
|
|
11028
11497
|
var _a;
|
|
11029
|
-
|
|
11030
|
-
|
|
11031
|
-
/** @type {any} */
|
|
11032
|
-
(_a = p.chart.ctx) == null ? void 0 : _a.events
|
|
11033
|
-
);
|
|
11034
|
-
if (!(ev == null ? void 0 : ev.addEventListener)) return;
|
|
11498
|
+
const ev = p.chart !== chart && ((_a = p.chart) == null ? void 0 : _a.ctx.events);
|
|
11499
|
+
if (!ev) return;
|
|
11035
11500
|
ev.addEventListener("dataPointMouseEnter", legend._onCellEnter);
|
|
11036
11501
|
ev.addEventListener("dataPointMouseLeave", legend._onCellLeave);
|
|
11037
|
-
}
|
|
11502
|
+
};
|
|
11503
|
+
t2.panels.forEach((p) => wire(0, p));
|
|
11504
|
+
t2.ctx.events.addEventListener("panelMounted", wire);
|
|
11505
|
+
this._gradWire = wire;
|
|
11038
11506
|
}
|
|
11039
11507
|
/** Tear down the shared gradient strip (P5). */
|
|
11040
11508
|
destroyGradientLegend() {
|
|
@@ -11044,6 +11512,7 @@ class TrellisChrome {
|
|
|
11044
11512
|
(_b = (_a = t2.ctx.events).removeEventListener) == null ? void 0 : _b.call(_a, "panelMounted", this._gradPending);
|
|
11045
11513
|
this._gradPending = null;
|
|
11046
11514
|
}
|
|
11515
|
+
t2.ctx.events.removeEventListener("panelMounted", this._gradWire);
|
|
11047
11516
|
if (this.gradientLegend) {
|
|
11048
11517
|
try {
|
|
11049
11518
|
this.gradientLegend.destroy();
|
|
@@ -11360,6 +11829,7 @@ class TrellisSync {
|
|
|
11360
11829
|
});
|
|
11361
11830
|
};
|
|
11362
11831
|
const loop = () => {
|
|
11832
|
+
if (elGrid !== this.trellis.elGrid) return raf2 = 0;
|
|
11363
11833
|
apply();
|
|
11364
11834
|
raf2 = hoverTarget ? requestAnimationFrame(loop) : 0;
|
|
11365
11835
|
};
|
|
@@ -11842,15 +12312,33 @@ class TrellisVirtual {
|
|
|
11842
12312
|
this._gutterFloor = 0;
|
|
11843
12313
|
}
|
|
11844
12314
|
}
|
|
11845
|
-
|
|
11846
|
-
|
|
12315
|
+
Object.setPrototypeOf(
|
|
12316
|
+
{
|
|
12317
|
+
funnel: "bar",
|
|
12318
|
+
pyramid: "bar",
|
|
12319
|
+
gauge: "radialBar",
|
|
12320
|
+
waffle: "unit",
|
|
12321
|
+
histogram: "bar",
|
|
12322
|
+
waterfall: "rangeBar",
|
|
12323
|
+
dumbbell: "rangeBar",
|
|
12324
|
+
streamgraph: "rangeArea",
|
|
12325
|
+
raincloud: "violin",
|
|
12326
|
+
// `column` is the name half the world uses for a vertical bar chart, and the
|
|
12327
|
+
// combo path has always accepted it on `series[].type`. On `chart.type` it
|
|
12328
|
+
// used to fall through every dispatch and die inside the renderer (#5325),
|
|
12329
|
+
// so it is spelled out here as what it has always meant.
|
|
12330
|
+
column: "bar"
|
|
12331
|
+
},
|
|
12332
|
+
null
|
|
12333
|
+
);
|
|
12334
|
+
const BAR_PATHWAY_TYPES = [
|
|
11847
12335
|
"bar",
|
|
11848
|
-
"column",
|
|
11849
12336
|
"rangeBar",
|
|
11850
12337
|
"candlestick",
|
|
11851
12338
|
"boxPlot",
|
|
11852
12339
|
"violin"
|
|
11853
12340
|
];
|
|
12341
|
+
const CURSOR_PAD = 14;
|
|
11854
12342
|
class TrellisTooltip {
|
|
11855
12343
|
/**
|
|
11856
12344
|
* @param {import('./Trellis').default} trellis
|
|
@@ -11915,7 +12403,7 @@ class TrellisTooltip {
|
|
|
11915
12403
|
return -1;
|
|
11916
12404
|
}
|
|
11917
12405
|
}
|
|
11918
|
-
const slotted = (
|
|
12406
|
+
const slotted = (BAR_PATHWAY_TYPES.includes(w.config.chart.type) || w.config.xaxis.tickPlacement === "between") && !w.config.xaxis.convertedCatToNumeric;
|
|
11919
12407
|
const j2 = slotted ? Math.ceil(hoverX / (gridWidth / n2)) - 1 : Math.round(hoverX / (gridWidth / Math.max(1, n2 - 1)));
|
|
11920
12408
|
return Math.max(0, Math.min(n2 - 1, j2));
|
|
11921
12409
|
}
|
|
@@ -13063,8 +13551,12 @@ class Trellis {
|
|
|
13063
13551
|
// gap is the breathing room here).
|
|
13064
13552
|
parentHeightOffset: 0,
|
|
13065
13553
|
toolbar: { show: false },
|
|
13554
|
+
// the shared toolbar owns the one reset (TrellisSync.resetAll); with
|
|
13555
|
+
// toolbar 'none' a panel's own reset is the only way back, unless the
|
|
13556
|
+
// page turned it off
|
|
13066
13557
|
zoom: {
|
|
13067
|
-
enabled: this.cfg.zoom !== "none"
|
|
13558
|
+
enabled: this.cfg.zoom !== "none",
|
|
13559
|
+
resetControl: this.cfg.toolbar == "none" && w.config.chart.zoom.resetControl !== false
|
|
13068
13560
|
}
|
|
13069
13561
|
}, animationsOff ? { animations: { enabled: false } } : {}), this._panelRenderer ? { renderer: this._panelRenderer } : {}), {
|
|
13070
13562
|
events: __spreadProps(__spreadValues({}, userEvents), {
|
|
@@ -15870,6 +16362,7 @@ function licensedForPremium(key) {
|
|
|
15870
16362
|
}
|
|
15871
16363
|
function reinstateWatermark(ctx, elWrap) {
|
|
15872
16364
|
const node = C.add(elWrap, { manage: false });
|
|
16365
|
+
ctx._wmPainted = true;
|
|
15873
16366
|
if (!node || typeof MutationObserver === "undefined") return;
|
|
15874
16367
|
if (ctx._wmNodeObserver && ctx._wmObservedNode === node) return;
|
|
15875
16368
|
if (ctx._wmNodeObserver) ctx._wmNodeObserver.disconnect();
|
|
@@ -15898,6 +16391,8 @@ function addWatermark(ctx, elWrap) {
|
|
|
15898
16391
|
ctx._wmObservedWrap = elWrap;
|
|
15899
16392
|
}
|
|
15900
16393
|
function teardownWatermark(ctx, elWrap) {
|
|
16394
|
+
if (!ctx._wmPainted) return;
|
|
16395
|
+
ctx._wmPainted = false;
|
|
15901
16396
|
if (ctx._wmWrapObserver) {
|
|
15902
16397
|
ctx._wmWrapObserver.disconnect();
|
|
15903
16398
|
ctx._wmWrapObserver = null;
|
|
@@ -17290,6 +17785,7 @@ class CanvasGraphics {
|
|
|
17290
17785
|
cmd.strokeWidth = opts.strokeWidth;
|
|
17291
17786
|
cmd.fill = opts.fill;
|
|
17292
17787
|
cmd.lineCap = opts.strokeLinecap;
|
|
17788
|
+
cmd.strokeDash = this._g.seriesDash(opts.realIndex);
|
|
17293
17789
|
cmd.si = opts.realIndex;
|
|
17294
17790
|
if (typeof opts.j === "number") cmd.dj = opts.j;
|
|
17295
17791
|
if (opts.shouldClipToGrid !== false) {
|
|
@@ -18959,405 +19455,135 @@ class History {
|
|
|
18959
19455
|
return;
|
|
18960
19456
|
}
|
|
18961
19457
|
applyViewInteraction(this.ctx, cp.view);
|
|
18962
|
-
this._refreshSettle();
|
|
18963
|
-
this._emitChange();
|
|
18964
|
-
}).catch(() => {
|
|
18965
|
-
this.applying = false;
|
|
18966
|
-
});
|
|
18967
|
-
}
|
|
18968
|
-
/**
|
|
18969
|
-
* Hold `applying` true until the restore's burst of async 'updated' events
|
|
18970
|
-
* has drained (one macrotask after the last one). Refreshed by _onUpdated.
|
|
18971
|
-
*/
|
|
18972
|
-
_refreshSettle() {
|
|
18973
|
-
if (!Environment.isBrowser()) {
|
|
18974
|
-
this.applying = false;
|
|
18975
|
-
return;
|
|
18976
|
-
}
|
|
18977
|
-
clearTimeout(this._settleTimer);
|
|
18978
|
-
this._settleTimer = setTimeout(() => {
|
|
18979
|
-
this.applying = false;
|
|
18980
|
-
}, 0);
|
|
18981
|
-
}
|
|
18982
|
-
// ─── Public API ─────────────────────────────────────────────────────────
|
|
18983
|
-
/**
|
|
18984
|
-
* Commit a checkpoint of the current state now (a discrete undo step). Used by
|
|
18985
|
-
* callers that mutate `w.config` without going through a full re-render (e.g.
|
|
18986
|
-
* Ink Layer's targeted annotation redraws, which fire no 'updated' event).
|
|
18987
|
-
* No-op when disabled or while a restore is applying.
|
|
18988
|
-
* @param {string} [label]
|
|
18989
|
-
*/
|
|
18990
|
-
snapshot(label2) {
|
|
18991
|
-
if (!this.enabled || this.applying) return;
|
|
18992
|
-
this._commit(label2 || "change");
|
|
18993
|
-
}
|
|
18994
|
-
/**
|
|
18995
|
-
* @param {boolean} [animate]
|
|
18996
|
-
*/
|
|
18997
|
-
undo(animate = true) {
|
|
18998
|
-
if (!this.canUndo()) return;
|
|
18999
|
-
this.pointer--;
|
|
19000
|
-
this._restore(this.stack[this.pointer], animate);
|
|
19001
|
-
}
|
|
19002
|
-
/**
|
|
19003
|
-
* @param {boolean} [animate]
|
|
19004
|
-
*/
|
|
19005
|
-
redo(animate = true) {
|
|
19006
|
-
if (!this.canRedo()) return;
|
|
19007
|
-
this.pointer++;
|
|
19008
|
-
this._restore(this.stack[this.pointer], animate);
|
|
19009
|
-
}
|
|
19010
|
-
canUndo() {
|
|
19011
|
-
return this.pointer > 0;
|
|
19012
|
-
}
|
|
19013
|
-
canRedo() {
|
|
19014
|
-
return this.pointer > -1 && this.pointer < this.stack.length - 1;
|
|
19015
|
-
}
|
|
19016
|
-
/**
|
|
19017
|
-
* @param {string} id
|
|
19018
|
-
* @param {boolean} [animate]
|
|
19019
|
-
*/
|
|
19020
|
-
jump(id, animate = true) {
|
|
19021
|
-
const idx = this.stack.findIndex((c) => c.id === id);
|
|
19022
|
-
if (idx === -1 || idx === this.pointer) return;
|
|
19023
|
-
this.pointer = idx;
|
|
19024
|
-
this._restore(this.stack[idx], animate);
|
|
19025
|
-
}
|
|
19026
|
-
/** Clear the history, keeping the current state as the new baseline. */
|
|
19027
|
-
clear() {
|
|
19028
|
-
clearTimeout(this._coalesceTimer);
|
|
19029
|
-
this._coalesceTimer = null;
|
|
19030
|
-
const current = this.stack[this.pointer];
|
|
19031
|
-
this.stack = current ? [current] : [];
|
|
19032
|
-
this.pointer = this.stack.length - 1;
|
|
19033
|
-
this._emitChange();
|
|
19034
|
-
}
|
|
19035
|
-
/**
|
|
19036
|
-
* Group multiple edits into a single undo step. `fn` may be async; await your
|
|
19037
|
-
* updateOptions/updateSeries calls inside it so the intermediate 'updated'
|
|
19038
|
-
* events are suppressed and only one checkpoint is committed afterwards.
|
|
19039
|
-
* @param {() => (void | Promise<any>)} fn
|
|
19040
|
-
* @param {{ label?: string }} [opts]
|
|
19041
|
-
* @returns {Promise<void>}
|
|
19042
|
-
*/
|
|
19043
|
-
transaction(fn, opts = {}) {
|
|
19044
|
-
if (typeof fn !== "function") return Promise.resolve();
|
|
19045
|
-
const wasBatching = this._batching;
|
|
19046
|
-
this._batching = true;
|
|
19047
|
-
return Promise.resolve().then(() => fn()).finally(() => {
|
|
19048
|
-
this._batching = wasBatching;
|
|
19049
|
-
if (!wasBatching) this._commit(opts.label || "transaction", true);
|
|
19050
|
-
});
|
|
19051
|
-
}
|
|
19052
|
-
/**
|
|
19053
|
-
* @returns {{ id: string, label: string, at: number }[]}
|
|
19054
|
-
*/
|
|
19055
|
-
entries() {
|
|
19056
|
-
return this.stack.map((c) => ({ id: c.id, label: c.label, at: c.at }));
|
|
19057
|
-
}
|
|
19058
|
-
/** Lightweight state for the historyChange event / a history-rail UI. */
|
|
19059
|
-
state() {
|
|
19060
|
-
return {
|
|
19061
|
-
canUndo: this.canUndo(),
|
|
19062
|
-
canRedo: this.canRedo(),
|
|
19063
|
-
index: this.pointer,
|
|
19064
|
-
length: this.stack.length
|
|
19065
|
-
};
|
|
19066
|
-
}
|
|
19067
|
-
_emitChange() {
|
|
19068
|
-
this.ctx.events.fireEvent("historyChange", [this.ctx, this.state()]);
|
|
19069
|
-
}
|
|
19070
|
-
/** Drop the stack + detach listeners (called on full destroy). */
|
|
19071
|
-
teardown() {
|
|
19072
|
-
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
19073
|
-
clearTimeout(this._coalesceTimer);
|
|
19074
|
-
clearTimeout(this._settleTimer);
|
|
19075
|
-
this._coalesceTimer = null;
|
|
19076
|
-
this._settleTimer = null;
|
|
19077
|
-
this._unwireKeyboard();
|
|
19078
|
-
if (this._wired) {
|
|
19079
|
-
(_b = (_a = this.ctx).removeEventListener) == null ? void 0 : _b.call(_a, "mounted", this._onMounted);
|
|
19080
|
-
(_d = (_c = this.ctx).removeEventListener) == null ? void 0 : _d.call(_c, "updated", this._onUpdated);
|
|
19081
|
-
(_f = (_e = this.ctx).removeEventListener) == null ? void 0 : _f.call(_e, "scrolled", this._onUpdated);
|
|
19082
|
-
(_h = (_g = this.ctx).removeEventListener) == null ? void 0 : _h.call(_g, "dataPointSelection", this._onSelection);
|
|
19083
|
-
}
|
|
19084
|
-
this.stack = [];
|
|
19085
|
-
this.pointer = -1;
|
|
19086
|
-
this._wired = false;
|
|
19087
|
-
}
|
|
19088
|
-
}
|
|
19089
|
-
ApexCharts__default.registerFeatures({ history: History });
|
|
19090
|
-
const DataLabels = ApexCharts.__apex_DataLabels;
|
|
19091
|
-
const resolveEasing = ApexCharts.__apex_Easing_resolveEasing;
|
|
19092
|
-
const parsePath = ApexCharts.__apex_PathMorphing_parsePath;
|
|
19093
|
-
const arrayToPath = ApexCharts.__apex_PathMorphing_arrayToPath;
|
|
19094
|
-
function buildUnionEntries(join, oldN) {
|
|
19095
|
-
const exitSet = new Set(join.exits);
|
|
19096
|
-
const entries = [];
|
|
19097
|
-
let oi = 0;
|
|
19098
|
-
for (let nj = 0; nj < join.toOld.length; nj++) {
|
|
19099
|
-
const oj = join.toOld[nj];
|
|
19100
|
-
if (oj !== -1) {
|
|
19101
|
-
while (oi < oj) {
|
|
19102
|
-
if (exitSet.has(oi)) entries.push({ oldJ: oi, newJ: -1 });
|
|
19103
|
-
oi++;
|
|
19104
|
-
}
|
|
19105
|
-
entries.push({ oldJ: oj, newJ: nj });
|
|
19106
|
-
oi = oj + 1;
|
|
19107
|
-
} else {
|
|
19108
|
-
entries.push({ oldJ: -1, newJ: nj });
|
|
19109
|
-
}
|
|
19110
|
-
}
|
|
19111
|
-
while (oi < oldN) {
|
|
19112
|
-
if (exitSet.has(oi)) entries.push({ oldJ: oi, newJ: -1 });
|
|
19113
|
-
oi++;
|
|
19114
|
-
}
|
|
19115
|
-
return entries;
|
|
19116
|
-
}
|
|
19117
|
-
function analyzeSeriesPath(d, expectedAnchors, isArea) {
|
|
19118
|
-
if (!d || typeof d !== "string") return null;
|
|
19119
|
-
const cmds = parsePath(d);
|
|
19120
|
-
if (!cmds.length || cmds[0][0] !== "M") return null;
|
|
19121
|
-
for (let i2 = 1; i2 < cmds.length; i2++) {
|
|
19122
|
-
if (cmds[i2][0] === "M") return null;
|
|
19123
|
-
}
|
|
19124
|
-
let body = cmds;
|
|
19125
|
-
let closing = null;
|
|
19126
|
-
if (isArea) {
|
|
19127
|
-
if (cmds.length < 5) return null;
|
|
19128
|
-
closing = cmds.slice(-3);
|
|
19129
|
-
body = cmds.slice(0, -3);
|
|
19130
|
-
if (closing[2][0] !== "Z") return null;
|
|
19131
|
-
if (closing[1][0] !== "L") return null;
|
|
19132
|
-
if (closing[0][0] !== "L" && closing[0][0] !== "C") return null;
|
|
19133
|
-
} else if (cmds[cmds.length - 1][0] === "Z") {
|
|
19134
|
-
return null;
|
|
19135
|
-
}
|
|
19136
|
-
if (body.length !== expectedAnchors || body.length < 2) return null;
|
|
19137
|
-
const segType = body[1][0];
|
|
19138
|
-
if (segType !== "L" && segType !== "C") return null;
|
|
19139
|
-
for (let i2 = 2; i2 < body.length; i2++) {
|
|
19140
|
-
if (body[i2][0] !== segType) return null;
|
|
19141
|
-
}
|
|
19142
|
-
const anchors = body.map(
|
|
19143
|
-
(c) => c[0] === "C" ? [Number(c[5]), Number(c[6])] : [Number(c[1]), Number(c[2])]
|
|
19144
|
-
);
|
|
19145
|
-
for (const a2 of anchors) {
|
|
19146
|
-
if (!isFinite(a2[0]) || !isFinite(a2[1])) return null;
|
|
19147
|
-
}
|
|
19148
|
-
return { body, closing, segType, anchors };
|
|
19149
|
-
}
|
|
19150
|
-
function lerpPt(a2, b, t2) {
|
|
19151
|
-
return [a2[0] + (b[0] - a2[0]) * t2, a2[1] + (b[1] - a2[1]) * t2];
|
|
19152
|
-
}
|
|
19153
|
-
function splitCubic(s2, cmd, t2) {
|
|
19154
|
-
const p0 = s2;
|
|
19155
|
-
const p1 = [cmd[1], cmd[2]];
|
|
19156
|
-
const p2 = [cmd[3], cmd[4]];
|
|
19157
|
-
const p3 = [cmd[5], cmd[6]];
|
|
19158
|
-
const p01 = lerpPt(p0, p1, t2);
|
|
19159
|
-
const p12 = lerpPt(p1, p2, t2);
|
|
19160
|
-
const p23 = lerpPt(p2, p3, t2);
|
|
19161
|
-
const p012 = lerpPt(p01, p12, t2);
|
|
19162
|
-
const p123 = lerpPt(p12, p23, t2);
|
|
19163
|
-
const mid = lerpPt(p012, p123, t2);
|
|
19164
|
-
return {
|
|
19165
|
-
first: ["C", p01[0], p01[1], p012[0], p012[1], mid[0], mid[1]],
|
|
19166
|
-
second: ["C", p123[0], p123[1], p23[0], p23[1], p3[0], p3[1]],
|
|
19167
|
-
mid
|
|
19168
|
-
};
|
|
19169
|
-
}
|
|
19170
|
-
function splitLine(s2, cmd, t2) {
|
|
19171
|
-
const e2 = [cmd[1], cmd[2]];
|
|
19172
|
-
const mid = lerpPt(s2, e2, t2);
|
|
19173
|
-
return {
|
|
19174
|
-
first: ["L", mid[0], mid[1]],
|
|
19175
|
-
second: ["L", e2[0], e2[1]],
|
|
19176
|
-
mid
|
|
19177
|
-
};
|
|
19178
|
-
}
|
|
19179
|
-
function expandPath(analysis, ownIdx) {
|
|
19180
|
-
const { body, closing, segType, anchors } = analysis;
|
|
19181
|
-
const n2 = anchors.length;
|
|
19182
|
-
const m = ownIdx.length;
|
|
19183
|
-
const degen = (p) => segType === "C" ? ["C", p[0], p[1], p[0], p[1], p[0], p[1]] : ["L", p[0], p[1]];
|
|
19184
|
-
const out = [["M", anchors[0][0], anchors[0][1]]];
|
|
19185
|
-
let firstOwn = 0;
|
|
19186
|
-
while (firstOwn < m && ownIdx[firstOwn] !== 0) firstOwn++;
|
|
19187
|
-
for (let q2 = 1; q2 <= firstOwn; q2++) out.push(degen(anchors[0]));
|
|
19188
|
-
let entry = firstOwn + 1;
|
|
19189
|
-
for (let s2 = 0; s2 < n2 - 1; s2++) {
|
|
19190
|
-
let interior = 0;
|
|
19191
|
-
while (entry + interior < m && ownIdx[entry + interior] === -1) interior++;
|
|
19192
|
-
const cmd = body[s2 + 1];
|
|
19193
|
-
if (!interior) {
|
|
19194
|
-
out.push(cmd.slice());
|
|
19195
|
-
} else {
|
|
19196
|
-
const totalParts = interior + 1;
|
|
19197
|
-
let start = anchors[s2];
|
|
19198
|
-
let rest = cmd;
|
|
19199
|
-
for (let q2 = 0; q2 < interior; q2++) {
|
|
19200
|
-
const t2 = 1 / (totalParts - q2);
|
|
19201
|
-
const sp = segType === "C" ? splitCubic(start, rest, t2) : splitLine(start, rest, t2);
|
|
19202
|
-
out.push(sp.first);
|
|
19203
|
-
start = sp.mid;
|
|
19204
|
-
rest = sp.second;
|
|
19205
|
-
}
|
|
19206
|
-
out.push(rest);
|
|
19458
|
+
this._refreshSettle();
|
|
19459
|
+
this._emitChange();
|
|
19460
|
+
}).catch(() => {
|
|
19461
|
+
this.applying = false;
|
|
19462
|
+
});
|
|
19463
|
+
}
|
|
19464
|
+
/**
|
|
19465
|
+
* Hold `applying` true until the restore's burst of async 'updated' events
|
|
19466
|
+
* has drained (one macrotask after the last one). Refreshed by _onUpdated.
|
|
19467
|
+
*/
|
|
19468
|
+
_refreshSettle() {
|
|
19469
|
+
if (!Environment.isBrowser()) {
|
|
19470
|
+
this.applying = false;
|
|
19471
|
+
return;
|
|
19207
19472
|
}
|
|
19208
|
-
|
|
19473
|
+
clearTimeout(this._settleTimer);
|
|
19474
|
+
this._settleTimer = setTimeout(() => {
|
|
19475
|
+
this.applying = false;
|
|
19476
|
+
}, 0);
|
|
19209
19477
|
}
|
|
19210
|
-
|
|
19211
|
-
|
|
19212
|
-
|
|
19478
|
+
// ─── Public API ─────────────────────────────────────────────────────────
|
|
19479
|
+
/**
|
|
19480
|
+
* Commit a checkpoint of the current state now (a discrete undo step). Used by
|
|
19481
|
+
* callers that mutate `w.config` without going through a full re-render (e.g.
|
|
19482
|
+
* Ink Layer's targeted annotation redraws, which fire no 'updated' event).
|
|
19483
|
+
* No-op when disabled or while a restore is applying.
|
|
19484
|
+
* @param {string} [label]
|
|
19485
|
+
*/
|
|
19486
|
+
snapshot(label2) {
|
|
19487
|
+
if (!this.enabled || this.applying) return;
|
|
19488
|
+
this._commit(label2 || "change");
|
|
19213
19489
|
}
|
|
19214
|
-
|
|
19215
|
-
|
|
19216
|
-
|
|
19217
|
-
|
|
19218
|
-
|
|
19219
|
-
|
|
19220
|
-
|
|
19221
|
-
if (!toAnalysis) return null;
|
|
19222
|
-
if (fromAnalysis.segType !== toAnalysis.segType) return null;
|
|
19223
|
-
if ((fromAnalysis.closing || toAnalysis.closing) && (!fromAnalysis.closing || !toAnalysis.closing || fromAnalysis.closing[0][0] !== toAnalysis.closing[0][0])) {
|
|
19224
|
-
return null;
|
|
19490
|
+
/**
|
|
19491
|
+
* @param {boolean} [animate]
|
|
19492
|
+
*/
|
|
19493
|
+
undo(animate = true) {
|
|
19494
|
+
if (!this.canUndo()) return;
|
|
19495
|
+
this.pointer--;
|
|
19496
|
+
this._restore(this.stack[this.pointer], animate);
|
|
19225
19497
|
}
|
|
19226
|
-
|
|
19227
|
-
|
|
19228
|
-
|
|
19229
|
-
|
|
19230
|
-
|
|
19231
|
-
|
|
19232
|
-
|
|
19233
|
-
function lengthTransitionEnabled(w) {
|
|
19234
|
-
var _a;
|
|
19235
|
-
const anim = w.config.chart.animations;
|
|
19236
|
-
if (!anim || anim.enabled === false) return false;
|
|
19237
|
-
if (!anim.dynamicAnimation || anim.dynamicAnimation.enabled === false) {
|
|
19238
|
-
return false;
|
|
19498
|
+
/**
|
|
19499
|
+
* @param {boolean} [animate]
|
|
19500
|
+
*/
|
|
19501
|
+
redo(animate = true) {
|
|
19502
|
+
if (!this.canRedo()) return;
|
|
19503
|
+
this.pointer++;
|
|
19504
|
+
this._restore(this.stack[this.pointer], animate);
|
|
19239
19505
|
}
|
|
19240
|
-
|
|
19241
|
-
|
|
19242
|
-
return !!(Environment.isBrowser() && w.globals.dataChanged && w.globals.shouldAnimate);
|
|
19243
|
-
}
|
|
19244
|
-
function datumKey(w, realIndex, j2) {
|
|
19245
|
-
var _a, _b, _c, _d;
|
|
19246
|
-
if ((_a = w.axisFlags) == null ? void 0 : _a.isXNumeric) {
|
|
19247
|
-
const sx = (_c = (_b = w.seriesData) == null ? void 0 : _b.seriesX) == null ? void 0 : _c[realIndex];
|
|
19248
|
-
if (sx && sx.length && sx[j2] != null) return "x:" + sx[j2];
|
|
19506
|
+
canUndo() {
|
|
19507
|
+
return this.pointer > 0;
|
|
19249
19508
|
}
|
|
19250
|
-
|
|
19251
|
-
|
|
19252
|
-
return "c:" + (Array.isArray(lbl) ? lbl.join(" ") : String(lbl));
|
|
19509
|
+
canRedo() {
|
|
19510
|
+
return this.pointer > -1 && this.pointer < this.stack.length - 1;
|
|
19253
19511
|
}
|
|
19254
|
-
|
|
19255
|
-
}
|
|
19256
|
-
|
|
19257
|
-
|
|
19258
|
-
|
|
19259
|
-
const
|
|
19260
|
-
if (
|
|
19512
|
+
/**
|
|
19513
|
+
* @param {string} id
|
|
19514
|
+
* @param {boolean} [animate]
|
|
19515
|
+
*/
|
|
19516
|
+
jump(id, animate = true) {
|
|
19517
|
+
const idx = this.stack.findIndex((c) => c.id === id);
|
|
19518
|
+
if (idx === -1 || idx === this.pointer) return;
|
|
19519
|
+
this.pointer = idx;
|
|
19520
|
+
this._restore(this.stack[idx], animate);
|
|
19261
19521
|
}
|
|
19262
|
-
|
|
19263
|
-
|
|
19264
|
-
|
|
19522
|
+
/** Clear the history, keeping the current state as the new baseline. */
|
|
19523
|
+
clear() {
|
|
19524
|
+
clearTimeout(this._coalesceTimer);
|
|
19525
|
+
this._coalesceTimer = null;
|
|
19526
|
+
const current = this.stack[this.pointer];
|
|
19527
|
+
this.stack = current ? [current] : [];
|
|
19528
|
+
this.pointer = this.stack.length - 1;
|
|
19529
|
+
this._emitChange();
|
|
19265
19530
|
}
|
|
19266
|
-
|
|
19267
|
-
|
|
19268
|
-
|
|
19269
|
-
|
|
19270
|
-
|
|
19271
|
-
|
|
19272
|
-
|
|
19273
|
-
|
|
19274
|
-
|
|
19275
|
-
|
|
19276
|
-
|
|
19277
|
-
|
|
19278
|
-
|
|
19279
|
-
|
|
19280
|
-
|
|
19281
|
-
|
|
19282
|
-
usedOld.add(oi);
|
|
19283
|
-
if (oi < prev) ordered = false;
|
|
19284
|
-
prev = oi;
|
|
19285
|
-
}
|
|
19286
|
-
if (oi !== i2) identity = false;
|
|
19287
|
-
});
|
|
19288
|
-
const exits = [];
|
|
19289
|
-
for (let i2 = 0; i2 < oldKeys.length; i2++) {
|
|
19290
|
-
if (!usedOld.has(i2)) exits.push(i2);
|
|
19531
|
+
/**
|
|
19532
|
+
* Group multiple edits into a single undo step. `fn` may be async; await your
|
|
19533
|
+
* updateOptions/updateSeries calls inside it so the intermediate 'updated'
|
|
19534
|
+
* events are suppressed and only one checkpoint is committed afterwards.
|
|
19535
|
+
* @param {() => (void | Promise<any>)} fn
|
|
19536
|
+
* @param {{ label?: string }} [opts]
|
|
19537
|
+
* @returns {Promise<void>}
|
|
19538
|
+
*/
|
|
19539
|
+
transaction(fn, opts = {}) {
|
|
19540
|
+
if (typeof fn !== "function") return Promise.resolve();
|
|
19541
|
+
const wasBatching = this._batching;
|
|
19542
|
+
this._batching = true;
|
|
19543
|
+
return Promise.resolve().then(() => fn()).finally(() => {
|
|
19544
|
+
this._batching = wasBatching;
|
|
19545
|
+
if (!wasBatching) this._commit(opts.label || "transaction", true);
|
|
19546
|
+
});
|
|
19291
19547
|
}
|
|
19292
|
-
|
|
19293
|
-
}
|
|
19294
|
-
|
|
19295
|
-
|
|
19296
|
-
|
|
19297
|
-
const count = seen.get(k2) || 0;
|
|
19298
|
-
seen.set(k2, count + 1);
|
|
19299
|
-
return count === 0 ? k2 : `${k2}#${count}`;
|
|
19300
|
-
});
|
|
19301
|
-
}
|
|
19302
|
-
function seriesJoin(w, realIndex, includeIdentity = false, allowReorder = false) {
|
|
19303
|
-
var _a, _b;
|
|
19304
|
-
if (!lengthTransitionEnabled(w)) return null;
|
|
19305
|
-
const frame = w.globals.prevStreamFrame;
|
|
19306
|
-
if (!frame) return null;
|
|
19307
|
-
const oldY = (_a = frame.seriesY) == null ? void 0 : _a[realIndex];
|
|
19308
|
-
const newY = (_b = w.seriesData.series) == null ? void 0 : _b[realIndex];
|
|
19309
|
-
if (!Array.isArray(oldY) || !Array.isArray(newY)) return null;
|
|
19310
|
-
if (!oldY.length || !newY.length) return null;
|
|
19311
|
-
const oldKeys = uniquifyKeys(
|
|
19312
|
-
oldY.map((_2, j2) => frameDatumKey(frame, realIndex, j2))
|
|
19313
|
-
);
|
|
19314
|
-
const newKeys = uniquifyKeys(newY.map((_2, j2) => datumKey(w, realIndex, j2)));
|
|
19315
|
-
const join = joinKeys(oldKeys, newKeys);
|
|
19316
|
-
if (!join.ordered && !allowReorder) return null;
|
|
19317
|
-
if (!join.changed && !includeIdentity) return null;
|
|
19318
|
-
return { join, oldKeys, newKeys };
|
|
19319
|
-
}
|
|
19320
|
-
function morphEasing(w) {
|
|
19321
|
-
var _a, _b;
|
|
19322
|
-
const anim = w.config.chart.animations;
|
|
19323
|
-
return resolveEasing((_b = (_a = anim.dynamicAnimation) == null ? void 0 : _a.easing) != null ? _b : anim.easing);
|
|
19324
|
-
}
|
|
19325
|
-
function reconcileSeriesPaths(w, { type, realIndex, pathFromLine, pathFromArea, linePaths, areaPaths }) {
|
|
19326
|
-
var _a, _b;
|
|
19327
|
-
const sj = seriesJoin(w, realIndex);
|
|
19328
|
-
if (!sj) return null;
|
|
19329
|
-
const { join, oldKeys, newKeys } = sj;
|
|
19330
|
-
const frame = w.globals.prevStreamFrame;
|
|
19331
|
-
if (!frame) return null;
|
|
19332
|
-
const oldY = (_a = frame.seriesY) == null ? void 0 : _a[realIndex];
|
|
19333
|
-
const newY = (_b = w.seriesData.series) == null ? void 0 : _b[realIndex];
|
|
19334
|
-
if (oldY.length < 2 || newY.length < 2) return null;
|
|
19335
|
-
if (oldY.some((v) => v === null) || newY.some((v) => v === null)) return null;
|
|
19336
|
-
const entries = buildUnionEntries(join, oldKeys.length);
|
|
19337
|
-
const out = {};
|
|
19338
|
-
if (Array.isArray(linePaths) && linePaths.length === 1 && pathFromLine) {
|
|
19339
|
-
out.line = reconcilePathPair(
|
|
19340
|
-
pathFromLine,
|
|
19341
|
-
linePaths[0],
|
|
19342
|
-
entries,
|
|
19343
|
-
oldKeys.length,
|
|
19344
|
-
newKeys.length,
|
|
19345
|
-
false
|
|
19346
|
-
);
|
|
19548
|
+
/**
|
|
19549
|
+
* @returns {{ id: string, label: string, at: number }[]}
|
|
19550
|
+
*/
|
|
19551
|
+
entries() {
|
|
19552
|
+
return this.stack.map((c) => ({ id: c.id, label: c.label, at: c.at }));
|
|
19347
19553
|
}
|
|
19348
|
-
|
|
19349
|
-
|
|
19350
|
-
|
|
19351
|
-
|
|
19352
|
-
|
|
19353
|
-
|
|
19354
|
-
|
|
19355
|
-
|
|
19356
|
-
|
|
19554
|
+
/** Lightweight state for the historyChange event / a history-rail UI. */
|
|
19555
|
+
state() {
|
|
19556
|
+
return {
|
|
19557
|
+
canUndo: this.canUndo(),
|
|
19558
|
+
canRedo: this.canRedo(),
|
|
19559
|
+
index: this.pointer,
|
|
19560
|
+
length: this.stack.length
|
|
19561
|
+
};
|
|
19562
|
+
}
|
|
19563
|
+
_emitChange() {
|
|
19564
|
+
this.ctx.events.fireEvent("historyChange", [this.ctx, this.state()]);
|
|
19565
|
+
}
|
|
19566
|
+
/** Drop the stack + detach listeners (called on full destroy). */
|
|
19567
|
+
teardown() {
|
|
19568
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
19569
|
+
clearTimeout(this._coalesceTimer);
|
|
19570
|
+
clearTimeout(this._settleTimer);
|
|
19571
|
+
this._coalesceTimer = null;
|
|
19572
|
+
this._settleTimer = null;
|
|
19573
|
+
this._unwireKeyboard();
|
|
19574
|
+
if (this._wired) {
|
|
19575
|
+
(_b = (_a = this.ctx).removeEventListener) == null ? void 0 : _b.call(_a, "mounted", this._onMounted);
|
|
19576
|
+
(_d = (_c = this.ctx).removeEventListener) == null ? void 0 : _d.call(_c, "updated", this._onUpdated);
|
|
19577
|
+
(_f = (_e = this.ctx).removeEventListener) == null ? void 0 : _f.call(_e, "scrolled", this._onUpdated);
|
|
19578
|
+
(_h = (_g = this.ctx).removeEventListener) == null ? void 0 : _h.call(_g, "dataPointSelection", this._onSelection);
|
|
19579
|
+
}
|
|
19580
|
+
this.stack = [];
|
|
19581
|
+
this.pointer = -1;
|
|
19582
|
+
this._wired = false;
|
|
19357
19583
|
}
|
|
19358
|
-
if (!out.line && !out.area) return null;
|
|
19359
|
-
return out;
|
|
19360
19584
|
}
|
|
19585
|
+
ApexCharts__default.registerFeatures({ history: History });
|
|
19586
|
+
const DataLabels = ApexCharts.__apex_DataLabels;
|
|
19361
19587
|
function detectStreamScroll(w, realIndex, newXPixels, newYPixels) {
|
|
19362
19588
|
var _a;
|
|
19363
19589
|
const gl = w.globals;
|
|
@@ -21324,9 +21550,9 @@ function wrapParentTip(hf, tm) {
|
|
|
21324
21550
|
}
|
|
21325
21551
|
const v = (_c = tm._tip()) == null ? void 0 : _c.querySelector(".apexcharts-tooltip-text-y-value");
|
|
21326
21552
|
if (!v) return;
|
|
21327
|
-
let rest = `/ ${tm._formatValue(h.total)}`;
|
|
21553
|
+
let rest = `/ ${tm._formatValue(h.total, node._si)}`;
|
|
21328
21554
|
if (tt.share && h.total) rest += ` · ${Math.round(h.share * 100)}%`;
|
|
21329
|
-
v.innerHTML = `${tm._formatValue(h.value)} <span class="apexcharts-highlight-total" style="font-weight: 400; opacity: 0.6">${rest}</span>`;
|
|
21555
|
+
v.innerHTML = `${tm._formatValue(h.value, node._si)} <span class="apexcharts-highlight-total" style="font-weight: 400; opacity: 0.6">${rest}</span>`;
|
|
21330
21556
|
};
|
|
21331
21557
|
}
|
|
21332
21558
|
function tone(rec, fore) {
|
|
@@ -21864,7 +22090,7 @@ class HighlightFilter {
|
|
|
21864
22090
|
const active = hd.active;
|
|
21865
22091
|
if (!active && !(prevMap == null ? void 0 : prevMap.size)) return void 0;
|
|
21866
22092
|
const { j: j2, realIndex } = o2;
|
|
21867
|
-
const key = BAR + `${realIndex}::${
|
|
22093
|
+
const key = BAR + `${realIndex}::${bar._keys(realIndex)[j2]}`;
|
|
21868
22094
|
this._seen.add(key);
|
|
21869
22095
|
const prev = prevMap == null ? void 0 : prevMap.get(key);
|
|
21870
22096
|
const p = active ? (_a = hd.parts[realIndex]) == null ? void 0 : _a[j2] : null;
|
|
@@ -22174,14 +22400,14 @@ class HighlightFilter {
|
|
|
22174
22400
|
}
|
|
22175
22401
|
/**
|
|
22176
22402
|
* The stack a stacked bar datum joins, as the renderer resolves it
|
|
22177
|
-
* (BarStacked
|
|
22178
|
-
*
|
|
22403
|
+
* (BarStacked): its series group, then its x value on a numeric or
|
|
22404
|
+
* datetime axis, else its index.
|
|
22179
22405
|
* @param {number} i @param {number} j
|
|
22180
22406
|
*/
|
|
22181
22407
|
_barKey(i2, j2) {
|
|
22182
22408
|
var _a;
|
|
22183
22409
|
const w = this.w;
|
|
22184
|
-
return w.labelData.seriesGroupIndex[i2] + "|" + (
|
|
22410
|
+
return w.labelData.seriesGroupIndex[i2] + "|" + (w.axisFlags.isXNumeric ? (_a = w.seriesData.seriesX[i2]) == null ? void 0 : _a[j2] : j2);
|
|
22185
22411
|
}
|
|
22186
22412
|
/**
|
|
22187
22413
|
* Line.draw, once per series right after its whole has been rendered and
|
|
@@ -22245,7 +22471,7 @@ class HighlightFilter {
|
|
|
22245
22471
|
const exit = !to && !!(prev == null ? void 0 : prev.d) && animate;
|
|
22246
22472
|
const base = active && animate && (exit || to && !(prev == null ? void 0 : prev.d) && (prev || this.cfg.enter === "baseline")) ? this._lineBase(ln, type, series, i2, realIndex, ti, has ? raw : null) : null;
|
|
22247
22473
|
if (pp && w.config.chart.stacked) {
|
|
22248
|
-
this._swap(ln, () => ln._recordStackTops(realIndex, pp.yArrj));
|
|
22474
|
+
this._swap(ln, () => ln._recordStackTops(realIndex, pp.yArrj, pp.S[i2]));
|
|
22249
22475
|
this._stkPrev.push(pp.yArrj);
|
|
22250
22476
|
}
|
|
22251
22477
|
if (exit) {
|