@wick-charts/vue 0.5.1 → 0.6.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 (82) hide show
  1. package/README.md +45 -6
  2. package/dist/BarSeries.vue.js +26 -20
  3. package/dist/CandlestickSeries.vue.js +30 -24
  4. package/dist/ChartContainer.vue.js +125 -72
  5. package/dist/HeatmapSeries.vue.js +40 -0
  6. package/dist/HeatmapSeries.vue2.js +4 -0
  7. package/dist/LineSeries.vue.js +26 -20
  8. package/dist/PieSeries.vue.js +24 -18
  9. package/dist/core/dist/animation/animator.js +21 -21
  10. package/dist/core/dist/animation/config.js +114 -87
  11. package/dist/core/dist/animation/easing.js +3 -1
  12. package/dist/core/dist/animation/intro-wave.js +68 -0
  13. package/dist/core/dist/axis/dom-labels.js +13 -14
  14. package/dist/core/dist/chart/badge-animator.js +56 -0
  15. package/dist/core/dist/chart/edge-indicators.js +28 -13
  16. package/dist/core/dist/chart/last-value.js +18 -17
  17. package/dist/core/dist/chart/options.js +27 -16
  18. package/dist/core/dist/chart/y-target.js +13 -12
  19. package/dist/core/dist/chart.js +868 -441
  20. package/dist/core/dist/components/annotation-chip.js +28 -0
  21. package/dist/core/dist/components/crosshair.js +8 -6
  22. package/dist/core/dist/components/edge-indicator.js +58 -26
  23. package/dist/core/dist/components/loading-indicator.js +46 -0
  24. package/dist/core/dist/components/marker.js +49 -31
  25. package/dist/core/dist/components/reference-line.js +27 -36
  26. package/dist/core/dist/components/time-region.js +30 -28
  27. package/dist/core/dist/data/store.js +38 -19
  28. package/dist/core/dist/data/sync.js +60 -38
  29. package/dist/core/dist/heatmap-tooltip.js +16 -0
  30. package/dist/core/dist/interactions/handler.js +86 -46
  31. package/dist/core/dist/perf/perf-hud.js +5 -5
  32. package/dist/core/dist/scales/x-scale.js +85 -37
  33. package/dist/core/dist/scales/y-scale.js +38 -27
  34. package/dist/core/dist/series/bar-intro.js +18 -0
  35. package/dist/core/dist/series/bar.js +337 -205
  36. package/dist/core/dist/series/base-multi-layer.js +224 -96
  37. package/dist/core/dist/series/candlestick-intro.js +57 -0
  38. package/dist/core/dist/series/candlestick.js +454 -276
  39. package/dist/core/dist/series/heatmap.js +387 -0
  40. package/dist/core/dist/series/line-intro.js +85 -0
  41. package/dist/core/dist/series/line.js +590 -282
  42. package/dist/core/dist/series/painters/builtins.js +2 -2
  43. package/dist/core/dist/series/pie.js +396 -259
  44. package/dist/core/dist/series/register-builtins.js +8 -7
  45. package/dist/core/dist/series/types.js +6 -0
  46. package/dist/core/dist/series/wave-intro.js +26 -0
  47. package/dist/core/dist/theme/create.js +69 -63
  48. package/dist/core/dist/theme/themes/mint-breeze.js +2 -2
  49. package/dist/core/dist/theme/themes/sand-dune.js +2 -2
  50. package/dist/core/dist/utils/color.js +109 -34
  51. package/dist/core/dist/utils/deep-equal.js +18 -0
  52. package/dist/core/dist/utils/time.js +25 -19
  53. package/dist/index.d.ts +1494 -122
  54. package/dist/index.js +177 -130
  55. package/dist/ui/Crosshair.vue.js +20 -21
  56. package/dist/ui/HeatmapTooltip.vue.js +96 -0
  57. package/dist/ui/HeatmapTooltip.vue2.js +4 -0
  58. package/dist/ui/InfoBar.vue.js +46 -47
  59. package/dist/ui/Legend.vue.js +80 -79
  60. package/dist/ui/PieLegend.vue.js +5 -5
  61. package/dist/ui/PieTooltip.vue.js +77 -67
  62. package/dist/ui/Tooltip.vue.js +60 -60
  63. package/dist/ui/YAxis.vue.js +2 -2
  64. package/dist/ui/YLabel.vue.js +94 -61
  65. package/package.json +2 -2
  66. package/src/BarSeries.vue +23 -7
  67. package/src/CandlestickSeries.vue +23 -7
  68. package/src/ChartContainer.vue +250 -13
  69. package/src/HeatmapSeries.vue +69 -0
  70. package/src/LineSeries.vue +23 -7
  71. package/src/PieSeries.vue +22 -6
  72. package/src/index.ts +84 -3
  73. package/src/ui/Crosshair.vue +1 -2
  74. package/src/ui/HeatmapTooltip.vue +144 -0
  75. package/src/ui/InfoBar.vue +1 -2
  76. package/src/ui/Legend.vue +13 -0
  77. package/src/ui/Marker.vue +1 -1
  78. package/src/ui/PieTooltip.vue +10 -0
  79. package/src/ui/ReferenceLine.vue +2 -2
  80. package/src/ui/TimeRegion.vue +2 -2
  81. package/src/ui/Tooltip.vue +2 -2
  82. package/src/ui/YLabel.vue +123 -8
