@wick-charts/vue 0.4.2 → 0.5.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 +5 -3
- package/dist/BarSeries.vue.js +44 -0
- package/dist/BarSeries.vue2.js +4 -0
- package/dist/CandlestickSeries.vue.js +45 -0
- package/dist/CandlestickSeries.vue2.js +4 -0
- package/dist/ChartContainer.vue.js +168 -0
- package/dist/ChartContainer.vue2.js +4 -0
- package/dist/LineSeries.vue.js +44 -0
- package/dist/LineSeries.vue2.js +4 -0
- package/dist/PieSeries.vue.js +34 -0
- package/dist/PieSeries.vue2.js +4 -0
- package/dist/composables.js +44 -0
- package/dist/context.js +25 -0
- package/dist/core/dist/animation/animator.js +72 -0
- package/dist/core/dist/animation/config.js +145 -0
- package/dist/core/dist/animation/easing.js +4 -0
- package/dist/core/dist/animation/scalar-spring.js +57 -0
- package/dist/core/dist/animation/spring.js +11 -0
- package/dist/core/dist/animation/time.js +19 -0
- package/dist/core/dist/animation/viewport-engine.js +174 -0
- package/dist/core/dist/animation/visible-range-spring.js +64 -0
- package/dist/core/dist/animation/y-range-hermite.js +72 -0
- package/dist/core/dist/animation/y-range-snap.js +31 -0
- package/dist/core/dist/animation/y-range-spring.js +59 -0
- package/dist/core/dist/axis/dom-labels.js +60 -0
- package/dist/core/dist/canvas-manager.js +109 -0
- package/dist/core/dist/chart/edge-indicators.js +26 -0
- package/dist/core/dist/chart/fit-to-data.js +9 -0
- package/dist/core/dist/chart/last-value.js +31 -0
- package/dist/core/dist/chart/options.js +35 -0
- package/dist/core/dist/chart/pan-zoom-math.js +66 -0
- package/dist/core/dist/chart/streaming-cadence.js +70 -0
- package/dist/core/dist/chart/streaming-target.js +22 -0
- package/dist/core/dist/chart/viewport-padding.js +6 -0
- package/dist/core/dist/chart/y-target.js +24 -0
- package/dist/core/dist/chart.js +1550 -0
- package/dist/core/dist/components/crosshair.js +9 -0
- package/dist/core/dist/components/edge-indicator.js +36 -0
- package/dist/core/dist/components/grid.js +22 -0
- package/dist/core/dist/components/marker.js +41 -0
- package/dist/core/dist/components/reference-line.js +48 -0
- package/dist/core/dist/components/time-region.js +35 -0
- package/dist/core/dist/data/decimation.js +54 -0
- package/dist/core/dist/data/store.js +76 -0
- package/dist/core/dist/data/sync.js +47 -0
- package/dist/core/dist/events.js +19 -0
- package/dist/core/dist/interactions/handler.js +84 -0
- package/dist/core/dist/interactions/pan.js +26 -0
- package/dist/core/dist/interactions/zoom.js +21 -0
- package/dist/core/dist/navigator/controller.js +374 -0
- package/dist/core/dist/navigator/decimate.js +44 -0
- package/dist/core/dist/navigator/interactions.js +28 -0
- package/dist/core/dist/navigator/render.js +68 -0
- package/dist/core/dist/perf/counting-context.js +19 -0
- package/dist/core/dist/perf/perf-hud.js +453 -0
- package/dist/core/dist/perf/perf-monitor.js +132 -0
- package/dist/core/dist/render-scheduler.js +31 -0
- package/dist/core/dist/scales/tick-tracker.js +110 -0
- package/dist/core/dist/scales/x-scale.js +145 -0
- package/dist/core/dist/scales/y-scale.js +156 -0
- package/dist/core/dist/series/bar.js +341 -0
- package/dist/core/dist/series/base-multi-layer.js +438 -0
- package/dist/core/dist/series/candlestick.js +481 -0
- package/dist/core/dist/series/definition.js +11 -0
- package/dist/core/dist/series/line.js +446 -0
- package/dist/core/dist/series/painters/builtins.js +36 -0
- package/dist/core/dist/series/painters/canvas-path.js +79 -0
- package/dist/core/dist/series/painters/resolve.js +32 -0
- package/dist/core/dist/series/pie.js +545 -0
- package/dist/core/dist/series/register-builtins.js +11 -0
- package/dist/core/dist/series/stack-math.js +17 -0
- package/dist/core/dist/snapshots.js +107 -0
- package/dist/core/dist/theme/create.js +176 -0
- package/dist/core/dist/theme/resolve.js +14 -0
- package/dist/core/dist/theme/themes/andromeda.js +33 -0
- package/dist/core/dist/theme/themes/ayu-mirage.js +33 -0
- package/dist/core/dist/theme/themes/catppuccin.js +33 -0
- package/dist/core/dist/theme/themes/dracula.js +35 -0
- package/dist/core/dist/theme/themes/github-light.js +34 -0
- package/dist/core/dist/theme/themes/gruvbox.js +33 -0
- package/dist/core/dist/theme/themes/handwritten.js +101 -0
- package/dist/core/dist/theme/themes/high-contrast.js +33 -0
- package/dist/core/dist/theme/themes/lavender-mist.js +33 -0
- package/dist/core/dist/theme/themes/light-pink.js +34 -0
- package/dist/core/dist/theme/themes/material-palenight.js +33 -0
- package/dist/core/dist/theme/themes/minimal-light.js +34 -0
- package/dist/core/dist/theme/themes/mint-breeze.js +33 -0
- package/dist/core/dist/theme/themes/monokai-pro.js +33 -0
- package/dist/core/dist/theme/themes/night-owl.js +35 -0
- package/dist/core/dist/theme/themes/one-dark-pro.js +33 -0
- package/dist/core/dist/theme/themes/panda.js +33 -0
- package/dist/core/dist/theme/themes/peach-cream.js +33 -0
- package/dist/core/dist/theme/themes/quiet-light.js +37 -0
- package/dist/core/dist/theme/themes/rose-pine-dawn.js +33 -0
- package/dist/core/dist/theme/themes/sand-dune.js +33 -0
- package/dist/core/dist/theme/themes/solarized-light.js +34 -0
- package/dist/core/dist/tooltip-position.js +10 -0
- package/dist/core/dist/utils/color.js +37 -0
- package/dist/core/dist/utils/format.js +29 -0
- package/dist/core/dist/utils/math.js +26 -0
- package/dist/core/dist/utils/poisoned-data-reporter.js +15 -0
- package/dist/core/dist/utils/time.js +41 -0
- package/dist/index.d.ts +834 -63
- package/dist/index.js +142 -8025
- package/dist/ui/Crosshair.vue.js +53 -0
- package/dist/ui/Crosshair.vue2.js +4 -0
- package/dist/ui/InfoBar.vue.js +143 -0
- package/dist/ui/InfoBar.vue2.js +4 -0
- package/dist/ui/Legend.vue.js +212 -0
- package/dist/ui/Legend.vue2.js +4 -0
- package/dist/ui/Marker.vue.js +47 -0
- package/dist/ui/Marker.vue2.js +4 -0
- package/dist/ui/Navigator.vue.js +58 -0
- package/dist/ui/Navigator.vue2.js +4 -0
- package/dist/ui/NumberFlow.vue.js +69 -0
- package/dist/ui/NumberFlow.vue2.js +4 -0
- package/dist/ui/PieLegend.vue.js +132 -0
- package/dist/ui/PieLegend.vue2.js +4 -0
- package/dist/ui/PieTooltip.vue.js +135 -0
- package/dist/ui/PieTooltip.vue2.js +4 -0
- package/dist/ui/ReferenceLine.vue.js +44 -0
- package/dist/ui/ReferenceLine.vue2.js +4 -0
- package/dist/ui/TimeAxis.vue.js +43 -0
- package/dist/ui/TimeAxis.vue2.js +4 -0
- package/dist/ui/TimeRegion.vue.js +41 -0
- package/dist/ui/TimeRegion.vue2.js +4 -0
- package/dist/ui/Title.vue.js +54 -0
- package/dist/ui/Title.vue2.js +4 -0
- package/dist/ui/Tooltip.vue.js +195 -0
- package/dist/ui/Tooltip.vue2.js +4 -0
- package/dist/ui/YAxis.vue.js +42 -0
- package/dist/ui/YAxis.vue2.js +4 -0
- package/dist/ui/YLabel.vue.js +105 -0
- package/dist/ui/YLabel.vue2.js +4 -0
- package/package.json +2 -2
- package/src/BarSeries.vue +12 -13
- package/src/CandlestickSeries.vue +17 -6
- package/src/LineSeries.vue +12 -13
- package/src/PieSeries.vue +2 -1
- package/src/index.ts +23 -0
- package/src/ui/Legend.vue +1 -2
- package/src/ui/Marker.vue +62 -0
- package/src/ui/ReferenceLine.vue +58 -0
- package/src/ui/TimeRegion.vue +54 -0
|
@@ -0,0 +1,545 @@
|
|
|
1
|
+
import { lighten as st } from "../utils/color.js";
|
|
2
|
+
import { smoothToward as K, clamp as E } from "../utils/math.js";
|
|
3
|
+
const tt = {
|
|
4
|
+
mode: "outside",
|
|
5
|
+
content: "both",
|
|
6
|
+
fontSize: 11,
|
|
7
|
+
// 2.5° ≈ 0.7% of the pie. The PAV pass handles the resulting vertical
|
|
8
|
+
// crowding; raise when labels-per-slice still crosses into illegible.
|
|
9
|
+
minSliceAngle: 2.5,
|
|
10
|
+
elbowLen: 12,
|
|
11
|
+
legPad: 6,
|
|
12
|
+
// Radial distance from the pie edge to the label ring. The label then
|
|
13
|
+
// extends horizontally outward by `railWidth` so the text anchor sits
|
|
14
|
+
// past a consistent-length horizontal tail.
|
|
15
|
+
distance: 14,
|
|
16
|
+
railWidth: 16,
|
|
17
|
+
// Multiplier on fontSize for min vertical gap between same-side labels.
|
|
18
|
+
// 1.8 gives each label room to breathe without spreading so aggressively
|
|
19
|
+
// that PAV collapses into a centered block on dense datasets.
|
|
20
|
+
labelGap: 1.8
|
|
21
|
+
}, ot = {
|
|
22
|
+
innerRadiusRatio: 0,
|
|
23
|
+
// 1.15° ≈ 0.02 rad — same visual default as before the radians→degrees switch.
|
|
24
|
+
padAngle: 1.15,
|
|
25
|
+
sliceLabels: { ...tt },
|
|
26
|
+
// Motion off by default: label draw-in + hover explode both skipped.
|
|
27
|
+
animate: !1,
|
|
28
|
+
// Small-slice grouping on by default: dense datasets collapse into the top
|
|
29
|
+
// slices plus a single "Other" so outside labels stay legible.
|
|
30
|
+
other: !0,
|
|
31
|
+
// Radial depth gradient (lighter center → flat edge) on by default. Set
|
|
32
|
+
// false for flat, solid-color slices.
|
|
33
|
+
gradient: !0
|
|
34
|
+
}, Q = {
|
|
35
|
+
maxSlices: 8,
|
|
36
|
+
label: "Other"
|
|
37
|
+
};
|
|
38
|
+
function nt(l) {
|
|
39
|
+
return l === !1 ? null : l === !0 || l === void 0 ? Q : { ...Q, ...l };
|
|
40
|
+
}
|
|
41
|
+
const U = Math.PI / 180;
|
|
42
|
+
function lt(l, e) {
|
|
43
|
+
return { ...l ?? {}, ...e };
|
|
44
|
+
}
|
|
45
|
+
function it(l) {
|
|
46
|
+
return { ...tt, ...l ?? {} };
|
|
47
|
+
}
|
|
48
|
+
function at(l) {
|
|
49
|
+
const e = { color: "rgba(0, 0, 0, 0.22)", blur: 24, offsetX: 0, offsetY: 10 };
|
|
50
|
+
return l === !0 || l === !1 ? e : { ...e, ...l };
|
|
51
|
+
}
|
|
52
|
+
function rt(l) {
|
|
53
|
+
const e = { color: "rgba(0, 0, 0, 0.1)", depth: 0.3 };
|
|
54
|
+
return l === !0 || l === !1 ? e : { ...e, ...l };
|
|
55
|
+
}
|
|
56
|
+
const N = Math.PI * 2, et = 0.85;
|
|
57
|
+
function Z(l) {
|
|
58
|
+
const { bitmapWidth: e, bitmapHeight: t, padTop: o, padBottom: i } = l, s = Math.max(0, l.labelReserve ?? 0), d = Math.min(Math.max(0, o), t), r = Math.min(Math.max(0, i), t - d), c = t - d - r, g = Math.max(0, e - 2 * s), C = e / 2, x = d + c / 2, R = Math.max(0, Math.min(g, c) / 2 * et);
|
|
59
|
+
return { cx: C, cy: x, maxR: R };
|
|
60
|
+
}
|
|
61
|
+
function ht(l) {
|
|
62
|
+
if (!l.startsWith("#")) return !1;
|
|
63
|
+
const e = parseInt(l.slice(1, 3), 16), t = parseInt(l.slice(3, 5), 16), o = parseInt(l.slice(5, 7), 16);
|
|
64
|
+
return e * 0.299 + t * 0.587 + o * 0.114 > 150;
|
|
65
|
+
}
|
|
66
|
+
function ct(l, e) {
|
|
67
|
+
if (!l.startsWith("#")) return l;
|
|
68
|
+
const t = l.length === 4 ? `#${l[1]}${l[1]}${l[2]}${l[2]}${l[3]}${l[3]}` : l;
|
|
69
|
+
return st(t, e);
|
|
70
|
+
}
|
|
71
|
+
function J(l) {
|
|
72
|
+
if (l.startsWith("#"))
|
|
73
|
+
return {
|
|
74
|
+
r: parseInt(l.slice(1, 3), 16) || 0,
|
|
75
|
+
g: parseInt(l.slice(3, 5), 16) || 0,
|
|
76
|
+
b: parseInt(l.slice(5, 7), 16) || 0,
|
|
77
|
+
a: 1
|
|
78
|
+
};
|
|
79
|
+
const e = l.match(/^rgba?\s*\(([^)]+)\)$/i);
|
|
80
|
+
if (e) {
|
|
81
|
+
const t = e[1].split(",").map((o) => o.trim());
|
|
82
|
+
return {
|
|
83
|
+
r: Number.parseFloat(t[0]) || 0,
|
|
84
|
+
g: Number.parseFloat(t[1]) || 0,
|
|
85
|
+
b: Number.parseFloat(t[2]) || 0,
|
|
86
|
+
a: t[3] === void 0 ? 1 : Number.parseFloat(t[3])
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
return { r: 0, g: 0, b: 0, a: 1 };
|
|
90
|
+
}
|
|
91
|
+
function ut(l, e) {
|
|
92
|
+
const t = J(l), o = J(e), i = o.a, s = Math.round(o.r * i + t.r * (1 - i)), d = Math.round(o.g * i + t.g * (1 - i)), r = Math.round(o.b * i + t.b * (1 - i));
|
|
93
|
+
return `#${s.toString(16).padStart(2, "0")}${d.toString(16).padStart(2, "0")}${r.toString(16).padStart(2, "0")}`;
|
|
94
|
+
}
|
|
95
|
+
class ft {
|
|
96
|
+
kind = "pie";
|
|
97
|
+
#n = [];
|
|
98
|
+
/**
|
|
99
|
+
* Slices actually rendered. Equals {@link #data} unless "other" grouping is
|
|
100
|
+
* active and the dataset exceeds `maxSlices` — then the smallest slices are
|
|
101
|
+
* summed into a synthetic "Other" slice appended at the end. Every read
|
|
102
|
+
* path (render, hit-test, hover / slice info, label reserve) goes through
|
|
103
|
+
* this array so the grouped view is consistent across all surfaces.
|
|
104
|
+
*/
|
|
105
|
+
#t = [];
|
|
106
|
+
/**
|
|
107
|
+
* Index of the synthetic "Other" slice in {@link #display}, or -1 when
|
|
108
|
+
* grouping didn't apply. Lets the color resolution pick the theme's muted
|
|
109
|
+
* `pie.otherColor` for the aggregate instead of the next palette color.
|
|
110
|
+
*/
|
|
111
|
+
#c = -1;
|
|
112
|
+
#e;
|
|
113
|
+
/** Index of the hovered slice (-1 = none). Set via {@link setHoverIndex}. */
|
|
114
|
+
#i = -1;
|
|
115
|
+
/** Animated offset per slice (0..1), smoothly interpolated toward target. */
|
|
116
|
+
#s = [];
|
|
117
|
+
#u = 0;
|
|
118
|
+
/**
|
|
119
|
+
* Outside-label reveal progress (0..1). Eased toward 1 on mount / data-swap
|
|
120
|
+
* when `animate` is on; drives the leader-line draw-in and label fade-in
|
|
121
|
+
* stagger. When `animate` is off (the default) this stays pinned at 1 so
|
|
122
|
+
* labels paint fully-revealed on the first frame.
|
|
123
|
+
*/
|
|
124
|
+
#a = 1;
|
|
125
|
+
/**
|
|
126
|
+
* Cached horizontal bitmap-pixel reserve for outside labels. Invalidated on
|
|
127
|
+
* `setData` / `updateOptions`; computed lazily on first `render` call per
|
|
128
|
+
* frame using the live canvas context for accurate `measureText`.
|
|
129
|
+
*/
|
|
130
|
+
#l = null;
|
|
131
|
+
/** Subscribers notified on setData (pie has no TimeSeriesStore to piggy-back on). */
|
|
132
|
+
#r = [];
|
|
133
|
+
constructor(e) {
|
|
134
|
+
this.#e = this.#m(ot, e ?? {});
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Merge partial options onto a base, deep-merging `sliceLabels` and `other`
|
|
138
|
+
* so callers can override one field (e.g. `mode` or `maxSlices`) without
|
|
139
|
+
* dropping sibling defaults.
|
|
140
|
+
*/
|
|
141
|
+
#m(e, t) {
|
|
142
|
+
const o = { ...e, ...t };
|
|
143
|
+
return t.sliceLabels !== void 0 && (o.sliceLabels = lt(e.sliceLabels, t.sliceLabels)), typeof t.other == "object" && typeof e.other == "object" && (o.other = { ...e.other, ...t.other }), o;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Build the display array from the raw data. When grouping applies, the
|
|
147
|
+
* largest `maxSlices - 1` slices are kept in their original order; the rest
|
|
148
|
+
* are summed into one "Other" slice appended at the end. Ranking uses the
|
|
149
|
+
* layout-sanitized value so negative / non-finite entries can never outrank
|
|
150
|
+
* a real slice.
|
|
151
|
+
*/
|
|
152
|
+
#p() {
|
|
153
|
+
this.#c = -1;
|
|
154
|
+
const e = nt(this.#e.other);
|
|
155
|
+
if (!e || this.#n.length <= e.maxSlices) return this.#n;
|
|
156
|
+
const t = Math.max(1, e.maxSlices - 1), o = this.#n.map((r, c) => ({ index: c, value: this.#o(r.value) })).sort((r, c) => c.value - r.value), i = /* @__PURE__ */ new Set();
|
|
157
|
+
for (const r of o.slice(0, t))
|
|
158
|
+
i.add(r.index);
|
|
159
|
+
const s = [];
|
|
160
|
+
let d = 0;
|
|
161
|
+
for (let r = 0; r < this.#n.length; r++)
|
|
162
|
+
i.has(r) ? s.push(this.#n[r]) : d += this.#o(this.#n[r].value);
|
|
163
|
+
return s.push({ label: e.label, value: d, color: e.color }), this.#c = s.length - 1, s;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Paint color for one display slice: explicit slice color → theme-driven
|
|
167
|
+
* "Other" color for the synthetic aggregate → palette by index. The
|
|
168
|
+
* `axis.textColor` fallback matches what {@link createTheme} derives for
|
|
169
|
+
* `pie.otherColor`, so hand-built theme literals without the `pie` block
|
|
170
|
+
* get the same muted tone.
|
|
171
|
+
*/
|
|
172
|
+
#h(e) {
|
|
173
|
+
const { index: t, palette: o, theme: i } = e, s = this.#t[t];
|
|
174
|
+
return s?.color ? s.color : t === this.#c ? i.pie?.otherColor ?? i.axis.textColor : o[t % o.length];
|
|
175
|
+
}
|
|
176
|
+
getData() {
|
|
177
|
+
return this.#n;
|
|
178
|
+
}
|
|
179
|
+
setData(e) {
|
|
180
|
+
const t = e ?? [];
|
|
181
|
+
this.#n = t, this.#t = this.#p(), this.#s = new Array(this.#t.length).fill(0), this.#a = this.#e.animate ? 0 : 1, this.#l = null;
|
|
182
|
+
for (const o of this.#r)
|
|
183
|
+
o();
|
|
184
|
+
}
|
|
185
|
+
onDataChanged(e) {
|
|
186
|
+
return this.#r.push(e), () => {
|
|
187
|
+
const t = this.#r.indexOf(e);
|
|
188
|
+
t >= 0 && this.#r.splice(t, 1);
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
updateOptions(e) {
|
|
192
|
+
const t = this.#e.sliceLabels?.mode;
|
|
193
|
+
this.#e = this.#m(this.#e, e ?? {}), this.#e.sliceLabels?.mode === "outside" && t !== "outside" && (this.#a = this.#e.animate ? 0 : 1), this.#t = this.#p(), this.#s.length !== this.#t.length && (this.#s = new Array(this.#t.length).fill(0)), this.#l = null;
|
|
194
|
+
}
|
|
195
|
+
getColor() {
|
|
196
|
+
return this.#t[0]?.color ?? this.#e.colors?.[0] ?? "#888";
|
|
197
|
+
}
|
|
198
|
+
getLayerCount() {
|
|
199
|
+
return 1;
|
|
200
|
+
}
|
|
201
|
+
setLayerVisible(e, t) {
|
|
202
|
+
}
|
|
203
|
+
isLayerVisible(e) {
|
|
204
|
+
return !0;
|
|
205
|
+
}
|
|
206
|
+
getLayerColors() {
|
|
207
|
+
return [this.getColor()];
|
|
208
|
+
}
|
|
209
|
+
applyTheme(e, t) {
|
|
210
|
+
e.typography.fontFamily !== t.typography.fontFamily && (this.#l = null);
|
|
211
|
+
}
|
|
212
|
+
/** Hit-test: which slice is at this bitmap coordinate? Returns index or -1. */
|
|
213
|
+
hitTest(e, t, o, i, s) {
|
|
214
|
+
if (this.#t.length === 0) return -1;
|
|
215
|
+
const d = this.#f();
|
|
216
|
+
if (d <= 0) return -1;
|
|
217
|
+
const r = this.#l?.reserve ?? 0, { cx: c, cy: g, maxR: C } = Z({
|
|
218
|
+
bitmapWidth: o,
|
|
219
|
+
bitmapHeight: i,
|
|
220
|
+
padTop: s?.top ?? 0,
|
|
221
|
+
padBottom: s?.bottom ?? 0,
|
|
222
|
+
labelReserve: r
|
|
223
|
+
}), x = C, R = x * this.#e.innerRadiusRatio, M = e - c, X = t - g, $ = Math.sqrt(M * M + X * X);
|
|
224
|
+
if ($ > x || $ < R) return -1;
|
|
225
|
+
let L = Math.atan2(X, M) + Math.PI / 2;
|
|
226
|
+
L < 0 && (L += N);
|
|
227
|
+
let A = 0;
|
|
228
|
+
for (let b = 0; b < this.#t.length; b++) {
|
|
229
|
+
const I = this.#o(this.#t[b].value) / d * N;
|
|
230
|
+
if (L >= A && L < A + I) return b;
|
|
231
|
+
A += I;
|
|
232
|
+
}
|
|
233
|
+
return -1;
|
|
234
|
+
}
|
|
235
|
+
setHoverIndex(e) {
|
|
236
|
+
return this.#i === e ? !1 : (this.#i = e, !0);
|
|
237
|
+
}
|
|
238
|
+
getHoverIndex() {
|
|
239
|
+
return this.#i;
|
|
240
|
+
}
|
|
241
|
+
getHoverInfo(e) {
|
|
242
|
+
if (this.#i < 0) return null;
|
|
243
|
+
const t = this.#t[this.#i];
|
|
244
|
+
if (!t) return null;
|
|
245
|
+
const o = this.#f(), i = this.#e.colors ?? e.seriesColors;
|
|
246
|
+
return {
|
|
247
|
+
label: t.label,
|
|
248
|
+
value: t.value,
|
|
249
|
+
percent: o > 0 ? this.#o(t.value) / o * 100 : 0,
|
|
250
|
+
color: this.#h({ index: this.#i, palette: i, theme: e })
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
getSliceInfo(e) {
|
|
254
|
+
if (this.#t.length === 0) return null;
|
|
255
|
+
const t = this.#f(), o = this.#e.colors ?? e.seriesColors;
|
|
256
|
+
return this.#t.map((i, s) => ({
|
|
257
|
+
label: i.label,
|
|
258
|
+
value: i.value,
|
|
259
|
+
percent: t > 0 ? this.#o(i.value) / t * 100 : 0,
|
|
260
|
+
color: this.#h({ index: s, palette: o, theme: e })
|
|
261
|
+
}));
|
|
262
|
+
}
|
|
263
|
+
/** Returns true if animation is still in progress. */
|
|
264
|
+
get needsAnimation() {
|
|
265
|
+
if (!this.#e.animate) return !1;
|
|
266
|
+
for (let e = 0; e < this.#s.length; e++) {
|
|
267
|
+
const t = e === this.#i ? 1 : 0;
|
|
268
|
+
if (Math.abs(this.#s[e] - t) > 0.01) return !0;
|
|
269
|
+
}
|
|
270
|
+
return this.#e.sliceLabels?.mode === "outside" && this.#a < 0.99;
|
|
271
|
+
}
|
|
272
|
+
dispose() {
|
|
273
|
+
this.#r = [], this.#n = [], this.#t = [], this.#c = -1, this.#s = [], this.#u = 0;
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* @internal Test-only accessor for the animated slice offsets. The backing
|
|
277
|
+
* `#sliceOffsets` field is ECMAScript-private and can't be reached via a
|
|
278
|
+
* type-cast escape hatch, so the pie-animation regression tests use this
|
|
279
|
+
* method to assert convergence behavior. Do not call from production code.
|
|
280
|
+
*/
|
|
281
|
+
_inspectSliceOffsets() {
|
|
282
|
+
return this.#s;
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Layout-only sanitized slice value: finite and positive, else 0. Negative
|
|
286
|
+
* and non-finite values would corrupt the arc sweep (a negative slice drags
|
|
287
|
+
* the running angle backwards, desyncing fills / labels / hit-test, and a
|
|
288
|
+
* `NaN` slips past the `total <= 0` guard since `NaN <= 0` is false), so they
|
|
289
|
+
* contribute nothing to the geometry. The original value is still surfaced
|
|
290
|
+
* verbatim in reported SliceInfo / HoverInfo.
|
|
291
|
+
*/
|
|
292
|
+
#o(e) {
|
|
293
|
+
return Number.isFinite(e) && e > 0 ? e : 0;
|
|
294
|
+
}
|
|
295
|
+
/** Sum of layout-sanitized slice values — the denominator for every arc
|
|
296
|
+
* sweep and percentage. Always finite and ≥ 0. */
|
|
297
|
+
#f() {
|
|
298
|
+
let e = 0;
|
|
299
|
+
for (const t of this.#t)
|
|
300
|
+
e += this.#o(t.value);
|
|
301
|
+
return e;
|
|
302
|
+
}
|
|
303
|
+
/** Build the text shown for one slice given the resolved content mode. */
|
|
304
|
+
#d(e, t, o) {
|
|
305
|
+
const i = t > 0 ? this.#o(e.value) / t * 100 : 0, s = `${i.toFixed(i >= 10 ? 0 : 1)}%`;
|
|
306
|
+
return o === "percent" ? s : o === "label" ? e.label : `${e.label} ${s}`;
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Bitmap-pixel horizontal reserve needed for outside labels. Measured using
|
|
310
|
+
* the live `context` so font metrics match the paint path exactly. Cached
|
|
311
|
+
* until `setData` / `updateOptions` fires (`#labelReserveCache` is cleared).
|
|
312
|
+
*
|
|
313
|
+
* Keyed by both `fontScale` (= `horizontalPixelRatio` — HiDPI changes) and
|
|
314
|
+
* the active `context.font` string so a theme swap that changes the font
|
|
315
|
+
* family / size busts the cache and triggers a fresh measurement.
|
|
316
|
+
*/
|
|
317
|
+
#b(e, t, o, i) {
|
|
318
|
+
const s = e.font;
|
|
319
|
+
if (this.#l && this.#l.fontScale === i && this.#l.font === s)
|
|
320
|
+
return this.#l.reserve;
|
|
321
|
+
let d = 0;
|
|
322
|
+
for (const g of this.#t) {
|
|
323
|
+
const C = this.#d(g, o, t.content), x = e.measureText(C).width;
|
|
324
|
+
x > d && (d = x);
|
|
325
|
+
}
|
|
326
|
+
const r = Math.max(t.distance, t.elbowLen), c = (d + (r + Math.max(0, t.railWidth) + t.legPad + 4) * i) / et;
|
|
327
|
+
return this.#l = { fontScale: i, font: s, reserve: c }, c;
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* Draw one outside label: anchor dot → radial elbow (per-slice, at slice
|
|
331
|
+
* midangle) → short diagonal to the de-cluster-adjusted rail y → horizontal
|
|
332
|
+
* rail → text. Keeping the elbow local to each slice is what stops leader
|
|
333
|
+
* lines from cutting across the pie when several small slices cluster near
|
|
334
|
+
* 12 o'clock or 6 o'clock.
|
|
335
|
+
*/
|
|
336
|
+
#g(e) {
|
|
337
|
+
const { context: t, entry: o, textColor: i, labels: s, hpr: d, progress: r } = e;
|
|
338
|
+
if (r <= 0) return;
|
|
339
|
+
const { anchorX: c, anchorY: g, elbowX: C, elbowY: x, side: R, text: M, color: X, labelX: $, labelY: L } = o, A = $ + R * s.legPad * d, b = E(r / 0.15, 0, 1), I = E((r - 0.15) / 0.45, 0, 1), S = E((r - 0.6) / 0.4, 0, 1);
|
|
340
|
+
if (t.save(), t.globalAlpha = b, t.fillStyle = X, t.beginPath(), t.arc(c, g, 2.5 * d, 0, N), t.fill(), t.restore(), I > 0) {
|
|
341
|
+
t.save(), t.globalAlpha = I, t.strokeStyle = X, t.lineWidth = 1 * d, t.lineCap = "round", t.beginPath(), t.moveTo(c, g);
|
|
342
|
+
const v = c + (C - c) * I, u = g + (x - g) * I;
|
|
343
|
+
if (t.lineTo(v, u), S > 0) {
|
|
344
|
+
const a = C + ($ - C) * S, w = x + (L - x) * S;
|
|
345
|
+
t.lineTo(a, w);
|
|
346
|
+
}
|
|
347
|
+
t.stroke(), t.restore();
|
|
348
|
+
}
|
|
349
|
+
S > 0 && (t.save(), t.globalAlpha = S, t.fillStyle = i, t.textAlign = R >= 0 ? "left" : "right", t.textBaseline = "middle", t.fillText(M, A, L), t.restore());
|
|
350
|
+
}
|
|
351
|
+
/**
|
|
352
|
+
* Lay out one outside label per eligible slice. Returns entries in original
|
|
353
|
+
* slice order so the caller can map by index to reveal progress / explode.
|
|
354
|
+
*
|
|
355
|
+
* Radial per-slice layout: each label sits on its own slice's radial ray at
|
|
356
|
+
* radius `outerR + distance`. Rails stay short regardless of slice angle
|
|
357
|
+
* because the label is placed next to its slice, not at a canvas-wide
|
|
358
|
+
* column. PAV resolves vertical crowding by adjusting Y (labelX stays
|
|
359
|
+
* pinned to the slice's midangle ray).
|
|
360
|
+
*
|
|
361
|
+
* Side assignment is purely geometric (sign of cos). `balanceSides` is a
|
|
362
|
+
* no-op here because each label's X is tied to its slice — forcing a slice
|
|
363
|
+
* to the opposite side would mean flipping text direction without moving
|
|
364
|
+
* the label, which would push text across the pie.
|
|
365
|
+
*/
|
|
366
|
+
#x(e) {
|
|
367
|
+
const { cx: t, cy: o, outerR: i, total: s, palette: d, theme: r, labels: c, hpr: g, bitmapHeight: C } = e, x = new Array(this.#t.length).fill(null), R = c.elbowLen * g, M = Math.max(c.distance, c.elbowLen) * g, X = Math.max(0, c.railWidth) * g, $ = [];
|
|
368
|
+
let L = -Math.PI / 2;
|
|
369
|
+
const A = c.minSliceAngle * U;
|
|
370
|
+
for (let v = 0; v < this.#t.length; v++) {
|
|
371
|
+
const u = this.#t[v], a = this.#o(u.value) / s * N;
|
|
372
|
+
if (a >= A) {
|
|
373
|
+
const w = L + a / 2, n = this.#s[v] * (8 * g), f = Math.cos(w), h = Math.sin(w), m = f >= 0 ? 1 : -1, O = t + f * (i + n), P = o + h * (i + n), H = t + f * (i + n + R), p = o + h * (i + n + R), W = t + f * (i + n + M) + m * X, y = o + h * (i + n + M), Y = {
|
|
374
|
+
anchorX: O,
|
|
375
|
+
anchorY: P,
|
|
376
|
+
elbowX: H,
|
|
377
|
+
elbowY: p,
|
|
378
|
+
side: m,
|
|
379
|
+
labelX: W,
|
|
380
|
+
labelY: y,
|
|
381
|
+
text: this.#d(u, s, c.content),
|
|
382
|
+
color: this.#h({ index: v, palette: d, theme: r })
|
|
383
|
+
};
|
|
384
|
+
x[v] = Y, $.push({ entry: Y });
|
|
385
|
+
}
|
|
386
|
+
L += a;
|
|
387
|
+
}
|
|
388
|
+
const b = Math.max(1, c.fontSize * c.labelGap) * g, I = c.fontSize * g, S = C - c.fontSize * g;
|
|
389
|
+
for (const v of [1, -1]) {
|
|
390
|
+
const u = [];
|
|
391
|
+
for (const n of $)
|
|
392
|
+
n.entry.side === v && u.push(n.entry);
|
|
393
|
+
if (u.length === 0) continue;
|
|
394
|
+
u.sort((n, f) => n.labelY - f.labelY);
|
|
395
|
+
const a = [];
|
|
396
|
+
for (let n = 0; n < u.length; n++)
|
|
397
|
+
for (a.push({ count: 1, sumIdeal: u[n].labelY, startIdx: n }); a.length >= 2; ) {
|
|
398
|
+
const f = a[a.length - 2], h = a[a.length - 1], m = f.sumIdeal / f.count, O = h.sumIdeal / h.count, P = m + (f.count - 1) * b / 2;
|
|
399
|
+
if (O - (h.count - 1) * b / 2 >= P + b) break;
|
|
400
|
+
f.count += h.count, f.sumIdeal += h.sumIdeal, a.pop();
|
|
401
|
+
}
|
|
402
|
+
if (a.length > 0) {
|
|
403
|
+
const n = a[0], f = n.sumIdeal / n.count - (n.count - 1) * b / 2;
|
|
404
|
+
if (f < I)
|
|
405
|
+
for (n.sumIdeal += (I - f) * n.count; a.length >= 2; ) {
|
|
406
|
+
const h = a[0], m = a[1], O = h.sumIdeal / h.count, P = m.sumIdeal / m.count, H = O + (h.count - 1) * b / 2;
|
|
407
|
+
if (P - (m.count - 1) * b / 2 >= H + b) break;
|
|
408
|
+
h.count += m.count, h.sumIdeal += m.sumIdeal, a.splice(1, 1);
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
if (a.length > 0) {
|
|
412
|
+
const n = a[a.length - 1], f = n.sumIdeal / n.count + (n.count - 1) * b / 2;
|
|
413
|
+
if (f > S)
|
|
414
|
+
for (n.sumIdeal -= (f - S) * n.count; a.length >= 2; ) {
|
|
415
|
+
const h = a[a.length - 2], m = a[a.length - 1], O = h.sumIdeal / h.count, P = m.sumIdeal / m.count, H = O + (h.count - 1) * b / 2;
|
|
416
|
+
if (P - (m.count - 1) * b / 2 >= H + b) break;
|
|
417
|
+
h.count += m.count, h.sumIdeal += m.sumIdeal, a.pop();
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
const w = (I + S) / 2;
|
|
421
|
+
for (const n of a) {
|
|
422
|
+
const f = (n.count - 1) * b, h = n.sumIdeal / n.count;
|
|
423
|
+
f > S - I && h - f / 2 < I && (n.sumIdeal = w * n.count);
|
|
424
|
+
}
|
|
425
|
+
for (const n of a) {
|
|
426
|
+
const f = n.sumIdeal / n.count;
|
|
427
|
+
for (let h = 0; h < n.count; h++)
|
|
428
|
+
u[n.startIdx + h].labelY = f + (h - (n.count - 1) / 2) * b;
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
for (const v of $) {
|
|
432
|
+
const u = v.entry, a = u.labelY - u.anchorY;
|
|
433
|
+
let w;
|
|
434
|
+
if (Math.abs(a) <= R) {
|
|
435
|
+
const h = u.side * Math.sqrt(Math.max(0, R * R - a * a));
|
|
436
|
+
w = u.anchorX + h;
|
|
437
|
+
} else
|
|
438
|
+
w = (u.anchorX + u.labelX) / 2;
|
|
439
|
+
const n = Math.min(u.anchorX, u.labelX), f = Math.max(u.anchorX, u.labelX);
|
|
440
|
+
u.elbowX = Math.max(n, Math.min(f, w)), u.elbowY = u.labelY;
|
|
441
|
+
}
|
|
442
|
+
return x;
|
|
443
|
+
}
|
|
444
|
+
render(e) {
|
|
445
|
+
if (this.#t.length === 0) return;
|
|
446
|
+
const { scope: t, theme: o, padding: i } = e, { context: s, bitmapSize: d, horizontalPixelRatio: r, verticalPixelRatio: c } = t, g = performance.now(), C = this.#u ? Math.min(0.05, (g - this.#u) / 1e3) : 0;
|
|
447
|
+
this.#u = g;
|
|
448
|
+
const x = this.#f();
|
|
449
|
+
if (x <= 0) return;
|
|
450
|
+
const R = 12;
|
|
451
|
+
for (; this.#s.length < this.#t.length; )
|
|
452
|
+
this.#s.push(0);
|
|
453
|
+
if (this.#e.animate)
|
|
454
|
+
for (let p = 0; p < this.#t.length; p++) {
|
|
455
|
+
const W = p === this.#i ? 1 : 0;
|
|
456
|
+
this.#s[p] = K(this.#s[p], W, R, C);
|
|
457
|
+
}
|
|
458
|
+
const M = it(this.#e.sliceLabels);
|
|
459
|
+
s.font = `${M.fontSize * r}px ${o.typography.fontFamily}`, M.mode === "outside" && this.#e.animate && (this.#a = K(this.#a, 1, 6, C));
|
|
460
|
+
const X = this.#e.colors ?? o.seriesColors, $ = M.mode === "outside" ? this.#b(s, M, x, r) : 0, { cx: L, cy: A, maxR: b } = Z({
|
|
461
|
+
bitmapWidth: d.width,
|
|
462
|
+
bitmapHeight: d.height,
|
|
463
|
+
padTop: i.top * c,
|
|
464
|
+
padBottom: i.bottom * c,
|
|
465
|
+
labelReserve: $
|
|
466
|
+
}), I = b, S = I * this.#e.innerRadiusRatio, v = this.#e.padAngle * U, u = 8 * r, a = this.#e.shadow ?? !1, w = at(a), n = this.#e.innerShadow ?? !1, f = rt(n), h = this.#e.gradient !== !1;
|
|
467
|
+
let m = -Math.PI / 2;
|
|
468
|
+
for (let p = 0; p < this.#t.length; p++) {
|
|
469
|
+
const W = this.#t[p], y = this.#o(W.value) / x * N, Y = m + v / 2, B = m + y - v / 2, D = m + y / 2, F = this.#h({ index: p, palette: X, theme: o });
|
|
470
|
+
if (B <= Y) {
|
|
471
|
+
m += y;
|
|
472
|
+
continue;
|
|
473
|
+
}
|
|
474
|
+
const V = this.#s[p] * u, q = Math.cos(D) * V, _ = Math.sin(D) * V, z = L + q, k = A + _;
|
|
475
|
+
if (s.beginPath(), s.arc(z, k, I, Y, B), S > 0 ? s.arc(z, k, S, B, Y, !0) : s.lineTo(z, k), s.closePath(), h || n) {
|
|
476
|
+
const T = s.createRadialGradient(z, k, S || 0, z, k, I);
|
|
477
|
+
if (T.addColorStop(0, h ? ct(F, 0.15) : F), n) {
|
|
478
|
+
const G = Math.max(0, Math.min(0.999, 1 - f.depth));
|
|
479
|
+
T.addColorStop(G, F), T.addColorStop(1, ut(F, f.color));
|
|
480
|
+
} else
|
|
481
|
+
T.addColorStop(1, F);
|
|
482
|
+
s.fillStyle = T;
|
|
483
|
+
} else
|
|
484
|
+
s.fillStyle = F;
|
|
485
|
+
const j = this.#s[p];
|
|
486
|
+
if (a || j > 0.01) {
|
|
487
|
+
const T = a ? 1 : 0, G = j;
|
|
488
|
+
s.shadowColor = a ? w.color : "rgba(0,0,0,0.25)", s.shadowBlur = (w.blur * T + 12 * G) * r, s.shadowOffsetX = w.offsetX * T * r + q * 0.3 * G, s.shadowOffsetY = w.offsetY * T * c + _ * 0.3 * G;
|
|
489
|
+
}
|
|
490
|
+
s.fill(), s.shadowColor = "transparent", s.shadowBlur = 0, s.shadowOffsetX = 0, s.shadowOffsetY = 0, m += y;
|
|
491
|
+
}
|
|
492
|
+
if (M.mode === "none") return;
|
|
493
|
+
m = -Math.PI / 2;
|
|
494
|
+
const O = o.tooltip.textColor;
|
|
495
|
+
if (M.mode === "outside") {
|
|
496
|
+
const p = this.#x({
|
|
497
|
+
cx: L,
|
|
498
|
+
cy: A,
|
|
499
|
+
outerR: I,
|
|
500
|
+
total: x,
|
|
501
|
+
palette: X,
|
|
502
|
+
theme: o,
|
|
503
|
+
labels: M,
|
|
504
|
+
hpr: r,
|
|
505
|
+
bitmapHeight: d.height
|
|
506
|
+
}), W = p.length > 1 ? Math.min(0.06, 0.9 / (p.length - 1)) : 0;
|
|
507
|
+
for (let y = 0; y < p.length; y++) {
|
|
508
|
+
const Y = p[y];
|
|
509
|
+
if (Y === null) continue;
|
|
510
|
+
const B = y * W, D = E((this.#a - B) / (1 - B), 0, 1);
|
|
511
|
+
this.#g({
|
|
512
|
+
context: s,
|
|
513
|
+
entry: Y,
|
|
514
|
+
textColor: O,
|
|
515
|
+
labels: M,
|
|
516
|
+
hpr: r,
|
|
517
|
+
progress: D
|
|
518
|
+
});
|
|
519
|
+
}
|
|
520
|
+
return;
|
|
521
|
+
}
|
|
522
|
+
const P = S > 0 ? (I + S) / 2 : I * 0.65;
|
|
523
|
+
s.textAlign = "center", s.textBaseline = "middle";
|
|
524
|
+
const H = M.minSliceAngle * U;
|
|
525
|
+
for (let p = 0; p < this.#t.length; p++) {
|
|
526
|
+
const W = this.#t[p], y = this.#o(W.value) / x * N;
|
|
527
|
+
if (y >= H) {
|
|
528
|
+
const Y = m + y / 2, B = this.#s[p] * u, D = this.#h({ index: p, palette: X, theme: o }), F = this.#d(W, x, M.content), V = s.measureText(F).width, q = M.fontSize * 1.2 * r, _ = y < Math.PI ? 2 * P * Math.sin(y / 2) : 2 * P, z = V > _ - 4 * r, k = S > 0 && P - S < q;
|
|
529
|
+
if (!z && !k) {
|
|
530
|
+
const j = L + Math.cos(Y) * (P + B), T = A + Math.sin(Y) * (P + B);
|
|
531
|
+
s.fillStyle = ht(D) ? "#000000" : "#ffffff", s.fillText(F, j, T);
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
m += y;
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
const pt = {
|
|
539
|
+
type: "pie",
|
|
540
|
+
create: (l, e) => new ft({ ...e })
|
|
541
|
+
};
|
|
542
|
+
export {
|
|
543
|
+
ft as PieRenderer,
|
|
544
|
+
pt as PieSeriesDef
|
|
545
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { BarSeriesDef as i } from "./bar.js";
|
|
2
|
+
import { CandlestickSeriesDef as r } from "./candlestick.js";
|
|
3
|
+
import { registerSeriesDefinition as e } from "./definition.js";
|
|
4
|
+
import { LineSeriesDef as t } from "./line.js";
|
|
5
|
+
import { PieSeriesDef as s } from "./pie.js";
|
|
6
|
+
function S() {
|
|
7
|
+
e(r), e(t), e(i), e(s);
|
|
8
|
+
}
|
|
9
|
+
export {
|
|
10
|
+
S as registerBuiltinSeries
|
|
11
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
function r(t) {
|
|
2
|
+
let n = 0, i = 0;
|
|
3
|
+
for (const e of t)
|
|
4
|
+
e > 0 ? n += e : e < 0 && (i += e);
|
|
5
|
+
return { positive: n, negative: i };
|
|
6
|
+
}
|
|
7
|
+
function o(t) {
|
|
8
|
+
return t.positive > 0 ? t.positive : t.negative < 0 ? t.negative : 0;
|
|
9
|
+
}
|
|
10
|
+
function a(t) {
|
|
11
|
+
return t.positive > 0 ? 100 : t.negative < 0 ? -100 : 0;
|
|
12
|
+
}
|
|
13
|
+
export {
|
|
14
|
+
a as renderedStackPercentTop,
|
|
15
|
+
o as renderedStackTop,
|
|
16
|
+
r as sumStack
|
|
17
|
+
};
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
const f = /* @__PURE__ */ new WeakMap();
|
|
2
|
+
function b(e, r) {
|
|
3
|
+
return f.get(e)?.get(r);
|
|
4
|
+
}
|
|
5
|
+
function g(e, r, o) {
|
|
6
|
+
let n = f.get(e);
|
|
7
|
+
n || (n = /* @__PURE__ */ new Map(), f.set(e, n)), n.set(r, o);
|
|
8
|
+
}
|
|
9
|
+
function y(e) {
|
|
10
|
+
return "close" in e ? e.close : e.value;
|
|
11
|
+
}
|
|
12
|
+
function I(e, r) {
|
|
13
|
+
if (r === "none" || e.length <= 1) return e;
|
|
14
|
+
const o = [...e];
|
|
15
|
+
return o.sort((n, s) => {
|
|
16
|
+
const i = y(n.data), l = y(s.data);
|
|
17
|
+
return r === "asc" ? i - l : l - i;
|
|
18
|
+
}), o;
|
|
19
|
+
}
|
|
20
|
+
function u(e) {
|
|
21
|
+
const r = Object.freeze({ ...e.data }), o = {
|
|
22
|
+
id: e.id,
|
|
23
|
+
seriesId: e.seriesId,
|
|
24
|
+
layerIndex: e.layerIndex,
|
|
25
|
+
label: e.label,
|
|
26
|
+
data: r,
|
|
27
|
+
color: e.color
|
|
28
|
+
};
|
|
29
|
+
return Object.freeze(o);
|
|
30
|
+
}
|
|
31
|
+
function m(e, r) {
|
|
32
|
+
const o = r.sort ?? "none", n = e.getOverlayVersion(), s = b(e, r.cacheKey);
|
|
33
|
+
if (s && s.version === n && s.time === r.time && s.sort === o)
|
|
34
|
+
return s.data;
|
|
35
|
+
const i = [];
|
|
36
|
+
for (const t of e.getSeriesIds()) {
|
|
37
|
+
if (!e.isSeriesVisible(t)) continue;
|
|
38
|
+
if (e.getSeriesLayers(t) !== null) {
|
|
39
|
+
const d = e.getLayerSnapshots(t, r.time);
|
|
40
|
+
if (!d) continue;
|
|
41
|
+
for (const a of d)
|
|
42
|
+
i.push(
|
|
43
|
+
u({
|
|
44
|
+
id: `${t}_layer${a.layerIndex}`,
|
|
45
|
+
seriesId: t,
|
|
46
|
+
layerIndex: a.layerIndex,
|
|
47
|
+
label: e.getLayerLabel(t, a.layerIndex),
|
|
48
|
+
data: { time: a.time, value: a.value },
|
|
49
|
+
color: a.color
|
|
50
|
+
})
|
|
51
|
+
);
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
const c = e.getDataAtTime(t, r.time);
|
|
55
|
+
c && i.push(
|
|
56
|
+
u({
|
|
57
|
+
id: t,
|
|
58
|
+
seriesId: t,
|
|
59
|
+
label: e.getSeriesLabel(t),
|
|
60
|
+
data: c,
|
|
61
|
+
color: e.getSeriesColor(t) ?? "#888"
|
|
62
|
+
})
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
const l = Object.freeze(I(i, o));
|
|
66
|
+
return g(e, r.cacheKey, { version: n, time: r.time, sort: o, data: l }), l;
|
|
67
|
+
}
|
|
68
|
+
function S(e, r) {
|
|
69
|
+
const o = r.sort ?? "none", n = e.getOverlayVersion(), s = b(e, r.cacheKey);
|
|
70
|
+
if (s && s.version === n && s.time === null && s.sort === o)
|
|
71
|
+
return s.data;
|
|
72
|
+
const i = [];
|
|
73
|
+
for (const t of e.getSeriesIds()) {
|
|
74
|
+
if (!e.isSeriesVisible(t)) continue;
|
|
75
|
+
const c = e.getLayerLastSnapshots(t);
|
|
76
|
+
if (c) {
|
|
77
|
+
for (const a of c)
|
|
78
|
+
i.push(
|
|
79
|
+
u({
|
|
80
|
+
id: `${t}_layer${a.layerIndex}`,
|
|
81
|
+
seriesId: t,
|
|
82
|
+
layerIndex: a.layerIndex,
|
|
83
|
+
label: e.getLayerLabel(t, a.layerIndex),
|
|
84
|
+
data: { time: a.time, value: a.value },
|
|
85
|
+
color: a.color
|
|
86
|
+
})
|
|
87
|
+
);
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
const d = e.getLastData(t);
|
|
91
|
+
d && i.push(
|
|
92
|
+
u({
|
|
93
|
+
id: t,
|
|
94
|
+
seriesId: t,
|
|
95
|
+
label: e.getSeriesLabel(t),
|
|
96
|
+
data: d,
|
|
97
|
+
color: e.getSeriesColor(t) ?? "#888"
|
|
98
|
+
})
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
const l = Object.freeze(I(i, o));
|
|
102
|
+
return g(e, r.cacheKey, { version: n, time: null, sort: o, data: l }), l;
|
|
103
|
+
}
|
|
104
|
+
export {
|
|
105
|
+
m as buildHoverSnapshots,
|
|
106
|
+
S as buildLastSnapshots
|
|
107
|
+
};
|