@wick-charts/vue 0.4.2 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (144) hide show
  1. package/README.md +5 -3
  2. package/dist/BarSeries.vue.js +44 -0
  3. package/dist/BarSeries.vue2.js +4 -0
  4. package/dist/CandlestickSeries.vue.js +45 -0
  5. package/dist/CandlestickSeries.vue2.js +4 -0
  6. package/dist/ChartContainer.vue.js +168 -0
  7. package/dist/ChartContainer.vue2.js +4 -0
  8. package/dist/LineSeries.vue.js +44 -0
  9. package/dist/LineSeries.vue2.js +4 -0
  10. package/dist/PieSeries.vue.js +34 -0
  11. package/dist/PieSeries.vue2.js +4 -0
  12. package/dist/composables.js +44 -0
  13. package/dist/context.js +25 -0
  14. package/dist/core/dist/animation/animator.js +72 -0
  15. package/dist/core/dist/animation/config.js +145 -0
  16. package/dist/core/dist/animation/easing.js +4 -0
  17. package/dist/core/dist/animation/scalar-spring.js +57 -0
  18. package/dist/core/dist/animation/spring.js +11 -0
  19. package/dist/core/dist/animation/time.js +19 -0
  20. package/dist/core/dist/animation/viewport-engine.js +174 -0
  21. package/dist/core/dist/animation/visible-range-spring.js +64 -0
  22. package/dist/core/dist/animation/y-range-hermite.js +72 -0
  23. package/dist/core/dist/animation/y-range-snap.js +31 -0
  24. package/dist/core/dist/animation/y-range-spring.js +59 -0
  25. package/dist/core/dist/axis/dom-labels.js +60 -0
  26. package/dist/core/dist/canvas-manager.js +109 -0
  27. package/dist/core/dist/chart/edge-indicators.js +26 -0
  28. package/dist/core/dist/chart/fit-to-data.js +9 -0
  29. package/dist/core/dist/chart/last-value.js +31 -0
  30. package/dist/core/dist/chart/options.js +35 -0
  31. package/dist/core/dist/chart/pan-zoom-math.js +66 -0
  32. package/dist/core/dist/chart/streaming-cadence.js +70 -0
  33. package/dist/core/dist/chart/streaming-target.js +22 -0
  34. package/dist/core/dist/chart/viewport-padding.js +6 -0
  35. package/dist/core/dist/chart/y-target.js +24 -0
  36. package/dist/core/dist/chart.js +1550 -0
  37. package/dist/core/dist/components/crosshair.js +9 -0
  38. package/dist/core/dist/components/edge-indicator.js +36 -0
  39. package/dist/core/dist/components/grid.js +22 -0
  40. package/dist/core/dist/components/marker.js +41 -0
  41. package/dist/core/dist/components/reference-line.js +48 -0
  42. package/dist/core/dist/components/time-region.js +35 -0
  43. package/dist/core/dist/data/decimation.js +54 -0
  44. package/dist/core/dist/data/store.js +76 -0
  45. package/dist/core/dist/data/sync.js +47 -0
  46. package/dist/core/dist/events.js +19 -0
  47. package/dist/core/dist/interactions/handler.js +84 -0
  48. package/dist/core/dist/interactions/pan.js +26 -0
  49. package/dist/core/dist/interactions/zoom.js +21 -0
  50. package/dist/core/dist/navigator/controller.js +374 -0
  51. package/dist/core/dist/navigator/decimate.js +44 -0
  52. package/dist/core/dist/navigator/interactions.js +28 -0
  53. package/dist/core/dist/navigator/render.js +68 -0
  54. package/dist/core/dist/perf/counting-context.js +19 -0
  55. package/dist/core/dist/perf/perf-hud.js +453 -0
  56. package/dist/core/dist/perf/perf-monitor.js +132 -0
  57. package/dist/core/dist/render-scheduler.js +31 -0
  58. package/dist/core/dist/scales/tick-tracker.js +110 -0
  59. package/dist/core/dist/scales/x-scale.js +145 -0
  60. package/dist/core/dist/scales/y-scale.js +156 -0
  61. package/dist/core/dist/series/bar.js +341 -0
  62. package/dist/core/dist/series/base-multi-layer.js +438 -0
  63. package/dist/core/dist/series/candlestick.js +481 -0
  64. package/dist/core/dist/series/definition.js +11 -0
  65. package/dist/core/dist/series/line.js +446 -0
  66. package/dist/core/dist/series/painters/builtins.js +36 -0
  67. package/dist/core/dist/series/painters/canvas-path.js +79 -0
  68. package/dist/core/dist/series/painters/resolve.js +32 -0
  69. package/dist/core/dist/series/pie.js +545 -0
  70. package/dist/core/dist/series/register-builtins.js +11 -0
  71. package/dist/core/dist/series/stack-math.js +17 -0
  72. package/dist/core/dist/snapshots.js +107 -0
  73. package/dist/core/dist/theme/create.js +176 -0
  74. package/dist/core/dist/theme/resolve.js +14 -0
  75. package/dist/core/dist/theme/themes/andromeda.js +33 -0
  76. package/dist/core/dist/theme/themes/ayu-mirage.js +33 -0
  77. package/dist/core/dist/theme/themes/catppuccin.js +33 -0
  78. package/dist/core/dist/theme/themes/dracula.js +35 -0
  79. package/dist/core/dist/theme/themes/github-light.js +34 -0
  80. package/dist/core/dist/theme/themes/gruvbox.js +33 -0
  81. package/dist/core/dist/theme/themes/handwritten.js +101 -0
  82. package/dist/core/dist/theme/themes/high-contrast.js +33 -0
  83. package/dist/core/dist/theme/themes/lavender-mist.js +33 -0
  84. package/dist/core/dist/theme/themes/light-pink.js +34 -0
  85. package/dist/core/dist/theme/themes/material-palenight.js +33 -0
  86. package/dist/core/dist/theme/themes/minimal-light.js +34 -0
  87. package/dist/core/dist/theme/themes/mint-breeze.js +33 -0
  88. package/dist/core/dist/theme/themes/monokai-pro.js +33 -0
  89. package/dist/core/dist/theme/themes/night-owl.js +35 -0
  90. package/dist/core/dist/theme/themes/one-dark-pro.js +33 -0
  91. package/dist/core/dist/theme/themes/panda.js +33 -0
  92. package/dist/core/dist/theme/themes/peach-cream.js +33 -0
  93. package/dist/core/dist/theme/themes/quiet-light.js +37 -0
  94. package/dist/core/dist/theme/themes/rose-pine-dawn.js +33 -0
  95. package/dist/core/dist/theme/themes/sand-dune.js +33 -0
  96. package/dist/core/dist/theme/themes/solarized-light.js +34 -0
  97. package/dist/core/dist/tooltip-position.js +10 -0
  98. package/dist/core/dist/utils/color.js +37 -0
  99. package/dist/core/dist/utils/format.js +29 -0
  100. package/dist/core/dist/utils/math.js +26 -0
  101. package/dist/core/dist/utils/poisoned-data-reporter.js +15 -0
  102. package/dist/core/dist/utils/time.js +41 -0
  103. package/dist/index.d.ts +834 -63
  104. package/dist/index.js +142 -8025
  105. package/dist/ui/Crosshair.vue.js +53 -0
  106. package/dist/ui/Crosshair.vue2.js +4 -0
  107. package/dist/ui/InfoBar.vue.js +143 -0
  108. package/dist/ui/InfoBar.vue2.js +4 -0
  109. package/dist/ui/Legend.vue.js +212 -0
  110. package/dist/ui/Legend.vue2.js +4 -0
  111. package/dist/ui/Marker.vue.js +47 -0
  112. package/dist/ui/Marker.vue2.js +4 -0
  113. package/dist/ui/Navigator.vue.js +58 -0
  114. package/dist/ui/Navigator.vue2.js +4 -0
  115. package/dist/ui/NumberFlow.vue.js +69 -0
  116. package/dist/ui/NumberFlow.vue2.js +4 -0
  117. package/dist/ui/PieLegend.vue.js +132 -0
  118. package/dist/ui/PieLegend.vue2.js +4 -0
  119. package/dist/ui/PieTooltip.vue.js +135 -0
  120. package/dist/ui/PieTooltip.vue2.js +4 -0
  121. package/dist/ui/ReferenceLine.vue.js +44 -0
  122. package/dist/ui/ReferenceLine.vue2.js +4 -0
  123. package/dist/ui/TimeAxis.vue.js +43 -0
  124. package/dist/ui/TimeAxis.vue2.js +4 -0
  125. package/dist/ui/TimeRegion.vue.js +41 -0
  126. package/dist/ui/TimeRegion.vue2.js +4 -0
  127. package/dist/ui/Title.vue.js +54 -0
  128. package/dist/ui/Title.vue2.js +4 -0
  129. package/dist/ui/Tooltip.vue.js +195 -0
  130. package/dist/ui/Tooltip.vue2.js +4 -0
  131. package/dist/ui/YAxis.vue.js +42 -0
  132. package/dist/ui/YAxis.vue2.js +4 -0
  133. package/dist/ui/YLabel.vue.js +105 -0
  134. package/dist/ui/YLabel.vue2.js +4 -0
  135. package/package.json +2 -2
  136. package/src/BarSeries.vue +12 -13
  137. package/src/CandlestickSeries.vue +17 -6
  138. package/src/LineSeries.vue +12 -13
  139. package/src/PieSeries.vue +2 -1
  140. package/src/index.ts +23 -0
  141. package/src/ui/Legend.vue +1 -2
  142. package/src/ui/Marker.vue +62 -0
  143. package/src/ui/ReferenceLine.vue +58 -0
  144. package/src/ui/TimeRegion.vue +54 -0
