@wick-charts/vue 0.8.1 → 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.
Files changed (38) hide show
  1. package/dist/BandSeries.vue.js +25 -24
  2. package/dist/BarSeries.vue.js +27 -26
  3. package/dist/CandlestickSeries.vue.js +25 -24
  4. package/dist/HeatmapSeries.vue.js +21 -20
  5. package/dist/LineSeries.vue.js +24 -23
  6. package/dist/PieSeries.vue.js +25 -24
  7. package/dist/composables.js +63 -36
  8. package/dist/core/dist/axis/dom-labels.js +64 -53
  9. package/dist/core/dist/chart/options.js +1 -1
  10. package/dist/core/dist/chart/y-target.js +38 -32
  11. package/dist/core/dist/chart.js +475 -439
  12. package/dist/core/dist/data/decimation.js +52 -51
  13. package/dist/core/dist/data/store.js +38 -20
  14. package/dist/core/dist/data/sync.js +80 -69
  15. package/dist/core/dist/perf/perf-hud.js +3 -3
  16. package/dist/core/dist/scales/tick-tracker.js +2 -1
  17. package/dist/core/dist/series/band.js +1 -1
  18. package/dist/core/dist/series/bar.js +240 -211
  19. package/dist/core/dist/series/base-multi-layer.js +267 -249
  20. package/dist/core/dist/series/candlestick.js +116 -116
  21. package/dist/core/dist/series/line.js +540 -455
  22. package/dist/core/dist/snapshots.js +96 -77
  23. package/dist/index.d.ts +22 -4
  24. package/dist/ui/InfoBar.vue.js +68 -68
  25. package/dist/ui/NumberFlow.vue.js +36 -27
  26. package/dist/ui/Tooltip.vue.js +127 -130
  27. package/package.json +2 -2
  28. package/src/BandSeries.vue +5 -3
  29. package/src/BarSeries.vue +5 -3
  30. package/src/CandlestickSeries.vue +5 -4
  31. package/src/ChartContainer.vue +1 -1
  32. package/src/HeatmapSeries.vue +5 -4
  33. package/src/LineSeries.vue +5 -3
  34. package/src/PieSeries.vue +6 -5
  35. package/src/composables.ts +64 -1
  36. package/src/ui/InfoBar.vue +11 -3
  37. package/src/ui/NumberFlow.vue +17 -3
  38. package/src/ui/Tooltip.vue +23 -12
