@wick-charts/vue 0.6.1 → 0.6.3

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 (52) hide show
  1. package/dist/ChartContainer.vue.js +43 -37
  2. package/dist/LineSeries.vue.js +2 -2
  3. package/dist/composables.js +39 -26
  4. package/dist/core/dist/animation/config.js +66 -64
  5. package/dist/core/dist/animation/intro-wave.js +19 -21
  6. package/dist/core/dist/animation/reduced-motion.js +6 -0
  7. package/dist/core/dist/axis/dom-labels.js +58 -45
  8. package/dist/core/dist/chart/badge-animator.js +15 -19
  9. package/dist/core/dist/chart/options.js +5 -5
  10. package/dist/core/dist/chart/scale-guards.js +26 -0
  11. package/dist/core/dist/chart/y-target.js +46 -19
  12. package/dist/core/dist/chart.js +752 -570
  13. package/dist/core/dist/components/crosshair.js +8 -8
  14. package/dist/core/dist/components/grid.js +28 -15
  15. package/dist/core/dist/components/marker.js +28 -28
  16. package/dist/core/dist/components/reference-line.js +16 -16
  17. package/dist/core/dist/interactions/handler.js +3 -2
  18. package/dist/core/dist/interactions/zoom.js +6 -5
  19. package/dist/core/dist/navigator/controller.js +43 -40
  20. package/dist/core/dist/perf/perf-hud.js +3 -3
  21. package/dist/core/dist/scales/log-scale.js +76 -0
  22. package/dist/core/dist/scales/tick-tracker.js +2 -2
  23. package/dist/core/dist/scales/x-scale.js +47 -32
  24. package/dist/core/dist/scales/y-scale.js +155 -38
  25. package/dist/core/dist/series/bar-intro.js +11 -11
  26. package/dist/core/dist/series/bar.js +299 -249
  27. package/dist/core/dist/series/base-multi-layer.js +100 -76
  28. package/dist/core/dist/series/candlestick.js +252 -249
  29. package/dist/core/dist/series/heatmap.js +16 -16
  30. package/dist/core/dist/series/line-intro.js +18 -18
  31. package/dist/core/dist/series/line.js +522 -424
  32. package/dist/core/dist/series/scale-stack.js +25 -0
  33. package/dist/core/dist/tooltip-position.js +5 -5
  34. package/dist/core/dist/utils/pixel-grid.js +10 -0
  35. package/dist/index.d.ts +279 -32
  36. package/dist/index.js +59 -57
  37. package/dist/ui/Crosshair.vue.js +14 -14
  38. package/dist/ui/HeatmapTooltip.vue.js +6 -6
  39. package/dist/ui/PieTooltip.vue.js +4 -4
  40. package/dist/ui/TimeAxis.vue.js +23 -22
  41. package/dist/ui/Tooltip.vue.js +71 -69
  42. package/dist/ui/YAxis.vue.js +25 -24
  43. package/dist/ui/YLabel.vue.js +50 -49
  44. package/package.json +2 -2
  45. package/src/ChartContainer.vue +20 -8
  46. package/src/composables.ts +35 -1
  47. package/src/index.ts +5 -0
  48. package/src/ui/Crosshair.vue +2 -2
  49. package/src/ui/TimeAxis.vue +7 -4
  50. package/src/ui/Tooltip.vue +4 -1
  51. package/src/ui/YAxis.vue +5 -3
  52. package/src/ui/YLabel.vue +3 -3