@@ -0,0 +1,438 @@
1
+ import { Animator as m } from "../animation/animator.js";
2
+ import { ScalarSpring as g } from "../animation/scalar-spring.js";
3
+ import { TimeSeriesStore as p } from "../data/store.js";
4
+ import { resolveColor as d } from "../utils/color.js";
5
+ import { normalizeTimePointArray as v, normalizeTime as c } from "../utils/time.js";
6
+ import { sumStack as y, renderedStackPercentTop as L, renderedStackTop as V } from "./stack-math.js";
7
+ const A = (f, t, e) => f + (t - f) * e;
8
+ class D {
9
+ stores;
10
+ // --- Animation state (per layer) ----------------------------------------
11
+ /**
12
+ * Per-point entrance animation registry. Subclasses read it through
13
+ * {@link entranceProgress}; tests reach in directly via type-cast (kept
14
+ * `protected` rather than `#` so the existing test helper keeps working).
15
+ */
16
+ entries;
17
+ /**
18
+ * Latest rendered Y for each layer's last point, chased smoothly by
19
+ * `updateLastPoint`. `null` while the store is empty.
20
+ */
21
+ displayedLastValues;
22
+ /** Per-layer chase spring. `null` when settled or when smoothing is off. */
23
+ #t;
24
+ /**
25
+ * Chase displaced from the last slot by an append, still settling toward the
26
+ * (now-penultimate) point's stored value. Pinned to that point's `time` so
27
+ * {@link effectiveValue} keeps substituting the smoothed Y until it lands —
28
+ * killing the spring on append would snap the vertex to its raw value the
29
+ * very frame a new point arrives (a visible 1–2-frame kink at the line head).
30
+ */
31
+ #e;
32
+ /**
33
+ * Per-layer alpha for the visibility cross-fade. `setAlpha` (whole series)
34
+ * fans out across the array; `setLayerAlpha` targets a single index. Render
35
+ * loops multiply the layer's alpha into `globalAlpha` per draw.
36
+ */
37
+ #s;
38
+ constructor(t) {
39
+ 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(
40
+ { length: t },
41
+ () => new m({ initial: 1, duration: 0, lerp: A })
42
+ );
43
+ }
44
+ // --- Color accessors ------------------------------------------------------
45
+ /**
46
+ * Per-layer color overrides carried in `data` (sparse — `undefined` leaves a
47
+ * layer on the theme base in `options.colors`). Kept separate from the base so
48
+ * a theme swap, which rewrites `options.colors`, leaves these untouched.
49
+ */
50
+ #r = [];
51
+ setColorOverrides(t) {
52
+ this.#r = t;
53
+ }
54
+ /** The active resolver for a layer — the `data` override if set, else the theme base (cycled). */
55
+ #i(t) {
56
+ const e = this.#r[t];
57
+ if (e !== void 0) return e;
58
+ const s = this.options.colors;
59
+ return s[t % s.length];
60
+ }
61
+ /** The first layer's color resolver (string or value-fn). */
62
+ getColor() {
63
+ return this.#i(0);
64
+ }
65
+ getColors() {
66
+ return this.options.colors;
67
+ }
68
+ /** Resolve one layer's color for a given datum value. */
69
+ resolveLayerColor(t, e) {
70
+ return d(this.#i(t), e);
71
+ }
72
+ // --- Data ingest ----------------------------------------------------------
73
+ setData(t, e = 0) {
74
+ const s = this.stores[e];
75
+ if (!s) return;
76
+ const i = v(t ?? []);
77
+ s.setData(i);
78
+ const r = s.last();
79
+ this.displayedLastValues[e] = r ? r.value : null, this.#t[e] = null, this.#e[e] = null, this.entries[e].clear();
80
+ }
81
+ appendPoint(t, e = 0) {
82
+ const s = this.stores[e];
83
+ if (!s) return;
84
+ const i = t, r = c(i.time), n = s.last(), l = s.length;
85
+ s.append({ ...i, time: r });
86
+ const o = this.#t[e];
87
+ o !== null && n !== void 0 && s.length > l && (this.#e[e] = { time: n.time, anim: o }), this.displayedLastValues[e] = i.value, this.#t[e] = null;
88
+ const a = this.options.entryMs;
89
+ this.isEntryEnabled() && a > 0 && this.entries[e].set(r, { startTime: performance.now() });
90
+ }
91
+ updateLastPoint(t, e = 0) {
92
+ const s = this.stores[e];
93
+ if (!s) return;
94
+ const i = t;
95
+ s.updateLast({ ...i, time: c(i.time) });
96
+ const r = i.value, n = this.options.smoothMs;
97
+ if (n <= 0) {
98
+ this.displayedLastValues[e] = r, this.#t[e] = null;
99
+ return;
100
+ }
101
+ let l = this.#t[e];
102
+ if (l === null) {
103
+ const o = this.displayedLastValues[e] ?? r;
104
+ l = new g(o), this.#t[e] = l;
105
+ }
106
+ l.retarget(r, { settleMs: n });
107
+ }
108
+ keepLast(t, e = 0) {
109
+ const s = this.stores[e];
110
+ if (!s || t < 0) return;
111
+ const i = s.length - t;
112
+ i <= 0 || s.trimStart(i);
113
+ }
114
+ // --- Layer model ----------------------------------------------------------
115
+ getLayerCount() {
116
+ return this.stores.length;
117
+ }
118
+ setLayerVisible(t, e) {
119
+ this.stores[t]?.setVisible(e);
120
+ }
121
+ isLayerVisible(t) {
122
+ return this.stores[t]?.isVisible() ?? !0;
123
+ }
124
+ /** Representative concrete color per layer — value-fns are resolved at the
125
+ * layer's last value, giving the legend swatch / color-change detection a
126
+ * stable string. Honors per-layer `data` overrides. */
127
+ getLayerColors() {
128
+ const t = [];
129
+ for (let e = 0; e < this.stores.length; e++) {
130
+ const s = this.stores[e]?.last()?.value ?? 0;
131
+ t.push(this.resolveLayerColor(e, s));
132
+ }
133
+ return t;
134
+ }
135
+ // --- Lifecycle ------------------------------------------------------------
136
+ onDataChanged(t) {
137
+ for (const e of this.stores) e.on("update", t);
138
+ return () => {
139
+ for (const e of this.stores) e.off("update", t);
140
+ };
141
+ }
142
+ dispose() {
143
+ for (const t of this.stores) t.removeAllListeners();
144
+ }
145
+ // --- Animation primitives — renderer-owned state --------------------------
146
+ /**
147
+ * Per-point entrance progress in `[0, 1]`. Reads the local entry registry,
148
+ * returning `1` for a settled or absent entry (which matches the visual
149
+ * default: nothing to fade in).
150
+ */
151
+ entranceProgress(t, e, s) {
152
+ const i = this.entries[e]?.get(s);
153
+ if (i === void 0) return 1;
154
+ const r = this.options.entryMs;
155
+ if (r <= 0) return 1;
156
+ const n = performance.now() - i.startTime;
157
+ return n <= 0 ? 0 : n >= r ? 1 : n / r;
158
+ }
159
+ /**
160
+ * Trailing data points whose entrance is still unsettled, oldest first.
161
+ * Walks back from the store's last point and stops at the first settled
162
+ * point — that point is the stable anchor a chained grow-lerp hangs off.
163
+ *
164
+ * A feed that appends faster than `entryMs` keeps several entrances in
165
+ * flight at once; animating only the newest (and snapping the rest to
166
+ * their raw spots) makes the head region jump a segment-fraction forward
167
+ * on every append. Renderers lerp each chain link from the previous
168
+ * link's *rendered* position instead, so geometry stays continuous.
169
+ */
170
+ unsettledTail(t, e) {
171
+ const s = this.stores[e]?.getAll();
172
+ if (!s || s.length < 2) return [];
173
+ const i = [];
174
+ for (let r = s.length - 1; r >= 1; r--) {
175
+ const n = this.entranceProgress(t, e, s[r].time);
176
+ if (n >= 1) break;
177
+ i.unshift({ time: s[r].time, progress: n });
178
+ }
179
+ return i;
180
+ }
181
+ /**
182
+ * Substitute the renderer-smoothed last value for `rawValue` when the
183
+ * query `time` matches the layer's current last point, or the still-settling
184
+ * pinned chase (see {@link appendPoint}) when it matches the penultimate.
185
+ * Falls back to `rawValue` when the store is empty or no smoothing has
186
+ * happened yet.
187
+ */
188
+ effectiveValue(t, e, s, i) {
189
+ const r = this.stores[e]?.last()?.time;
190
+ if (r !== void 0 && s === r)
191
+ return this.displayedLastValues[e] ?? i;
192
+ const n = this.#e[e];
193
+ return n !== null && n.time === s ? n.anim.current : i;
194
+ }
195
+ // --- Animation lifecycle --------------------------------------------------
196
+ /**
197
+ * Advance owned animators against `now` and prune fully-settled entries.
198
+ * Called by the subclass's `render()` once per frame, before drawing. The
199
+ * subclass passes its own clock so test harnesses (which stub
200
+ * `performance.now`) can drive progression deterministically.
201
+ */
202
+ tickAnimations(t) {
203
+ for (const e of this.#s) e.tick(t);
204
+ for (let e = 0; e < this.stores.length; e++) {
205
+ const s = this.#t[e];
206
+ if (s !== null) {
207
+ const l = s.tick(t);
208
+ this.displayedLastValues[e] = s.current, l || (this.#t[e] = null);
209
+ }
210
+ const i = this.#e[e];
211
+ i !== null && !i.anim.tick(t) && (this.#e[e] = null);
212
+ const r = this.options.entryMs;
213
+ if (r <= 0) {
214
+ this.entries[e].clear();
215
+ continue;
216
+ }
217
+ const n = this.entries[e];
218
+ for (const [l, o] of n)
219
+ t - o.startTime >= r && n.delete(l);
220
+ }
221
+ }
222
+ /** True while any layer has an active chase, unsettled entry, or alpha fade. */
223
+ get needsAnimation() {
224
+ for (const t of this.#s)
225
+ if (t.animating) return !0;
226
+ for (const t of this.#t)
227
+ if (t !== null) return !0;
228
+ for (const t of this.#e)
229
+ if (t !== null) return !0;
230
+ for (const t of this.entries)
231
+ if (t.size > 0) return !0;
232
+ return !1;
233
+ }
234
+ /**
235
+ * Abort in-flight per-point entrance animations on every layer. Live-value
236
+ * chase (`displayedLastValues`) is intentionally left alone — its motion
237
+ * is subtle and shouldn't jump when the viewport moves.
238
+ */
239
+ cancelEntranceAnimations() {
240
+ for (const t of this.entries) t.clear();
241
+ }
242
+ /**
243
+ * Start a series-wide fade toward `target` over `durationMs`. Fans out
244
+ * across every per-layer animator so a `setSeriesVisible` toggle is just
245
+ * "set every layer to the same target". `durationMs <= 0` snaps.
246
+ */
247
+ setAlpha(t, e) {
248
+ for (const s of this.#s)
249
+ s.setTarget(t, { duration: e });
250
+ }
251
+ /**
252
+ * `1` while any layer has alpha > 0 OR is animating, `0` when every layer
253
+ * has fully faded and is at rest. Per-layer alpha is composed into
254
+ * `globalAlpha` by the renderer's own draw loops, so this stays a binary
255
+ * skip-gate at the chart level.
256
+ *
257
+ * The `animating` check matters when every layer is at `current = 0` and
258
+ * the user toggles one back in: `setLayerAlpha(idx, 1, ms)` flips the
259
+ * animator to `animating = true` but `current` is still `0` until the next
260
+ * `tick`. If chart skipped the render based on `current` alone, the
261
+ * animator would never tick (render is what advances it), and the fade-in
262
+ * would deadlock at `0`.
263
+ */
264
+ getAlpha() {
265
+ for (const t of this.#s)
266
+ if (t.current > 0 || t.animating) return 1;
267
+ return 0;
268
+ }
269
+ /**
270
+ * Start a fade for a single layer toward `target` over `durationMs`.
271
+ * Subclass draw loops multiply this into `globalAlpha` per layer so the
272
+ * fade lives next to the geometry it affects.
273
+ */
274
+ setLayerAlpha(t, e, s) {
275
+ this.#s[t]?.setTarget(e, { duration: s });
276
+ }
277
+ /** Latest rendered per-layer alpha. Defaults to 1 for out-of-range indices. */
278
+ getLayerAlpha(t) {
279
+ return this.#s[t]?.current ?? 1;
280
+ }
281
+ // --- Data queries ---------------------------------------------------------
282
+ getLastValue() {
283
+ for (let t = this.stores.length - 1; t >= 0; t--) {
284
+ const e = this.stores[t].last();
285
+ if (e) return e.value;
286
+ }
287
+ return null;
288
+ }
289
+ getDataAtTime(t, e) {
290
+ return this.stores[0]?.findNearest(t, e) ?? null;
291
+ }
292
+ getLayerSnapshots(t, e) {
293
+ if (this.stores.length <= 1) return null;
294
+ const s = [];
295
+ for (let i = 0; i < this.stores.length; i++) {
296
+ if (!this.stores[i].isVisible()) continue;
297
+ const r = this.stores[i].getVisibleData(t - e, t + e);
298
+ if (r.length === 0) continue;
299
+ let n = r[0], l = Math.abs(r[0].time - t);
300
+ for (let o = 1; o < r.length; o++) {
301
+ const a = Math.abs(r[o].time - t);
302
+ a <= l && (l = a, n = r[o]);
303
+ }
304
+ s.push({
305
+ layerIndex: i,
306
+ time: n.time,
307
+ value: n.value,
308
+ // Resolve the layer's color at the hovered datum's value so a value-fn
309
+ // colors the tooltip dot to match the bar / segment under the cursor.
310
+ color: this.resolveLayerColor(i, n.value)
311
+ });
312
+ }
313
+ return s.length > 0 ? s : null;
314
+ }
315
+ getStackedLastValue() {
316
+ if (this.stores.length <= 1) {
317
+ const r = this.stores[0]?.last();
318
+ return r ? { value: r.value, isLive: !0 } : null;
319
+ }
320
+ let t = -1 / 0;
321
+ for (const r of this.stores) {
322
+ if (!r.isVisible()) continue;
323
+ const n = r.last();
324
+ n && n.time > t && (t = n.time);
325
+ }
326
+ if (t === -1 / 0) return null;
327
+ const e = this.options.stacking;
328
+ if (e === "off") {
329
+ for (let r = this.stores.length - 1; r >= 0; r--) {
330
+ if (!this.stores[r].isVisible()) continue;
331
+ const n = this.stores[r].last();
332
+ if (n) return { value: n.value, isLive: !0 };
333
+ }
334
+ return null;
335
+ }
336
+ const s = [];
337
+ for (const r of this.stores) {
338
+ if (!r.isVisible()) continue;
339
+ const n = r.last();
340
+ s.push(n && n.time === t ? n.value : 0);
341
+ }
342
+ const i = y(s);
343
+ return { value: e === "percent" ? L(i) : V(i), isLive: !0 };
344
+ }
345
+ getLayerLastSnapshots() {
346
+ if (this.stores.length <= 1) return null;
347
+ const t = [];
348
+ for (let e = 0; e < this.stores.length; e++) {
349
+ if (!this.stores[e].isVisible()) continue;
350
+ const s = this.stores[e].last();
351
+ s && t.push({
352
+ layerIndex: e,
353
+ time: s.time,
354
+ value: s.value,
355
+ color: this.resolveLayerColor(e, s.value)
356
+ });
357
+ }
358
+ return t.length > 0 ? t : null;
359
+ }
360
+ getTotalLength() {
361
+ let t = 0;
362
+ for (const e of this.stores) t += e.length;
363
+ return t;
364
+ }
365
+ // --- TimeSeriesRenderer data queries --------------------------------------
366
+ /** Earliest first-sample / latest last-sample across ALL layers, skipping
367
+ * empty ones. Aggregating every layer (not just `stores[0]`) is what fixes
368
+ * the multi-layer time-range leak: a populated layer 1 with an empty layer 0
369
+ * still reports the real bounds. */
370
+ getTimeBounds() {
371
+ let t = 1 / 0, e = -1 / 0;
372
+ for (const s of this.stores) {
373
+ const i = s.first();
374
+ if (!i) continue;
375
+ const r = s.last() ?? i;
376
+ i.time < t && (t = i.time), r.time > e && (e = r.time);
377
+ }
378
+ return t === 1 / 0 ? null : { first: t, last: e };
379
+ }
380
+ /**
381
+ * Last data point of **layer 0 (`stores[0]`) only** — preserves the behavior
382
+ * of the deleted `get store()` getter. NOTE: this is intentionally NOT the
383
+ * same as {@link getStackedLastValue}, which for non-stacked multi-layer
384
+ * reports the top visible layer and for stacked reports the cumulative sum.
385
+ * Last-data / previous-close semantics stay pinned to layer 0 for back-compat.
386
+ */
387
+ getLastDataPoint() {
388
+ return this.stores[0]?.last() ?? null;
389
+ }
390
+ /** Second-to-last point of layer 0 (`stores[0]`). See {@link getLastDataPoint}. */
391
+ getSecondLastDataPoint() {
392
+ const t = this.stores[0]?.getAll();
393
+ return !t || t.length < 2 ? null : t[t.length - 2];
394
+ }
395
+ /** First `maxCount` sample times from the first populated layer. */
396
+ sampleTimes(t) {
397
+ for (const e of this.stores) {
398
+ const s = e.getAll();
399
+ if (s.length !== 0)
400
+ return s.slice(0, t).map((i) => i.time);
401
+ }
402
+ return [];
403
+ }
404
+ /** Visible points of layer 0 (`stores[0]`). See {@link getLastDataPoint}. */
405
+ getVisibleDataPoints(t, e) {
406
+ return this.stores[0]?.getVisibleData(t, e) ?? [];
407
+ }
408
+ getValueRange(t, e) {
409
+ const s = this.options.stacking;
410
+ if (s === "percent")
411
+ return { min: 0, max: 100 };
412
+ const i = this.stores.map((o) => o.isVisible() ? o.getVisibleData(t, e) : []);
413
+ if (s === "off") {
414
+ let o = 1 / 0, a = -1 / 0;
415
+ for (const u of i)
416
+ for (const h of u)
417
+ Number.isFinite(h.value) && (h.value < o && (o = h.value), h.value > a && (a = h.value));
418
+ return o < 1 / 0 ? { min: o, max: a } : null;
419
+ }
420
+ const r = /* @__PURE__ */ new Map();
421
+ for (let o = 0; o < i.length; o++)
422
+ for (const a of i[o]) {
423
+ let u = r.get(a.time);
424
+ u || (u = new Array(i.length).fill(0), r.set(a.time, u)), u[o] = Number.isFinite(a.value) ? a.value : 0;
425
+ }
426
+ let n = 0, l = 0;
427
+ for (const o of r.values()) {
428
+ let a = 0, u = 0;
429
+ for (const h of o)
430
+ h > 0 ? a += h : u += h;
431
+ a > l && (l = a), u < n && (n = u);
432
+ }
433
+ return l > n ? { min: n, max: l } : null;
434
+ }
435
+ }
436
+ export {
437
+ D as BaseMultiLayerSeries
438
+ };