@@ -1,12 +1,12 @@
1
- import { Animator as k } from "../animation/animator.js";
1
+ import { Animator as b } 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
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 {
5
+ import { resolveColor as S } from "../utils/color.js";
6
+ import { normalizeTimePointArray as d, normalizeTime as L, sliceSample as M } from "../utils/time.js";
7
+ import { sumStack as w, renderedStackPercentTop as A, renderedStackTop as k } from "./stack-math.js";
8
+ const F = (m, t, e) => m + (t - m) * e;
9
+ class I {
10
10
  stores;
11
11
  // --- Animation state (per layer) ----------------------------------------
12
12
  /**
@@ -53,10 +53,10 @@ class z {
53
53
  * (the pre-prepend first point). Stagger position is `0` at the boundary
54
54
  * and `1` at the deepest point. */
55
55
  historyRange = null;
56
- constructor(e) {
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
- { length: e },
59
- () => new k({ initial: 1, duration: 0, lerp: S })
56
+ constructor(t) {
57
+ this.stores = Array.from({ length: t }, () => new P()), this.entries = Array.from({ length: t }, () => /* @__PURE__ */ new Map()), this.displayedLastValues = new Array(t).fill(null), this.#t = new Array(t).fill(null), this.#e = new Array(t).fill(null), this.#s = Array.from({ length: t }, () => /* @__PURE__ */ new Map()), this.#i = Array.from(
58
+ { length: t },
59
+ () => new b({ initial: 1, duration: 0, lerp: F })
60
60
  );
61
61
  }
62
62
  // --- Color accessors ------------------------------------------------------
@@ -66,15 +66,15 @@ class z {
66
66
  * a theme swap, which rewrites `options.colors`, leaves these untouched.
67
67
  */
68
68
  #n = [];
69
- setColorOverrides(e) {
70
- this.#n = e;
69
+ setColorOverrides(t) {
70
+ this.#n = t;
71
71
  }
72
72
  /** The active resolver for a layer — the `data` override if set, else the theme base (cycled). */
73
- #r(e) {
74
- const t = this.#n[e];
75
- if (t !== void 0) return t;
73
+ #r(t) {
74
+ const e = this.#n[t];
75
+ if (e !== void 0) return e;
76
76
  const s = this.options.colors;
77
- return s[e % s.length];
77
+ return s[t % s.length];
78
78
  }
79
79
  /** The first layer's color resolver (string or value-fn). */
80
80
  getColor() {
@@ -84,71 +84,71 @@ class z {
84
84
  return this.options.colors;
85
85
  }
86
86
  /** Resolve one layer's color for a given datum value. */
87
- resolveLayerColor(e, t) {
88
- return M(this.#r(e), t);
87
+ resolveLayerColor(t, e) {
88
+ return S(this.#r(t), e);
89
89
  }
90
90
  // --- Data ingest ----------------------------------------------------------
91
- setData(e, t = 0) {
92
- const s = this.stores[t];
91
+ setData(t, e = 0) {
92
+ const s = this.stores[e];
93
93
  if (!s) return;
94
94
  let i = !1;
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;
95
+ for (const o of this.stores)
96
+ o.length > 0 && (i = !0);
97
+ const n = d(t ?? []);
98
+ !i && n.length > 0 && this.introWave.arm(this.options.introMs), s.setData(n);
99
+ const r = s.last();
100
+ this.displayedLastValues[e] = r ? r.value : null, this.#t[e] = null, this.#e[e] = null, this.#s[e].clear(), this.entries[e].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
104
104
  * `time` from the value on screen to its new one over `smoothMs`; a point
105
105
  * with a new `time` plays its entrance.
106
106
  */
107
- morphData(e, t = 0) {
108
- const s = this.stores[t];
107
+ morphData(t, e = 0) {
108
+ const s = this.stores[e];
109
109
  if (!s) return;
110
110
  if (!this.stores.some((h) => h.length > 0)) {
111
- this.setData(e, t);
111
+ this.setData(t, e);
112
112
  return;
113
113
  }
114
114
  const i = /* @__PURE__ */ new Map();
115
115
  for (const h of s.getAll())
116
- i.set(h.time, this.liveValue(t, h.time, h.value));
117
- const n = d(e ?? []);
116
+ i.set(h.time, this.liveValue(e, h.time, h.value));
117
+ const n = d(t ?? []);
118
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();
119
+ const r = this.options.smoothMs, o = this.isEntryEnabled() && this.options.entryMs > 0, l = this.entries[e], u = this.#s[e], a = /* @__PURE__ */ new Map();
120
120
  for (const h of n) {
121
121
  const g = i.get(h.time);
122
122
  if (g === void 0) {
123
- r && o.set(h.time, { startTime: performance.now() });
123
+ o && l.set(h.time, { startTime: performance.now() });
124
124
  continue;
125
125
  }
126
126
  const p = h.value;
127
- if (g === p || l <= 0 || !Number.isFinite(g) || !Number.isFinite(p)) continue;
127
+ if (g === p || r <= 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: l }), a.set(h.time, v);
129
+ v.target !== p && v.retarget(p, { settleMs: r }), a.set(h.time, v);
130
130
  }
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
- this.#s[t] = a;
135
- const c = s.last();
136
- this.displayedLastValues[t] = c ? c.value : null, this.#t[t] = null, this.#e[t] = null;
137
- }
138
- appendPoint(e, t = 0) {
139
- const s = this.stores[t];
131
+ const c = new Set(n.map((h) => h.time));
132
+ for (const h of l.keys())
133
+ c.has(h) || l.delete(h);
134
+ this.#s[e] = a;
135
+ const f = s.last();
136
+ this.displayedLastValues[e] = f ? f.value : null, this.#t[e] = null, this.#e[e] = null;
137
+ }
138
+ appendPoint(t, e = 0) {
139
+ const s = this.stores[e];
140
140
  if (!s) return;
141
- const i = e, n = L(i.time), l = s.last(), r = s.length;
141
+ const i = t, n = L(i.time), r = s.last(), o = s.length;
142
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;
143
+ const l = this.#t[e];
144
+ l !== null && r !== void 0 && s.length > o && (this.#e[e] = { time: r.time, anim: l }), this.displayedLastValues[e] = i.value, this.#t[e] = null;
145
145
  const u = this.options.entryMs;
146
- this.isEntryEnabled() && u > 0 && this.entries[t].set(n, { startTime: performance.now() });
146
+ this.isEntryEnabled() && u > 0 && this.entries[e].set(n, { startTime: performance.now() });
147
147
  }
148
- prependPoints(e, t = 0) {
149
- const s = this.stores[t];
150
- if (!s || e.length === 0) return;
151
- const i = d(e), n = s.first()?.time;
148
+ prependPoints(t, e = 0) {
149
+ const s = this.stores[e];
150
+ if (!s || t.length === 0) return;
151
+ const i = d(t), n = s.first()?.time;
152
152
  s.prepend(i), this.#o(i[0]?.time, n);
153
153
  }
154
154
  /**
@@ -157,71 +157,71 @@ class z {
157
157
  * another layer — only the range grows; restarting the clock would snap
158
158
  * half-revealed points back to invisible.
159
159
  */
160
- #o(e, t) {
160
+ #o(t, e) {
161
161
  const s = this.options.historyRevealMs;
162
- if (!(this.options.historyReveal === "none" || s <= 0) && !(e === void 0 || t === void 0)) {
162
+ if (!(this.options.historyReveal === "none" || s <= 0) && !(t === void 0 || e === void 0)) {
163
163
  if (this.historyWave.active && this.historyRange !== null) {
164
- this.historyRange = { from: Math.min(this.historyRange.from, e), to: this.historyRange.to };
164
+ this.historyRange = { from: Math.min(this.historyRange.from, t), to: this.historyRange.to };
165
165
  return;
166
166
  }
167
- this.historyRange = { from: e, to: t }, this.historyWave.arm(s);
167
+ this.historyRange = { from: t, to: e }, this.historyWave.arm(s);
168
168
  }
169
169
  }
170
- updateLastPoint(e, t = 0) {
171
- const s = this.stores[t];
170
+ updateLastPoint(t, e = 0) {
171
+ const s = this.stores[e];
172
172
  if (!s) return;
173
- const i = e, n = s.last()?.time;
173
+ const i = t, n = s.last()?.time;
174
174
  s.updateLast({ ...i, time: L(i.time) });
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;
175
+ const r = this.#s[e], o = n === void 0 ? void 0 : r.get(n);
176
+ n !== void 0 && o !== void 0 && (r.delete(n), this.displayedLastValues[e] = o.current, this.#t[e] = o);
177
+ const l = i.value, u = this.options.smoothMs;
178
178
  if (u <= 0) {
179
- this.displayedLastValues[t] = o, this.#t[t] = null;
179
+ this.displayedLastValues[e] = l, this.#t[e] = null;
180
180
  return;
181
181
  }
182
- let a = this.#t[t];
182
+ let a = this.#t[e];
183
183
  if (a === null) {
184
- const f = this.displayedLastValues[t] ?? o;
185
- a = new V(f), this.#t[t] = a;
184
+ const c = this.displayedLastValues[e] ?? l;
185
+ a = new V(c), this.#t[e] = a;
186
186
  }
187
- a.retarget(o, { settleMs: u });
187
+ a.retarget(l, { settleMs: u });
188
188
  }
189
- keepLast(e, t = 0) {
190
- const s = this.stores[t];
191
- if (!s || e < 0) return;
192
- const i = s.length - e;
189
+ keepLast(t, e = 0) {
190
+ const s = this.stores[e];
191
+ if (!s || t < 0) return;
192
+ const i = s.length - t;
193
193
  i <= 0 || s.trimStart(i);
194
194
  }
195
195
  // --- Layer model ----------------------------------------------------------
196
196
  getLayerCount() {
197
197
  return this.stores.length;
198
198
  }
199
- setLayerVisible(e, t) {
200
- this.stores[e]?.setVisible(t);
199
+ setLayerVisible(t, e) {
200
+ this.stores[t]?.setVisible(e);
201
201
  }
202
- isLayerVisible(e) {
203
- return this.stores[e]?.isVisible() ?? !0;
202
+ isLayerVisible(t) {
203
+ return this.stores[t]?.isVisible() ?? !0;
204
204
  }
205
205
  /** Representative concrete color per layer — value-fns are resolved at the
206
206
  * layer's last value, giving the legend swatch / color-change detection a
207
207
  * stable string. Honors per-layer `data` overrides. */
208
208
  getLayerColors() {
209
- const e = [];
210
- for (let t = 0; t < this.stores.length; t++) {
211
- const s = this.lastFinitePoint(t)?.value ?? 0;
212
- e.push(this.resolveLayerColor(t, s));
209
+ const t = [];
210
+ for (let e = 0; e < this.stores.length; e++) {
211
+ const s = this.lastFinitePoint(e)?.value ?? 0;
212
+ t.push(this.resolveLayerColor(e, s));
213
213
  }
214
- return e;
214
+ return t;
215
215
  }
216
216
  // --- Lifecycle ------------------------------------------------------------
217
- onDataChanged(e) {
218
- for (const t of this.stores) t.on("update", e);
217
+ onDataChanged(t) {
218
+ for (const e of this.stores) e.on("update", t);
219
219
  return () => {
220
- for (const t of this.stores) t.off("update", e);
220
+ for (const e of this.stores) e.off("update", t);
221
221
  };
222
222
  }
223
223
  dispose() {
224
- for (const e of this.stores) e.removeAllListeners();
224
+ for (const t of this.stores) t.removeAllListeners();
225
225
  }
226
226
  // --- Animation primitives — renderer-owned state --------------------------
227
227
  /**
@@ -231,8 +231,8 @@ class z {
231
231
  * pure function of wall time — so tooltip/last-value queries (which have
232
232
  * no context to hand) can read it too.
233
233
  */
234
- entranceProgress(e, t) {
235
- const s = this.entries[e]?.get(t);
234
+ entranceProgress(t, e) {
235
+ const s = this.entries[t]?.get(e);
236
236
  if (s === void 0) return 1;
237
237
  const i = this.options.entryMs;
238
238
  if (i <= 0) return 1;
@@ -247,9 +247,9 @@ class z {
247
247
  * (bar) fold this into their {@link entranceProgress} override; the line
248
248
  * renders its own continuous sweep instead.
249
249
  */
250
- introProgressAt(e, t) {
250
+ introProgressAt(t, e) {
251
251
  if (!this.introWave.active) return 1;
252
- const s = e.timeScale.getRange(), i = s.to - s.from, n = i > 0 ? (t - s.from) / i : 0;
252
+ const s = t.timeScale.getRange(), i = s.to - s.from, n = i > 0 ? (e - s.from) / i : 0;
253
253
  return this.introWave.progressAt(n);
254
254
  }
255
255
  /**
@@ -258,10 +258,10 @@ class z {
258
258
  * point — so the wave travels into history. `1` for points outside the
259
259
  * prepended span or when no reveal is in flight.
260
260
  */
261
- historyProgressAt(e) {
262
- const t = this.historyRange;
263
- if (!this.historyWave.active || t === null || e >= t.to) return 1;
264
- const s = t.to - t.from, i = s > 0 ? (t.to - e) / s : 0;
261
+ historyProgressAt(t) {
262
+ const e = this.historyRange;
263
+ if (!this.historyWave.active || e === null || t >= e.to) return 1;
264
+ const s = e.to - e.from, i = s > 0 ? (e.to - t) / s : 0;
265
265
  return this.historyWave.progressAt(i);
266
266
  }
267
267
  /**
@@ -275,14 +275,14 @@ class z {
275
275
  * on every append. Renderers lerp each chain link from the previous
276
276
  * link's *rendered* position instead, so geometry stays continuous.
277
277
  */
278
- unsettledTail(e) {
279
- const t = this.stores[e]?.getAll();
280
- if (!t || t.length < 2) return [];
278
+ unsettledTail(t) {
279
+ const e = this.stores[t]?.getAll();
280
+ if (!e || e.length < 2) return [];
281
281
  const s = [];
282
- for (let i = t.length - 1; i >= 1; i--) {
283
- const n = this.entranceProgress(e, t[i].time);
282
+ for (let i = e.length - 1; i >= 1; i--) {
283
+ const n = this.entranceProgress(t, e[i].time);
284
284
  if (n >= 1) break;
285
- s.unshift({ time: t[i].time, progress: n });
285
+ s.unshift({ time: e[i].time, progress: n });
286
286
  }
287
287
  return s;
288
288
  }
@@ -294,8 +294,8 @@ class z {
294
294
  * Falls back to `rawValue` when the store is empty or no smoothing has
295
295
  * happened yet.
296
296
  */
297
- effectiveValue(e, t, s, i) {
298
- return this.liveValue(t, s, i);
297
+ effectiveValue(t, e, s, i) {
298
+ return this.liveValue(e, s, i);
299
299
  }
300
300
  /**
301
301
  * The ctx-independent core of {@link effectiveValue} — used directly by the
@@ -304,14 +304,14 @@ class z {
304
304
  * transform). Those queries only need the live smoothing/chase this base
305
305
  * method already provides, never the intro's positional transform.
306
306
  */
307
- liveValue(e, t, s) {
308
- const i = this.#s[e]?.get(t);
307
+ liveValue(t, e, s) {
308
+ const i = this.#s[t]?.get(e);
309
309
  if (i !== void 0) return i.current;
310
- const n = this.stores[e]?.last()?.time;
311
- if (n !== void 0 && t === n)
312
- return this.displayedLastValues[e] ?? s;
313
- const l = this.#e[e];
314
- return l !== null && l.time === t ? l.anim.current : s;
310
+ const n = this.stores[t]?.last()?.time;
311
+ if (n !== void 0 && e === n)
312
+ return this.displayedLastValues[t] ?? s;
313
+ const r = this.#e[t];
314
+ return r !== null && r.time === e ? r.anim.current : s;
315
315
  }
316
316
  /**
317
317
  * Value a last-value/tooltip query should report for `time` — defaults to
@@ -320,8 +320,8 @@ class z {
320
320
  * override) without that lerp feeding back into `effectiveValue`, which
321
321
  * the renderer's own per-point draws use as an unlerp'd target.
322
322
  */
323
- snapshotValue(e, t, s) {
324
- return this.liveValue(e, t, s);
323
+ snapshotValue(t, e, s) {
324
+ return this.liveValue(t, e, s);
325
325
  }
326
326
  // --- Animation lifecycle --------------------------------------------------
327
327
  /**
@@ -330,44 +330,44 @@ class z {
330
330
  * subclass passes its own clock so test harnesses (which stub
331
331
  * `performance.now`) can drive progression deterministically.
332
332
  */
333
- tickAnimations(e) {
334
- this.introWave.tick(e), this.historyWave.tick(e);
335
- for (const t of this.#i) t.tick(e);
336
- for (let t = 0; t < this.stores.length; t++) {
337
- const s = this.#t[t];
333
+ tickAnimations(t) {
334
+ this.introWave.tick(t), this.historyWave.tick(t);
335
+ for (const e of this.#i) e.tick(t);
336
+ for (let e = 0; e < this.stores.length; e++) {
337
+ const s = this.#t[e];
338
338
  if (s !== null) {
339
- const o = s.tick(e);
340
- this.displayedLastValues[t] = s.current, o || (this.#t[t] = null);
339
+ const l = s.tick(t);
340
+ this.displayedLastValues[e] = s.current, l || (this.#t[e] = null);
341
341
  }
342
- const i = this.#e[t];
343
- i !== null && !i.anim.tick(e) && (this.#e[t] = null);
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
- this.entries[t].clear();
342
+ const i = this.#e[e];
343
+ i !== null && !i.anim.tick(t) && (this.#e[e] = null);
344
+ const n = this.#s[e];
345
+ for (const [l, u] of n)
346
+ u.tick(t) || n.delete(l);
347
+ const r = this.options.entryMs;
348
+ if (r <= 0) {
349
+ this.entries[e].clear();
350
350
  continue;
351
351
  }
352
- const r = this.entries[t];
353
- for (const [o, u] of r)
354
- e - u.startTime >= l && r.delete(o);
352
+ const o = this.entries[e];
353
+ for (const [l, u] of o)
354
+ t - u.startTime >= r && o.delete(l);
355
355
  }
356
356
  }
357
357
  /** True while any layer has an active chase, unsettled entry, alpha fade,
358
358
  * or the initial-load reveal is still sweeping. */
359
359
  get needsAnimation() {
360
360
  if (this.introWave.active || this.historyWave.active) return !0;
361
- for (const e of this.#i)
362
- if (e.animating) return !0;
363
- for (const e of this.#t)
364
- if (e !== null) return !0;
365
- for (const e of this.#e)
366
- if (e !== null) return !0;
367
- for (const e of this.#s)
368
- if (e.size > 0) return !0;
369
- for (const e of this.entries)
370
- if (e.size > 0) return !0;
361
+ for (const t of this.#i)
362
+ if (t.animating) return !0;
363
+ for (const t of this.#t)
364
+ if (t !== null) return !0;
365
+ for (const t of this.#e)
366
+ if (t !== null) return !0;
367
+ for (const t of this.#s)
368
+ if (t.size > 0) return !0;
369
+ for (const t of this.entries)
370
+ if (t.size > 0) return !0;
371
371
  return !1;
372
372
  }
373
373
  /** Reveal-front position of the initial-load intro; `1` once settled. */
@@ -382,16 +382,16 @@ class z {
382
382
  */
383
383
  cancelEntranceAnimations() {
384
384
  this.introWave.finish();
385
- for (const e of this.entries) e.clear();
385
+ for (const t of this.entries) t.clear();
386
386
  }
387
387
  /**
388
388
  * Start a series-wide fade toward `target` over `durationMs`. Fans out
389
389
  * across every per-layer animator so a `setSeriesVisible` toggle is just
390
390
  * "set every layer to the same target". `durationMs <= 0` snaps.
391
391
  */
392
- setAlpha(e, t) {
392
+ setAlpha(t, e) {
393
393
  for (const s of this.#i)
394
- s.setTarget(e, { duration: t });
394
+ s.setTarget(t, { duration: e });
395
395
  }
396
396
  /**
397
397
  * `1` while any layer has alpha > 0 OR is animating, `0` when every layer
@@ -407,8 +407,8 @@ class z {
407
407
  * would deadlock at `0`.
408
408
  */
409
409
  getAlpha() {
410
- for (const e of this.#i)
411
- if (e.current > 0 || e.animating) return 1;
410
+ for (const t of this.#i)
411
+ if (t.current > 0 || t.animating) return 1;
412
412
  return 0;
413
413
  }
414
414
  /**
@@ -416,21 +416,21 @@ class z {
416
416
  * Subclass draw loops multiply this into `globalAlpha` per layer so the
417
417
  * fade lives next to the geometry it affects.
418
418
  */
419
- setLayerAlpha(e, t, s) {
420
- this.#i[e]?.setTarget(t, { duration: s });
419
+ setLayerAlpha(t, e, s) {
420
+ this.#i[t]?.setTarget(e, { duration: s });
421
421
  }
422
422
  /** Latest rendered per-layer alpha. Defaults to 1 for out-of-range indices. */
423
- getLayerAlpha(e) {
424
- return this.#i[e]?.current ?? 1;
423
+ getLayerAlpha(t) {
424
+ return this.#i[t]?.current ?? 1;
425
425
  }
426
426
  // --- Data queries ---------------------------------------------------------
427
427
  /**
428
428
  * The layer's newest point with a finite value, after skipping `skip` such
429
429
  * points — a trailing `null` / `NaN` is a gap, not the latest reading.
430
430
  */
431
- lastFinitePoint(e, t = 0) {
432
- const s = this.stores[e]?.getAll() ?? [];
433
- let i = t;
431
+ lastFinitePoint(t, e = 0) {
432
+ const s = this.stores[t]?.getAll() ?? [];
433
+ let i = e;
434
434
  for (let n = s.length - 1; n >= 0; n--)
435
435
  if (Number.isFinite(s[n].value)) {
436
436
  if (i === 0) return s[n];
@@ -439,44 +439,45 @@ class z {
439
439
  return null;
440
440
  }
441
441
  getLastValue() {
442
- for (let e = this.stores.length - 1; e >= 0; e--) {
443
- const t = this.lastFinitePoint(e);
444
- if (t) return t.value;
442
+ for (let t = this.stores.length - 1; t >= 0; t--) {
443
+ const e = this.lastFinitePoint(t);
444
+ if (e) return e.value;
445
445
  }
446
446
  return null;
447
447
  }
448
- getDataAtTime(e, t) {
449
- return this.stores[0]?.findNearest(e, t) ?? null;
448
+ getDataAtTime(t, e) {
449
+ return this.stores[0]?.findNearest(t, e) ?? null;
450
450
  }
451
- getLayerSnapshots(e, t) {
451
+ getLayerSnapshots(t, e) {
452
452
  if (this.stores.length <= 1) return null;
453
453
  const s = [];
454
- for (let i = 0; i < this.stores.length; i++) {
455
- if (!this.stores[i].isVisible()) continue;
456
- const n = this.stores[i].findNearest(e, t);
457
- if (n === null) continue;
458
- const l = {
459
- layerIndex: i,
460
- time: n.time,
454
+ for (let n = 0; n < this.stores.length; n++) {
455
+ if (!this.stores[n].isVisible()) continue;
456
+ const r = this.stores[n].findNearest(t, e);
457
+ if (r === null) continue;
458
+ const o = {
459
+ layerIndex: n,
460
+ time: r.time,
461
461
  // Routes through the same live/pinned-chase smoothing the renderer
462
462
  // paints, so hovering the live edge mid-animation doesn't jump ahead
463
463
  // to the raw target before the on-screen marker gets there.
464
- value: this.snapshotValue(i, n.time, n.value),
464
+ value: this.snapshotValue(n, r.time, r.value),
465
465
  // Resolve the layer's color at the hovered datum's value so a value-fn
466
466
  // colors the tooltip dot to match the bar / segment under the cursor.
467
- color: this.resolveLayerColor(i, n.value)
467
+ color: this.resolveLayerColor(n, r.value)
468
468
  };
469
- n.x !== void 0 && (l.x = n.x), s.push(l);
469
+ r.x !== void 0 && (o.x = r.x), s.push(o);
470
470
  }
471
- return s.length > 0 ? s : null;
471
+ const i = this.withShares({ rows: s, keepGaps: !1 });
472
+ return i.length > 0 ? i : null;
472
473
  }
473
474
  getStackedLastValue() {
474
475
  if (this.stores.length <= 1) {
475
476
  const i = this.lastFinitePoint(0);
476
477
  return i ? { value: this.snapshotValue(0, i.time, i.value), isLive: !0 } : null;
477
478
  }
478
- const e = this.options.stacking;
479
- if (e === "off") {
479
+ const t = this.options.stacking;
480
+ if (t === "off") {
480
481
  for (let i = this.stores.length - 1; i >= 0; i--) {
481
482
  if (!this.stores[i].isVisible()) continue;
482
483
  const n = this.lastFinitePoint(i);
@@ -484,88 +485,105 @@ class z {
484
485
  }
485
486
  return null;
486
487
  }
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 };
488
+ const e = this.stackHeadValues((i) => this.stores[i].last() ?? null) ?? this.lastDrawnRowValues();
489
+ if (!e) return null;
490
+ const s = w(e);
491
+ return { value: t === "percent" ? A(s) : k(s), isLive: !0 };
491
492
  }
492
493
  /** Stack contributions at the newest time any visible layer has a finite point. */
493
494
  lastDrawnRowValues() {
494
- let e = null;
495
+ let t = null;
495
496
  for (let s = 0; s < this.stores.length; s++) {
496
497
  if (!this.stores[s].isVisible()) continue;
497
498
  const i = this.lastFinitePoint(s);
498
- i !== null && (e === null || i.time > e) && (e = i.time);
499
+ i !== null && (t === null || i.time > t) && (t = i.time);
499
500
  }
500
- if (e === null) return null;
501
- const t = e;
502
- return this.stackHeadValues((s) => this.stores[s].findNearest(t, 0));
501
+ if (t === null) return null;
502
+ const e = t;
503
+ return this.stackHeadValues((s) => this.stores[s].findNearest(e, 0));
503
504
  }
504
505
  /** Each visible layer's stack contribution at `pick(layer)`, or `null` when none is finite. */
505
- stackHeadValues(e) {
506
- let t = !1;
506
+ stackHeadValues(t) {
507
+ let e = !1;
507
508
  const s = [];
508
509
  for (let i = 0; i < this.stores.length; i++) {
509
510
  if (!this.stores[i].isVisible()) continue;
510
- const n = e(i);
511
+ const n = t(i);
511
512
  if (!n || !Number.isFinite(n.value)) {
512
513
  s.push(0);
513
514
  continue;
514
515
  }
515
- t = !0, s.push(this.snapshotValue(i, n.time, n.value));
516
+ e = !0, s.push(this.snapshotValue(i, n.time, n.value));
516
517
  }
517
- return t ? s : null;
518
+ return e ? s : null;
518
519
  }
519
- getStackedValueAtTime(e, t) {
520
+ getStackedValueAtTime(t, e) {
520
521
  if (this.stores.length <= 1) {
521
- const r = this.stores[0]?.findNearest(e, t);
522
- return r ? this.snapshotValue(0, r.time, r.value) : null;
522
+ const o = this.stores[0]?.findNearest(t, e);
523
+ return o ? this.snapshotValue(0, o.time, o.value) : null;
523
524
  }
524
525
  const s = this.options.stacking;
525
526
  if (s === "off") {
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);
527
+ for (let o = this.stores.length - 1; o >= 0; o--) {
528
+ if (!this.stores[o].isVisible()) continue;
529
+ const l = this.stores[o].findNearest(t, e);
530
+ if (l) return this.snapshotValue(o, l.time, l.value);
530
531
  }
531
532
  return null;
532
533
  }
533
534
  let i = !1;
534
535
  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) {
536
+ for (let o = 0; o < this.stores.length; o++) {
537
+ if (!this.stores[o].isVisible()) continue;
538
+ const l = this.stores[o].findNearest(t, e);
539
+ if (!l) {
539
540
  n.push(0);
540
541
  continue;
541
542
  }
542
- i = !0, n.push(this.snapshotValue(r, o.time, o.value));
543
+ i = !0, n.push(this.snapshotValue(o, l.time, l.value));
543
544
  }
544
545
  if (!i) return null;
545
- const l = A(n);
546
- return s === "percent" ? w(l) : b(l);
546
+ const r = w(n);
547
+ return s === "percent" ? A(r) : k(r);
547
548
  }
548
549
  getLayerLastSnapshots() {
549
550
  if (this.stores.length <= 1) return null;
550
- const e = [];
551
- for (let t = 0; t < this.stores.length; t++) {
552
- if (!this.stores[t].isVisible()) continue;
553
- const s = this.lastFinitePoint(t);
554
- if (!s) continue;
555
- const i = {
556
- layerIndex: t,
557
- time: s.time,
558
- value: this.snapshotValue(t, s.time, s.value),
559
- color: this.resolveLayerColor(t, s.value)
551
+ const t = [];
552
+ for (let s = 0; s < this.stores.length; s++) {
553
+ if (!this.stores[s].isVisible()) continue;
554
+ const i = this.lastFinitePoint(s);
555
+ if (!i) continue;
556
+ const n = {
557
+ layerIndex: s,
558
+ time: i.time,
559
+ value: this.snapshotValue(s, i.time, i.value),
560
+ color: this.resolveLayerColor(s, i.value)
560
561
  };
561
- s.x !== void 0 && (i.x = s.x), e.push(i);
562
+ i.x !== void 0 && (n.x = i.x), t.push(n);
562
563
  }
564
+ const e = this.withShares({ rows: t, keepGaps: !0 });
563
565
  return e.length > 0 ? e : null;
564
566
  }
567
+ /**
568
+ * On a percent stack, give each row its share of the column at the row's own
569
+ * time — ragged layers end at different columns. A row whose column is a gap
570
+ * is dropped, or kept without a share when `keepGaps`.
571
+ */
572
+ withShares(t) {
573
+ if (this.options.stacking !== "percent") return t.rows;
574
+ const e = /* @__PURE__ */ new Map(), s = [];
575
+ for (const i of t.rows) {
576
+ let n = e.get(i.time);
577
+ n === void 0 && (n = this.percentShares(i.time), e.set(i.time, n));
578
+ const r = n?.get(i.layerIndex);
579
+ r !== void 0 && (i.share = r), (r !== void 0 || t.keepGaps) && s.push(i);
580
+ }
581
+ return s;
582
+ }
565
583
  getTotalLength() {
566
- let e = 0;
567
- for (const t of this.stores) e += t.length;
568
- return e;
584
+ let t = 0;
585
+ for (const e of this.stores) t += e.length;
586
+ return t;
569
587
  }
570
588
  // --- TimeSeriesRenderer data queries --------------------------------------
571
589
  /** Earliest first-sample / latest last-sample across ALL layers, skipping
@@ -573,14 +591,14 @@ class z {
573
591
  * the multi-layer time-range leak: a populated layer 1 with an empty layer 0
574
592
  * still reports the real bounds. */
575
593
  getTimeBounds() {
576
- let e = 1 / 0, t = -1 / 0;
594
+ let t = 1 / 0, e = -1 / 0;
577
595
  for (const s of this.stores) {
578
596
  const i = s.first();
579
597
  if (!i) continue;
580
598
  const n = s.last() ?? i;
581
- i.time < e && (e = i.time), n.time > t && (t = n.time);
599
+ i.time < t && (t = i.time), n.time > e && (e = n.time);
582
600
  }
583
- return e === 1 / 0 ? null : { first: e, last: t };
601
+ return t === 1 / 0 ? null : { first: t, last: e };
584
602
  }
585
603
  /**
586
604
  * Last finite data point of **layer 0 (`stores[0]`) only** — preserves the behavior
@@ -597,70 +615,70 @@ class z {
597
615
  return this.lastFinitePoint(0, 1);
598
616
  }
599
617
  /** First (or with `'end'`, last) `maxCount` sample times from the first populated layer. */
600
- sampleTimes(e, t = "start") {
618
+ sampleTimes(t, e = "start") {
601
619
  for (const s of this.stores) {
602
620
  const i = s.getAll();
603
621
  if (i.length !== 0)
604
- return F(i, { maxCount: e, from: t }).map((n) => n.time);
622
+ return M(i, { maxCount: t, from: e }).map((n) => n.time);
605
623
  }
606
624
  return [];
607
625
  }
608
626
  /** Visible points of layer 0 (`stores[0]`). See {@link getLastDataPoint}. */
609
- getVisibleDataPoints(e, t) {
610
- return this.stores[0]?.getVisibleData(e, t) ?? [];
627
+ getVisibleDataPoints(t, e) {
628
+ return this.stores[0]?.getVisibleData(t, e) ?? [];
611
629
  }
612
630
  get stacking() {
613
631
  return this.options.stacking;
614
632
  }
615
- getValueRange(e, t, s) {
633
+ getValueRange(t, e, s) {
616
634
  const i = this.options.stacking;
617
635
  if (i === "percent")
618
636
  return { min: 0, max: 100 };
619
- const n = this.stores.map((a) => a.isVisible() ? a.getVisibleData(e, t) : []), l = s?.plottable;
637
+ const n = this.stores.map((a) => a.isVisible() ? a.getVisibleData(t, e) : []), r = s?.plottable;
620
638
  if (i === "off") {
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;
639
+ let a = 1 / 0, c = -1 / 0;
640
+ for (const f of n)
641
+ for (const h of f)
642
+ Number.isFinite(h.value) && (r && !r(h.value) || (h.value < a && (a = h.value), h.value > c && (c = h.value)));
643
+ return a < 1 / 0 ? { min: a, max: c } : null;
626
644
  }
627
- if (l) return T(n, l);
628
- const r = /* @__PURE__ */ new Map();
645
+ if (r) return T(n, r);
646
+ const o = /* @__PURE__ */ new Map();
629
647
  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;
648
+ for (const c of n[a]) {
649
+ let f = o.get(c.time);
650
+ f || (f = new Array(n.length).fill(0), o.set(c.time, f)), f[a] = Number.isFinite(c.value) ? c.value : 0;
633
651
  }
634
- let o = 0, u = 0;
635
- for (const a of r.values()) {
636
- let f = 0, c = 0;
652
+ let l = 0, u = 0;
653
+ for (const a of o.values()) {
654
+ let c = 0, f = 0;
637
655
  for (const h of a)
638
- h > 0 ? f += h : c += h;
639
- f > u && (u = f), c < o && (o = c);
656
+ h > 0 ? c += h : f += h;
657
+ c > u && (u = c), f < l && (l = f);
640
658
  }
641
- return u > o ? { min: o, max: u } : null;
659
+ return u > l ? { min: l, max: u } : null;
642
660
  }
643
661
  }
644
- function T(m, e) {
645
- const t = /* @__PURE__ */ new Map();
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;
662
+ function T(m, t) {
663
+ const e = /* @__PURE__ */ new Map();
664
+ for (let r = 0; r < m.length; r++)
665
+ for (const o of m[r]) {
666
+ let l = e.get(o.time);
667
+ l || (l = new Array(m.length).fill(0), e.set(o.time, l)), l[r] = t(o.value) ? o.value : 0;
650
668
  }
651
- const s = e(0);
669
+ const s = t(0);
652
670
  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) {
671
+ for (const r of e.values()) {
672
+ let o = 0, l = 0;
673
+ for (const u of r) {
656
674
  if (u === 0) continue;
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));
675
+ u > 0 ? o += u : l += u;
676
+ const a = u > 0 ? o : l;
677
+ t(a) && (a < i && (i = a), a > n && (n = a));
660
678
  }
661
679
  }
662
680
  return i < 1 / 0 ? { min: i, max: n } : null;
663
681
  }
664
682
  export {
665
- z as BaseMultiLayerSeries
683
+ I as BaseMultiLayerSeries
666
684
  };