@wick-charts/vue 0.8.0 → 0.8.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 +2 -0
- package/dist/BandSeries.vue.js +40 -30
- package/dist/BarSeries.vue.js +39 -29
- package/dist/CandlestickSeries.vue.js +2 -2
- package/dist/ChartContainer.vue.js +1 -1
- package/dist/LineSeries.vue.js +40 -30
- package/dist/core/dist/chart/badge-animator.js +38 -28
- package/dist/core/dist/chart.js +801 -694
- package/dist/core/dist/data/sync.js +77 -50
- package/dist/core/dist/navigator/controller.js +11 -11
- 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 +82 -82
- package/dist/core/dist/series/bar.js +1 -1
- package/dist/core/dist/series/base-multi-layer.js +182 -152
- package/dist/core/dist/series/candlestick.js +96 -96
- package/dist/core/dist/series/line.js +297 -292
- package/dist/core/dist/snapshots.js +39 -35
- package/dist/core/dist/utils/point.js +4 -0
- package/dist/core/dist/utils/time.js +42 -26
- package/dist/index.d.ts +45 -24
- package/dist/ui/InfoBar.vue.js +13 -13
- package/dist/ui/Tooltip.vue.js +11 -11
- package/dist/ui/YLabel.vue.js +47 -47
- package/package.json +2 -2
- package/src/BandSeries.vue +16 -3
- package/src/BarSeries.vue +16 -3
- package/src/ChartContainer.vue +14 -8
- package/src/LineSeries.vue +16 -3
- package/src/ui/YLabel.vue +28 -27
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { Animator as k } from "../animation/animator.js";
|
|
2
2
|
import { IntroWave as y } from "../animation/intro-wave.js";
|
|
3
3
|
import { ScalarSpring as V } from "../animation/scalar-spring.js";
|
|
4
|
-
import { TimeSeriesStore as
|
|
5
|
-
import { resolveColor as
|
|
6
|
-
import { normalizeTimePointArray as d, normalizeTime as L } from "../utils/time.js";
|
|
7
|
-
import { sumStack as A, renderedStackPercentTop as
|
|
8
|
-
const
|
|
9
|
-
class
|
|
4
|
+
import { TimeSeriesStore as P } from "../data/store.js";
|
|
5
|
+
import { resolveColor as M } from "../utils/color.js";
|
|
6
|
+
import { normalizeTimePointArray as d, normalizeTime as L, sliceSample as F } from "../utils/time.js";
|
|
7
|
+
import { sumStack as A, renderedStackPercentTop as w, renderedStackTop as b } from "./stack-math.js";
|
|
8
|
+
const S = (m, e, t) => m + (e - m) * t;
|
|
9
|
+
class z {
|
|
10
10
|
stores;
|
|
11
11
|
// --- Animation state (per layer) ----------------------------------------
|
|
12
12
|
/**
|
|
@@ -54,9 +54,9 @@ class F {
|
|
|
54
54
|
* and `1` at the deepest point. */
|
|
55
55
|
historyRange = null;
|
|
56
56
|
constructor(e) {
|
|
57
|
-
this.stores = Array.from({ length: e }, () => new
|
|
57
|
+
this.stores = Array.from({ length: e }, () => new P()), this.entries = Array.from({ length: e }, () => /* @__PURE__ */ new Map()), this.displayedLastValues = new Array(e).fill(null), this.#t = new Array(e).fill(null), this.#e = new Array(e).fill(null), this.#s = Array.from({ length: e }, () => /* @__PURE__ */ new Map()), this.#i = Array.from(
|
|
58
58
|
{ length: e },
|
|
59
|
-
() => new k({ initial: 1, duration: 0, lerp:
|
|
59
|
+
() => new k({ initial: 1, duration: 0, lerp: S })
|
|
60
60
|
);
|
|
61
61
|
}
|
|
62
62
|
// --- Color accessors ------------------------------------------------------
|
|
@@ -65,39 +65,39 @@ class F {
|
|
|
65
65
|
* layer on the theme base in `options.colors`). Kept separate from the base so
|
|
66
66
|
* a theme swap, which rewrites `options.colors`, leaves these untouched.
|
|
67
67
|
*/
|
|
68
|
-
#
|
|
68
|
+
#n = [];
|
|
69
69
|
setColorOverrides(e) {
|
|
70
|
-
this.#
|
|
70
|
+
this.#n = e;
|
|
71
71
|
}
|
|
72
72
|
/** The active resolver for a layer — the `data` override if set, else the theme base (cycled). */
|
|
73
|
-
#
|
|
74
|
-
const t = this.#
|
|
73
|
+
#r(e) {
|
|
74
|
+
const t = this.#n[e];
|
|
75
75
|
if (t !== void 0) return t;
|
|
76
76
|
const s = this.options.colors;
|
|
77
77
|
return s[e % s.length];
|
|
78
78
|
}
|
|
79
79
|
/** The first layer's color resolver (string or value-fn). */
|
|
80
80
|
getColor() {
|
|
81
|
-
return this.#
|
|
81
|
+
return this.#r(0);
|
|
82
82
|
}
|
|
83
83
|
getColors() {
|
|
84
84
|
return this.options.colors;
|
|
85
85
|
}
|
|
86
86
|
/** Resolve one layer's color for a given datum value. */
|
|
87
87
|
resolveLayerColor(e, t) {
|
|
88
|
-
return
|
|
88
|
+
return M(this.#r(e), t);
|
|
89
89
|
}
|
|
90
90
|
// --- Data ingest ----------------------------------------------------------
|
|
91
91
|
setData(e, t = 0) {
|
|
92
92
|
const s = this.stores[t];
|
|
93
93
|
if (!s) return;
|
|
94
94
|
let i = !1;
|
|
95
|
-
for (const
|
|
96
|
-
|
|
97
|
-
const
|
|
98
|
-
s.setData(
|
|
99
|
-
const
|
|
100
|
-
this.displayedLastValues[t] =
|
|
95
|
+
for (const r of this.stores)
|
|
96
|
+
r.length > 0 && (i = !0);
|
|
97
|
+
const n = d(e ?? []);
|
|
98
|
+
s.setData(n), !i && n.length > 0 && this.introWave.arm(this.options.introMs);
|
|
99
|
+
const l = s.last();
|
|
100
|
+
this.displayedLastValues[t] = l ? l.value : null, this.#t[t] = null, this.#e[t] = null, this.#s[t].clear(), this.entries[t].clear(), this.historyWave.finish(), this.historyRange = null;
|
|
101
101
|
}
|
|
102
102
|
/**
|
|
103
103
|
* Replace a layer like {@link setData}, but ease each point that keeps its
|
|
@@ -114,42 +114,42 @@ class F {
|
|
|
114
114
|
const i = /* @__PURE__ */ new Map();
|
|
115
115
|
for (const h of s.getAll())
|
|
116
116
|
i.set(h.time, this.liveValue(t, h.time, h.value));
|
|
117
|
-
const
|
|
118
|
-
s.setData(
|
|
119
|
-
const
|
|
120
|
-
for (const h of
|
|
117
|
+
const n = d(e ?? []);
|
|
118
|
+
s.setData(n);
|
|
119
|
+
const l = this.options.smoothMs, r = this.isEntryEnabled() && this.options.entryMs > 0, o = this.entries[t], u = this.#s[t], a = /* @__PURE__ */ new Map();
|
|
120
|
+
for (const h of n) {
|
|
121
121
|
const g = i.get(h.time);
|
|
122
122
|
if (g === void 0) {
|
|
123
|
-
|
|
123
|
+
r && o.set(h.time, { startTime: performance.now() });
|
|
124
124
|
continue;
|
|
125
125
|
}
|
|
126
126
|
const p = h.value;
|
|
127
|
-
if (g === p ||
|
|
127
|
+
if (g === p || l <= 0 || !Number.isFinite(g) || !Number.isFinite(p)) continue;
|
|
128
128
|
const v = u.get(h.time) ?? new V(g);
|
|
129
|
-
v.target !== p && v.retarget(p, { settleMs:
|
|
129
|
+
v.target !== p && v.retarget(p, { settleMs: l }), a.set(h.time, v);
|
|
130
130
|
}
|
|
131
|
-
const
|
|
132
|
-
for (const h of
|
|
133
|
-
|
|
131
|
+
const f = new Set(n.map((h) => h.time));
|
|
132
|
+
for (const h of o.keys())
|
|
133
|
+
f.has(h) || o.delete(h);
|
|
134
134
|
this.#s[t] = a;
|
|
135
|
-
const
|
|
136
|
-
this.displayedLastValues[t] =
|
|
135
|
+
const c = s.last();
|
|
136
|
+
this.displayedLastValues[t] = c ? c.value : null, this.#t[t] = null, this.#e[t] = null;
|
|
137
137
|
}
|
|
138
138
|
appendPoint(e, t = 0) {
|
|
139
139
|
const s = this.stores[t];
|
|
140
140
|
if (!s) return;
|
|
141
|
-
const i = e,
|
|
142
|
-
s.append({ ...i, time:
|
|
143
|
-
const
|
|
144
|
-
|
|
141
|
+
const i = e, n = L(i.time), l = s.last(), r = s.length;
|
|
142
|
+
s.append({ ...i, time: n });
|
|
143
|
+
const o = this.#t[t];
|
|
144
|
+
o !== null && l !== void 0 && s.length > r && (this.#e[t] = { time: l.time, anim: o }), this.displayedLastValues[t] = i.value, this.#t[t] = null;
|
|
145
145
|
const u = this.options.entryMs;
|
|
146
|
-
this.isEntryEnabled() && u > 0 && this.entries[t].set(
|
|
146
|
+
this.isEntryEnabled() && u > 0 && this.entries[t].set(n, { startTime: performance.now() });
|
|
147
147
|
}
|
|
148
148
|
prependPoints(e, t = 0) {
|
|
149
149
|
const s = this.stores[t];
|
|
150
150
|
if (!s || e.length === 0) return;
|
|
151
|
-
const i = d(e),
|
|
152
|
-
s.prepend(i), this.#o(i[0]?.time,
|
|
151
|
+
const i = d(e), n = s.first()?.time;
|
|
152
|
+
s.prepend(i), this.#o(i[0]?.time, n);
|
|
153
153
|
}
|
|
154
154
|
/**
|
|
155
155
|
* Arm (or extend) the history-reveal wave for freshly prepended points.
|
|
@@ -170,21 +170,21 @@ class F {
|
|
|
170
170
|
updateLastPoint(e, t = 0) {
|
|
171
171
|
const s = this.stores[t];
|
|
172
172
|
if (!s) return;
|
|
173
|
-
const i = e,
|
|
173
|
+
const i = e, n = s.last()?.time;
|
|
174
174
|
s.updateLast({ ...i, time: L(i.time) });
|
|
175
|
-
const
|
|
176
|
-
|
|
177
|
-
const
|
|
175
|
+
const l = this.#s[t], r = n === void 0 ? void 0 : l.get(n);
|
|
176
|
+
n !== void 0 && r !== void 0 && (l.delete(n), this.displayedLastValues[t] = r.current, this.#t[t] = r);
|
|
177
|
+
const o = i.value, u = this.options.smoothMs;
|
|
178
178
|
if (u <= 0) {
|
|
179
|
-
this.displayedLastValues[t] =
|
|
179
|
+
this.displayedLastValues[t] = o, this.#t[t] = null;
|
|
180
180
|
return;
|
|
181
181
|
}
|
|
182
182
|
let a = this.#t[t];
|
|
183
183
|
if (a === null) {
|
|
184
|
-
const
|
|
185
|
-
a = new V(
|
|
184
|
+
const f = this.displayedLastValues[t] ?? o;
|
|
185
|
+
a = new V(f), this.#t[t] = a;
|
|
186
186
|
}
|
|
187
|
-
a.retarget(
|
|
187
|
+
a.retarget(o, { settleMs: u });
|
|
188
188
|
}
|
|
189
189
|
keepLast(e, t = 0) {
|
|
190
190
|
const s = this.stores[t];
|
|
@@ -208,7 +208,7 @@ class F {
|
|
|
208
208
|
getLayerColors() {
|
|
209
209
|
const e = [];
|
|
210
210
|
for (let t = 0; t < this.stores.length; t++) {
|
|
211
|
-
const s = this.
|
|
211
|
+
const s = this.lastFinitePoint(t)?.value ?? 0;
|
|
212
212
|
e.push(this.resolveLayerColor(t, s));
|
|
213
213
|
}
|
|
214
214
|
return e;
|
|
@@ -236,8 +236,8 @@ class F {
|
|
|
236
236
|
if (s === void 0) return 1;
|
|
237
237
|
const i = this.options.entryMs;
|
|
238
238
|
if (i <= 0) return 1;
|
|
239
|
-
const
|
|
240
|
-
return
|
|
239
|
+
const n = performance.now() - s.startTime;
|
|
240
|
+
return n <= 0 ? 0 : n >= i ? 1 : n / i;
|
|
241
241
|
}
|
|
242
242
|
/**
|
|
243
243
|
* Initial-load reveal progress for a datum, keyed by its normalized
|
|
@@ -249,8 +249,8 @@ class F {
|
|
|
249
249
|
*/
|
|
250
250
|
introProgressAt(e, t) {
|
|
251
251
|
if (!this.introWave.active) return 1;
|
|
252
|
-
const s = e.timeScale.getRange(), i = s.to - s.from,
|
|
253
|
-
return this.introWave.progressAt(
|
|
252
|
+
const s = e.timeScale.getRange(), i = s.to - s.from, n = i > 0 ? (t - s.from) / i : 0;
|
|
253
|
+
return this.introWave.progressAt(n);
|
|
254
254
|
}
|
|
255
255
|
/**
|
|
256
256
|
* History-prepend reveal progress for a datum. Stagger position is
|
|
@@ -280,9 +280,9 @@ class F {
|
|
|
280
280
|
if (!t || t.length < 2) return [];
|
|
281
281
|
const s = [];
|
|
282
282
|
for (let i = t.length - 1; i >= 1; i--) {
|
|
283
|
-
const
|
|
284
|
-
if (
|
|
285
|
-
s.unshift({ time: t[i].time, progress:
|
|
283
|
+
const n = this.entranceProgress(e, t[i].time);
|
|
284
|
+
if (n >= 1) break;
|
|
285
|
+
s.unshift({ time: t[i].time, progress: n });
|
|
286
286
|
}
|
|
287
287
|
return s;
|
|
288
288
|
}
|
|
@@ -307,11 +307,11 @@ class F {
|
|
|
307
307
|
liveValue(e, t, s) {
|
|
308
308
|
const i = this.#s[e]?.get(t);
|
|
309
309
|
if (i !== void 0) return i.current;
|
|
310
|
-
const
|
|
311
|
-
if (
|
|
310
|
+
const n = this.stores[e]?.last()?.time;
|
|
311
|
+
if (n !== void 0 && t === n)
|
|
312
312
|
return this.displayedLastValues[e] ?? s;
|
|
313
|
-
const
|
|
314
|
-
return
|
|
313
|
+
const l = this.#e[e];
|
|
314
|
+
return l !== null && l.time === t ? l.anim.current : s;
|
|
315
315
|
}
|
|
316
316
|
/**
|
|
317
317
|
* Value a last-value/tooltip query should report for `time` — defaults to
|
|
@@ -336,22 +336,22 @@ class F {
|
|
|
336
336
|
for (let t = 0; t < this.stores.length; t++) {
|
|
337
337
|
const s = this.#t[t];
|
|
338
338
|
if (s !== null) {
|
|
339
|
-
const
|
|
340
|
-
this.displayedLastValues[t] = s.current,
|
|
339
|
+
const o = s.tick(e);
|
|
340
|
+
this.displayedLastValues[t] = s.current, o || (this.#t[t] = null);
|
|
341
341
|
}
|
|
342
342
|
const i = this.#e[t];
|
|
343
343
|
i !== null && !i.anim.tick(e) && (this.#e[t] = null);
|
|
344
|
-
const
|
|
345
|
-
for (const [
|
|
346
|
-
u.tick(e) ||
|
|
347
|
-
const
|
|
348
|
-
if (
|
|
344
|
+
const n = this.#s[t];
|
|
345
|
+
for (const [o, u] of n)
|
|
346
|
+
u.tick(e) || n.delete(o);
|
|
347
|
+
const l = this.options.entryMs;
|
|
348
|
+
if (l <= 0) {
|
|
349
349
|
this.entries[t].clear();
|
|
350
350
|
continue;
|
|
351
351
|
}
|
|
352
|
-
const
|
|
353
|
-
for (const [
|
|
354
|
-
e - u.startTime >=
|
|
352
|
+
const r = this.entries[t];
|
|
353
|
+
for (const [o, u] of r)
|
|
354
|
+
e - u.startTime >= l && r.delete(o);
|
|
355
355
|
}
|
|
356
356
|
}
|
|
357
357
|
/** True while any layer has an active chase, unsettled entry, alpha fade,
|
|
@@ -424,9 +424,23 @@ class F {
|
|
|
424
424
|
return this.#i[e]?.current ?? 1;
|
|
425
425
|
}
|
|
426
426
|
// --- Data queries ---------------------------------------------------------
|
|
427
|
+
/**
|
|
428
|
+
* The layer's newest point with a finite value, after skipping `skip` such
|
|
429
|
+
* points — a trailing `null` / `NaN` is a gap, not the latest reading.
|
|
430
|
+
*/
|
|
431
|
+
lastFinitePoint(e, t = 0) {
|
|
432
|
+
const s = this.stores[e]?.getAll() ?? [];
|
|
433
|
+
let i = t;
|
|
434
|
+
for (let n = s.length - 1; n >= 0; n--)
|
|
435
|
+
if (Number.isFinite(s[n].value)) {
|
|
436
|
+
if (i === 0) return s[n];
|
|
437
|
+
i--;
|
|
438
|
+
}
|
|
439
|
+
return null;
|
|
440
|
+
}
|
|
427
441
|
getLastValue() {
|
|
428
442
|
for (let e = this.stores.length - 1; e >= 0; e--) {
|
|
429
|
-
const t = this.
|
|
443
|
+
const t = this.lastFinitePoint(e);
|
|
430
444
|
if (t) return t.value;
|
|
431
445
|
}
|
|
432
446
|
return null;
|
|
@@ -439,87 +453,104 @@ class F {
|
|
|
439
453
|
const s = [];
|
|
440
454
|
for (let i = 0; i < this.stores.length; i++) {
|
|
441
455
|
if (!this.stores[i].isVisible()) continue;
|
|
442
|
-
const
|
|
443
|
-
if (
|
|
444
|
-
const
|
|
456
|
+
const n = this.stores[i].findNearest(e, t);
|
|
457
|
+
if (n === null) continue;
|
|
458
|
+
const l = {
|
|
445
459
|
layerIndex: i,
|
|
446
|
-
time:
|
|
460
|
+
time: n.time,
|
|
447
461
|
// Routes through the same live/pinned-chase smoothing the renderer
|
|
448
462
|
// paints, so hovering the live edge mid-animation doesn't jump ahead
|
|
449
463
|
// to the raw target before the on-screen marker gets there.
|
|
450
|
-
value: this.snapshotValue(i,
|
|
464
|
+
value: this.snapshotValue(i, n.time, n.value),
|
|
451
465
|
// Resolve the layer's color at the hovered datum's value so a value-fn
|
|
452
466
|
// colors the tooltip dot to match the bar / segment under the cursor.
|
|
453
|
-
color: this.resolveLayerColor(i,
|
|
467
|
+
color: this.resolveLayerColor(i, n.value)
|
|
454
468
|
};
|
|
455
|
-
|
|
469
|
+
n.x !== void 0 && (l.x = n.x), s.push(l);
|
|
456
470
|
}
|
|
457
471
|
return s.length > 0 ? s : null;
|
|
458
472
|
}
|
|
459
473
|
getStackedLastValue() {
|
|
460
474
|
if (this.stores.length <= 1) {
|
|
461
|
-
const
|
|
462
|
-
return
|
|
475
|
+
const i = this.lastFinitePoint(0);
|
|
476
|
+
return i ? { value: this.snapshotValue(0, i.time, i.value), isLive: !0 } : null;
|
|
463
477
|
}
|
|
464
478
|
const e = this.options.stacking;
|
|
465
479
|
if (e === "off") {
|
|
466
|
-
for (let
|
|
467
|
-
if (!this.stores[
|
|
468
|
-
const n = this.
|
|
469
|
-
if (n) return { value: this.snapshotValue(
|
|
480
|
+
for (let i = this.stores.length - 1; i >= 0; i--) {
|
|
481
|
+
if (!this.stores[i].isVisible()) continue;
|
|
482
|
+
const n = this.lastFinitePoint(i);
|
|
483
|
+
if (n) return { value: this.snapshotValue(i, n.time, n.value), isLive: !0 };
|
|
470
484
|
}
|
|
471
485
|
return null;
|
|
472
486
|
}
|
|
487
|
+
const t = this.stackHeadValues((i) => this.stores[i].last() ?? null) ?? this.lastDrawnRowValues();
|
|
488
|
+
if (!t) return null;
|
|
489
|
+
const s = A(t);
|
|
490
|
+
return { value: e === "percent" ? w(s) : b(s), isLive: !0 };
|
|
491
|
+
}
|
|
492
|
+
/** Stack contributions at the newest time any visible layer has a finite point. */
|
|
493
|
+
lastDrawnRowValues() {
|
|
494
|
+
let e = null;
|
|
495
|
+
for (let s = 0; s < this.stores.length; s++) {
|
|
496
|
+
if (!this.stores[s].isVisible()) continue;
|
|
497
|
+
const i = this.lastFinitePoint(s);
|
|
498
|
+
i !== null && (e === null || i.time > e) && (e = i.time);
|
|
499
|
+
}
|
|
500
|
+
if (e === null) return null;
|
|
501
|
+
const t = e;
|
|
502
|
+
return this.stackHeadValues((s) => this.stores[s].findNearest(t, 0));
|
|
503
|
+
}
|
|
504
|
+
/** Each visible layer's stack contribution at `pick(layer)`, or `null` when none is finite. */
|
|
505
|
+
stackHeadValues(e) {
|
|
473
506
|
let t = !1;
|
|
474
507
|
const s = [];
|
|
475
|
-
for (let
|
|
476
|
-
if (!this.stores[
|
|
477
|
-
const n =
|
|
478
|
-
if (!n) {
|
|
508
|
+
for (let i = 0; i < this.stores.length; i++) {
|
|
509
|
+
if (!this.stores[i].isVisible()) continue;
|
|
510
|
+
const n = e(i);
|
|
511
|
+
if (!n || !Number.isFinite(n.value)) {
|
|
479
512
|
s.push(0);
|
|
480
513
|
continue;
|
|
481
514
|
}
|
|
482
|
-
t = !0, s.push(this.snapshotValue(
|
|
515
|
+
t = !0, s.push(this.snapshotValue(i, n.time, n.value));
|
|
483
516
|
}
|
|
484
|
-
|
|
485
|
-
const i = A(s);
|
|
486
|
-
return { value: e === "percent" ? b(i) : w(i), isLive: !0 };
|
|
517
|
+
return t ? s : null;
|
|
487
518
|
}
|
|
488
519
|
getStackedValueAtTime(e, t) {
|
|
489
520
|
if (this.stores.length <= 1) {
|
|
490
|
-
const
|
|
491
|
-
return
|
|
521
|
+
const r = this.stores[0]?.findNearest(e, t);
|
|
522
|
+
return r ? this.snapshotValue(0, r.time, r.value) : null;
|
|
492
523
|
}
|
|
493
524
|
const s = this.options.stacking;
|
|
494
525
|
if (s === "off") {
|
|
495
|
-
for (let
|
|
496
|
-
if (!this.stores[
|
|
497
|
-
const
|
|
498
|
-
if (
|
|
526
|
+
for (let r = this.stores.length - 1; r >= 0; r--) {
|
|
527
|
+
if (!this.stores[r].isVisible()) continue;
|
|
528
|
+
const o = this.stores[r].findNearest(e, t);
|
|
529
|
+
if (o) return this.snapshotValue(r, o.time, o.value);
|
|
499
530
|
}
|
|
500
531
|
return null;
|
|
501
532
|
}
|
|
502
533
|
let i = !1;
|
|
503
|
-
const
|
|
504
|
-
for (let
|
|
505
|
-
if (!this.stores[
|
|
506
|
-
const
|
|
507
|
-
if (!
|
|
508
|
-
|
|
534
|
+
const n = [];
|
|
535
|
+
for (let r = 0; r < this.stores.length; r++) {
|
|
536
|
+
if (!this.stores[r].isVisible()) continue;
|
|
537
|
+
const o = this.stores[r].findNearest(e, t);
|
|
538
|
+
if (!o) {
|
|
539
|
+
n.push(0);
|
|
509
540
|
continue;
|
|
510
541
|
}
|
|
511
|
-
i = !0,
|
|
542
|
+
i = !0, n.push(this.snapshotValue(r, o.time, o.value));
|
|
512
543
|
}
|
|
513
544
|
if (!i) return null;
|
|
514
|
-
const
|
|
515
|
-
return s === "percent" ?
|
|
545
|
+
const l = A(n);
|
|
546
|
+
return s === "percent" ? w(l) : b(l);
|
|
516
547
|
}
|
|
517
548
|
getLayerLastSnapshots() {
|
|
518
549
|
if (this.stores.length <= 1) return null;
|
|
519
550
|
const e = [];
|
|
520
551
|
for (let t = 0; t < this.stores.length; t++) {
|
|
521
552
|
if (!this.stores[t].isVisible()) continue;
|
|
522
|
-
const s = this.
|
|
553
|
+
const s = this.lastFinitePoint(t);
|
|
523
554
|
if (!s) continue;
|
|
524
555
|
const i = {
|
|
525
556
|
layerIndex: t,
|
|
@@ -546,32 +577,31 @@ class F {
|
|
|
546
577
|
for (const s of this.stores) {
|
|
547
578
|
const i = s.first();
|
|
548
579
|
if (!i) continue;
|
|
549
|
-
const
|
|
550
|
-
i.time < e && (e = i.time),
|
|
580
|
+
const n = s.last() ?? i;
|
|
581
|
+
i.time < e && (e = i.time), n.time > t && (t = n.time);
|
|
551
582
|
}
|
|
552
583
|
return e === 1 / 0 ? null : { first: e, last: t };
|
|
553
584
|
}
|
|
554
585
|
/**
|
|
555
|
-
* Last data point of **layer 0 (`stores[0]`) only** — preserves the behavior
|
|
586
|
+
* Last finite data point of **layer 0 (`stores[0]`) only** — preserves the behavior
|
|
556
587
|
* of the deleted `get store()` getter. NOTE: this is intentionally NOT the
|
|
557
588
|
* same as {@link getStackedLastValue}, which for non-stacked multi-layer
|
|
558
589
|
* reports the top visible layer and for stacked reports the cumulative sum.
|
|
559
590
|
* Last-data / previous-close semantics stay pinned to layer 0 for back-compat.
|
|
560
591
|
*/
|
|
561
592
|
getLastDataPoint() {
|
|
562
|
-
return this.
|
|
593
|
+
return this.lastFinitePoint(0);
|
|
563
594
|
}
|
|
564
595
|
/** Second-to-last point of layer 0 (`stores[0]`). See {@link getLastDataPoint}. */
|
|
565
596
|
getSecondLastDataPoint() {
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
return s.slice(0, e).map((i) => i.time);
|
|
597
|
+
return this.lastFinitePoint(0, 1);
|
|
598
|
+
}
|
|
599
|
+
/** First (or with `'end'`, last) `maxCount` sample times from the first populated layer. */
|
|
600
|
+
sampleTimes(e, t = "start") {
|
|
601
|
+
for (const s of this.stores) {
|
|
602
|
+
const i = s.getAll();
|
|
603
|
+
if (i.length !== 0)
|
|
604
|
+
return F(i, { maxCount: e, from: t }).map((n) => n.time);
|
|
575
605
|
}
|
|
576
606
|
return [];
|
|
577
607
|
}
|
|
@@ -586,51 +616,51 @@ class F {
|
|
|
586
616
|
const i = this.options.stacking;
|
|
587
617
|
if (i === "percent")
|
|
588
618
|
return { min: 0, max: 100 };
|
|
589
|
-
const
|
|
619
|
+
const n = this.stores.map((a) => a.isVisible() ? a.getVisibleData(e, t) : []), l = s?.plottable;
|
|
590
620
|
if (i === "off") {
|
|
591
|
-
let a = 1 / 0,
|
|
592
|
-
for (const
|
|
593
|
-
for (const h of
|
|
594
|
-
Number.isFinite(h.value) && (
|
|
595
|
-
return a < 1 / 0 ? { min: a, max:
|
|
621
|
+
let a = 1 / 0, f = -1 / 0;
|
|
622
|
+
for (const c of n)
|
|
623
|
+
for (const h of c)
|
|
624
|
+
Number.isFinite(h.value) && (l && !l(h.value) || (h.value < a && (a = h.value), h.value > f && (f = h.value)));
|
|
625
|
+
return a < 1 / 0 ? { min: a, max: f } : null;
|
|
596
626
|
}
|
|
597
|
-
if (
|
|
598
|
-
const
|
|
599
|
-
for (let a = 0; a <
|
|
600
|
-
for (const
|
|
601
|
-
let
|
|
602
|
-
|
|
627
|
+
if (l) return T(n, l);
|
|
628
|
+
const r = /* @__PURE__ */ new Map();
|
|
629
|
+
for (let a = 0; a < n.length; a++)
|
|
630
|
+
for (const f of n[a]) {
|
|
631
|
+
let c = r.get(f.time);
|
|
632
|
+
c || (c = new Array(n.length).fill(0), r.set(f.time, c)), c[a] = Number.isFinite(f.value) ? f.value : 0;
|
|
603
633
|
}
|
|
604
|
-
let
|
|
605
|
-
for (const a of
|
|
606
|
-
let
|
|
634
|
+
let o = 0, u = 0;
|
|
635
|
+
for (const a of r.values()) {
|
|
636
|
+
let f = 0, c = 0;
|
|
607
637
|
for (const h of a)
|
|
608
|
-
h > 0 ?
|
|
609
|
-
|
|
638
|
+
h > 0 ? f += h : c += h;
|
|
639
|
+
f > u && (u = f), c < o && (o = c);
|
|
610
640
|
}
|
|
611
|
-
return u >
|
|
641
|
+
return u > o ? { min: o, max: u } : null;
|
|
612
642
|
}
|
|
613
643
|
}
|
|
614
|
-
function
|
|
644
|
+
function T(m, e) {
|
|
615
645
|
const t = /* @__PURE__ */ new Map();
|
|
616
|
-
for (let
|
|
617
|
-
for (const
|
|
618
|
-
let
|
|
619
|
-
|
|
646
|
+
for (let l = 0; l < m.length; l++)
|
|
647
|
+
for (const r of m[l]) {
|
|
648
|
+
let o = t.get(r.time);
|
|
649
|
+
o || (o = new Array(m.length).fill(0), t.set(r.time, o)), o[l] = e(r.value) ? r.value : 0;
|
|
620
650
|
}
|
|
621
651
|
const s = e(0);
|
|
622
|
-
let i = s ? 0 : 1 / 0,
|
|
623
|
-
for (const
|
|
624
|
-
let
|
|
625
|
-
for (const u of
|
|
652
|
+
let i = s ? 0 : 1 / 0, n = s ? 0 : -1 / 0;
|
|
653
|
+
for (const l of t.values()) {
|
|
654
|
+
let r = 0, o = 0;
|
|
655
|
+
for (const u of l) {
|
|
626
656
|
if (u === 0) continue;
|
|
627
|
-
u > 0 ?
|
|
628
|
-
const a = u > 0 ?
|
|
629
|
-
e(a) && (a < i && (i = a), a >
|
|
657
|
+
u > 0 ? r += u : o += u;
|
|
658
|
+
const a = u > 0 ? r : o;
|
|
659
|
+
e(a) && (a < i && (i = a), a > n && (n = a));
|
|
630
660
|
}
|
|
631
661
|
}
|
|
632
|
-
return i < 1 / 0 ? { min: i, max:
|
|
662
|
+
return i < 1 / 0 ? { min: i, max: n } : null;
|
|
633
663
|
}
|
|
634
664
|
export {
|
|
635
|
-
|
|
665
|
+
z as BaseMultiLayerSeries
|
|
636
666
|
};
|