@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,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,26 +1,35 @@
1
- import { crispLineWidth as h, crispCenterOffset as d } from "../utils/pixel-grid.js";
2
- function x({ scope: p, timeScale: m, yScale: f, theme: a, yTicks: u, timeTicks: T, alpha: n = 1 }) {
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
+ }) {
3
12
  if (n <= 0.01) return;
4
- const { context: e, bitmapSize: c, horizontalPixelRatio: t, verticalPixelRatio: l } = p;
13
+ const { context: e, bitmapSize: c, horizontalPixelRatio: t, verticalPixelRatio: h } = f;
5
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]);
6
- const g = h(l), v = d(l);
7
- e.lineWidth = g;
15
+ const T = d(h), y = p(h), b = l > 0 ? -l : 0;
16
+ e.lineWidth = T;
8
17
  for (const { value: r, opacity: s } of u.entries) {
9
- const i = s * n;
10
- if (i <= 0.01) continue;
11
- const o = Math.round(f.valueToBitmapY(r)) + v;
12
- e.globalAlpha = i, e.beginPath(), e.moveTo(0, o), e.lineTo(c.width, o), e.stroke();
18
+ const o = s * n;
19
+ if (o <= 0.01) continue;
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();
13
22
  }
14
- const y = h(t), b = d(t);
15
- e.lineWidth = y;
16
- for (const { value: r, opacity: s } of T.entries) {
17
- const i = s * n;
18
- if (i <= 0.01) continue;
19
- const o = Math.round(m.timeToBitmapX(r)) + b;
20
- e.globalAlpha = i, e.beginPath(), e.moveTo(o, 0), e.lineTo(o, c.height), e.stroke();
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;
27
+ if (o <= 0.01) continue;
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();
21
30
  }
22
31
  e.restore();
23
32
  }
