@wick-charts/vue 0.6.2 → 0.6.4

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 (61) hide show
  1. package/README.md +2 -2
  2. package/dist/BandSeries.vue.js +50 -0
  3. package/dist/BandSeries.vue2.js +4 -0
  4. package/dist/ChartContainer.vue.js +45 -39
  5. package/dist/composables.js +39 -26
  6. package/dist/core/dist/animation/config.js +92 -75
  7. package/dist/core/dist/axis/dom-labels.js +56 -43
  8. package/dist/core/dist/chart/badge-animator.js +30 -22
  9. package/dist/core/dist/chart/edge-indicators.js +22 -21
  10. package/dist/core/dist/chart/last-value.js +33 -26
  11. package/dist/core/dist/chart/options.js +5 -5
  12. package/dist/core/dist/chart/scale-guards.js +26 -0
  13. package/dist/core/dist/chart/y-target.js +46 -19
  14. package/dist/core/dist/chart.js +670 -518
  15. package/dist/core/dist/components/crosshair.js +8 -8
  16. package/dist/core/dist/components/grid.js +26 -17
  17. package/dist/core/dist/components/marker.js +28 -28
  18. package/dist/core/dist/components/reference-line.js +16 -16
  19. package/dist/core/dist/data/decimation.js +58 -39
  20. package/dist/core/dist/interactions/handler.js +3 -2
  21. package/dist/core/dist/interactions/zoom.js +6 -5
  22. package/dist/core/dist/navigator/controller.js +47 -44
  23. package/dist/core/dist/perf/perf-hud.js +3 -3
  24. package/dist/core/dist/scales/log-scale.js +76 -0
  25. package/dist/core/dist/scales/y-scale.js +134 -35
  26. package/dist/core/dist/series/band.js +670 -0
  27. package/dist/core/dist/series/bar-intro.js +11 -11
  28. package/dist/core/dist/series/bar.js +301 -251
  29. package/dist/core/dist/series/base-multi-layer.js +100 -76
  30. package/dist/core/dist/series/candlestick.js +238 -235
  31. package/dist/core/dist/series/heatmap.js +5 -5
  32. package/dist/core/dist/series/line-intro.js +50 -40
  33. package/dist/core/dist/series/line.js +561 -483
  34. package/dist/core/dist/series/painters/builtins.js +4 -4
  35. package/dist/core/dist/series/painters/canvas-path.js +64 -52
  36. package/dist/core/dist/series/register-builtins.js +9 -8
  37. package/dist/core/dist/series/scale-stack.js +25 -0
  38. package/dist/core/dist/snapshots.js +36 -35
  39. package/dist/core/dist/tooltip-position.js +5 -5
  40. package/dist/core/dist/utils/point.js +10 -0
  41. package/dist/index.d.ts +501 -128
  42. package/dist/index.js +195 -189
  43. package/dist/ui/Crosshair.vue.js +14 -14
  44. package/dist/ui/HeatmapTooltip.vue.js +6 -6
  45. package/dist/ui/InfoBar.vue.js +100 -81
  46. package/dist/ui/PieTooltip.vue.js +4 -4
  47. package/dist/ui/TimeAxis.vue.js +23 -22
  48. package/dist/ui/Tooltip.vue.js +140 -111
  49. package/dist/ui/YAxis.vue.js +25 -24
  50. package/dist/ui/YLabel.vue.js +63 -70
  51. package/package.json +2 -2
  52. package/src/BandSeries.vue +87 -0
  53. package/src/ChartContainer.vue +20 -8
  54. package/src/composables.ts +35 -1
  55. package/src/index.ts +13 -0
  56. package/src/ui/Crosshair.vue +2 -2
  57. package/src/ui/InfoBar.vue +20 -1
  58. package/src/ui/TimeAxis.vue +7 -4
  59. package/src/ui/Tooltip.vue +40 -3
  60. package/src/ui/YAxis.vue +5 -3
  61. package/src/ui/YLabel.vue +5 -16
@@ -1,21 +1,21 @@
1
- import { Animator as st } from "../animation/animator.js";
2
- import { DEFAULT_HISTORY_REVEAL as tt, DEFAULT_CANDLESTICK_INTRO as it, DEFAULT_CANDLESTICK_SMOOTH as et, DEFAULT_CANDLESTICK_ENTRY as ot } from "../animation/config.js";
3
- import { easeOutCubic as nt } from "../animation/easing.js";
1
+ import { Animator as nt } from "../animation/animator.js";
2
+ import { DEFAULT_HISTORY_REVEAL as it, DEFAULT_CANDLESTICK_INTRO as et, DEFAULT_CANDLESTICK_SMOOTH as ot, DEFAULT_CANDLESTICK_ENTRY as st } from "../animation/config.js";
3
+ import { easeOutCubic as at } from "../animation/easing.js";
4
4
  import { IntroWave as U } from "../animation/intro-wave.js";
5
- import { ScalarSpring as V } from "../animation/scalar-spring.js";
6
- import { decimateOHLCData as at } from "../data/decimation.js";
7
- import { TimeSeriesStore as rt } from "../data/store.js";
5
+ import { ScalarSpring as $ } from "../animation/scalar-spring.js";
6
+ import { decimateOHLCData as rt } from "../data/decimation.js";
7
+ import { TimeSeriesStore as lt } from "../data/store.js";
8
8
  import { resolveCandlestickBodyColor as I } from "../theme/resolve.js";
9
9
  import { hexToRgba as K, mixColors as G } from "../utils/color.js";
10
- import { clamp as _, lerp as z } from "../utils/math.js";
10
+ import { clamp as F, lerp as z } from "../utils/math.js";
11
11
  import { isPoisonedNumber as N, reportPoisonedData as ht } from "../utils/poisoned-data-reporter.js";
12
12
  import { normalizeOHLCArray as J, normalizeTime as Q } from "../utils/time.js";