@@ -1,11 +1,12 @@
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 {
1
+ import { Animator as y } from "../animation/animator.js";
2
+ import { IntroWave as c } from "../animation/intro-wave.js";
3
+ import { ScalarSpring as V } from "../animation/scalar-spring.js";
4
+ import { TimeSeriesStore as L } from "../data/store.js";
5
+ import { resolveColor as A } from "../utils/color.js";
6
+ import { normalizeTimePointArray as m, normalizeTime as g } from "../utils/time.js";
7
+ import { sumStack as p, renderedStackPercentTop as v, renderedStackTop as d } from "./stack-math.js";
8
+ const b = (f, t, e) => f + (t - f) * e;
9
+ class R {
9
10
  stores;
10
11
  // --- Animation state (per layer) ----------------------------------------
11
12
  /**
@@ -35,10 +36,25 @@ class D {
35
36
  * loops multiply the layer's alpha into `globalAlpha` per draw.
36
37
  */
37
38
  #s;
39
+ /**
40
+ * Initial-load reveal clock — armed once when the dataset transitions
41
+ * empty → non-empty in {@link setData}, shared across every layer so a
42
+ * multi-layer seed rides one wave. Subclasses read it through
43
+ * {@link introProgressAt} (per-element wave) or directly (line's sweep).
44
+ */
45
+ introWave = new c();
46
+ /** History-prepend reveal clock — armed by {@link prependPoints} so newly
47
+ * loaded older points wave in from the data boundary instead of popping.
48
+ * Shared across layers: a multi-layer prepend rides one wave. */
49
+ historyWave = new c();
50
+ /** Prepended time span: `from` = deepest new point, `to` = the boundary
51
+ * (the pre-prepend first point). Stagger position is `0` at the boundary
52
+ * and `1` at the deepest point. */
53
+ historyRange = null;
38
54
  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(
55
+ this.stores = Array.from({ length: t }, () => new L()), 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
56
  { length: t },
41
- () => new m({ initial: 1, duration: 0, lerp: A })
57
+ () => new y({ initial: 1, duration: 0, lerp: b })
42
58
  );
43
59
  }
44
60
  // --- Color accessors ------------------------------------------------------
@@ -47,63 +63,88 @@ class D {
47
63
  * layer on the theme base in `options.colors`). Kept separate from the base so
48
64
  * a theme swap, which rewrites `options.colors`, leaves these untouched.
49
65
  */
50
- #r = [];
66
+ #i = [];
51
67
  setColorOverrides(t) {
52
- this.#r = t;
68
+ this.#i = t;
53
69
  }
54
70
  /** 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];
71
+ #r(t) {
72
+ const e = this.#i[t];
57
73
  if (e !== void 0) return e;
58
74
  const s = this.options.colors;
59
75
  return s[t % s.length];
60
76
  }
61
77
  /** The first layer's color resolver (string or value-fn). */
62
78
  getColor() {
63
- return this.#i(0);
79
+ return this.#r(0);
64
80
  }
65
81
  getColors() {
66
82
  return this.options.colors;
67
83
  }
68
84
  /** Resolve one layer's color for a given datum value. */
69
85
  resolveLayerColor(t, e) {
70
- return d(this.#i(t), e);
86
+ return A(this.#r(t), e);
71
87
  }
72
88
  // --- Data ingest ----------------------------------------------------------
73
89
  setData(t, e = 0) {
74
90
  const s = this.stores[e];
75
91
  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();
92
+ let i = !1;
93
+ for (const n of this.stores)
94
+ n.length > 0 && (i = !0);
95
+ const r = m(t ?? []);
96
+ s.setData(r), !i && r.length > 0 && this.introWave.arm(this.options.introMs);
97
+ const l = s.last();
98
+ this.displayedLastValues[e] = l ? l.value : null, this.#t[e] = null, this.#e[e] = null, this.entries[e].clear(), this.historyWave.finish(), this.historyRange = null;
80
99
  }
81
100
  appendPoint(t, e = 0) {
82
101
  const s = this.stores[e];
83
102
  if (!s) return;
84
- const i = t, r = c(i.time), n = s.last(), l = s.length;
103
+ const i = t, r = g(i.time), l = s.last(), n = s.length;
85
104
  s.append({ ...i, time: r });
86
105
  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;
106
+ o !== null && l !== void 0 && s.length > n && (this.#e[e] = { time: l.time, anim: o }), this.displayedLastValues[e] = i.value, this.#t[e] = null;
88
107
  const a = this.options.entryMs;
89
108
  this.isEntryEnabled() && a > 0 && this.entries[e].set(r, { startTime: performance.now() });
90
109
  }
110
+ prependPoints(t, e = 0) {
111
+ const s = this.stores[e];
112
+ if (!s || t.length === 0) return;
113
+ const i = m(t), r = s.first()?.time;
114
+ s.prepend(i), this.#n(i[0]?.time, r);
115
+ }
116
+ /**
117
+ * Arm (or extend) the history-reveal wave for freshly prepended points.
118
+ * While a reveal is already in flight — including a same-frame prepend to
119
+ * another layer — only the range grows; restarting the clock would snap
120
+ * half-revealed points back to invisible.
121
+ */
122
+ #n(t, e) {
123
+ const s = this.options.historyRevealMs;
124
+ if (!(this.options.historyReveal === "none" || s <= 0) && !(t === void 0 || e === void 0)) {
125
+ if (this.historyWave.active && this.historyRange !== null) {
126
+ this.historyRange = { from: Math.min(this.historyRange.from, t), to: this.historyRange.to };
127
+ return;
128
+ }
129
+ this.historyRange = { from: t, to: e }, this.historyWave.arm(s);
130
+ }
131
+ }
91
132
  updateLastPoint(t, e = 0) {
92
133
  const s = this.stores[e];
93
134
  if (!s) return;
94
135
  const i = t;
95
- s.updateLast({ ...i, time: c(i.time) });
96
- const r = i.value, n = this.options.smoothMs;
97
- if (n <= 0) {
136
+ s.updateLast({ ...i, time: g(i.time) });
137
+ const r = i.value, l = this.options.smoothMs;
138
+ if (l <= 0) {
98
139
  this.displayedLastValues[e] = r, this.#t[e] = null;
99
140
  return;
100
141
  }
101
- let l = this.#t[e];
102
- if (l === null) {
142
+ let n = this.#t[e];
143
+ if (n === null) {
103
144
  const o = this.displayedLastValues[e] ?? r;
104
- l = new g(o), this.#t[e] = l;
145
+ n = new V(o), this.#t[e] = n;
105
146
  }
106
- l.retarget(r, { settleMs: n });
147
+ n.retarget(r, { settleMs: l });
107
148
  }
108
149
  keepLast(t, e = 0) {
109
150
  const s = this.stores[e];
@@ -146,15 +187,42 @@ class D {
146
187
  /**
147
188
  * Per-point entrance progress in `[0, 1]`. Reads the local entry registry,
148
189
  * returning `1` for a settled or absent entry (which matches the visual
149
- * default: nothing to fade in).
190
+ * default: nothing to fade in). Takes no render context — progress is a
191
+ * pure function of wall time — so tooltip/last-value queries (which have
192
+ * no context to hand) can read it too.
150
193
  */
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;
194
+ entranceProgress(t, e) {
195
+ const s = this.entries[t]?.get(e);
196
+ if (s === void 0) return 1;
197
+ const i = this.options.entryMs;
198
+ if (i <= 0) return 1;
199
+ const r = performance.now() - s.startTime;
200
+ return r <= 0 ? 0 : r >= i ? 1 : r / i;
201
+ }
202
+ /**
203
+ * Initial-load reveal progress for a datum, keyed by its normalized
204
+ * position across the *visible* time window — the wave sweeps whatever
205
+ * the user actually sees, regardless of how much history sits off-screen.
206
+ * `1` when no intro is in flight. Subclasses that animate per element
207
+ * (bar) fold this into their {@link entranceProgress} override; the line
208
+ * renders its own continuous sweep instead.
209
+ */
210
+ introProgressAt(t, e) {
211
+ 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;
213
+ return this.introWave.progressAt(r);
214
+ }
215
+ /**
216
+ * History-prepend reveal progress for a datum. Stagger position is
217
+ * anchored at the data boundary — `0` there, `1` at the deepest prepended
218
+ * point — so the wave travels into history. `1` for points outside the
219
+ * prepended span or when no reveal is in flight.
220
+ */
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;
225
+ return this.historyWave.progressAt(i);
158
226
  }
159
227
  /**
160
228
  * Trailing data points whose entrance is still unsettled, oldest first.
@@ -167,16 +235,16 @@ class D {
167
235
  * on every append. Renderers lerp each chain link from the previous
168
236
  * link's *rendered* position instead, so geometry stays continuous.
169
237
  */
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 });
238
+ unsettledTail(t) {
239
+ const e = this.stores[t]?.getAll();
240
+ if (!e || e.length < 2) return [];
241
+ const s = [];
242
+ for (let i = e.length - 1; i >= 1; i--) {
243
+ const r = this.entranceProgress(t, e[i].time);
244
+ if (r >= 1) break;
245
+ s.unshift({ time: e[i].time, progress: r });
178
246
  }
179
- return i;
247
+ return s;
180
248
  }
181
249
  /**
182
250
  * Substitute the renderer-smoothed last value for `rawValue` when the
@@ -186,11 +254,31 @@ class D {
186
254
  * happened yet.
187
255
  */
188
256
  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;
257
+ return this.liveValue(e, s, i);
258
+ }
259
+ /**
260
+ * The ctx-independent core of {@link effectiveValue} — used directly by the
261
+ * tooltip/last-value query methods below, which have no render context to
262
+ * hand a subclass's ctx-dependent override (e.g. Line's intro value
263
+ * transform). Those queries only need the live smoothing/chase this base
264
+ * method already provides, never the intro's positional transform.
265
+ */
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;
272
+ }
273
+ /**
274
+ * Value a last-value/tooltip query should report for `time` — defaults to
275
+ * {@link liveValue}. Distinct from `liveValue` so a subclass can layer its
276
+ * *entrance* animation's value-space equivalent on top (see Line's
277
+ * override) without that lerp feeding back into `effectiveValue`, which
278
+ * the renderer's own per-point draws use as an unlerp'd target.
279
+ */
280
+ snapshotValue(t, e, s) {
281
+ return this.liveValue(t, e, s);
194
282
  }
195
283
  // --- Animation lifecycle --------------------------------------------------
196
284
  /**
@@ -200,12 +288,13 @@ class D {
200
288
  * `performance.now`) can drive progression deterministically.
201
289
  */
202
290
  tickAnimations(t) {
291
+ this.introWave.tick(t), this.historyWave.tick(t);
203
292
  for (const e of this.#s) e.tick(t);
204
293
  for (let e = 0; e < this.stores.length; e++) {
205
294
  const s = this.#t[e];
206
295
  if (s !== null) {
207
- const l = s.tick(t);
208
- this.displayedLastValues[e] = s.current, l || (this.#t[e] = null);
296
+ const n = s.tick(t);
297
+ this.displayedLastValues[e] = s.current, n || (this.#t[e] = null);
209
298
  }
210
299
  const i = this.#e[e];
211
300
  i !== null && !i.anim.tick(t) && (this.#e[e] = null);
@@ -214,13 +303,15 @@ class D {
214
303
  this.entries[e].clear();
215
304
  continue;
216
305
  }
217
- const n = this.entries[e];
218
- for (const [l, o] of n)
219
- t - o.startTime >= r && n.delete(l);
306
+ const l = this.entries[e];
307
+ for (const [n, o] of l)
308
+ t - o.startTime >= r && l.delete(n);
220
309
  }
221
310
  }
222
- /** True while any layer has an active chase, unsettled entry, or alpha fade. */
311
+ /** True while any layer has an active chase, unsettled entry, alpha fade,
312
+ * or the initial-load reveal is still sweeping. */
223
313
  get needsAnimation() {
314
+ if (this.introWave.active || this.historyWave.active) return !0;
224
315
  for (const t of this.#s)
225
316
  if (t.animating) return !0;
226
317
  for (const t of this.#t)
@@ -231,12 +322,18 @@ class D {
231
322
  if (t.size > 0) return !0;
232
323
  return !1;
233
324
  }
325
+ /** Reveal-front position of the initial-load intro; `1` once settled. */
326
+ getIntroFront() {
327
+ return this.introWave.sweep();
328
+ }
234
329
  /**
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.
330
+ * Abort in-flight per-point entrance animations on every layer, including
331
+ * the initial-load reveal. Live-value chase (`displayedLastValues`) is
332
+ * intentionally left alone — its motion is subtle and shouldn't jump when
333
+ * the viewport moves.
238
334
  */
239
335
  cancelEntranceAnimations() {
336
+ this.introWave.finish();
240
337
  for (const t of this.entries) t.clear();
241
338
  }
242
339
  /**
@@ -296,18 +393,21 @@ class D {
296
393
  if (!this.stores[i].isVisible()) continue;
297
394
  const r = this.stores[i].getVisibleData(t - e, t + e);
298
395
  if (r.length === 0) continue;
299
- let n = r[0], l = Math.abs(r[0].time - t);
396
+ let l = r[0], n = Math.abs(r[0].time - t);
300
397
  for (let o = 1; o < r.length; o++) {
301
398
  const a = Math.abs(r[o].time - t);
302
- a <= l && (l = a, n = r[o]);
399
+ a <= n && (n = a, l = r[o]);
303
400
  }
304
401
  s.push({
305
402
  layerIndex: i,
306
- time: n.time,
307
- value: n.value,
403
+ time: l.time,
404
+ // Routes through the same live/pinned-chase smoothing the renderer
405
+ // paints, so hovering the live edge mid-animation doesn't jump ahead
406
+ // to the raw target before the on-screen marker gets there.
407
+ value: this.snapshotValue(i, l.time, l.value),
308
408
  // Resolve the layer's color at the hovered datum's value so a value-fn
309
409
  // colors the tooltip dot to match the bar / segment under the cursor.
310
- color: this.resolveLayerColor(i, n.value)
410
+ color: this.resolveLayerColor(i, l.value)
311
411
  });
312
412
  }
313
413
  return s.length > 0 ? s : null;
@@ -315,32 +415,60 @@ class D {
315
415
  getStackedLastValue() {
316
416
  if (this.stores.length <= 1) {
317
417
  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);
418
+ return r ? { value: this.snapshotValue(0, r.time, r.value), isLive: !0 } : null;
325
419
  }
326
- if (t === -1 / 0) return null;
327
- const e = this.options.stacking;
328
- if (e === "off") {
420
+ const t = this.options.stacking;
421
+ if (t === "off") {
329
422
  for (let r = this.stores.length - 1; r >= 0; r--) {
330
423
  if (!this.stores[r].isVisible()) continue;
331
- const n = this.stores[r].last();
332
- if (n) return { value: n.value, isLive: !0 };
424
+ const l = this.stores[r].last();
425
+ if (l) return { value: this.snapshotValue(r, l.time, l.value), isLive: !0 };
333
426
  }
334
427
  return null;
335
428
  }
429
+ let e = !1;
336
430
  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);
431
+ for (let r = 0; r < this.stores.length; r++) {
432
+ if (!this.stores[r].isVisible()) continue;
433
+ const l = this.stores[r].last();
434
+ if (!l) {
435
+ s.push(0);
436
+ continue;
437
+ }
438
+ e = !0, s.push(this.snapshotValue(r, l.time, l.value));
439
+ }
440
+ if (!e) return null;
441
+ const i = p(s);
442
+ return { value: t === "percent" ? v(i) : d(i), isLive: !0 };
443
+ }
444
+ getStackedValueAtTime(t, e) {
445
+ 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;
448
+ }
449
+ const s = this.options.stacking;
450
+ if (s === "off") {
451
+ for (let n = this.stores.length - 1; n >= 0; n--) {
452
+ if (!this.stores[n].isVisible()) continue;
453
+ const o = this.stores[n].findNearest(t, e);
454
+ if (o) return this.snapshotValue(n, o.time, o.value);
455
+ }
456
+ return null;
457
+ }
458
+ let i = !1;
459
+ const r = [];
460
+ for (let n = 0; n < this.stores.length; n++) {
461
+ if (!this.stores[n].isVisible()) continue;
462
+ const o = this.stores[n].findNearest(t, e);
463
+ if (!o) {
464
+ r.push(0);
465
+ continue;
466
+ }
467
+ i = !0, r.push(this.snapshotValue(n, o.time, o.value));
341
468
  }
342
- const i = y(s);
343
- return { value: e === "percent" ? L(i) : V(i), isLive: !0 };
469
+ if (!i) return null;
470
+ const l = p(r);
471
+ return s === "percent" ? v(l) : d(l);
344
472
  }
345
473
  getLayerLastSnapshots() {
346
474
  if (this.stores.length <= 1) return null;
@@ -351,7 +479,7 @@ class D {
351
479
  s && t.push({
352
480
  layerIndex: e,
353
481
  time: s.time,
354
- value: s.value,
482
+ value: this.snapshotValue(e, s.time, s.value),
355
483
  color: this.resolveLayerColor(e, s.value)
356
484
  });
357
485
  }
@@ -412,27 +540,27 @@ class D {
412
540
  const i = this.stores.map((o) => o.isVisible() ? o.getVisibleData(t, e) : []);
413
541
  if (s === "off") {
414
542
  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));
543
+ for (const h of i)
544
+ for (const u of h)
545
+ Number.isFinite(u.value) && (u.value < o && (o = u.value), u.value > a && (a = u.value));
418
546
  return o < 1 / 0 ? { min: o, max: a } : null;
419
547
  }
420
548
  const r = /* @__PURE__ */ new Map();
421
549
  for (let o = 0; o < i.length; o++)
422
550
  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;
551
+ let h = r.get(a.time);
552
+ h || (h = new Array(i.length).fill(0), r.set(a.time, h)), h[o] = Number.isFinite(a.value) ? a.value : 0;
425
553
  }
426
- let n = 0, l = 0;
554
+ let l = 0, n = 0;
427
555
  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);
556
+ let a = 0, h = 0;
557
+ for (const u of o)
558
+ u > 0 ? a += u : h += u;
559
+ a > n && (n = a), h < l && (l = h);
432
560
  }
433
- return l > n ? { min: n, max: l } : null;
561
+ return n > l ? { min: l, max: n } : null;
434
562
  }
435
563
  }
436
564
  export {
437
- D as BaseMultiLayerSeries
565
+ R as BaseMultiLayerSeries
438
566
  };
@@ -0,0 +1,57 @@
1
+ import { lerp as p } from "../utils/math.js";
2
+ import { fadeIntro as g } from "./wave-intro.js";
3
+ function h(e) {
4
+ return e <= 0 ? 0 : e >= 1 ? 1 : e;
5
+ }
6
+ function w() {
7
+ return () => ({
8
+ element: (e) => ({ unfold: e.progress, alpha: e.progress })
9
+ });
10
+ }
11
+ const b = 0.55, m = 0.45, d = 0.35, k = 1.5;
12
+ function Y(e = {}) {
13
+ const l = e.fallback ?? g();
14
+ return (r) => {
15
+ const s = r.placeholders;
16
+ if (s === void 0 || s.length === 0) return l(r);
17
+ const f = l(r);
18
+ return {
19
+ ...f,
20
+ element: (t) => {
21
+ const u = t.element === "wick" ? t.x : t.x + t.barWidth / 2;
22
+ let o = null, a = 1 / 0;
23
+ for (const c of s) {
24
+ const i = Math.abs(c.x - u);
25
+ i < a && (a = i, o = c);
26
+ }
27
+ if (o === null || a > o.width * k)
28
+ return f.element?.(t) ?? {};
29
+ const n = t.progress;
30
+ return t.element === "volume" ? { alpha: n } : {
31
+ topY: p(o.y - o.halfHeight, t.topY, n),
32
+ bottomY: p(o.y + o.halfHeight, t.bottomY, n),
33
+ offsetX: (o.x - u) * (1 - n),
34
+ alpha: d + (1 - d) * n,
35
+ tint: 1 - n
36
+ };
37
+ }
38
+ };
39
+ };
40
+ }
41
+ function y() {
42
+ return () => ({
43
+ element: (e) => {
44
+ if (e.element === "wick") {
45
+ const r = h(e.progress / b);
46
+ return { unfold: r, alpha: r > 0 ? 1 : 0 };
47
+ }
48
+ const l = h((e.progress - m) / (1 - m));
49
+ return { unfold: l, alpha: l };
50
+ }
51
+ });
52
+ }
53
+ export {
54
+ w as candleUnfoldIntro,
55
+ Y as skeletonMorphIntro,
56
+ y as wickBodyIntro
57
+ };