24
33
  export {
25
- x as renderGrid
34
+ L as renderGrid
26
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
@@ -1,54 +1,73 @@
1
- function D(t, o) {
2
- return t.length <= o ? t : x(
1
+ function D(t, h) {
2
+ return t.length <= h ? t : v(
3
3
  t,
4
- o,
4
+ h,
5
5
  (l) => l.time,
6
6
  (l) => l.value
7
7
  );
8
8
  }
9
- function L(t, o) {
10
- if (t.length <= o) return t;
11
- const l = Math.ceil(t.length / o), c = [];
12
- for (let h = 0; h < t.length; h += l) {
13
- const s = Math.min(h + l, t.length);
14
- let r = -1 / 0, a = 1 / 0, f = 0;
15
- for (let n = h; n < s; n++)
16
- t[n].high > r && (r = t[n].high), t[n].low < a && (a = t[n].low), f += t[n].volume ?? 0;
17
- c.push({
18
- time: t[h].time,
19
- open: t[h].open,
20
- high: r,
21
- low: a,
22
- close: t[s - 1].close,
23
- volume: f
9
+ function k(t, h) {
10
+ if (t.length <= h) return t;
11
+ const l = Math.ceil(t.length / h), u = [];
12
+ for (let o = 0; o < t.length; o += l) {
13
+ const n = Math.min(o + l, t.length);
14
+ let s = -1 / 0, i = 1 / 0, c = 0;
15
+ for (let r = o; r < n; r++)
16
+ t[r].high > s && (s = t[r].high), t[r].low < i && (i = t[r].low), c += t[r].volume ?? 0;
17
+ u.push({
18
+ time: t[o].time,
19
+ open: t[o].open,
20
+ high: s,
21
+ low: i,
22
+ close: t[n - 1].close,
23
+ volume: c
24
24
  });
25
25
  }
26
- return c;
26
+ return u;
27
27
  }
28
- function x(t, o, l, c) {
29
- if (o >= t.length || o < 3) return t;
30
- const h = [t[0]], s = (t.length - 2) / (o - 2);
31
- let r = 0;
32
- for (let a = 0; a < o - 2; a++) {
33
- const f = Math.floor((a + 1) * s) + 1, n = Math.min(Math.floor((a + 2) * s) + 1, t.length - 1);
34
- let u = 0, g = 0;
35
- const M = n, p = Math.min(Math.floor((a + 3) * s) + 1, t.length), e = p - M;
36
- if (e > 0) {
37
- for (let i = M; i < p; i++)
38
- u += l(t[i]), g += c(t[i]);
39
- u /= e, g /= e;
28
+ function x(t, h) {
29
+ if (t.length <= h || h < 3) return t;
30
+ const l = t.length - 1, u = Math.ceil((t.length - 2) / (h - 2)), o = [t[0]];
31
+ for (let n = 1; n < l; n += u) {
32
+ const s = Math.min(n + u, l);
33
+ let i = 1 / 0, c = -1 / 0, r = !1;
34
+ for (let f = n; f < s; f++) {
35
+ const a = t[f];
36
+ if (!Number.isFinite(a.low) || !Number.isFinite(a.high)) {
37
+ r = !0;
38
+ break;
39
+ }
40
+ a.low < i && (i = a.low), a.high > c && (c = a.high);
40
41
  }
41
- let v = -1, m = f;
42
- const w = l(t[r]), b = c(t[r]);
43
- for (let i = f; i < n; i++) {
44
- const d = Math.abs((w - u) * (c(t[i]) - b) - (w - l(t[i])) * (g - b));
45
- d > v && (v = d, m = i);
42
+ o.push(r ? { time: t[n].time, low: Number.NaN, high: Number.NaN } : { time: t[n].time, low: i, high: c });
43
+ }
44
+ return o.push(t[l]), o;
45
+ }
46
+ function v(t, h, l, u) {
47
+ if (h >= t.length || h < 3) return t;
48
+ const o = [t[0]], n = (t.length - 2) / (h - 2);
49
+ let s = 0;
50
+ for (let i = 0; i < h - 2; i++) {
51
+ const c = Math.floor((i + 1) * n) + 1, r = Math.min(Math.floor((i + 2) * n) + 1, t.length - 1);
52
+ let f = 0, a = 0;
53
+ const M = r, p = Math.min(Math.floor((i + 3) * n) + 1, t.length), g = p - M;
54
+ if (g > 0) {
55
+ for (let e = M; e < p; e++)
56
+ f += l(t[e]), a += u(t[e]);
57
+ f /= g, a /= g;
58
+ }
59
+ let w = -1, m = c;
60
+ const N = l(t[s]), b = u(t[s]);
61
+ for (let e = c; e < r; e++) {
62
+ const d = Math.abs((N - f) * (u(t[e]) - b) - (N - l(t[e])) * (a - b));
63
+ d > w && (w = d, m = e);
46
64
  }
47
- h.push(t[m]), r = m;
65
+ o.push(t[m]), s = m;
48
66
  }
49
- return h.push(t[t.length - 1]), h;
67
+ return o.push(t[t.length - 1]), o;
50
68
  }
51
69
  export {
70
+ x as decimateBandData,
52
71
  D as decimateLineData,
53
- L as decimateOHLCData
72
+ k as decimateOHLCData
54
73
  };
@@ -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
  };
@@ -1,9 +1,9 @@
1
1
  import { DEFAULT_LINE_ENTRY as w } from "../animation/config.js";
2
2
  import { XScale as T } from "../scales/x-scale.js";
3
- import { YScale as R } from "../scales/y-scale.js";
4
- import { decimateCandles as k, decimateLinear as C } from "./decimate.js";
5
- import { hitTest as y, computeSnapCenter as E, computePan as I, computeResize as $ } from "./interactions.js";
6
- import { computeWindowGeometry as M, renderBackground as V, renderMiniCandlestick as L, renderMiniBar as N, renderMiniLine as P } from "./render.js";
3
+ import { YScale as k } from "../scales/y-scale.js";
4
+ import { decimateCandles as R, decimateLinear as C } from "./decimate.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;
@@ -22,10 +22,10 @@ class G {
22
22
  // Own scales — both cover the full data span. The main chart's scales move
23
23
  // with the viewport; these don't.
24
24
  #u = new T();
25
- #F = new R();
25
+ #F = new k();
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. */
@@ -35,7 +35,7 @@ class G {
35
35
  * `setData` (guards in-place mutation of a re-passed array); a buckets
36
36
  * mismatch (resize) recomputes per entry.
37
37
  */
38
- #R = /* @__PURE__ */ new Map();
38
+ #k = /* @__PURE__ */ new Map();
39
39
  /**
40
40
  * Eases the alpha of the trailing bar/candle/line-segment from 0 → 1 over
41
41
  * `DEFAULT_LINE_ENTRY` whenever {@link setData} reports a new last point
@@ -45,10 +45,10 @@ 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
- #k = null;
51
+ #R = null;
52
52
  /** Series index in `lineSeriesList(data)` that owns the newest last-time,
53
53
  * so the tail fade applies to the series that actually grew — not always
54
54
  * the last entry in the stack. -1 for candlestick (single-series). */
@@ -60,32 +60,32 @@ class G {
60
60
  #I;
61
61
  #$;
62
62
  #M;
63
- #V;
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.#$ = () => this.#f(), this.#M = () => this.#B(), this.#e.on("viewportChange", this.#I), this.#e.on("overlayChange", this.#$), this.#e.on("tickFrame", this.#M), this.#V = (s) => this.#U(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.#j(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
- if (i !== null && this.#k !== null && i !== this.#k) {
80
- const s = this.#h?.current ?? 0;
81
- this.#h = new S({
79
+ if (i !== null && this.#R !== null && i !== this.#R) {
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
- this.#k = i, this.#C = e?.seriesIndex ?? -1, this.#x = t, this.#R.clear(), this.#f();
88
+ this.#R = i, this.#C = e?.seriesIndex ?? -1, this.#x = t, this.#k.clear(), this.#f();
89
89
  }
90
90
  setOptions(t) {
91
91
  this.#v = t, this.#D(), this.#f();
@@ -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.#$), this.#e.off("tickFrame", this.#M), 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,7 +108,8 @@ 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
  }
@@ -118,7 +119,7 @@ class G {
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(), M(this.#u, this.#Y(), this.#y());
175
+ return this.#P(), M(this.#u, this.#Y(), this.#b());
173
176
  }
174
177
  #H() {
175
- const t = this.#y(), e = t.to - t.from;
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
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.#H();
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({
@@ -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, R), 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,22 +272,22 @@ 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. */
282
285
  #q(t, e, i) {
283
- const s = this.#R.get(t);
286
+ const s = this.#k.get(t);
284
287
  if (s !== void 0 && s.buckets === e)
285
288
  return s.result;
286
289
  const n = i(t, e);
287
- return this.#R.set(t, { buckets: e, result: n }), n;
290
+ return this.#k.set(t, { buckets: e, result: n }), n;
288
291
  }
289
292
  #G(t, e) {
290
293
  if (e.to <= e.from) return;
@@ -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++) {