@wick-charts/vue 0.6.4 → 0.8.0

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