@wick-charts/vue 0.8.0 → 0.8.2
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 +2 -0
- package/dist/BandSeries.vue.js +43 -32
- package/dist/BarSeries.vue.js +44 -33
- package/dist/CandlestickSeries.vue.js +24 -23
- package/dist/ChartContainer.vue.js +1 -1
- package/dist/HeatmapSeries.vue.js +21 -20
- package/dist/LineSeries.vue.js +43 -32
- package/dist/PieSeries.vue.js +25 -24
- package/dist/composables.js +63 -36
- package/dist/core/dist/axis/dom-labels.js +64 -53
- package/dist/core/dist/chart/badge-animator.js +38 -28
- package/dist/core/dist/chart/options.js +1 -1
- package/dist/core/dist/chart/y-target.js +38 -32
- package/dist/core/dist/chart.js +852 -709
- package/dist/core/dist/data/decimation.js +52 -51
- package/dist/core/dist/data/store.js +38 -20
- package/dist/core/dist/data/sync.js +97 -59
- package/dist/core/dist/navigator/controller.js +11 -11
- package/dist/core/dist/perf/perf-hud.js +3 -3
- package/dist/core/dist/scales/tick-tracker.js +2 -1
- package/dist/core/dist/scales/time-ticks.js +99 -0
- package/dist/core/dist/scales/x-scale.js +33 -27
- package/dist/core/dist/series/band.js +83 -83
- package/dist/core/dist/series/bar.js +240 -211
- package/dist/core/dist/series/base-multi-layer.js +288 -240
- package/dist/core/dist/series/candlestick.js +168 -168
- package/dist/core/dist/series/line.js +545 -455
- package/dist/core/dist/snapshots.js +109 -86
- package/dist/core/dist/utils/point.js +4 -0
- package/dist/core/dist/utils/time.js +42 -26
- package/dist/index.d.ts +67 -28
- package/dist/ui/InfoBar.vue.js +69 -69
- package/dist/ui/NumberFlow.vue.js +36 -27
- package/dist/ui/Tooltip.vue.js +128 -131
- package/dist/ui/YLabel.vue.js +47 -47
- package/package.json +2 -2
- package/src/BandSeries.vue +20 -5
- package/src/BarSeries.vue +20 -5
- package/src/CandlestickSeries.vue +5 -4
- package/src/ChartContainer.vue +15 -9
- package/src/HeatmapSeries.vue +5 -4
- package/src/LineSeries.vue +20 -5
- package/src/PieSeries.vue +6 -5
- package/src/composables.ts +64 -1
- package/src/ui/InfoBar.vue +11 -3
- package/src/ui/NumberFlow.vue +17 -3
- package/src/ui/Tooltip.vue +23 -12
- package/src/ui/YLabel.vue +28 -27
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { clamp as
|
|
1
|
+
import { clamp as f } from "../utils/math.js";
|
|
2
2
|
import { crispCenterOffset as v } from "../utils/pixel-grid.js";
|
|
3
|
-
import { formatTime as
|
|
3
|
+
import { formatTime as p, niceTimeIntervals as g } from "../utils/time.js";
|
|
4
4
|
import { AxisTickTracker as I } from "./tick-tracker.js";
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
import { timeTicks as k } from "./time-ticks.js";
|
|
6
|
+
import { pickNiceCeiling as b, pickNiceFloor as y } from "./y-scale.js";
|
|
7
|
+
const o = 50, T = 80, h = 0.3, u = 0.2;
|
|
8
|
+
class w {
|
|
8
9
|
/**
|
|
9
10
|
* Shared fade state for time ticks. Grid lines (canvas) and DOM tick labels
|
|
10
11
|
* read opacity from the same tracker, so a tick fading in/out looks
|
|
@@ -44,20 +45,20 @@ class W {
|
|
|
44
45
|
return this.labelCountHintValue;
|
|
45
46
|
}
|
|
46
47
|
get minLabelSpacing() {
|
|
47
|
-
return this.minSpacingValue ??
|
|
48
|
+
return this.minSpacingValue ?? T;
|
|
48
49
|
}
|
|
49
50
|
update(t, i, s, e) {
|
|
50
51
|
if (this.from = t.from, this.to = t.to, this.width = i, this.pixelRatio = s, this.type === "time" && e !== void 0 && e > 0) {
|
|
51
|
-
const r =
|
|
52
|
+
const r = m(e);
|
|
52
53
|
this.lastBucketKey !== null && this.lastBucketKey !== r && this.resetHysteresis(), this.lastBucketKey = r, this.dataInterval = e;
|
|
53
54
|
}
|
|
54
55
|
this.resolveInterval();
|
|
55
56
|
}
|
|
56
57
|
setLabelCount(t) {
|
|
57
|
-
this.labelCountHintValue =
|
|
58
|
+
this.labelCountHintValue = x(t), this.resetHysteresis(), this.resolveInterval();
|
|
58
59
|
}
|
|
59
60
|
setMinSpacing(t) {
|
|
60
|
-
this.minSpacingValue =
|
|
61
|
+
this.minSpacingValue = V(t), this.resetHysteresis(), this.resolveInterval();
|
|
61
62
|
}
|
|
62
63
|
setFormat(t) {
|
|
63
64
|
this.customFormat = t;
|
|
@@ -83,8 +84,8 @@ class W {
|
|
|
83
84
|
/** Band spacing on a category axis; an omitted or invalid side takes its default. */
|
|
84
85
|
setBandPadding(t) {
|
|
85
86
|
this.bandPadding = {
|
|
86
|
-
inner:
|
|
87
|
-
outer:
|
|
87
|
+
inner: c({ value: t?.inner, fallback: h, max: 1 }),
|
|
88
|
+
outer: c({ value: t?.outer, fallback: u, max: 1 / 0 })
|
|
88
89
|
};
|
|
89
90
|
}
|
|
90
91
|
getBandPadding() {
|
|
@@ -110,7 +111,7 @@ class W {
|
|
|
110
111
|
*/
|
|
111
112
|
snapToBand(t) {
|
|
112
113
|
const i = this.categories.length;
|
|
113
|
-
return this.type !== "category" || i === 0 ? t :
|
|
114
|
+
return this.type !== "category" || i === 0 ? t : f(Math.round(t), 0, i - 1);
|
|
114
115
|
}
|
|
115
116
|
/**
|
|
116
117
|
* An internal coordinate in the axis domain: the category name at that
|
|
@@ -151,7 +152,7 @@ class W {
|
|
|
151
152
|
*/
|
|
152
153
|
formatX(t, i) {
|
|
153
154
|
const s = this.domainValue(t);
|
|
154
|
-
return this.customFormat ? this.customFormat(s, i) : this.type === "category" ? String(s) : this.type === "numeric" ?
|
|
155
|
+
return this.customFormat ? this.customFormat(s, i) : this.type === "category" ? String(s) : this.type === "numeric" ? M({ value: t, step: i, locale: this.localeValue }) : p(t, i, { locale: this.localeValue, timeZone: this.timeZoneValue });
|
|
155
156
|
}
|
|
156
157
|
/**
|
|
157
158
|
* Format a data point's X for a tooltip or info-bar header. Like
|
|
@@ -197,7 +198,9 @@ class W {
|
|
|
197
198
|
return Math.max(1, Math.round(this.barWidthMedia(t) * this.pixelRatio));
|
|
198
199
|
}
|
|
199
200
|
/**
|
|
200
|
-
*
|
|
201
|
+
* "Nice" tick values. A time axis puts them on calendar boundaries in the
|
|
202
|
+
* installed time zone (Jan 1, the 1st of a month, midnight), so their gaps
|
|
203
|
+
* vary; `tickInterval` is the tier's nominal span. Resolution uses the cached
|
|
201
204
|
* `dataInterval` set by `update()`; callers that bypass `update()` can
|
|
202
205
|
* still pass it here for back-compat.
|
|
203
206
|
*/
|
|
@@ -209,11 +212,14 @@ class W {
|
|
|
209
212
|
}
|
|
210
213
|
if (this.type === "category") return this.bandTicks();
|
|
211
214
|
if (this.type === "time" && this.dataInterval !== t) {
|
|
212
|
-
const a =
|
|
215
|
+
const a = m(t);
|
|
213
216
|
this.lastBucketKey !== null && this.lastBucketKey !== a && this.resetHysteresis(), this.lastBucketKey = a, this.dataInterval = t, this.resolveInterval();
|
|
214
217
|
}
|
|
215
218
|
if (this.resolvedInterval == null) return { ticks: [], tickInterval: 0 };
|
|
216
|
-
const i = this.resolvedInterval
|
|
219
|
+
const i = this.resolvedInterval;
|
|
220
|
+
if (this.type === "time")
|
|
221
|
+
return { ticks: k({ from: this.from, to: this.to, interval: i, timeZone: this.timeZoneValue, max: o }), tickInterval: i };
|
|
222
|
+
const s = Math.ceil(this.from / i) * i, e = Math.max(0, Math.min(o, Math.floor((this.to - s) / i) + 1)), r = [];
|
|
217
223
|
for (let a = 0; a < e; a++) r.push(s + a * i);
|
|
218
224
|
return { ticks: r, tickInterval: i };
|
|
219
225
|
}
|
|
@@ -244,7 +250,7 @@ class W {
|
|
|
244
250
|
this.resolvedInterval = null;
|
|
245
251
|
return;
|
|
246
252
|
}
|
|
247
|
-
const t =
|
|
253
|
+
const t = g(this.dataInterval), i = this.to - this.from, s = i / this.width * this.minLabelSpacing;
|
|
248
254
|
let e;
|
|
249
255
|
if (this.labelCountHint != null) {
|
|
250
256
|
const l = Math.max(1, this.labelCountHint);
|
|
@@ -252,8 +258,8 @@ class W {
|
|
|
252
258
|
} else
|
|
253
259
|
e = s;
|
|
254
260
|
if (this.lastInterval != null && this.lastWant != null && t.includes(this.lastInterval)) {
|
|
255
|
-
const l = e >= this.lastWant * 0.8 && e <= this.lastWant * 1.25,
|
|
256
|
-
if (l &&
|
|
261
|
+
const l = e >= this.lastWant * 0.8 && e <= this.lastWant * 1.25, d = this.lastInterval >= s;
|
|
262
|
+
if (l && d) {
|
|
257
263
|
this.resolvedInterval = this.lastInterval;
|
|
258
264
|
return;
|
|
259
265
|
}
|
|
@@ -289,7 +295,7 @@ class W {
|
|
|
289
295
|
}
|
|
290
296
|
let r = b(e);
|
|
291
297
|
if (this.labelCountHint != null && this.countTicks(r) < this.labelCountHint) {
|
|
292
|
-
const a =
|
|
298
|
+
const a = y(e);
|
|
293
299
|
a >= i && (r = a);
|
|
294
300
|
}
|
|
295
301
|
this.resolvedInterval = r, this.lastInterval = r, this.lastWant = e;
|
|
@@ -300,23 +306,23 @@ class W {
|
|
|
300
306
|
return Math.max(0, Math.floor((this.to - i) / t) + 1);
|
|
301
307
|
}
|
|
302
308
|
}
|
|
303
|
-
function
|
|
309
|
+
function m(n) {
|
|
304
310
|
return n < 6e4 ? 0 : n < 36e5 ? 1 : n < 864e5 ? 2 : 3;
|
|
305
311
|
}
|
|
306
|
-
function
|
|
307
|
-
const { value: t, step: i, locale: s } = n, e = Number.isFinite(i) && i > 0 ? -Math.floor(Math.log10(i)) : 2, r =
|
|
312
|
+
function M(n) {
|
|
313
|
+
const { value: t, step: i, locale: s } = n, e = Number.isFinite(i) && i > 0 ? -Math.floor(Math.log10(i)) : 2, r = f(e, 0, 20);
|
|
308
314
|
return t.toLocaleString(s ?? "en-US", { maximumFractionDigits: r });
|
|
309
315
|
}
|
|
310
|
-
function
|
|
316
|
+
function c(n) {
|
|
311
317
|
const { value: t, fallback: i, max: s } = n;
|
|
312
318
|
return t === void 0 || !Number.isFinite(t) || t < 0 ? i : Math.min(t, s);
|
|
313
319
|
}
|
|
314
|
-
function
|
|
320
|
+
function x(n) {
|
|
315
321
|
return typeof n == "number" && Number.isFinite(n) && n >= 2 ? Math.floor(n) : null;
|
|
316
322
|
}
|
|
317
|
-
function
|
|
323
|
+
function V(n) {
|
|
318
324
|
return typeof n == "number" && Number.isFinite(n) && n > 0 ? n : null;
|
|
319
325
|
}
|
|
320
326
|
export {
|
|
321
|
-
|
|
327
|
+
w as XScale
|
|
322
328
|
};
|
|
@@ -2,15 +2,15 @@ import { Animator as I } from "../animation/animator.js";
|
|
|
2
2
|
import { DEFAULT_HISTORY_REVEAL as z, DEFAULT_BAND_INTRO as F, DEFAULT_BAND_SMOOTH as O, DEFAULT_BAND_ENTRY as _ } from "../animation/config.js";
|
|
3
3
|
import { easeOutCubic as Y } from "../animation/easing.js";
|
|
4
4
|
import { IntroWave as N } from "../animation/intro-wave.js";
|
|
5
|
-
import { ScalarSpring as
|
|
5
|
+
import { ScalarSpring as A } from "../animation/scalar-spring.js";
|
|
6
6
|
import { decimateBandData as $ } from "../data/decimation.js";
|
|
7
7
|
import { TimeSeriesStore as H } from "../data/store.js";
|
|
8
8
|
import { resolveColor as U, hexToRgba as T } from "../utils/color.js";
|
|
9
9
|
import { lerp as L } from "../utils/math.js";
|
|
10
|
-
import {
|
|
11
|
-
import { unfoldIntro as
|
|
12
|
-
import { buildCurveSegments as B, replaySegmentsForward as R, replaySegmentsReversed as
|
|
13
|
-
const
|
|
10
|
+
import { sliceSample as W, normalizeTime as J } from "../utils/time.js";
|
|
11
|
+
import { unfoldIntro as j, scaleMean as G, backfillSweepIntro as Z } from "./line-intro.js";
|
|
12
|
+
import { buildCurveSegments as B, replaySegmentsForward as R, replaySegmentsReversed as q } from "./painters/canvas-path.js";
|
|
13
|
+
const K = {
|
|
14
14
|
colors: ["#2962FF"],
|
|
15
15
|
fill: void 0,
|
|
16
16
|
stroke: { visible: !0, width: 1, color: void 0 },
|
|
@@ -22,11 +22,11 @@ const Z = {
|
|
|
22
22
|
historyRevealMs: z,
|
|
23
23
|
introAnimation: void 0,
|
|
24
24
|
historyReveal: void 0
|
|
25
|
-
},
|
|
25
|
+
}, Q = 0.4, tt = 0.04, E = 0.6, et = Z();
|
|
26
26
|
function k(a, t) {
|
|
27
27
|
return a === !1 ? 0 : a ?? t;
|
|
28
28
|
}
|
|
29
|
-
function
|
|
29
|
+
function C(a, t) {
|
|
30
30
|
const i = t.stroke;
|
|
31
31
|
return {
|
|
32
32
|
colors: t.colors ?? a.colors,
|
|
@@ -46,12 +46,12 @@ function V(a, t) {
|
|
|
46
46
|
historyReveal: "historyReveal" in t ? t.historyReveal : a.historyReveal
|
|
47
47
|
};
|
|
48
48
|
}
|
|
49
|
-
const
|
|
49
|
+
const it = (a, t, i) => a + (t - a) * i;
|
|
50
50
|
function P(a) {
|
|
51
51
|
return a <= 0 ? 0 : a >= 1 ? 1 : a;
|
|
52
52
|
}
|
|
53
|
-
function
|
|
54
|
-
const t =
|
|
53
|
+
function S(a) {
|
|
54
|
+
const t = J(a.time), { low: i, high: e } = a;
|
|
55
55
|
return !Number.isFinite(i) || !Number.isFinite(e) ? { ...a, time: t, low: Number.NaN, high: Number.NaN } : { ...a, time: t, low: Math.min(i, e), high: Math.max(i, e) };
|
|
56
56
|
}
|
|
57
57
|
function b(a) {
|
|
@@ -60,25 +60,25 @@ function b(a) {
|
|
|
60
60
|
function x(a) {
|
|
61
61
|
return { low: a.low, high: a.high };
|
|
62
62
|
}
|
|
63
|
-
function
|
|
63
|
+
function ot(a) {
|
|
64
64
|
const { upperSegs: t, lowerSegs: i } = a;
|
|
65
65
|
for (let e = 0; e < t.length; e++) {
|
|
66
66
|
const o = t[e], s = i[e];
|
|
67
67
|
if (o.kind !== "bezier" || s.kind !== "bezier") continue;
|
|
68
|
-
const n =
|
|
68
|
+
const n = V(o.cp1y, s.cp1y), l = V(o.cp2y, s.cp2y);
|
|
69
69
|
t[e] = { ...o, cp1y: n.top, cp2y: l.top }, i[e] = { ...s, cp1y: n.bottom, cp2y: l.bottom };
|
|
70
70
|
}
|
|
71
71
|
}
|
|
72
|
-
function
|
|
72
|
+
function V(a, t) {
|
|
73
73
|
if (a <= t) return { top: a, bottom: t };
|
|
74
74
|
const i = (a + t) / 2;
|
|
75
75
|
return { top: i, bottom: i };
|
|
76
76
|
}
|
|
77
|
-
class
|
|
77
|
+
class st {
|
|
78
78
|
store = new H();
|
|
79
79
|
/** Entrance start wall-time per appended point, keyed by point time. */
|
|
80
80
|
entries = /* @__PURE__ */ new Map();
|
|
81
|
-
alpha = new I({ initial: 1, duration: 0, lerp:
|
|
81
|
+
alpha = new I({ initial: 1, duration: 0, lerp: it });
|
|
82
82
|
/** Displayed edges of the last point; the chase moves them toward the stored ones. */
|
|
83
83
|
displayedLast = null;
|
|
84
84
|
chase = null;
|
|
@@ -91,7 +91,7 @@ class ot {
|
|
|
91
91
|
/** Per-point eases started by `morphData`, keyed by point time; pruned on settle. */
|
|
92
92
|
morphs = /* @__PURE__ */ new Map();
|
|
93
93
|
}
|
|
94
|
-
class
|
|
94
|
+
class nt {
|
|
95
95
|
kind = "band";
|
|
96
96
|
#e;
|
|
97
97
|
#t;
|
|
@@ -109,10 +109,10 @@ class st {
|
|
|
109
109
|
/** True while a ghost pre-pass draws — edges only, no fill. */
|
|
110
110
|
#c = !1;
|
|
111
111
|
constructor(t, i) {
|
|
112
|
-
this.#t = Array.from({ length: Math.max(1, t) }, () => new
|
|
112
|
+
this.#t = Array.from({ length: Math.max(1, t) }, () => new st()), this.#e = C(K, i ?? {});
|
|
113
113
|
}
|
|
114
114
|
updateOptions(t) {
|
|
115
|
-
this.#e =
|
|
115
|
+
this.#e = C(this.#e, t);
|
|
116
116
|
}
|
|
117
117
|
applyTheme(t) {
|
|
118
118
|
this.updateOptions({ colors: X(t, this.#t.length) });
|
|
@@ -121,8 +121,8 @@ class st {
|
|
|
121
121
|
setData(t, i = 0) {
|
|
122
122
|
const e = this.#t[i];
|
|
123
123
|
if (!e) return;
|
|
124
|
-
const o = this.#t.some((l) => l.store.length > 0), s = (t ?? []).map(
|
|
125
|
-
|
|
124
|
+
const o = this.#t.some((l) => l.store.length > 0), s = (t ?? []).map(S);
|
|
125
|
+
!o && s.length > 0 && this.#i.arm(this.#e.introMs), e.store.setData(s);
|
|
126
126
|
const n = e.store.last();
|
|
127
127
|
e.displayedLast = n ? x(n) : null, e.chase = null, e.pinned = null, e.morphs.clear(), e.entries.clear(), this.#o.finish(), this.#s = null;
|
|
128
128
|
}
|
|
@@ -141,7 +141,7 @@ class st {
|
|
|
141
141
|
const o = /* @__PURE__ */ new Map();
|
|
142
142
|
for (const h of e.store.getAll())
|
|
143
143
|
o.set(h.time, this.#u(e, h));
|
|
144
|
-
const s = (t ?? []).map(
|
|
144
|
+
const s = (t ?? []).map(S);
|
|
145
145
|
e.store.setData(s);
|
|
146
146
|
const n = this.#e.smoothMs, l = this.#e.entryAnimation !== "none" && this.#e.entryMs > 0, r = /* @__PURE__ */ new Map();
|
|
147
147
|
for (const h of s) {
|
|
@@ -152,8 +152,8 @@ class st {
|
|
|
152
152
|
}
|
|
153
153
|
if (u.low === h.low && u.high === h.high || n <= 0 || b(h) || !Number.isFinite(u.low)) continue;
|
|
154
154
|
const g = e.morphs.get(h.time) ?? {
|
|
155
|
-
low: new
|
|
156
|
-
high: new
|
|
155
|
+
low: new A(u.low),
|
|
156
|
+
high: new A(u.high)
|
|
157
157
|
};
|
|
158
158
|
g.low.target !== h.low && g.low.retarget(h.low, { settleMs: n }), g.high.target !== h.high && g.high.retarget(h.high, { settleMs: n }), r.set(h.time, g);
|
|
159
159
|
}
|
|
@@ -167,7 +167,7 @@ class st {
|
|
|
167
167
|
appendPoint(t, i = 0) {
|
|
168
168
|
const e = this.#t[i];
|
|
169
169
|
if (!e) return;
|
|
170
|
-
const o =
|
|
170
|
+
const o = S(t), s = e.store.last(), n = e.store.length;
|
|
171
171
|
e.store.append(o);
|
|
172
172
|
const l = e.store.length > n;
|
|
173
173
|
e.chase !== null && s !== void 0 && l && (e.pinned = { time: s.time, chase: e.chase }), e.displayedLast = x(o), e.chase = null, this.#e.entryAnimation !== "none" && this.#e.entryMs > 0 && e.entries.set(o.time, performance.now());
|
|
@@ -175,11 +175,11 @@ class st {
|
|
|
175
175
|
prependPoints(t, i = 0) {
|
|
176
176
|
const e = this.#t[i];
|
|
177
177
|
if (!e || t.length === 0) return;
|
|
178
|
-
const o = t.map(
|
|
179
|
-
e.store.prepend(o), this.#
|
|
178
|
+
const o = t.map(S), s = e.store.first()?.time;
|
|
179
|
+
e.store.prepend(o), this.#S(o[0]?.time, s);
|
|
180
180
|
}
|
|
181
181
|
/** While a reveal is in flight only the range grows — a restart would hide half-revealed points again. */
|
|
182
|
-
#
|
|
182
|
+
#S(t, i) {
|
|
183
183
|
const e = this.#e.historyRevealMs;
|
|
184
184
|
if (!(this.#e.historyReveal === "none" || e <= 0) && !(t === void 0 || i === void 0)) {
|
|
185
185
|
if (this.#o.active && this.#s !== null) {
|
|
@@ -192,7 +192,7 @@ class st {
|
|
|
192
192
|
updateLastPoint(t, i = 0) {
|
|
193
193
|
const e = this.#t[i];
|
|
194
194
|
if (!e) return;
|
|
195
|
-
const o =
|
|
195
|
+
const o = S(t), s = e.store.last()?.time;
|
|
196
196
|
e.store.updateLast(o);
|
|
197
197
|
const n = s === void 0 ? void 0 : e.morphs.get(s);
|
|
198
198
|
s !== void 0 && n !== void 0 && (e.morphs.delete(s), e.displayedLast = { low: n.low.current, high: n.high.current }, e.chase = n);
|
|
@@ -203,7 +203,7 @@ class st {
|
|
|
203
203
|
}
|
|
204
204
|
if (e.chase === null) {
|
|
205
205
|
const r = e.displayedLast, c = r !== null && Number.isFinite(r.low) ? r : x(o);
|
|
206
|
-
e.chase = { low: new
|
|
206
|
+
e.chase = { low: new A(c.low), high: new A(c.high) };
|
|
207
207
|
}
|
|
208
208
|
e.chase.low.retarget(o.low, { settleMs: l }), e.chase.high.retarget(o.high, { settleMs: l });
|
|
209
209
|
}
|
|
@@ -239,9 +239,9 @@ class st {
|
|
|
239
239
|
#g(t) {
|
|
240
240
|
this.#i.tick(t), this.#o.tick(t);
|
|
241
241
|
for (const i of this.#t)
|
|
242
|
-
i.alpha.tick(t), this.#
|
|
242
|
+
i.alpha.tick(t), this.#A(i, t), this.#T(i, t);
|
|
243
243
|
}
|
|
244
|
-
#
|
|
244
|
+
#A(t, i) {
|
|
245
245
|
const e = t.chase;
|
|
246
246
|
if (e !== null) {
|
|
247
247
|
const s = e.low.tick(i), n = e.high.tick(i);
|
|
@@ -350,7 +350,7 @@ class st {
|
|
|
350
350
|
* link grows from the previous link's rendered spot, so a feed faster than
|
|
351
351
|
* `entryMs` keeps every head unfurling instead of snapping older ones.
|
|
352
352
|
*/
|
|
353
|
-
#
|
|
353
|
+
#w(t, i) {
|
|
354
354
|
if (this.#e.entryAnimation !== "grow") return null;
|
|
355
355
|
const e = this.#t[i], o = this.#k(e);
|
|
356
356
|
if (o.length === 0) return null;
|
|
@@ -363,12 +363,12 @@ class st {
|
|
|
363
363
|
for (let p = 0; p < o.length; p++) {
|
|
364
364
|
const h = s[n + 1 + p], u = this.#l(t, i, h);
|
|
365
365
|
if (u === null) return null;
|
|
366
|
-
const g = Y(o[p].progress),
|
|
366
|
+
const g = Y(o[p].progress), v = {
|
|
367
367
|
x: L(c.x, u.x, g),
|
|
368
368
|
top: L(c.top, u.top, g),
|
|
369
369
|
bottom: L(c.bottom, u.bottom, g)
|
|
370
370
|
};
|
|
371
|
-
r.set(h.time,
|
|
371
|
+
r.set(h.time, v), c = v;
|
|
372
372
|
}
|
|
373
373
|
return r;
|
|
374
374
|
}
|
|
@@ -379,17 +379,17 @@ class st {
|
|
|
379
379
|
this.#n = null;
|
|
380
380
|
const e = this.#s;
|
|
381
381
|
if (this.#o.active && e !== null) {
|
|
382
|
-
const n = this.#e.historyReveal ??
|
|
383
|
-
n !== "none" && (this.#n = n(this.#
|
|
382
|
+
const n = this.#e.historyReveal ?? et;
|
|
383
|
+
n !== "none" && (this.#n = n(this.#V(t, e)));
|
|
384
384
|
}
|
|
385
385
|
const o = this.#n;
|
|
386
|
-
this.#
|
|
386
|
+
this.#v(t, o?.ghostAlpha ?? 0);
|
|
387
387
|
const s = this.#D(t, o, e);
|
|
388
388
|
this.#i.active ? this.#R(t) : (this.#a = null, this.#m(t)), s && i.restore();
|
|
389
389
|
}
|
|
390
390
|
#R(t) {
|
|
391
|
-
const i = (this.#e.introAnimation ?? this.#P())(this.#
|
|
392
|
-
this.#a = i, this.#
|
|
391
|
+
const i = (this.#e.introAnimation ?? this.#P())(this.#C(t));
|
|
392
|
+
this.#a = i, this.#v(t, i.ghostAlpha ?? 0);
|
|
393
393
|
const { context: e } = t.scope, { width: o, height: s } = t.scope.bitmapSize, n = i.clip, l = n !== void 0 && (n.fromX !== void 0 || n.toX !== void 0);
|
|
394
394
|
if (l) {
|
|
395
395
|
const r = n.fromX ?? 0, c = n.toX ?? o;
|
|
@@ -398,10 +398,10 @@ class st {
|
|
|
398
398
|
this.#m(t), l && e.restore();
|
|
399
399
|
}
|
|
400
400
|
#P() {
|
|
401
|
-
return this.#h === null && (this.#h =
|
|
401
|
+
return this.#h === null && (this.#h = j()), this.#h;
|
|
402
402
|
}
|
|
403
403
|
/** Edges-only skeleton under the main pass, so a clip reveal never reads as an empty chart. */
|
|
404
|
-
#
|
|
404
|
+
#v(t, i) {
|
|
405
405
|
if (i <= 0) return;
|
|
406
406
|
const { context: e } = t.scope;
|
|
407
407
|
e.save(), e.globalAlpha *= i, this.#c = !0, this.#m(t), this.#c = !1, e.restore();
|
|
@@ -423,16 +423,16 @@ class st {
|
|
|
423
423
|
const { scope: s, timeScale: n } = t, l = n.getRange();
|
|
424
424
|
let r = e.store.getVisibleData(l.from, l.to);
|
|
425
425
|
if (r.length > s.mediaSize.width * 2 && (r = $(r, Math.round(s.mediaSize.width * 1.5))), r.length === 0) return;
|
|
426
|
-
const c = r[r.length - 1], p = this.#y(e, r), h = p ? this.#
|
|
426
|
+
const c = r[r.length - 1], p = this.#y(e, r), h = p ? this.#w(t, i) : null, u = this.#B(t, { layerIndex: i, data: r, grown: h });
|
|
427
427
|
if (u.length === 0) return;
|
|
428
|
-
const g = p ? this.#d(e, c.time) : 1,
|
|
428
|
+
const g = p ? this.#d(e, c.time) : 1, v = p && !b(c) && this.#e.entryAnimation === "fade" && g < 1 ? rt(u) : null, { context: m } = s;
|
|
429
429
|
m.save(), o < 1 && (m.globalAlpha *= o);
|
|
430
|
-
const f = this.#r(i),
|
|
431
|
-
if (
|
|
432
|
-
this.#p(
|
|
430
|
+
const f = this.#r(i), w = { ctx: t, runs: u, color: f, growing: h !== null };
|
|
431
|
+
if (v === null)
|
|
432
|
+
this.#p(w);
|
|
433
433
|
else {
|
|
434
434
|
const { width: d, height: y } = s.bitmapSize;
|
|
435
|
-
m.save(), m.beginPath(), m.rect(0, 0,
|
|
435
|
+
m.save(), m.beginPath(), m.rect(0, 0, v, y), m.clip(), this.#p(w), m.restore(), m.save(), m.beginPath(), m.rect(v, 0, Math.max(0, d - v), y), m.clip(), m.globalAlpha *= g, this.#p(w), m.restore();
|
|
436
436
|
}
|
|
437
437
|
m.restore();
|
|
438
438
|
}
|
|
@@ -466,24 +466,24 @@ class st {
|
|
|
466
466
|
p.push(f[0]);
|
|
467
467
|
continue;
|
|
468
468
|
}
|
|
469
|
-
const
|
|
469
|
+
const w = s && m === e.length - 1, d = f.map((M) => ({ x: M.x, y: M.top })), y = f.map((M) => ({ x: M.x, y: M.bottom })), D = {
|
|
470
470
|
upper: d,
|
|
471
471
|
lower: y,
|
|
472
|
-
upperSegs: B(d, r,
|
|
473
|
-
lowerSegs: B(y, r,
|
|
472
|
+
upperSegs: B(d, r, w),
|
|
473
|
+
lowerSegs: B(y, r, w)
|
|
474
474
|
};
|
|
475
|
-
|
|
475
|
+
ot(D), c.push(D);
|
|
476
476
|
}
|
|
477
477
|
if (!this.#c && c.length > 0) {
|
|
478
478
|
n.fillStyle = this.#E({ context: n, paths: c, color: o });
|
|
479
479
|
for (const m of c) {
|
|
480
480
|
n.beginPath(), n.moveTo(m.upper[0].x, m.upper[0].y), R(n, m.upperSegs);
|
|
481
481
|
const f = m.lower[m.lower.length - 1];
|
|
482
|
-
n.lineTo(f.x, f.y),
|
|
482
|
+
n.lineTo(f.x, f.y), q(n, m.lower, m.lowerSegs), n.closePath(), n.fill();
|
|
483
483
|
}
|
|
484
484
|
}
|
|
485
|
-
const h = this.#e.stroke, u = h.color ?? T(o, E), g = Math.max(1, Math.round(h.width * l)),
|
|
486
|
-
if (
|
|
485
|
+
const h = this.#e.stroke, u = h.color ?? T(o, E), g = Math.max(1, Math.round(h.width * l)), v = h.visible && h.width > 0;
|
|
486
|
+
if (v && c.length > 0) {
|
|
487
487
|
n.beginPath();
|
|
488
488
|
for (const m of c)
|
|
489
489
|
n.moveTo(m.upper[0].x, m.upper[0].y), R(n, m.upperSegs), n.moveTo(m.lower[0].x, m.lower[0].y), R(n, m.lowerSegs);
|
|
@@ -493,7 +493,7 @@ class st {
|
|
|
493
493
|
n.beginPath();
|
|
494
494
|
for (const m of p)
|
|
495
495
|
n.moveTo(m.x, m.top), n.lineTo(m.x, m.bottom);
|
|
496
|
-
n.strokeStyle =
|
|
496
|
+
n.strokeStyle = v ? u : T(o, E), n.lineWidth = g, n.lineCap = "round", n.stroke();
|
|
497
497
|
}
|
|
498
498
|
}
|
|
499
499
|
/** A gradient fill spans the layer's drawn extent this frame; a degenerate extent paints solid. */
|
|
@@ -501,8 +501,8 @@ class st {
|
|
|
501
501
|
const { context: i, paths: e, color: o } = t, s = this.#e.fill;
|
|
502
502
|
if (typeof s == "string") return s;
|
|
503
503
|
const [n, l] = s ?? [
|
|
504
|
-
T(o,
|
|
505
|
-
T(o,
|
|
504
|
+
T(o, Q),
|
|
505
|
+
T(o, tt)
|
|
506
506
|
];
|
|
507
507
|
let r = 1 / 0, c = -1 / 0;
|
|
508
508
|
for (const h of e) {
|
|
@@ -516,7 +516,7 @@ class st {
|
|
|
516
516
|
return p.addColorStop(0, n), p.addColorStop(1, l), p;
|
|
517
517
|
}
|
|
518
518
|
// --- Intro frames ---------------------------------------------------------
|
|
519
|
-
#
|
|
519
|
+
#C(t) {
|
|
520
520
|
return this.#b(t, {
|
|
521
521
|
progress: this.#i.linear(),
|
|
522
522
|
range: t.timeScale.getRange(),
|
|
@@ -524,7 +524,7 @@ class st {
|
|
|
524
524
|
width: t.timeScale.getMediaWidth() * t.scope.horizontalPixelRatio
|
|
525
525
|
});
|
|
526
526
|
}
|
|
527
|
-
#
|
|
527
|
+
#V(t, i) {
|
|
528
528
|
const { timeScale: e } = t;
|
|
529
529
|
return this.#b(t, {
|
|
530
530
|
progress: this.#o.linear(),
|
|
@@ -541,26 +541,26 @@ class st {
|
|
|
541
541
|
const { timeScale: e, yScale: o, scope: s } = t, { progress: n, range: l, width: r } = i, c = this.#t.length, p = new Array(c), h = new Array(c);
|
|
542
542
|
let u;
|
|
543
543
|
const g = (f) => {
|
|
544
|
-
const
|
|
545
|
-
if (
|
|
544
|
+
const w = p[f];
|
|
545
|
+
if (w !== void 0) return w;
|
|
546
546
|
const d = (this.#t[f]?.store.getVisibleData(l.from, l.to) ?? []).map((y) => ({
|
|
547
547
|
time: y.time,
|
|
548
548
|
value: b(y) ? Number.NaN : o.lerpValue(y.low, y.high, 0.5)
|
|
549
549
|
}));
|
|
550
550
|
return p[f] = d, d;
|
|
551
|
-
},
|
|
552
|
-
const
|
|
553
|
-
if (
|
|
554
|
-
const d =
|
|
551
|
+
}, v = (f) => {
|
|
552
|
+
const w = h[f];
|
|
553
|
+
if (w !== void 0) return w;
|
|
554
|
+
const d = G(g(f), o);
|
|
555
555
|
return h[f] = d, d;
|
|
556
556
|
}, m = () => {
|
|
557
557
|
if (u !== void 0) return u;
|
|
558
558
|
u = null;
|
|
559
559
|
for (let f = 0; f < c; f++) {
|
|
560
560
|
if (this.getLayerAlpha(f) <= 0 || !this.isLayerVisible(f)) continue;
|
|
561
|
-
const
|
|
562
|
-
if (!(
|
|
563
|
-
u =
|
|
561
|
+
const w = g(f).filter((d) => o.isPlottable(d.value));
|
|
562
|
+
if (!(w.length < 2)) {
|
|
563
|
+
u = w.map((d) => ({
|
|
564
564
|
x: e.timeToBitmapXExact(d.time),
|
|
565
565
|
y: o.valueToBitmapYExact(d.value),
|
|
566
566
|
time: d.time
|
|
@@ -579,10 +579,10 @@ class st {
|
|
|
579
579
|
timeToX: (f) => e.timeToBitmapXExact(f),
|
|
580
580
|
xToTime: (f) => e.xToTime(f / s.horizontalPixelRatio),
|
|
581
581
|
valueToY: (f) => o.valueToBitmapYExact(f),
|
|
582
|
-
lerpValue: (f,
|
|
582
|
+
lerpValue: (f, w, d) => o.lerpValue(f, w, d),
|
|
583
583
|
layerCount: c,
|
|
584
584
|
layerData: g,
|
|
585
|
-
layerMean:
|
|
585
|
+
layerMean: v,
|
|
586
586
|
primaryPath: m
|
|
587
587
|
};
|
|
588
588
|
}
|
|
@@ -602,15 +602,15 @@ class st {
|
|
|
602
602
|
if (u === null) continue;
|
|
603
603
|
const g = this.#r(r);
|
|
604
604
|
o.save(), o.globalAlpha *= p, o.fillStyle = g;
|
|
605
|
-
for (const
|
|
606
|
-
o.save(), o.globalAlpha *= 0.25, o.beginPath(), o.arc(u.x,
|
|
605
|
+
for (const v of [u.top, u.bottom])
|
|
606
|
+
o.save(), o.globalAlpha *= 0.25, o.beginPath(), o.arc(u.x, v, l, 0, Math.PI * 2), o.fill(), o.restore(), o.beginPath(), o.arc(u.x, v, n, 0, Math.PI * 2), o.fill();
|
|
607
607
|
o.restore();
|
|
608
608
|
}
|
|
609
609
|
}
|
|
610
610
|
/** The hovered sample where the fill draws it: an entering tail point sits on its grown head. */
|
|
611
611
|
#X(t, i, e) {
|
|
612
612
|
const o = this.#t[i], s = t.timeScale.getRange(), n = o.store.getVisibleData(s.from, s.to);
|
|
613
|
-
return (this.#y(o, n) ? this.#
|
|
613
|
+
return (this.#y(o, n) ? this.#w(t, i) : null)?.get(e.time) ?? this.#l(t, i, e);
|
|
614
614
|
}
|
|
615
615
|
// --- Data queries ---------------------------------------------------------
|
|
616
616
|
/** A sample as a query reports it: the drawn (live-chased) edges, `null` for a gap. */
|
|
@@ -670,11 +670,11 @@ class st {
|
|
|
670
670
|
const t = this.#t[0].store.getAll();
|
|
671
671
|
return t.length < 2 ? null : t[t.length - 2];
|
|
672
672
|
}
|
|
673
|
-
sampleTimes(t) {
|
|
674
|
-
for (const
|
|
675
|
-
const
|
|
676
|
-
if (
|
|
677
|
-
return
|
|
673
|
+
sampleTimes(t, i = "start") {
|
|
674
|
+
for (const e of this.#t) {
|
|
675
|
+
const o = e.store.getAll();
|
|
676
|
+
if (o.length !== 0)
|
|
677
|
+
return W(o, { maxCount: t, from: i }).map((s) => s.time);
|
|
678
678
|
}
|
|
679
679
|
return [];
|
|
680
680
|
}
|
|
@@ -708,16 +708,16 @@ class st {
|
|
|
708
708
|
function X(a, t) {
|
|
709
709
|
return t === 1 ? [a.bands.upper] : a.seriesColors.slice(0, t);
|
|
710
710
|
}
|
|
711
|
-
function
|
|
711
|
+
function rt(a) {
|
|
712
712
|
const t = a[a.length - 1];
|
|
713
713
|
return t.length < 2 ? null : Math.round(t[t.length - 2].x);
|
|
714
714
|
}
|
|
715
|
-
const
|
|
715
|
+
const yt = {
|
|
716
716
|
type: "band",
|
|
717
717
|
xTypes: ["time", "numeric", "category"],
|
|
718
|
-
create: ({ theme: a, layerCount: t }, i) => new
|
|
718
|
+
create: ({ theme: a, layerCount: t }, i) => new nt(t, { colors: X(a, t), ...i })
|
|
719
719
|
};
|
|
720
720
|
export {
|
|
721
|
-
|
|
722
|
-
|
|
721
|
+
nt as BandRenderer,
|
|
722
|
+
yt as BandSeriesDef
|
|
723
723
|
};
|