13
- import { candleUnfoldIntro as lt } from "./candlestick-intro.js";
13
+ import { candleUnfoldIntro as ct } from "./candlestick-intro.js";
14
14
  import { fillRoundedRect as Z } from "./painters/canvas-path.js";
15
15
  import { resolveCandlePainter as mt } from "./painters/resolve.js";
16
- import { fadeIntro as ct } from "./wave-intro.js";
17
- const pt = 0.15, ut = 5e-3;
18
- class dt {
16
+ import { fadeIntro as pt } from "./wave-intro.js";
17
+ const ut = 0.15, dt = 5e-3;
18
+ class ft {
19
19
  #t;
20
20
  #i;
21
21
  #s;
@@ -25,16 +25,16 @@ class dt {
25
25
  // Sticky once any seen candle carries volume — mirrors the old lerp, which
26
26
  // only emitted `volume` when a side had it, so a volume-less candle stays
27
27
  // volume-less and the histogram keeps skipping it.
28
- #h;
28
+ #l;
29
29
  constructor(t) {
30
- this.#t = new V(t.open), this.#i = new V(t.high), this.#s = new V(t.low), this.#r = new V(t.close), this.#e = new V(t.volume ?? 0), this.#n = t.time, this.#h = t.volume !== void 0;
30
+ this.#t = new $(t.open), this.#i = new $(t.high), this.#s = new $(t.low), this.#r = new $(t.close), this.#e = new $(t.volume ?? 0), this.#n = t.time, this.#l = t.volume !== void 0;
31
31
  }
32
32
  retarget(t, i = {}) {
33
- this.#n = t.time, t.volume !== void 0 && (this.#h = !0), this.#t.retarget(t.open, i), this.#i.retarget(t.high, i), this.#s.retarget(t.low, i), this.#r.retarget(t.close, i), this.#e.retarget(t.volume ?? 0, i);
33
+ this.#n = t.time, t.volume !== void 0 && (this.#l = !0), this.#t.retarget(t.open, i), this.#i.retarget(t.high, i), this.#s.retarget(t.low, i), this.#r.retarget(t.close, i), this.#e.retarget(t.volume ?? 0, i);
34
34
  }
35
35
  tick(t) {
36
- const i = this.#t.tick(t), e = this.#i.tick(t), o = this.#s.tick(t), a = this.#r.tick(t), s = this.#e.tick(t);
37
- return i || e || o || a || s;
36
+ const i = this.#t.tick(t), e = this.#i.tick(t), o = this.#s.tick(t), h = this.#r.tick(t), n = this.#e.tick(t);
37
+ return i || e || o || h || n;
38
38
  }
39
39
  get current() {
40
40
  const t = {
@@ -44,26 +44,29 @@ class dt {
44
44
  low: this.#s.current,
45
45
  close: this.#r.current
46
46
  };
47
- return this.#h && (t.volume = this.#e.current), t;
47
+ return this.#l && (t.volume = this.#e.current), t;
48
48
  }
49
49
  }
50
- const O = 2, ft = { tl: !0, tr: !0, br: !0, bl: !0 }, j = { tl: !0, tr: !0, br: !1, bl: !1 }, bt = lt(), Yt = ct(), gt = {
50
+ const _ = 2, bt = { tl: !0, tr: !0, br: !0, bl: !0 }, j = { tl: !0, tr: !0, br: !1, bl: !1 }, Yt = ct(), gt = pt(), yt = {
51
51
  up: { body: "#26a69a", wick: "#26a69a" },
52
52
  down: { body: "#ef5350", wick: "#ef5350" },
53
53
  bodyWidthRatio: 0.6,
54
- cornerRadius: O,
55
- entryMs: ot,
56
- smoothMs: et,
57
- introMs: it,
58
- historyRevealMs: tt
54
+ cornerRadius: _,
55
+ entryMs: st,
56
+ smoothMs: ot,
57
+ introMs: et,
58
+ historyRevealMs: it
59
59
  };
60
- function q(h) {
60
+ function q(a, t) {
61
+ return [a.open, a.high, a.low, a.close].every((i) => Number.isFinite(i) && t(i));
62
+ }
63
+ function tt(a) {
61
64
  return {
62
- ...h,
63
- entryMs: h.entryMs === !1 ? 0 : h.entryMs ?? ot,
64
- smoothMs: h.smoothMs === !1 ? 0 : h.smoothMs ?? et,
65
- introMs: h.introMs === !1 ? 0 : h.introMs ?? it,
66
- historyRevealMs: h.historyRevealMs === !1 ? 0 : h.historyRevealMs ?? tt
65
+ ...a,
66
+ entryMs: a.entryMs === !1 ? 0 : a.entryMs ?? st,
67
+ smoothMs: a.smoothMs === !1 ? 0 : a.smoothMs ?? ot,
68
+ introMs: a.introMs === !1 ? 0 : a.introMs ?? et,
69
+ historyRevealMs: a.historyRevealMs === !1 ? 0 : a.historyRevealMs ?? it
67
70
  };
68
71
  }
69
72
  class xt {
@@ -89,7 +92,7 @@ class xt {
89
92
  * clamps every bar to full band height for ~30 frames. */
90
93
  #r = !1;
91
94
  /** Series-level alpha for visibility cross-fade. Chart calls {@link setAlpha} on hide. */
92
- #e = new st({
95
+ #e = new nt({
93
96
  initial: 1,
94
97
  duration: 0,
95
98
  lerp: (t, i, e) => t + (i - t) * e
@@ -102,7 +105,7 @@ class xt {
102
105
  #n = null;
103
106
  /** Visible range captured alongside {@link #introDirectives} — positions
104
107
  * the per-element wave stagger. */
105
- #h = null;
108
+ #l = null;
106
109
  /** History-prepend reveal clock — armed by {@link prependPoints} so the
107
110
  * new candles wave in from the data boundary instead of popping. */
108
111
  #o = new U();
@@ -111,25 +114,25 @@ class xt {
111
114
  * boundary and `1` at the deepest point. */
112
115
  #a = null;
113
116
  /** Per-frame history-reveal directives; `null` when no reveal is in flight. */
114
- #l = null;
117
+ #h = null;
115
118
  /** Loading-indicator placeholder shapes handed over by the chart right
116
119
  * before a prepend (media px relative to `anchorTime`, the data boundary
117
120
  * they were measured against) — mapped into bitmap space each frame and
118
121
  * exposed to the reveal fn as {@link CandleIntroFrame.placeholders}.
119
122
  * Cleared once the reveal settles. */
120
- #m = null;
123
+ #c = null;
121
124
  /** Body gradients keyed by `top|bottom|height` — built once at y=0..h and
122
125
  * positioned per candle via `ctx.translate`, instead of a fresh
123
126
  * `createLinearGradient` for every body on every frame. */
124
- #c = /* @__PURE__ */ new Map();
127
+ #m = /* @__PURE__ */ new Map();
125
128
  constructor(t, i) {
126
- this.store = t, this.options = q({ ...gt, ...i }), this.displayedLast = t.last() ?? null;
129
+ this.store = t, this.options = tt({ ...yt, ...i }), this.displayedLast = t.last() ?? null;
127
130
  }
128
131
  isEntryEnabled() {
129
132
  return (this.options.entryAnimation ?? "unfold") !== "none";
130
133
  }
131
134
  updateOptions(t) {
132
- this.options = q({ ...this.options, ...t });
135
+ this.options = tt({ ...this.options, ...t });
133
136
  }
134
137
  getColor() {
135
138
  return I(this.options.up.body);
@@ -139,13 +142,13 @@ class xt {
139
142
  const i = this.store.length > 0;
140
143
  this.store.setData(J(t ?? [])), !i && this.store.length > 0 && this.introWave.arm(this.options.introMs);
141
144
  const e = this.store.last();
142
- this.displayedLast = e ?? null, this.#t = null, this.entries.clear(), this.#i = null, this.#o.finish(), this.#a = null, this.#m = null;
145
+ this.displayedLast = e ?? null, this.#t = null, this.entries.clear(), this.#i = null, this.#o.finish(), this.#a = null, this.#c = null;
143
146
  }
144
147
  appendPoint(t) {
145
148
  const i = t, e = Q(i.time), o = { ...i, time: e };
146
149
  this.store.append(o), this.displayedLast = o, this.#t = null;
147
- const a = this.options.entryMs;
148
- this.isEntryEnabled() && a > 0 && this.entries.set(e, { startTime: performance.now() });
150
+ const h = this.options.entryMs;
151
+ this.isEntryEnabled() && h > 0 && this.entries.set(e, { startTime: performance.now() });
149
152
  }
150
153
  prependPoints(t) {
151
154
  if (t.length === 0) return;
@@ -169,22 +172,22 @@ class xt {
169
172
  }
170
173
  setHistoryHandoff(t) {
171
174
  const i = this.store.first()?.time;
172
- i !== void 0 && (this.#m = { bars: t, anchorTime: i });
175
+ i !== void 0 && (this.#c = { bars: t, anchorTime: i });
173
176
  }
174
177
  updateLastPoint(t) {
175
178
  const i = t, e = Q(i.time), o = { ...i, time: e };
176
179
  this.store.updateLast(o);
177
- const a = this.options.smoothMs;
178
- if (a <= 0) {
180
+ const h = this.options.smoothMs;
181
+ if (h <= 0) {
179
182
  this.displayedLast = o, this.#t = null;
180
183
  return;
181
184
  }
182
- let s = this.#t;
183
- if (s === null) {
184
- const u = this.displayedLast ?? o;
185
- s = new dt(u), this.#t = s;
185
+ let n = this.#t;
186
+ if (n === null) {
187
+ const l = this.displayedLast ?? o;
188
+ n = new ft(l), this.#t = n;
186
189
  }
187
- s.retarget(o, { settleMs: a });
190
+ n.retarget(o, { settleMs: h });
188
191
  }
189
192
  keepLast(t) {
190
193
  if (t < 0) return;
@@ -220,7 +223,7 @@ class xt {
220
223
  * fully-settled entrance entries. Called from `render()` once per frame.
221
224
  */
222
225
  tickAnimations(t) {
223
- this.introWave.tick(t), this.#o.tick(t), this.#o.active || (this.#m = null), this.#e.tick(t);
226
+ this.introWave.tick(t), this.#o.tick(t), this.#o.active || (this.#c = null), this.#e.tick(t);
224
227
  const i = this.#t;
225
228
  if (i !== null) {
226
229
  const o = i.tick(t);
@@ -231,8 +234,8 @@ class xt {
231
234
  this.entries.clear();
232
235
  return;
233
236
  }
234
- for (const [o, a] of this.entries)
235
- t - a.startTime >= e && this.entries.delete(o);
237
+ for (const [o, h] of this.entries)
238
+ t - h.startTime >= e && this.entries.delete(o);
236
239
  }
237
240
  /** True while OHLC chase, any per-candle entrance, the initial reveal,
238
241
  * alpha fade, or the volume scale is unsettled. */
@@ -279,134 +282,134 @@ class xt {
279
282
  getVisibleDataPoints(t, i) {
280
283
  return this.store.getVisibleData(t, i);
281
284
  }
282
- getValueRange(t, i) {
283
- const e = this.store.getVisibleData(t, i);
284
- let o = 1 / 0, a = -1 / 0;
285
- for (const s of e)
286
- Number.isFinite(s.low) && s.low < o && (o = s.low), Number.isFinite(s.high) && s.high > a && (a = s.high);
287
- return o === 1 / 0 || a === -1 / 0 ? null : { min: o, max: a };
285
+ getValueRange(t, i, e) {
286
+ const o = this.store.getVisibleData(t, i), h = e?.plottable;
287
+ let n = 1 / 0, l = -1 / 0;
288
+ for (const p of o)
289
+ h && !q(p, h) || (Number.isFinite(p.low) && p.low < n && (n = p.low), Number.isFinite(p.high) && p.high > l && (l = p.high));
290
+ return n === 1 / 0 || l === -1 / 0 ? null : { min: n, max: l };
288
291
  }
289
292
  render(t) {
290
293
  this.tickAnimations(performance.now());
291
- const { scope: i, timeScale: e, yScale: o, dataInterval: a } = t, { context: s, horizontalPixelRatio: u } = i, y = e.getRange();
292
- let m = this.store.getVisibleData(y.from, y.to);
293
- const b = i.mediaSize.width, w = m.length > b * 2;
294
- if (w && (m = at(m, Math.round(b * 1.5))), m.length === 0) return;
294
+ const { scope: i, timeScale: e, yScale: o, dataInterval: h } = t, { context: n, horizontalPixelRatio: l } = i, p = e.getRange();
295
+ let m = this.store.getVisibleData(p.from, p.to);
296
+ const Y = i.mediaSize.width, M = m.length > Y * 2;
297
+ if (M && (m = rt(m, Math.round(Y * 1.5))), o.getTransform() !== null && (m = m.filter((r) => q(r, (c) => o.isPlottable(c)))), m.length === 0) return;
295
298
  const S = this.displayedLast;
296
- if (!w && S !== null) {
299
+ if (!M && S !== null) {
297
300
  const r = m.length - 1;
298
301
  m[r].time === S.time && (m = [...m.slice(0, r), S]);
299
302
  }
300
- if (this.#n = null, this.#h = null, this.introWave.active) {
301
- const r = this.options.introAnimation ?? bt;
302
- this.#h = y, this.#n = r({
303
+ if (this.#n = null, this.#l = null, this.introWave.active) {
304
+ const r = this.options.introAnimation ?? Yt;
305
+ this.#l = p, this.#n = r({
303
306
  progress: this.introWave.linear(),
304
307
  // Plot-area extent, not the canvas bitmap — the canvas also carries
305
308
  // the axis strips, so a width-based front (wipeIntro) would overshoot
306
309
  // the data area.
307
310
  width: e.getMediaWidth() * i.horizontalPixelRatio,
308
311
  height: o.getMediaHeight() * i.verticalPixelRatio,
309
- range: y,
310
- timeToX: (l) => e.timeToBitmapX(l)
312
+ range: p,
313
+ timeToX: (c) => e.timeToBitmapX(c)
311
314
  });
312
315
  }
313
- this.#l = null;
314
- const c = this.#a;
315
- if (this.#o.active && c !== null) {
316
- const r = this.options.historyReveal ?? Yt;
316
+ this.#h = null;
317
+ const u = this.#a;
318
+ if (this.#o.active && u !== null) {
319
+ const r = this.options.historyReveal ?? gt;
317
320
  if (r !== "none") {
318
- let l;
319
- const x = this.#m;
321
+ let c;
322
+ const x = this.#c;
320
323
  if (x !== null && x.bars.length > 0) {
321
324
  const P = e.timeToBitmapX(x.anchorTime);
322
- l = x.bars.map((k) => ({
325
+ c = x.bars.map((k) => ({
323
326
  x: P - k.offsetX * i.horizontalPixelRatio,
324
327
  y: k.y * i.verticalPixelRatio,
325
328
  halfHeight: k.halfHeight * i.verticalPixelRatio,
326
329
  width: k.width * i.horizontalPixelRatio
327
330
  }));
328
331
  }
329
- this.#l = r({
332
+ this.#h = r({
330
333
  progress: this.#o.linear(),
331
- width: Math.abs(e.timeToBitmapX(c.to) - e.timeToBitmapX(c.from)),
334
+ width: Math.abs(e.timeToBitmapX(u.to) - e.timeToBitmapX(u.from)),
332
335
  height: o.getMediaHeight() * i.verticalPixelRatio,
333
- range: c,
336
+ range: u,
334
337
  timeToX: (P) => e.timeToBitmapX(P),
335
- placeholders: l
338
+ placeholders: c
336
339
  });
337
340
  }
338
341
  }
339
342
  let W = null;
340
343
  if (this.entries.size > 0) {
341
- const r = this.options.entryMs, l = performance.now();
344
+ const r = this.options.entryMs, c = performance.now();
342
345
  for (const x of m) {
343
346
  const P = this.entries.get(x.time);
344
347
  if (P === void 0 || r <= 0) continue;
345
- const k = l - P.startTime, $ = Math.min(1, Math.max(0, k / r));
346
- $ >= 1 || (W === null && (W = /* @__PURE__ */ new Map()), W.set(x.time, nt($)));
348
+ const k = c - P.startTime, V = Math.min(1, Math.max(0, k / r));
349
+ V >= 1 || (W === null && (W = /* @__PURE__ */ new Map()), W.set(x.time, at(V)));
347
350
  }
348
351
  }
349
- const X = e.barWidthBitmap(a), f = Math.round(30 * u), M = m.length <= 2 ? Math.min(f, X) : X, d = Math.max(1, Math.round(u));
350
- let Y = Math.max(1, Math.round(M * this.options.bodyWidthRatio) - 2);
351
- (Y & 1) !== (d & 1) && (Y = Y > 1 ? Y - 1 : 2);
352
- const R = Math.floor(Y / 2), v = this.#n?.clip;
352
+ const X = e.barWidthBitmap(h), b = Math.round(30 * l), w = m.length <= 2 ? Math.min(b, X) : X, f = Math.max(1, Math.round(l));
353
+ let g = Math.max(1, Math.round(w * this.options.bodyWidthRatio) - 2);
354
+ (g & 1) !== (f & 1) && (g = g > 1 ? g - 1 : 2);
355
+ const R = Math.floor(g / 2), v = this.#n?.clip;
353
356
  if (v !== void 0) {
354
- const r = v.fromX ?? 0, l = v.toX ?? i.bitmapSize.width;
355
- s.save(), s.beginPath(), s.rect(r, 0, Math.max(0, l - r), i.bitmapSize.height), s.clip();
357
+ const r = v.fromX ?? 0, c = v.toX ?? i.bitmapSize.width;
358
+ n.save(), n.beginPath(), n.rect(r, 0, Math.max(0, c - r), i.bitmapSize.height), n.clip();
356
359
  }
357
- const T = this.#l?.clip;
360
+ const T = this.#h?.clip;
358
361
  let A = !1;
359
- if (T !== void 0 && c !== null) {
360
- const r = e.timeToBitmapX(c.to), l = Math.abs(r - e.timeToBitmapX(c.from)), x = M, P = T.fromX ?? 0, k = T.toX ?? l;
361
- s.save(), s.beginPath(), s.rect(r - k - x, 0, Math.max(0, k - P + x), i.bitmapSize.height), s.rect(r, 0, Math.max(0, i.bitmapSize.width - r), i.bitmapSize.height), s.clip(), A = !0;
362
+ if (T !== void 0 && u !== null) {
363
+ const r = e.timeToBitmapX(u.to), c = Math.abs(r - e.timeToBitmapX(u.from)), x = w, P = T.fromX ?? 0, k = T.toX ?? c;
364
+ n.save(), n.beginPath(), n.rect(r - k - x, 0, Math.max(0, k - P + x), i.bitmapSize.height), n.rect(r, 0, Math.max(0, i.bitmapSize.width - r), i.bitmapSize.height), n.clip(), A = !0;
362
365
  }
363
- const n = w !== this.#r;
364
- this.#r = w;
365
- const p = Math.round(o.getMediaHeight() * i.verticalPixelRatio);
366
+ const s = M !== this.#r;
367
+ this.#r = M;
368
+ const d = Math.round(o.getMediaHeight() * i.verticalPixelRatio);
366
369
  this.drawVolume({
367
- ctx: s,
370
+ ctx: n,
368
371
  data: m,
369
372
  timeScale: e,
370
- chartHeight: p,
371
- barWidth: M,
372
- wickWidth: d,
373
+ chartHeight: d,
374
+ barWidth: w,
375
+ wickWidth: f,
373
376
  entranceByTime: W,
374
- snapVolScale: n,
375
- radius: (this.options.cornerRadius ?? O) * u
377
+ snapVolScale: s,
378
+ radius: (this.options.cornerRadius ?? _) * l
376
379
  });
377
- const g = [], L = [], B = [];
380
+ const y = [], L = [], B = [];
378
381
  let C = null;
379
382
  for (let r = 0; r < m.length; r++) {
380
- const l = m[r];
381
- if (N(l.open) || N(l.close) || N(l.high) || N(l.low)) {
382
- B.push(r), C === null && (C = l);
383
+ const c = m[r];
384
+ if (N(c.open) || N(c.close) || N(c.high) || N(c.low)) {
385
+ B.push(r), C === null && (C = c);
383
386
  continue;
384
387
  }
385
- l.close >= l.open ? g.push(l) : L.push(l);
388
+ c.close >= c.open ? y.push(c) : L.push(c);
386
389
  }
387
390
  C !== null && ht(this, "candlestick", B, `time ${C.time}`);
388
391
  const E = {
389
392
  painter: mt(this.options.candlePainter),
390
393
  env: {
391
- ctx: s,
394
+ ctx: n,
392
395
  theme: t.theme,
393
- horizontalPixelRatio: u,
396
+ horizontalPixelRatio: l,
394
397
  verticalPixelRatio: i.verticalPixelRatio
395
398
  },
396
- radius: (this.options.cornerRadius ?? O) * u
399
+ radius: (this.options.cornerRadius ?? _) * l
397
400
  }, D = {
398
- ctx: s,
401
+ ctx: n,
399
402
  timeScale: e,
400
403
  yScale: o,
401
404
  halfBody: R,
402
- bodyWidth: Y,
403
- wickWidth: d,
405
+ bodyWidth: g,
406
+ wickWidth: f,
404
407
  entranceByTime: W,
405
408
  candlePass: E
406
409
  };
407
410
  this.drawCandles({
408
411
  ...D,
409
- candles: g,
412
+ candles: y,
410
413
  body: this.options.up.body,
411
414
  wickColor: this.options.up.wick
412
415
  }), this.drawCandles({
@@ -414,7 +417,7 @@ class xt {
414
417
  candles: L,
415
418
  body: this.options.down.body,
416
419
  wickColor: this.options.down.wick
417
- }), A && s.restore(), v !== void 0 && s.restore();
420
+ }), A && n.restore(), v !== void 0 && n.restore();
418
421
  }
419
422
  /**
420
423
  * Apply the intro's per-element directive to one element's settled (or
@@ -422,15 +425,15 @@ class xt {
422
425
  * is in flight this frame.
423
426
  */
424
427
  introTransform(t) {
425
- const i = this.#l?.element, e = this.#a;
428
+ const i = this.#h?.element, e = this.#a;
426
429
  if (i !== void 0 && e !== null && t.time < e.to) {
427
- const m = e.to - e.from, b = m > 0 ? _((e.to - t.time) / m, 0, 1) : 0, w = i({ ...t, position: b, progress: this.#o.progressAt(b) });
428
- return this.#p(w, t);
430
+ const m = e.to - e.from, Y = m > 0 ? F((e.to - t.time) / m, 0, 1) : 0, M = i({ ...t, position: Y, progress: this.#o.progressAt(Y) });
431
+ return this.#p(M, t);
429
432
  }
430
- const o = this.#n?.element, a = this.#h;
431
- if (o === void 0 || a === null) return null;
432
- const s = a.to - a.from, u = s > 0 ? _((t.time - a.from) / s, 0, 1) : 0, y = o({ ...t, position: u, progress: this.introWave.progressAt(u) });
433
- return this.#p(y, t);
433
+ const o = this.#n?.element, h = this.#l;
434
+ if (o === void 0 || h === null) return null;
435
+ const n = h.to - h.from, l = n > 0 ? F((t.time - h.from) / n, 0, 1) : 0, p = o({ ...t, position: l, progress: this.introWave.progressAt(l) });
436
+ return this.#p(p, t);
434
437
  }
435
438
  /** Map a directive's declarative transform onto the element's settled
436
439
  * geometry. Absolute `topY`/`bottomY` overrides (a morph's arbitrary
@@ -451,65 +454,65 @@ class xt {
451
454
  data: i,
452
455
  timeScale: e,
453
456
  chartHeight: o,
454
- barWidth: a,
455
- wickWidth: s,
456
- entranceByTime: u,
457
- snapVolScale: y,
457
+ barWidth: h,
458
+ wickWidth: n,
459
+ entranceByTime: l,
460
+ snapVolScale: p,
458
461
  radius: m
459
462
  }) {
460
- let b = 0;
461
- for (const d of i)
462
- Number.isFinite(d.volume) && d.volume > b && (b = d.volume);
463
- if (b === 0) {
463
+ let Y = 0;
464
+ for (const f of i)
465
+ Number.isFinite(f.volume) && f.volume > Y && (Y = f.volume);
466
+ if (Y === 0) {
464
467
  this.#i = null, this.#s = !0;
465
468
  return;
466
469
  }
467
- this.#i === null || y ? this.#i = b : this.#i += (b - this.#i) * pt, this.#s = Math.abs(b - this.#i) <= b * ut;
468
- const w = this.#i, S = o * 0.2;
469
- let c = Math.max(1, a - 2);
470
- (c & 1) !== (s & 1) && (c = c > 1 ? c - 1 : 2);
471
- const W = Math.floor(c / 2), X = K(I(this.options.up.body), 0.2), f = K(I(this.options.down.body), 0.2), M = this.options.entryAnimation ?? "unfold";
472
- for (const d of i) {
473
- if (!Number.isFinite(d.volume) || d.volume <= 0) continue;
474
- const Y = d.volume, R = e.timeToBitmapX(d.time), v = Math.min(S, Math.max(1, Y / w * S)), T = d.close >= d.open;
475
- t.fillStyle = T ? X : f;
476
- const A = u?.get(d.time) ?? 1;
477
- let n = { x: R - W, topY: o - v, bottomY: o, alpha: 1 };
478
- if (A < 1 && M !== "none") {
479
- const g = F(A, M, {
480
- x: n.x,
481
- barWidth: c,
470
+ this.#i === null || p ? this.#i = Y : this.#i += (Y - this.#i) * ut, this.#s = Math.abs(Y - this.#i) <= Y * dt;
471
+ const M = this.#i, S = o * 0.2;
472
+ let u = Math.max(1, h - 2);
473
+ (u & 1) !== (n & 1) && (u = u > 1 ? u - 1 : 2);
474
+ const W = Math.floor(u / 2), X = K(I(this.options.up.body), 0.2), b = K(I(this.options.down.body), 0.2), w = this.options.entryAnimation ?? "unfold";
475
+ for (const f of i) {
476
+ if (!Number.isFinite(f.volume) || f.volume <= 0) continue;
477
+ const g = f.volume, R = e.timeToBitmapX(f.time), v = Math.min(S, Math.max(1, g / M * S)), T = f.close >= f.open;
478
+ t.fillStyle = T ? X : b;
479
+ const A = l?.get(f.time) ?? 1;
480
+ let s = { x: R - W, topY: o - v, bottomY: o, alpha: 1 };
481
+ if (A < 1 && w !== "none") {
482
+ const y = O(A, w, {
483
+ x: s.x,
484
+ barWidth: u,
482
485
  anchorY: o,
483
- topY: n.topY,
484
- bottomY: n.bottomY
486
+ topY: s.topY,
487
+ bottomY: s.bottomY
485
488
  });
486
- n = { x: g.x, topY: g.topY, bottomY: g.bottomY, alpha: g.alpha };
489
+ s = { x: y.x, topY: y.topY, bottomY: y.bottomY, alpha: y.alpha };
487
490
  }
488
- const p = this.introTransform({
491
+ const d = this.introTransform({
489
492
  element: "volume",
490
- time: d.time,
491
- x: n.x,
492
- topY: n.topY,
493
- bottomY: n.bottomY,
493
+ time: f.time,
494
+ x: s.x,
495
+ topY: s.topY,
496
+ bottomY: s.bottomY,
494
497
  anchorY: o,
495
- barWidth: c
498
+ barWidth: u
496
499
  });
497
- if (p !== null && (n = { x: p.x, topY: p.topY, bottomY: p.bottomY, alpha: n.alpha * p.alpha }), n.alpha >= 1) {
500
+ if (d !== null && (s = { x: d.x, topY: d.topY, bottomY: d.bottomY, alpha: s.alpha * d.alpha }), s.alpha >= 1) {
498
501
  Z(t, {
499
- x: n.x,
500
- y: n.topY,
501
- width: c,
502
- height: Math.max(1, n.bottomY - n.topY),
502
+ x: s.x,
503
+ y: s.topY,
504
+ width: u,
505
+ height: Math.max(1, s.bottomY - s.topY),
503
506
  radius: m,
504
507
  corners: j
505
508
  });
506
509
  continue;
507
510
  }
508
- t.save(), t.globalAlpha = n.alpha, Z(t, {
509
- x: n.x,
510
- y: n.topY,
511
- width: c,
512
- height: Math.max(1, n.bottomY - n.topY),
511
+ t.save(), t.globalAlpha = s.alpha, Z(t, {
512
+ x: s.x,
513
+ y: s.topY,
514
+ width: u,
515
+ height: Math.max(1, s.bottomY - s.topY),
513
516
  radius: m,
514
517
  corners: j
515
518
  }), t.restore();
@@ -520,85 +523,85 @@ class xt {
520
523
  candles: i,
521
524
  timeScale: e,
522
525
  yScale: o,
523
- halfBody: a,
524
- bodyWidth: s,
525
- wickWidth: u,
526
- body: y,
526
+ halfBody: h,
527
+ bodyWidth: n,
528
+ wickWidth: l,
529
+ body: p,
527
530
  wickColor: m,
528
- entranceByTime: b,
529
- candlePass: w
531
+ entranceByTime: Y,
532
+ candlePass: M
530
533
  }) {
531
534
  if (i.length === 0) return;
532
- const S = this.options.entryAnimation ?? "unfold", c = s + 2, W = w.env.theme.axis.textColor ?? "#787b86";
535
+ const S = this.options.entryAnimation ?? "unfold", u = n + 2, W = M.env.theme.axis.textColor ?? "#787b86";
533
536
  t.fillStyle = m;
534
- for (const f of i) {
535
- const M = b?.get(f.time) ?? 1, d = e.timeToBitmapX(f.time), Y = o.valueToBitmapY(f.open), R = o.valueToBitmapY(f.high), v = o.valueToBitmapY(f.low), T = d - Math.floor(u / 2);
536
- let A = !1, n = { x: T, topY: R, bottomY: v, alpha: 1 };
537
- if (M < 1 && S !== "none") {
538
- const L = F(M, S, {
537
+ for (const b of i) {
538
+ const w = Y?.get(b.time) ?? 1, f = e.timeToBitmapX(b.time), g = o.valueToBitmapY(b.open), R = o.valueToBitmapY(b.high), v = o.valueToBitmapY(b.low), T = f - Math.floor(l / 2);
539
+ let A = !1, s = { x: T, topY: R, bottomY: v, alpha: 1 };
540
+ if (w < 1 && S !== "none") {
541
+ const L = O(w, S, {
539
542
  x: T,
540
- barWidth: c,
541
- anchorY: Y,
543
+ barWidth: u,
544
+ anchorY: g,
542
545
  topY: R,
543
546
  bottomY: v
544
547
  });
545
- n = { x: L.x, topY: L.topY, bottomY: L.bottomY, alpha: L.alpha }, A = !0;
548
+ s = { x: L.x, topY: L.topY, bottomY: L.bottomY, alpha: L.alpha }, A = !0;
546
549
  }
547
- const p = this.introTransform({
550
+ const d = this.introTransform({
548
551
  element: "wick",
549
- time: f.time,
550
- x: n.x,
551
- topY: n.topY,
552
- bottomY: n.bottomY,
553
- anchorY: Y,
554
- barWidth: c
552
+ time: b.time,
553
+ x: s.x,
554
+ topY: s.topY,
555
+ bottomY: s.bottomY,
556
+ anchorY: g,
557
+ barWidth: u
555
558
  });
556
- let g = 0;
557
- if (p !== null && (n = { x: p.x, topY: p.topY, bottomY: p.bottomY, alpha: n.alpha * p.alpha }, g = p.tint ?? 0, A = !0), !A) {
558
- t.fillRect(T, R, u, v - R);
559
+ let y = 0;
560
+ if (d !== null && (s = { x: d.x, topY: d.topY, bottomY: d.bottomY, alpha: s.alpha * d.alpha }, y = d.tint ?? 0, A = !0), !A) {
561
+ t.fillRect(T, R, l, v - R);
559
562
  continue;
560
563
  }
561
- t.save(), t.globalAlpha = n.alpha, g > 0 && (t.fillStyle = G(m, W, g)), t.fillRect(n.x, n.topY, u, Math.max(1, n.bottomY - n.topY)), t.restore();
564
+ t.save(), t.globalAlpha = s.alpha, y > 0 && (t.fillStyle = G(m, W, y)), t.fillRect(s.x, s.topY, l, Math.max(1, s.bottomY - s.topY)), t.restore();
562
565
  }
563
- const X = Array.isArray(y);
564
- for (const f of i) {
565
- const M = b?.get(f.time) ?? 1, d = e.timeToBitmapX(f.time), Y = o.valueToBitmapY(f.open), R = o.valueToBitmapY(f.close), v = Math.min(Y, R), T = Math.max(Y, R), A = Math.max(1, T - v);
566
- let n = d - a, p = v, g = T, L = 1, B = !1;
567
- if (M < 1 && S !== "none") {
568
- const H = F(M, S, {
569
- x: n,
570
- barWidth: c,
571
- anchorY: Y,
566
+ const X = Array.isArray(p);
567
+ for (const b of i) {
568
+ const w = Y?.get(b.time) ?? 1, f = e.timeToBitmapX(b.time), g = o.valueToBitmapY(b.open), R = o.valueToBitmapY(b.close), v = Math.min(g, R), T = Math.max(g, R), A = Math.max(1, T - v);
569
+ let s = f - h, d = v, y = T, L = 1, B = !1;
570
+ if (w < 1 && S !== "none") {
571
+ const H = O(w, S, {
572
+ x: s,
573
+ barWidth: u,
574
+ anchorY: g,
572
575
  topY: v,
573
576
  bottomY: T
574
577
  });
575
- n = H.x, p = H.topY, g = H.bottomY, L = H.alpha, B = !0;
578
+ s = H.x, d = H.topY, y = H.bottomY, L = H.alpha, B = !0;
576
579
  }
577
580
  const C = this.introTransform({
578
581
  element: "body",
579
- time: f.time,
580
- x: n,
581
- topY: p,
582
- bottomY: g,
583
- anchorY: Y,
584
- barWidth: c
582
+ time: b.time,
583
+ x: s,
584
+ topY: d,
585
+ bottomY: y,
586
+ anchorY: g,
587
+ barWidth: u
585
588
  });
586
589
  let E = 0;
587
- C !== null && (n = C.x, p = C.topY, g = C.bottomY, L *= C.alpha, E = C.tint ?? 0, B = !0);
588
- const D = B ? Math.max(1, g - p) : A;
590
+ C !== null && (s = C.x, d = C.topY, y = C.bottomY, L *= C.alpha, E = C.tint ?? 0, B = !0);
591
+ const D = B ? Math.max(1, y - d) : A;
589
592
  B && t.save();
590
- const r = Array.isArray(y) ? y[0] : y, l = E > 0 ? G(r, W, E) : r, x = X && D > 2 && E <= 0, P = x ? this.#d(t, y, D) : l;
591
- t.fillStyle = P, B && (t.globalAlpha = L), x && t.translate(0, p);
592
- const k = x ? 0 : p, $ = _(w.radius, 0, Math.min(s, D) / 2);
593
- $ < 1 && !this.options.candlePainter ? t.fillRect(n, k, s, D) : w.painter(w.env, {
594
- geom: { x: n, y: k, width: s, height: D },
593
+ const r = Array.isArray(p) ? p[0] : p, c = E > 0 ? G(r, W, E) : r, x = X && D > 2 && E <= 0, P = x ? this.#d(t, p, D) : c;
594
+ t.fillStyle = P, B && (t.globalAlpha = L), x && t.translate(0, d);
595
+ const k = x ? 0 : d, V = F(M.radius, 0, Math.min(n, D) / 2);
596
+ V < 1 && !this.options.candlePainter ? t.fillRect(s, k, n, D) : M.painter(M.env, {
597
+ geom: { x: s, y: k, width: n, height: D },
595
598
  fillStyle: P,
596
- color: l,
597
- corners: ft,
598
- radius: $,
599
- progress: M,
600
- isBullish: f.close >= f.open
601
- }), x && t.translate(0, -p), B && t.restore();
599
+ color: c,
600
+ corners: bt,
601
+ radius: V,
602
+ progress: w,
603
+ isBullish: b.close >= b.open
604
+ }), x && t.translate(0, -d), B && t.restore();
602
605
  }
603
606
  }
604
607
  /**
@@ -609,51 +612,51 @@ class xt {
609
612
  * continuously, and a full clear is cheaper than an eviction policy.
610
613
  */
611
614
  #d(t, i, e) {
612
- const o = Math.max(3, Math.round(e)), a = `${i[0]}|${i[1]}|${o}`, s = this.#c.get(a);
613
- if (s !== void 0) return s;
614
- this.#c.size >= 512 && this.#c.clear();
615
- const u = t.createLinearGradient(0, 0, 0, o);
616
- return u.addColorStop(0, i[0]), u.addColorStop(1, i[1]), this.#c.set(a, u), u;
615
+ const o = Math.max(3, Math.round(e)), h = `${i[0]}|${i[1]}|${o}`, n = this.#m.get(h);
616
+ if (n !== void 0) return n;
617
+ this.#m.size >= 512 && this.#m.clear();
618
+ const l = t.createLinearGradient(0, 0, 0, o);
619
+ return l.addColorStop(0, i[0]), l.addColorStop(1, i[1]), this.#m.set(h, l), l;
617
620
  }
618
621
  }
619
- function F(h, t, i) {
622
+ function O(a, t, i) {
620
623
  switch (t) {
621
624
  case "none":
622
625
  return { x: i.x, topY: i.topY, bottomY: i.bottomY, alpha: 1 };
623
626
  case "fade":
624
- return { x: i.x, topY: i.topY, bottomY: i.bottomY, alpha: h };
627
+ return { x: i.x, topY: i.topY, bottomY: i.bottomY, alpha: a };
625
628
  case "unfold":
626
629
  return {
627
630
  x: i.x,
628
- topY: z(i.anchorY, i.topY, h),
629
- bottomY: z(i.anchorY, i.bottomY, h),
631
+ topY: z(i.anchorY, i.topY, a),
632
+ bottomY: z(i.anchorY, i.bottomY, a),
630
633
  alpha: 1
631
634
  };
632
635
  case "slide":
633
636
  return {
634
- x: i.x + (1 - h) * i.barWidth,
637
+ x: i.x + (1 - a) * i.barWidth,
635
638
  topY: i.topY,
636
639
  bottomY: i.bottomY,
637
- alpha: h
640
+ alpha: a
638
641
  };
639
642
  case "fade-unfold":
640
643
  return {
641
644
  x: i.x,
642
- topY: z(i.anchorY, i.topY, h),
643
- bottomY: z(i.anchorY, i.bottomY, h),
644
- alpha: h
645
+ topY: z(i.anchorY, i.topY, a),
646
+ bottomY: z(i.anchorY, i.bottomY, a),
647
+ alpha: a
645
648
  };
646
649
  }
647
650
  }
648
- const Et = {
651
+ const zt = {
649
652
  type: "candlestick",
650
- create: ({ theme: h }, t) => new xt(new rt(), {
651
- up: { ...h.candlestick.up },
652
- down: { ...h.candlestick.down },
653
+ create: ({ theme: a }, t) => new xt(new lt(), {
654
+ up: { ...a.candlestick.up },
655
+ down: { ...a.candlestick.down },
653
656
  ...t
654
657
  })
655
658
  };
656
659
  export {
657
660
  xt as CandlestickRenderer,
658
- Et as CandlestickSeriesDef
661
+ zt as CandlestickSeriesDef
659
662
  };