@@ -1,11 +1,11 @@
1
- function u(m) {
2
- const { scope: x, bitmapX: o, bitmapY: i, theme: M, pane: a } = m, { context: t, bitmapSize: h, horizontalPixelRatio: e, verticalPixelRatio: p } = x, n = o <= a.width, r = i <= a.height;
3
- if (!n && !r) return;
4
- const s = Math.max(1, Math.round(p)), c = Math.max(1, Math.round(e));
5
- t.strokeStyle = M.crosshair.color, t.lineWidth = Math.max(s, c), t.setLineDash([4 * e, 4 * e]);
6
- const l = Math.round(o) + (c % 2 === 1 ? 0.5 : 0), d = Math.round(i) + (s % 2 === 1 ? 0.5 : 0);
7
- t.beginPath(), n && (t.moveTo(l, 0), t.lineTo(l, h.height)), r && (t.moveTo(0, d), t.lineTo(h.width, d)), t.stroke(), t.setLineDash([]);
1
+ function b(M) {
2
+ const { scope: p, bitmapX: e, bitmapY: a, theme: u, pane: i, leftOverhang: h = 0 } = M, { context: t, bitmapSize: n, horizontalPixelRatio: o, verticalPixelRatio: x } = p, r = e >= 0 && e <= i.width, s = a <= i.height;
3
+ if (!r && !s) return;
4
+ const l = Math.max(1, Math.round(x)), c = Math.max(1, Math.round(o));
5
+ t.strokeStyle = u.crosshair.color, t.lineWidth = Math.max(l, c), t.setLineDash([4 * o, 4 * o]);
6
+ const m = Math.round(e) + (c % 2 === 1 ? 0.5 : 0), d = Math.round(a) + (l % 2 === 1 ? 0.5 : 0), v = h > 0 ? -h : 0;
7
+ t.beginPath(), r && (t.moveTo(m, 0), t.lineTo(m, n.height)), s && (t.moveTo(v, d), t.lineTo(n.width, d)), t.stroke(), t.setLineDash([]);
8
8
  }
9
9
  export {
10
- u as renderCrosshair
10
+ b as renderCrosshair
11
11
  };
@@ -1,22 +1,35 @@
1
- function T({ scope: c, timeScale: h, yScale: d, theme: a, yTicks: m, timeTicks: p }) {
2
- const { context: t, bitmapSize: s, horizontalPixelRatio: e, verticalPixelRatio: u } = c;
3
- t.save(), t.strokeStyle = a.grid.color, a.grid.style === "dashed" ? t.setLineDash([4 * e, 4 * e]) : a.grid.style === "dotted" && t.setLineDash([1 * e, 3 * e]);
4
- const l = Math.max(1, Math.round(u)), g = l % 2 === 1 ? 0.5 : 0;
5
- t.lineWidth = l;
6
- for (const { value: n, opacity: o } of m.entries) {
1
+ import { crispLineWidth as d, crispCenterOffset as p } from "../utils/pixel-grid.js";
2
+ function L({
3
+ scope: f,
4
+ timeScale: m,
5
+ yScale: g,
6
+ theme: a,
7
+ yTicks: u,
8
+ timeTicks: v,
9
+ alpha: n = 1,
10
+ leftOverhang: l = 0
11
+ }) {
12
+ if (n <= 0.01) return;
13
+ const { context: e, bitmapSize: c, horizontalPixelRatio: t, verticalPixelRatio: h } = f;
14
+ e.save(), e.strokeStyle = a.grid.color, a.grid.style === "dashed" ? e.setLineDash([4 * t, 4 * t]) : a.grid.style === "dotted" && e.setLineDash([1 * t, 3 * t]);
15
+ const T = d(h), y = p(h), b = l > 0 ? -l : 0;
16
+ e.lineWidth = T;
17
+ for (const { value: r, opacity: s } of u.entries) {
18
+ const o = s * n;
7
19
  if (o <= 0.01) continue;
8
- const i = Math.round(d.valueToBitmapY(n)) + g;
9
- t.globalAlpha = o, t.beginPath(), t.moveTo(0, i), t.lineTo(s.width, i), t.stroke();
20
+ const i = Math.round(g.valueToBitmapY(r)) + y;
21
+ e.globalAlpha = o, e.beginPath(), e.moveTo(b, i), e.lineTo(c.width, i), e.stroke();
10
22
  }
11
- const r = Math.max(1, Math.round(e)), y = r % 2 === 1 ? 0.5 : 0;
12
- t.lineWidth = r;
13
- for (const { value: n, opacity: o } of p.entries) {
23
+ const k = d(t), P = p(t);
24
+ e.lineWidth = k;
25
+ for (const { value: r, opacity: s } of v.entries) {
26
+ const o = s * n;
14
27
  if (o <= 0.01) continue;
15
- const i = Math.round(h.timeToBitmapX(n)) + y;
16
- t.globalAlpha = o, t.beginPath(), t.moveTo(i, 0), t.lineTo(i, s.height), t.stroke();
28
+ const i = Math.round(m.timeToBitmapX(r)) + P;
29
+ e.globalAlpha = o, e.beginPath(), e.moveTo(i, 0), e.lineTo(i, c.height), e.stroke();
17
30
  }
18
- t.restore();
31
+ e.restore();
19
32
  }
20
33
  export {
21
- T as renderGrid
34
+ L as renderGrid
22
35
  };
@@ -1,56 +1,56 @@
1
1
  import { hexToRgba as g } from "../utils/color.js";
2
2
  import { measureChip as I, drawChip as T, CHIP_TAIL_HEIGHT_MEDIA as S } from "./annotation-chip.js";
3
- const y = 4, H = 5, k = 9, W = 3, C = 4;
3
+ const P = 4, H = 5, k = 9, W = 3, C = 4;
4
4
  function Y(e) {
5
- const { scope: a, timeScale: r, yScale: l, theme: s, marker: t, phase: n, plotWidth: o, plotHeight: p } = e, { context: h, horizontalPixelRatio: i, verticalPixelRatio: d } = a, c = r.timeToBitmapX(t.time), b = l.valueToBitmapY(t.value);
6
- if (!Number.isFinite(c) || !Number.isFinite(b)) return;
7
- const m = y * i, f = t.shape === "arrow-up" || t.shape === "arrow-down", x = t.label !== void 0 && t.label !== "";
8
- h.save(), t.pulse && R({ context: h, bx: c, by: b, color: t.color, radius: m, hpr: i, phase: n }), f && x || _({ context: h, bx: c, by: b, color: t.color, radius: m, hpr: i, vpr: d, shape: t.shape }), t.label !== void 0 && t.label !== "" && A({
5
+ const { scope: l, timeScale: r, yScale: o, theme: s, marker: t, phase: i, plotWidth: a, plotHeight: n } = e, { context: h, horizontalPixelRatio: p, verticalPixelRatio: d } = l, c = r.timeToBitmapX(t.time), b = o.valueToBitmapY(t.value);
6
+ if (!o.isPlottable(t.value) || !Number.isFinite(c) || !Number.isFinite(b)) return;
7
+ const u = P * p, f = t.shape === "arrow-up" || t.shape === "arrow-down", x = t.label !== void 0 && t.label !== "";
8
+ h.save(), t.pulse && R({ context: h, bx: c, by: b, color: t.color, radius: u, hpr: p, phase: i }), f && x || _({ context: h, bx: c, by: b, color: t.color, radius: u, hpr: p, vpr: d, shape: t.shape }), t.label !== void 0 && t.label !== "" && A({
9
9
  context: h,
10
10
  bx: c,
11
11
  by: b,
12
12
  color: t.color,
13
13
  theme: s,
14
- hpr: i,
14
+ hpr: p,
15
15
  vpr: d,
16
16
  label: t.label,
17
17
  shape: t.shape,
18
- plotWidth: o,
19
- plotHeight: p
18
+ plotWidth: a,
19
+ plotHeight: n
20
20
  }), h.restore();
21
21
  }
22
- function R({ context: e, bx: a, by: r, color: l, radius: s, hpr: t, phase: n }) {
23
- const o = 0.4 + 0.6 * Math.abs(Math.sin(n * 2 * Math.PI)), p = s + 4 * t * o;
24
- e.beginPath(), e.arc(a, r, p, 0, Math.PI * 2), e.fillStyle = g(l, o * 0.3), e.fill();
22
+ function R({ context: e, bx: l, by: r, color: o, radius: s, hpr: t, phase: i }) {
23
+ const a = 0.4 + 0.6 * Math.abs(Math.sin(i * 2 * Math.PI)), n = s + 4 * t * a;
24
+ e.beginPath(), e.arc(l, r, n, 0, Math.PI * 2), e.fillStyle = g(o, a * 0.3), e.fill();
25
25
  }
26
- function _({ context: e, bx: a, by: r, color: l, radius: s, hpr: t, vpr: n, shape: o }) {
27
- if (o === "dot") {
28
- e.beginPath(), e.arc(a, r, s, 0, Math.PI * 2), e.fillStyle = l, e.fill();
26
+ function _({ context: e, bx: l, by: r, color: o, radius: s, hpr: t, vpr: i, shape: a }) {
27
+ if (a === "dot") {
28
+ e.beginPath(), e.arc(l, r, s, 0, Math.PI * 2), e.fillStyle = o, e.fill();
29
29
  return;
30
30
  }
31
- if (o === "circle") {
32
- e.beginPath(), e.arc(a, r, s, 0, Math.PI * 2), e.strokeStyle = l, e.lineWidth = Math.max(1, Math.round(1.5 * t)), e.stroke();
31
+ if (a === "circle") {
32
+ e.beginPath(), e.arc(l, r, s, 0, Math.PI * 2), e.strokeStyle = o, e.lineWidth = Math.max(1, Math.round(1.5 * t)), e.stroke();
33
33
  return;
34
34
  }
35
- const p = H * t, h = k * n, i = o === "arrow-down" ? -1 : 1;
36
- e.beginPath(), e.moveTo(a, r), e.lineTo(a - p, r + i * h), e.lineTo(a + p, r + i * h), e.closePath(), e.fillStyle = l, e.fill();
35
+ const n = H * t, h = k * i, p = a === "arrow-down" ? -1 : 1;
36
+ e.beginPath(), e.moveTo(l, r), e.lineTo(l - n, r + p * h), e.lineTo(l + n, r + p * h), e.closePath(), e.fillStyle = o, e.fill();
37
37
  }
38
38
  function A(e) {
39
- const { context: a, bx: r, by: l, color: s, theme: t, hpr: n, vpr: o, label: p, shape: h, plotWidth: i, plotHeight: d } = e, { width: c, height: b } = I({ context: a, theme: t, label: p, hpr: n, vpr: o }), m = S * o, f = C * n, x = h === "arrow-up" || h === "arrow-down" ? 0 : (y + W) * o, v = x + m + b;
40
- let u = h !== "arrow-up";
41
- u && l - v < 0 && (u = !1), !u && l + v > d && (u = !0);
42
- const w = u ? l - x : l + x, M = u ? w - m - b : w + m, P = Math.max(f, Math.min(r - c / 2, i - c - f));
39
+ const { context: l, bx: r, by: o, color: s, theme: t, hpr: i, vpr: a, label: n, shape: h, plotWidth: p, plotHeight: d } = e, { width: c, height: b } = I({ context: l, theme: t, label: n, hpr: i, vpr: a }), u = S * a, f = C * i, x = h === "arrow-up" || h === "arrow-down" ? 0 : (P + W) * a, v = x + u + b;
40
+ let m = h !== "arrow-up";
41
+ m && o - v < 0 && (m = !1), !m && o + v > d && (m = !0);
42
+ const w = m ? o - x : o + x, y = m ? w - u - b : w + u, M = Math.max(f, Math.min(r - c / 2, p - c - f));
43
43
  T({
44
- context: a,
44
+ context: l,
45
45
  theme: t,
46
46
  color: s,
47
- label: p,
48
- x: P,
49
- y: M,
47
+ label: n,
48
+ x: M,
49
+ y,
50
50
  width: c,
51
51
  height: b,
52
- hpr: n,
53
- vpr: o,
52
+ hpr: i,
53
+ vpr: a,
54
54
  tail: { tipX: r, tipY: w }
55
55
  });
56
56
  }
@@ -1,38 +1,38 @@
1
- import { measureChip as T, drawChip as b } from "./annotation-chip.js";
1
+ import { measureChip as f, drawChip as M } from "./annotation-chip.js";
2
2
  const v = 4, x = 6;
3
- function S(c) {
4
- const { scope: m, timeScale: r, yScale: d, theme: p, line: o, plotWidth: a, plotHeight: h } = c, { context: e, horizontalPixelRatio: n, verticalPixelRatio: s } = m;
3
+ function S(m) {
4
+ const { scope: d, timeScale: r, yScale: s, theme: p, line: o, plotWidth: a, plotHeight: l } = m, { context: e, horizontalPixelRatio: n, verticalPixelRatio: c } = d;
5
5
  if (e.save(), e.strokeStyle = o.color, o.style === "dashed" && e.setLineDash([v * n, v * n]), o.orientation === "horizontal") {
6
- const t = d.valueToBitmapY(o.coord);
7
- if (!Number.isFinite(t) || t < 0 || t > h) {
6
+ const t = s.valueToBitmapY(o.coord);
7
+ if (!s.isPlottable(o.coord) || !Number.isFinite(t) || t < 0 || t > l) {
8
8
  e.restore();
9
9
  return;
10
10
  }
11
- const l = Math.max(1, Math.round(o.width * s)), i = Math.round(t) + (l % 2 === 1 ? 0.5 : 0);
12
- e.lineWidth = l, e.beginPath(), e.moveTo(0, i), e.lineTo(a, i), e.stroke();
11
+ const h = Math.max(1, Math.round(o.width * c)), i = Math.round(t) + (h % 2 === 1 ? 0.5 : 0);
12
+ e.lineWidth = h, e.beginPath(), e.moveTo(0, i), e.lineTo(a, i), e.stroke();
13
13
  } else {
14
14
  const t = r.timeToBitmapX(o.coord);
15
15
  if (!Number.isFinite(t) || t < 0 || t > a) {
16
16
  e.restore();
17
17
  return;
18
18
  }
19
- const l = Math.max(1, Math.round(o.width * n)), i = Math.round(t) + (l % 2 === 1 ? 0.5 : 0);
20
- e.lineWidth = l, e.beginPath(), e.moveTo(i, 0), e.lineTo(i, h), e.stroke();
19
+ const h = Math.max(1, Math.round(o.width * n)), i = Math.round(t) + (h % 2 === 1 ? 0.5 : 0);
20
+ e.lineWidth = h, e.beginPath(), e.moveTo(i, 0), e.lineTo(i, l), e.stroke();
21
21
  }
22
- e.setLineDash([]), o.label !== void 0 && M({ context: e, theme: p, line: o, timeScale: r, yScale: d, plotWidth: a, hpr: n, vpr: s }), e.restore();
22
+ e.setLineDash([]), o.label !== void 0 && T({ context: e, theme: p, line: o, timeScale: r, yScale: s, plotWidth: a, hpr: n, vpr: c }), e.restore();
23
23
  }
24
- function M({ context: c, theme: m, line: r, timeScale: d, yScale: p, plotWidth: o, hpr: a, vpr: h }) {
24
+ function T({ context: m, theme: d, line: r, timeScale: s, yScale: p, plotWidth: o, hpr: a, vpr: l }) {
25
25
  const e = r.label;
26
26
  if (e === void 0) return;
27
- const { width: n, height: s } = T({ context: c, theme: m, label: e, hpr: a, vpr: h }), t = x * a, l = x * h;
27
+ const { width: n, height: c } = f({ context: m, theme: d, label: e, hpr: a, vpr: l }), t = x * a, h = x * l;
28
28
  let i, u;
29
29
  if (r.orientation === "horizontal")
30
- i = t, u = p.valueToBitmapY(r.coord) - s / 2;
30
+ i = t, u = p.valueToBitmapY(r.coord) - c / 2;
31
31
  else {
32
- const f = d.timeToBitmapX(r.coord);
33
- i = Math.min(f + t, o - n - t), u = l;
32
+ const b = s.timeToBitmapX(r.coord);
33
+ i = Math.min(b + t, o - n - t), u = h;
34
34
  }
35
- b({ context: c, theme: m, color: r.color, label: e, x: i, y: u, width: n, height: s, hpr: a, vpr: h });
35
+ M({ context: m, theme: d, color: r.color, label: e, x: i, y: u, width: n, height: c, hpr: a, vpr: l });
36
36
  }
37
37
  export {
38
38
  S as renderReferenceLine
@@ -82,7 +82,7 @@ class T extends a {
82
82
  else if (e.touches.length === 2) {
83
83
  const t = i(e.touches[0], e.touches[1]), s = (e.touches[0].clientX + e.touches[1].clientX) / 2, n = this.canvas.getBoundingClientRect();
84
84
  if (t > 0 && this.lastTouchDist > 0) {
85
- const h = l(this.lastTouchDist / t, 0.1, 10), c = this.timeScale.xToTime(s - n.left);
85
+ const h = l(this.lastTouchDist / t, 0.1, 10), c = this.timeScale.xToTime(s - n.left - (this.target.plotLeft ?? 0));
86
86
  this.target.zoomAt(c, h, this.timeScale.getMediaWidth());
87
87
  }
88
88
  this.lastTouchDist = t;
@@ -105,10 +105,11 @@ class T extends a {
105
105
  this.pan.handleMouseUp(), this.touchCount = 0, this.lastTouchDist = 0, this.downClient = null, this.gestureHadTwoFingers = !1, this.emit("crosshairMove", null);
106
106
  };
107
107
  posFromOffset(e, t) {
108
+ const s = e - (this.target.plotLeft ?? 0);
108
109
  return {
109
110
  mediaX: e,
110
111
  mediaY: t,
111
- time: this.timeScale.xToTime(e),
112
+ time: this.timeScale.xToTime(s),
112
113
  y: this.yScale.yToValue(t)
113
114
  };
114
115
  }
@@ -1,11 +1,12 @@
1
- class s {
1
+ import { clamp as s } from "../utils/math.js";
2
+ class c {
2
3
  constructor(e, a) {
3
4
  this.target = e, this.timeScale = a;
4
5
  }
5
6
  handleWheel(e) {
6
7
  e.preventDefault();
7
- const a = l(e.deltaY, e.deltaMode), i = Math.exp(a * 5e-3), n = this.timeScale.getMediaWidth(), o = Math.min(e.offsetX, n), h = this.timeScale.xToTime(o);
8
- this.target.zoomAt(h, i, n);
8
+ const a = r(e.deltaY, e.deltaMode), i = Math.exp(a * 5e-3), o = this.timeScale.getMediaWidth(), l = s(e.offsetX - (this.target.plotLeft ?? 0), 0, o), n = this.timeScale.xToTime(l);
9
+ this.target.zoomAt(n, i, o);
9
10
  }
10
11
  /** Kept for API parity with InteractionHandler.destroy. Phase 2 step 2
11
12
  * removed the wheel-idle rebound timer alongside the rest of the
@@ -13,9 +14,9 @@ class s {
13
14
  cancelPendingRebound() {
14
15
  }
15
16
  }
16
- function l(t, e) {
17
+ function r(t, e) {
17
18
  return e === WheelEvent.DOM_DELTA_LINE ? t * 8 : e === WheelEvent.DOM_DELTA_PAGE ? t * 24 : t;
18
19
  }
19
20
  export {
20
- s as ZoomHandler
21
+ c as ZoomHandler
21
22
  };
@@ -2,8 +2,8 @@ import { DEFAULT_LINE_ENTRY as w } from "../animation/config.js";
2
2
  import { XScale as T } from "../scales/x-scale.js";
3
3
  import { YScale as R } from "../scales/y-scale.js";
4
4
  import { decimateCandles as k, decimateLinear as C } from "./decimate.js";
5
- import { hitTest as y, computeSnapCenter as E, computePan as I, computeResize as M } from "./interactions.js";
6
- import { computeWindowGeometry as $, renderBackground as V, renderMiniCandlestick as L, renderMiniBar as N, renderMiniLine as P } from "./render.js";
5
+ import { hitTest as b, computeSnapCenter as E, computePan as I, computeResize as $ } from "./interactions.js";
6
+ import { computeWindowGeometry as M, renderBackground as L, renderMiniCandlestick as V, renderMiniBar as N, renderMiniLine as P } from "./render.js";
7
7
  import { Animator as S } from "../animation/animator.js";
8
8
  import { easeOutCubic as z } from "../animation/easing.js";
9
9
  class G {
@@ -11,7 +11,7 @@ class G {
11
11
  #t;
12
12
  #z;
13
13
  #e;
14
- #o;
14
+ #n;
15
15
  #d;
16
16
  #r;
17
17
  #l;
@@ -25,7 +25,7 @@ class G {
25
25
  #F = new R();
26
26
  #A = 0;
27
27
  #m = 0;
28
- #n = 1;
28
+ #h = 1;
29
29
  #p = null;
30
30
  /** A full canvas render is owed. A queued frame with `#dirty === false`
31
31
  * came from {@link #markWindowDirty} and only repositions the window DOM. */
@@ -45,7 +45,7 @@ class G {
45
45
  *
46
46
  * `null` means "no entrance in flight, draw the tail at full alpha".
47
47
  */
48
- #h = null;
48
+ #o = null;
49
49
  /** `time` of the last point we've ever seen — initialises after the first
50
50
  * `setData`/render so the first paint doesn't trigger a fade-in. */
51
51
  #k = null;
@@ -58,32 +58,32 @@ class G {
58
58
  #g = null;
59
59
  // Bound listeners so we can remove the same references on destroy.
60
60
  #I;
61
- #M;
62
61
  #$;
63
- #V;
62
+ #M;
64
63
  #L;
65
- #b;
64
+ #V;
65
+ #y;
66
66
  #N;
67
67
  constructor(t) {
68
68
  this.#s = t.container, this.#e = t.chart, this.#x = t.data, this.#v = t.options ?? {}, window.getComputedStyle(this.#s).position === "static" && (this.#s.style.position = "relative"), this.#t = document.createElement("canvas"), this.#t.style.position = "absolute", this.#t.style.left = "0", this.#t.style.top = "0", this.#t.style.height = "100%", this.#t.style.touchAction = "none", this.#s.appendChild(this.#t);
69
69
  const e = this.#t.getContext("2d", { alpha: !0 });
70
70
  if (!e) throw new Error("NavigatorController: failed to acquire 2D context");
71
- this.#z = e, this.#o = document.createElement("div"), this.#o.dataset.chartNavigatorOverlay = "", this.#o.style.cssText = "position:absolute;left:0;top:0;height:100%;pointer-events:none;", this.#d = document.createElement("div"), this.#d.style.cssText = "position:absolute;left:0;top:0;bottom:0;", this.#r = document.createElement("div"), this.#r.style.cssText = "position:absolute;top:0;bottom:0;", this.#l = document.createElement("div"), this.#l.style.cssText = "position:absolute;top:0;bottom:0;box-sizing:border-box;", this.#a = b(), this.#c = b(), this.#o.append(this.#d, this.#r, this.#l, this.#a, this.#c), this.#s.appendChild(this.#o), this.#I = () => this.#B(), this.#M = () => this.#f(), this.#$ = () => this.#B(), this.#e.on("viewportChange", this.#I), this.#e.on("overlayChange", this.#M), this.#e.on("tickFrame", this.#$), this.#V = (s) => this.#H(s), this.#L = (s) => this.#J(s), this.#b = (s) => this.#K(s), this.#N = () => {
71
+ this.#z = e, this.#n = document.createElement("div"), this.#n.dataset.chartNavigatorOverlay = "", this.#n.style.cssText = "position:absolute;left:0;top:0;height:100%;pointer-events:none;", this.#d = document.createElement("div"), this.#d.style.cssText = "position:absolute;left:0;top:0;bottom:0;", this.#r = document.createElement("div"), this.#r.style.cssText = "position:absolute;top:0;bottom:0;", this.#l = document.createElement("div"), this.#l.style.cssText = "position:absolute;top:0;bottom:0;box-sizing:border-box;", this.#a = y(), this.#c = y(), this.#n.append(this.#d, this.#r, this.#l, this.#a, this.#c), this.#s.appendChild(this.#n), this.#I = () => this.#B(), this.#$ = () => this.#f(), this.#M = () => this.#B(), this.#e.on("viewportChange", this.#I), this.#e.on("overlayChange", this.#$), this.#e.on("tickFrame", this.#M), this.#L = (s) => this.#U(s), this.#V = (s) => this.#J(s), this.#y = (s) => this.#K(s), this.#N = () => {
72
72
  this.#g === null && (this.#t.style.cursor = "default");
73
- }, this.#t.addEventListener("pointerdown", this.#V), this.#t.addEventListener("pointermove", this.#L), this.#t.addEventListener("pointerup", this.#b), this.#t.addEventListener("pointercancel", this.#b), this.#t.addEventListener("pointerleave", this.#N), this.#E = new ResizeObserver((s) => this.#U(s[0])), this.#E.observe(this.#s), this.#D();
73
+ }, this.#t.addEventListener("pointerdown", this.#L), this.#t.addEventListener("pointermove", this.#V), this.#t.addEventListener("pointerup", this.#y), this.#t.addEventListener("pointercancel", this.#y), this.#t.addEventListener("pointerleave", this.#N), this.#E = new ResizeObserver((s) => this.#j(s[0])), this.#E.observe(this.#s), this.#D();
74
74
  const i = this.#s.getBoundingClientRect();
75
75
  i.width > 0 && i.height > 0 && this.#W(i.width, i.height), this.#f();
76
76
  }
77
77
  setData(t) {
78
78
  const e = F(t), i = e?.time ?? null;
79
79
  if (i !== null && this.#k !== null && i !== this.#k) {
80
- const s = this.#h?.current ?? 0;
81
- this.#h = new S({
80
+ const s = this.#o?.current ?? 0;
81
+ this.#o = new S({
82
82
  initial: s,
83
83
  duration: w,
84
84
  easing: z,
85
85
  lerp: (n, h, l) => n + (h - n) * l
86
- }), this.#h.setTarget(1);
86
+ }), this.#o.setTarget(1);
87
87
  }
88
88
  this.#k = i, this.#C = e?.seriesIndex ?? -1, this.#x = t, this.#R.clear(), this.#f();
89
89
  }
@@ -100,7 +100,7 @@ class G {
100
100
  t !== void 0 && (this.#s.style.height = `${t}px`);
101
101
  }
102
102
  destroy() {
103
- this.#e.off("viewportChange", this.#I), this.#e.off("overlayChange", this.#M), this.#e.off("tickFrame", this.#$), this.#t.removeEventListener("pointerdown", this.#V), this.#t.removeEventListener("pointermove", this.#L), this.#t.removeEventListener("pointerup", this.#b), this.#t.removeEventListener("pointercancel", this.#b), this.#t.removeEventListener("pointerleave", this.#N), this.#E.disconnect(), this.#p !== null && (cancelAnimationFrame(this.#p), this.#p = null), this.#t.remove(), this.#o.remove();
103
+ this.#e.off("viewportChange", this.#I), this.#e.off("overlayChange", this.#$), this.#e.off("tickFrame", this.#M), this.#t.removeEventListener("pointerdown", this.#L), this.#t.removeEventListener("pointermove", this.#V), this.#t.removeEventListener("pointerup", this.#y), this.#t.removeEventListener("pointercancel", this.#y), this.#t.removeEventListener("pointerleave", this.#N), this.#E.disconnect(), this.#p !== null && (cancelAnimationFrame(this.#p), this.#p = null), this.#t.remove(), this.#n.remove();
104
104
  }
105
105
  /** CSS pixel height of the strip — theme default unless overridden. */
106
106
  get height() {
@@ -108,17 +108,18 @@ class G {
108
108
  }
109
109
  // --- internals ---------------------------------------------------------
110
110
  /** Effective drawing width — the navigator reserves the main chart's
111
- * `yAxisWidth` on the right so its active zone lines up with the plot area. */
111
+ * `yAxisWidth` on the Y-axis side so its active zone lines up with the
112
+ * plot area. */
112
113
  get #i() {
113
114
  return Math.max(0, this.#A - this.#e.yAxisWidth);
114
115
  }
115
- #U(t) {
116
+ #j(t) {
116
117
  if (!t) return;
117
118
  const e = t.contentBoxSize?.[0], i = e?.inlineSize ?? t.contentRect.width, s = e?.blockSize ?? t.contentRect.height;
118
119
  i <= 0 || s <= 0 || (this.#W(i, s), this.#f());
119
120
  }
120
121
  #W(t, e) {
121
- this.#A = t, this.#m = e, this.#n = window.devicePixelRatio || 1, this.#X();
122
+ this.#A = t, this.#m = e, this.#h = window.devicePixelRatio || 1, this.#X();
122
123
  }
123
124
  /**
124
125
  * Write canvas backing-store / CSS sizes only when they actually changed —
@@ -127,10 +128,12 @@ class G {
127
128
  * a repaint where nothing resized.
128
129
  */
129
130
  #X() {
130
- const t = Math.round(this.#i * this.#n), e = Math.round(this.#m * this.#n);
131
+ const t = Math.round(this.#i * this.#h), e = Math.round(this.#m * this.#h);
131
132
  this.#t.width !== t && (this.#t.width = t), this.#t.height !== e && (this.#t.height = e);
132
133
  const i = `${this.#i}px`;
133
- this.#t.style.width !== i && (this.#t.style.width = i, this.#o.style.width = i);
134
+ this.#t.style.width !== i && (this.#t.style.width = i, this.#n.style.width = i);
135
+ const s = `${this.#e.plotLeft}px`;
136
+ this.#t.style.left !== s && (this.#t.style.left = s, this.#n.style.left = s);
134
137
  }
135
138
  #f() {
136
139
  this.#T = !0, this.#O();
@@ -156,8 +159,8 @@ class G {
156
159
  * the first RAF-driven render — pointer handlers rely on this so hit-tests
157
160
  * compute against primed scales even on the opening gesture. */
158
161
  #P() {
159
- const t = this.#y(), e = this.#Z();
160
- return this.#u.update(t, this.#i, this.#n), this.#F.update(e, this.#m, this.#n), { xRange: t, yRange: e };
162
+ const t = this.#b(), e = this.#Z();
163
+ return this.#u.update(t, this.#i, this.#h), this.#F.update(e, this.#m, this.#h), { xRange: t, yRange: e };
161
164
  }
162
165
  /**
163
166
  * X range for the brush window. While the user drags the brush we track the
@@ -169,17 +172,17 @@ class G {
169
172
  return this.#g !== null ? this.#e.getVisibleRange() : this.#e.getAnimationState().xRange;
170
173
  }
171
174
  #S() {
172
- return this.#P(), $(this.#u, this.#Y(), this.#y());
175
+ return this.#P(), M(this.#u, this.#Y(), this.#b());
173
176
  }
174
- #j() {
175
- const t = this.#y(), e = t.to - t.from;
177
+ #H() {
178
+ const t = this.#b(), e = t.to - t.from;
176
179
  return e <= 0 || this.#i <= 0 ? 0 : this.#i / e;
177
180
  }
178
- #H(t) {
181
+ #U(t) {
179
182
  if (t.button !== void 0 && t.button !== 0) return;
180
- const e = this.#w(t), i = this.#y();
183
+ const e = this.#w(t), i = this.#b();
181
184
  if (i.to <= i.from) return;
182
- const s = this.#S(), n = y(e, s), h = this.#j();
185
+ const s = this.#S(), n = b(e, s), h = this.#H();
183
186
  if (h === 0) return;
184
187
  let l = this.#e.getVisibleRange();
185
188
  if (n.snapToCenter) {
@@ -205,7 +208,7 @@ class G {
205
208
  return;
206
209
  }
207
210
  if (t.pointerId !== e.pointerId) return;
208
- const i = this.#w(t) - e.startX, s = this.#y();
211
+ const i = this.#w(t) - e.startX, s = this.#b();
209
212
  let n;
210
213
  if (e.gesture === "pan")
211
214
  n = I({
@@ -216,7 +219,7 @@ class G {
216
219
  });
217
220
  else {
218
221
  const h = e.gesture === "resize-left" ? "left" : "right";
219
- n = M({
222
+ n = $({
220
223
  edge: h,
221
224
  startVisible: e.startVisible,
222
225
  deltaPx: i,
@@ -237,7 +240,7 @@ class G {
237
240
  const t = this.#e.getTheme().navigator, { xRange: e } = this.#P();
238
241
  this.#X();
239
242
  const i = this.#z, s = this.#t.width, n = this.#t.height;
240
- i.save(), i.clearRect(0, 0, s, n), i.scale(this.#n, this.#n);
243
+ i.save(), i.clearRect(0, 0, s, n), i.scale(this.#h, this.#h);
241
244
  const h = {
242
245
  ctx: i,
243
246
  timeScale: this.#u,
@@ -246,12 +249,12 @@ class G {
246
249
  mediaHeight: this.#m,
247
250
  theme: t
248
251
  };
249
- this.#t.style.boxShadow = `inset 0 1px 0 ${t.borderColor}, inset 0 -1px 0 ${t.borderColor}`, V(h);
252
+ this.#t.style.boxShadow = `inset 0 1px 0 ${t.borderColor}, inset 0 -1px 0 ${t.borderColor}`, L(h);
250
253
  let l = 1;
251
- this.#h !== null && (this.#h.tick(performance.now()), l = this.#h.current, this.#h.animating ? this.#f() : this.#h = null);
254
+ this.#o !== null && (this.#o.tick(performance.now()), l = this.#o.current, this.#o.animating ? this.#f() : this.#o = null);
252
255
  const r = Math.max(1, Math.round(this.#i)), a = this.#x;
253
256
  if (a.type === "candlestick")
254
- L(h, this.#q(a.points, r, k), l);
257
+ V(h, this.#q(a.points, r, k), l);
255
258
  else {
256
259
  const c = f(a), g = c.length === 1, d = this.#C >= 0 ? this.#C : c.length - 1;
257
260
  for (let u = 0; u < c.length; u++) {
@@ -269,13 +272,13 @@ class G {
269
272
  */
270
273
  #Q() {
271
274
  if (this.#i <= 0 || this.#m <= 0) return;
272
- const t = Math.round(this.#i * this.#n);
273
- if (this.#t.width !== t) {
275
+ const t = Math.round(this.#i * this.#h), e = this.#t.style.left !== `${this.#e.plotLeft}px`;
276
+ if (this.#t.width !== t || e) {
274
277
  this.#_();
275
278
  return;
276
279
  }
277
- const e = this.#e.getTheme().navigator, { xRange: i } = this.#P();
278
- this.#G(e, i);
280
+ const i = this.#e.getTheme().navigator, { xRange: s } = this.#P();
281
+ this.#G(i, s);
279
282
  }
280
283
  /** Decimate `points` into `buckets`, reusing the cached result while the
281
284
  * source array ref and bucket count are unchanged. */
@@ -299,7 +302,7 @@ class G {
299
302
  for (const m of this.#c.children)
300
303
  m.style.background = p;
301
304
  }
302
- #y() {
305
+ #b() {
303
306
  const t = this.#x;
304
307
  let e = Number.POSITIVE_INFINITY, i = Number.NEGATIVE_INFINITY, s = 0;
305
308
  if (t.type === "candlestick")
@@ -358,9 +361,9 @@ function x(o, t) {
358
361
  return v(A(o, t), !1);
359
362
  }
360
363
  function A(o, t) {
361
- return y(o, t).gesture;
364
+ return b(o, t).gesture;
362
365
  }
363
- function b() {
366
+ function y() {
364
367
  const o = document.createElement("div");
365
368
  o.style.cssText = "position:absolute;top:0;bottom:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:2px;";
366
369
  for (let t = 0; t < 3; t++) {
@@ -20,7 +20,7 @@ function I(i) {
20
20
  function O(i) {
21
21
  return -I(i) / 12;
22
22
  }
23
- const B = "#9aa6b6", c = "#5d6877", C = "#e8eef7", x = "#cdd6e2", y = "#3fd68f", V = "#f5c451", $ = "#f4756a", Y = "#5d6877", X = {
23
+ const V = "#9aa6b6", c = "#5d6877", C = "#e8eef7", x = "#cdd6e2", y = "#3fd68f", B = "#f5c451", $ = "#f4756a", Y = "#5d6877", X = {
24
24
  position: "absolute",
25
25
  top: "8px",
26
26
  right: "8px",
@@ -34,7 +34,7 @@ const B = "#9aa6b6", c = "#5d6877", C = "#e8eef7", x = "#cdd6e2", y = "#3fd68f",
34
34
  border: "1px solid rgba(255, 255, 255, 0.09)",
35
35
  borderRadius: "10px",
36
36
  boxShadow: "0 10px 28px rgba(0, 0, 0, 0.45), inset 0 1px 0 rgba(255, 255, 255, 0.05)",
37
- color: B,
37
+ color: V,
38
38
  font: "10px/1.5 ui-monospace, SFMono-Regular, Menlo, monospace",
39
39
  fontVariantNumeric: "tabular-nums",
40
40
  letterSpacing: "0.02em",
@@ -50,7 +50,7 @@ function G(i) {
50
50
  }`, i.head.appendChild(e);
51
51
  }
52
52
  function v(i) {
53
- return i <= H ? y : i <= F ? V : $;
53
+ return i <= H ? y : i <= F ? B : $;
54
54
  }
55
55
  function A(i) {
56
56
  return i >= 1e6 ? `${(i / 1e6).toFixed(1)}M` : i >= 1e4 ? `${(i / 1e3).toFixed(1)}k` : Math.round(i).toLocaleString("en-US");
@@ -0,0 +1,76 @@
1
+ import { formatCompact as x } from "../utils/format.js";
2
+ const b = 1e-9, p = /* @__PURE__ */ new Map();
3
+ function K(n = {}) {
4
+ const t = n.base ?? 10;
5
+ if (!Number.isFinite(t) || t <= 0 || t === 1)
6
+ throw new Error(`[wick-charts] logScale: base must be a positive number other than 1, got ${t}.`);
7
+ const o = p.get(t);
8
+ if (o) return o;
9
+ const a = S(t);
10
+ return p.set(t, a), a;
11
+ }
12
+ function S(n) {
13
+ const t = Math.log(n), o = n === 10 ? Math.log10 : n === 2 ? Math.log2 : (r) => Math.log(r) / t, a = n === 10 ? [1, 2, 5] : [1];
14
+ return {
15
+ forward: o,
16
+ inverse: (r) => n ** r,
17
+ isPlottable: (r) => r > 0,
18
+ ticks: (r) => C(r, P({ ...r, forward: o, base: n, mantissas: a })),
19
+ format: (r) => B(x(r))
20
+ };
21
+ }
22
+ function C(n, t) {
23
+ const { linear: o, labelCount: a, height: r, minSpacing: l } = n;
24
+ if (o.length < 2) return t;
25
+ if (t.length < 2) return o;
26
+ const s = a ?? Math.max(2, Math.floor(r / l)), e = Math.abs(t.length - s);
27
+ return Math.abs(o.length - s) + 1 < e ? o : t;
28
+ }
29
+ function P(n) {
30
+ const { min: t, max: o, height: a, minSpacing: r, labelCount: l, forward: s, base: e, mantissas: i } = n, c = s(t), h = s(o), u = a / (h - c), f = k({ lo: c, hi: h, pxPerPower: u, minSpacing: r, labelCount: l, base: e });
31
+ if (f > 1) return w({ lo: c, hi: h, step: f, base: e });
32
+ const g = M({ lo: c, hi: h, base: e, mantissas: [1], forward: s });
33
+ if (i.length === 1) return g;
34
+ const $ = s(i[1]) - s(i[0]);
35
+ if (u * $ < r) return g;
36
+ const m = M({ lo: c, hi: h, base: e, mantissas: i, forward: s });
37
+ return l !== null && m.length > l ? g : m;
38
+ }
39
+ function k(n) {
40
+ const { lo: t, hi: o, pxPerPower: a, minSpacing: r, labelCount: l, base: s } = n;
41
+ let e = 1;
42
+ for (; e < 1e6; ) {
43
+ const i = e * a >= r, c = l === null || w({ lo: t, hi: o, step: e, base: s }).length <= l;
44
+ if (i && c) return e;
45
+ e = v(e);
46
+ }
47
+ return e;
48
+ }
49
+ function v(n) {
50
+ const t = n / 10 ** Math.floor(Math.log10(n));
51
+ return t < 2 ? n * 2 : t < 5 ? n * 2.5 : n * 2;
52
+ }
53
+ function w(n) {
54
+ const { lo: t, hi: o, step: a, base: r } = n, l = Math.ceil(t / a - b), s = Math.floor(o / a + b), e = [];
55
+ for (let i = l; i <= s; i++)
56
+ e.push(d(1, r, i * a));
57
+ return e;
58
+ }
59
+ function M(n) {
60
+ const { lo: t, hi: o, base: a, mantissas: r, forward: l } = n, s = Math.floor(t), e = Math.floor(o + b), i = [];
61
+ for (let c = s; c <= e; c++)
62
+ for (const h of r) {
63
+ const u = d(h, a, c), f = l(u);
64
+ f < t - b || f > o + b || i.push(u);
65
+ }
66
+ return i;
67
+ }
68
+ function d(n, t, o) {
69
+ return o >= 0 ? n * t ** o : n / t ** -o;
70
+ }
71
+ function B(n) {
72
+ return n.replace(/(\.\d*?)0+([KMBT]?)$/, "$1$2").replace(/\.([KMBT]?)$/, "$1");
73
+ }
74
+ export {
75
+ K as logScale
76
+ };
@@ -8,7 +8,7 @@ function f(s, t) {
8
8
  if (s[e] !== t[e]) return !1;
9
9
  return !0;
10
10
  }
11
- class m {
11
+ let m = class {
12
12
  #e = [];
13
13
  #r = [];
14
14
  #t = /* @__PURE__ */ new Map();
@@ -104,7 +104,7 @@ class m {
104
104
  reset() {
105
105
  this.#e = [], this.#r = [], this.#t.clear(), this.#s = !1;
106
106
  }
107
- }
107
+ };
108
108
  export {
109
109
  m as AxisTickTracker
110
110
  };