@wick-charts/vue 0.6.2 → 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 (44) 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/axis/dom-labels.js +56 -43
  5. package/dist/core/dist/chart/options.js +5 -5
  6. package/dist/core/dist/chart/scale-guards.js +26 -0
  7. package/dist/core/dist/chart/y-target.js +46 -19
  8. package/dist/core/dist/chart.js +670 -519
  9. package/dist/core/dist/components/crosshair.js +8 -8
  10. package/dist/core/dist/components/grid.js +26 -17
  11. package/dist/core/dist/components/marker.js +28 -28
  12. package/dist/core/dist/components/reference-line.js +16 -16
  13. package/dist/core/dist/interactions/handler.js +3 -2
  14. package/dist/core/dist/interactions/zoom.js +6 -5
  15. package/dist/core/dist/navigator/controller.js +38 -35
  16. package/dist/core/dist/perf/perf-hud.js +3 -3
  17. package/dist/core/dist/scales/log-scale.js +76 -0
  18. package/dist/core/dist/scales/y-scale.js +134 -35
  19. package/dist/core/dist/series/bar-intro.js +11 -11
  20. package/dist/core/dist/series/bar.js +301 -251
  21. package/dist/core/dist/series/base-multi-layer.js +100 -76
  22. package/dist/core/dist/series/candlestick.js +244 -241
  23. package/dist/core/dist/series/line-intro.js +18 -18
  24. package/dist/core/dist/series/line.js +428 -390
  25. package/dist/core/dist/series/scale-stack.js +25 -0
  26. package/dist/core/dist/tooltip-position.js +5 -5
  27. package/dist/index.d.ts +246 -31
  28. package/dist/index.js +59 -57
  29. package/dist/ui/Crosshair.vue.js +14 -14
  30. package/dist/ui/HeatmapTooltip.vue.js +6 -6
  31. package/dist/ui/PieTooltip.vue.js +4 -4
  32. package/dist/ui/TimeAxis.vue.js +23 -22
  33. package/dist/ui/Tooltip.vue.js +71 -69
  34. package/dist/ui/YAxis.vue.js +25 -24
  35. package/dist/ui/YLabel.vue.js +48 -48
  36. package/package.json +2 -2
  37. package/src/ChartContainer.vue +20 -8
  38. package/src/composables.ts +35 -1
  39. package/src/index.ts +5 -0
  40. package/src/ui/Crosshair.vue +2 -2
  41. package/src/ui/TimeAxis.vue +7 -4
  42. package/src/ui/Tooltip.vue +4 -1
  43. package/src/ui/YAxis.vue +5 -3
  44. package/src/ui/YLabel.vue +3 -3
@@ -1,83 +1,94 @@
1
- import { DEFAULT_HISTORY_REVEAL as et, DEFAULT_LINE_INTRO as it, DEFAULT_LINE_PULSE as ot, DEFAULT_LINE_SMOOTH as st, DEFAULT_LINE_ENTRY as nt } from "../animation/config.js";
1
+ import { DEFAULT_HISTORY_REVEAL as nt, DEFAULT_LINE_INTRO as lt, DEFAULT_LINE_PULSE as at, DEFAULT_LINE_SMOOTH as rt, DEFAULT_LINE_ENTRY as ht } from "../animation/config.js";
2
2
  import { easeOutCubic as U } from "../animation/easing.js";
3
- import { decimateLineData as K } from "../data/decimation.js";
4
- import { hexToRgba as W } from "../utils/color.js";
5
- import { lerp as Y } from "../utils/math.js";
6
- import { BaseMultiLayerSeries as at } from "./base-multi-layer.js";
7
- import { unfoldIntro as lt, backfillSweepIntro as ht } from "./line-intro.js";
8
- import { buildCurveSegments as Q } from "./painters/canvas-path.js";
9
- import { resolveLinePainter as ct } from "./painters/resolve.js";
10
- const ut = {
3
+ import { decimateLineData as q } from "../data/decimation.js";
4
+ import { hexToRgba as X } from "../utils/color.js";
5
+ import { lerp as N } from "../utils/math.js";
6
+ import { BaseMultiLayerSeries as ut } from "./base-multi-layer.js";
7
+ import { unfoldIntro as ft, backfillSweepIntro as pt } from "./line-intro.js";
8
+ import { buildCurveSegments as tt } from "./painters/canvas-path.js";
9
+ import { resolveLinePainter as mt } from "./painters/resolve.js";
10
+ import { ScaleStack as et } from "./scale-stack.js";
11
+ const gt = {
11
12
  colors: ["#2962FF"],
12
13
  strokeWidth: 1,
13
14
  area: { visible: !0 },
14
15
  pulse: !0,
15
16
  stacking: "off",
16
17
  curve: "straight",
17
- entryMs: nt,
18
- smoothMs: st,
19
- pulseMs: ot,
20
- introMs: it,
21
- historyRevealMs: et
18
+ entryMs: ht,
19
+ smoothMs: rt,
20
+ pulseMs: at,
21
+ introMs: lt,
22
+ historyRevealMs: nt
22
23
  };
23
- function Z(g) {
24
- const t = g.areaFill, e = t !== void 0 && g.area === void 0 ? { visible: !!t } : g.area;
24
+ function it(x) {
25
+ const t = x.areaFill, e = t !== void 0 && x.area === void 0 ? { visible: !!t } : x.area;
25
26
  return {
26
- ...g,
27
+ ...x,
27
28
  area: e,
28
- entryMs: g.entryMs === !1 ? 0 : g.entryMs ?? nt,
29
- smoothMs: g.smoothMs === !1 ? 0 : g.smoothMs ?? st,
30
- pulseMs: g.pulseMs === !1 ? 0 : g.pulseMs ?? ot,
31
- introMs: g.introMs === !1 ? 0 : g.introMs ?? it,
32
- historyRevealMs: g.historyRevealMs === !1 ? 0 : g.historyRevealMs ?? et
29
+ entryMs: x.entryMs === !1 ? 0 : x.entryMs ?? ht,
30
+ smoothMs: x.smoothMs === !1 ? 0 : x.smoothMs ?? rt,
31
+ pulseMs: x.pulseMs === !1 ? 0 : x.pulseMs ?? at,
32
+ introMs: x.introMs === !1 ? 0 : x.introMs ?? lt,
33
+ historyRevealMs: x.historyRevealMs === !1 ? 0 : x.historyRevealMs ?? nt
33
34
  };
34
35
  }
35
- function $(g) {
36
- return g.map(([t, e]) => ({ x: t, y: e }));
36
+ function ot(x) {
37
+ return x.map(([t, e]) => ({ x: t, y: e }));
37
38
  }
38
- const J = 0.15, mt = ht();
39
- function j(g, t, e) {
40
- if (g.length === 0) return null;
41
- if (t <= g[0].time) return Number.isFinite(g[0].value) ? e(g[0]) : null;
42
- const i = g[g.length - 1];
43
- if (t >= i.time) return Number.isFinite(i.value) ? e(i) : null;
44
- let o = 0, s = g.length - 1;
45
- for (; s - o > 1; ) {
46
- const l = o + s >> 1;
47
- g[l].time <= t ? o = l : s = l;
48
- }
49
- const n = g[o], a = g[s];
50
- if (!Number.isFinite(n.value) || !Number.isFinite(a.value)) return null;
51
- const u = a.time - n.time;
52
- return u <= 0 ? e(n) : Y(e(n), e(a), (t - n.time) / u);
39
+ const J = 0.15, dt = pt();
40
+ function j(x, t, e) {
41
+ const { resolve: i, lerp: o = N } = e;
42
+ if (x.length === 0) return null;
43
+ if (t <= x[0].time) return Number.isFinite(x[0].value) ? i(x[0]) : null;
44
+ const s = x[x.length - 1];
45
+ if (t >= s.time) return Number.isFinite(s.value) ? i(s) : null;
46
+ let l = 0, a = x.length - 1;
47
+ for (; a - l > 1; ) {
48
+ const p = l + a >> 1;
49
+ x[p].time <= t ? l = p : a = p;
50
+ }
51
+ const f = x[l], r = x[a];
52
+ if (!Number.isFinite(f.value) || !Number.isFinite(r.value)) return null;
53
+ const m = r.time - f.time;
54
+ return m <= 0 ? i(f) : o(i(f), i(r), (t - f.time) / m);
53
55
  }
54
- function pt(g, t) {
55
- let e = 0, i = g.length - 1;
56
+ function xt(x, t) {
57
+ const e = t.getTransform();
58
+ let i = 0, o = 0;
59
+ for (const l of x)
60
+ t.isPlottable(l.value) && (i += e === null ? l.value : e.forward(l.value), o++);
61
+ if (o === 0) return null;
62
+ const s = i / o;
63
+ return e === null ? s : e.inverse(s);
64
+ }
65
+ function vt(x, t) {
66
+ let e = 0, i = x.length - 1;
56
67
  for (; e <= i; ) {
57
68
  const o = e + i >> 1;
58
- if (g[o] === t) return o;
59
- g[o] < t ? e = o + 1 : i = o - 1;
69
+ if (x[o] === t) return o;
70
+ x[o] < t ? e = o + 1 : i = o - 1;
60
71
  }
61
72
  return -1;
62
73
  }
63
- function tt(g, t) {
74
+ function st(x, t) {
64
75
  for (const e of t)
65
- e.kind === "line" ? g.lineTo(e.x, e.y) : g.bezierCurveTo(e.cp1x, e.cp1y, e.cp2x, e.cp2y, e.x, e.y);
76
+ e.kind === "line" ? x.lineTo(e.x, e.y) : x.bezierCurveTo(e.cp1x, e.cp1y, e.cp2x, e.cp2y, e.x, e.y);
66
77
  }
67
- function ft(g, t, e) {
78
+ function yt(x, t, e) {
68
79
  for (let i = e.length - 1; i >= 0; i--) {
69
80
  const o = e[i], s = i > 0 ? e[i - 1] : t[0];
70
- o.kind === "line" ? g.lineTo(s.x, s.y) : g.bezierCurveTo(o.cp2x, o.cp2y, o.cp1x, o.cp1y, s.x, s.y);
81
+ o.kind === "line" ? x.lineTo(s.x, s.y) : x.bezierCurveTo(o.cp2x, o.cp2y, o.cp1x, o.cp1y, s.x, s.y);
71
82
  }
72
83
  }
73
- class dt extends at {
84
+ class bt extends ut {
74
85
  kind = "line";
75
86
  areaGradientCache = /* @__PURE__ */ new Map();
76
87
  constructor(t, e) {
77
- super(t), this.options = Z({ ...ut, ...e });
88
+ super(t), this.options = it({ ...gt, ...e });
78
89
  }
79
90
  updateOptions(t) {
80
- this.options = Z({ ...this.options, ...t });
91
+ this.options = it({ ...this.options, ...t });
81
92
  }
82
93
  getStacking() {
83
94
  return this.options.stacking;
@@ -104,18 +115,18 @@ class dt extends at {
104
115
  return !1;
105
116
  }
106
117
  render(t) {
107
- this.tickAnimations(performance.now());
118
+ this.tickAnimations(performance.now()), this.lastYScale = t.yScale;
108
119
  const { context: e } = t.scope;
109
120
  this.historyDirectives = null;
110
121
  const i = this.historyRange;
111
122
  if (this.historyWave.active && i !== null) {
112
- const a = this.options.historyReveal ?? mt;
123
+ const a = this.options.historyReveal ?? dt;
113
124
  a !== "none" && (this.historyDirectives = a(this.buildHistoryFrame(t, i)));
114
125
  }
115
126
  const o = this.historyDirectives, s = o?.ghostAlpha ?? 0;
116
127
  s > 0 && (e.save(), e.globalAlpha *= s, this.introGhostPass = !0, this.renderBody(t), this.introGhostPass = !1, e.restore());
117
- const n = this.applyHistoryClip(t, o, i);
118
- this.introWave.active ? this.renderWithIntro(t) : (this.introDirectives = null, this.renderBody(t)), n && e.restore(), o?.heads !== void 0 && o.heads.length > 0 && this.drawIntroHeads(t, o.heads, this.historyWave.linear());
128
+ const l = this.applyHistoryClip(t, o, i);
129
+ this.introWave.active ? this.renderWithIntro(t) : (this.introDirectives = null, this.renderBody(t)), l && e.restore(), o?.heads !== void 0 && o.heads.length > 0 && this.drawIntroHeads(t, o.heads, this.historyWave.linear());
119
130
  }
120
131
  /**
121
132
  * Initial-load intro pass: the resolved LineIntroFn describes this frame
@@ -125,14 +136,14 @@ class dt extends at {
125
136
  renderWithIntro(t) {
126
137
  const e = this.resolveIntro()(this.buildIntroFrame(t));
127
138
  this.introDirectives = e;
128
- const { context: i } = t.scope, { width: o, height: s } = t.scope.bitmapSize, n = e.ghostAlpha ?? 0;
129
- n > 0 && (i.save(), i.globalAlpha *= n, this.introGhostPass = !0, this.renderBody(t), this.introGhostPass = !1, i.restore());
130
- const a = e.clip, u = a !== void 0 && (a.fromX !== void 0 || a.toX !== void 0);
131
- if (u) {
132
- const l = a.fromX ?? 0, p = a.toX ?? o;
133
- i.save(), i.beginPath(), i.rect(l, 0, Math.max(0, p - l), s), i.clip();
139
+ const { context: i } = t.scope, { width: o, height: s } = t.scope.bitmapSize, l = e.ghostAlpha ?? 0;
140
+ l > 0 && (i.save(), i.globalAlpha *= l, this.introGhostPass = !0, this.renderBody(t), this.introGhostPass = !1, i.restore());
141
+ const a = e.clip, f = a !== void 0 && (a.fromX !== void 0 || a.toX !== void 0);
142
+ if (f) {
143
+ const r = a.fromX ?? 0, m = a.toX ?? o;
144
+ i.save(), i.beginPath(), i.rect(r, 0, Math.max(0, m - r), s), i.clip();
134
145
  }
135
- this.renderBody(t), u && i.restore(), e.heads !== void 0 && e.heads.length > 0 && this.drawIntroHeads(t, e.heads, this.introWave.linear());
146
+ this.renderBody(t), f && i.restore(), e.heads !== void 0 && e.heads.length > 0 && this.drawIntroHeads(t, e.heads, this.introWave.linear());
136
147
  }
137
148
  /**
138
149
  * Apply the history reveal's clip directive, mapped from reveal space
@@ -143,8 +154,8 @@ class dt extends at {
143
154
  applyHistoryClip(t, e, i) {
144
155
  const o = e?.clip;
145
156
  if (o === void 0 || i === null || o.fromX === void 0 && o.toX === void 0) return !1;
146
- const { context: s } = t.scope, { width: n, height: a } = t.scope.bitmapSize, u = t.timeScale.timeToBitmapXExact(i.to), l = Math.abs(u - t.timeScale.timeToBitmapXExact(i.from)), p = Math.max(2, (this.options.strokeWidth ?? 1) * t.scope.horizontalPixelRatio), h = o.fromX ?? 0, d = o.toX ?? l;
147
- return s.save(), s.beginPath(), s.rect(u - d - p, 0, Math.max(0, d - h + p), a), s.rect(u, 0, Math.max(0, n - u), a), s.clip(), !0;
157
+ const { context: s } = t.scope, { width: l, height: a } = t.scope.bitmapSize, f = t.timeScale.timeToBitmapXExact(i.to), r = Math.abs(f - t.timeScale.timeToBitmapXExact(i.from)), m = Math.max(2, (this.options.strokeWidth ?? 1) * t.scope.horizontalPixelRatio), p = o.fromX ?? 0, v = o.toX ?? r;
158
+ return s.save(), s.beginPath(), s.rect(f - v - m, 0, Math.max(0, v - p + m), a), s.rect(f, 0, Math.max(0, l - f), a), s.clip(), !0;
148
159
  }
149
160
  renderBody(t) {
150
161
  this.options.stacking === "off" ? (this.stackedEdges = null, this.renderOff(t)) : this.renderStacked(t, this.options.stacking === "percent");
@@ -168,11 +179,13 @@ class dt extends at {
168
179
  introDirectives = null;
169
180
  /** Per-frame history-reveal directives; `null` when no reveal is in flight. */
170
181
  historyDirectives = null;
182
+ /** Y scale of the last render — value queries run without a render context. */
183
+ lastYScale = null;
171
184
  /** Default intro, built lazily — one instance per renderer. */
172
185
  defaultIntro = null;
173
186
  resolveIntro() {
174
187
  const t = this.options.introAnimation;
175
- return t !== void 0 ? t : (this.defaultIntro === null && (this.defaultIntro = lt()), this.defaultIntro);
188
+ return t !== void 0 ? t : (this.defaultIntro === null && (this.defaultIntro = ft()), this.defaultIntro);
176
189
  }
177
190
  /**
178
191
  * Frame context handed to the intro fn — progress plus memoized data
@@ -204,41 +217,36 @@ class dt extends at {
204
217
  });
205
218
  }
206
219
  buildFrame(t, e) {
207
- const { timeScale: i, yScale: o, scope: s } = t, { progress: n, range: a, width: u } = e, l = new Array(this.stores.length), p = new Array(this.stores.length);
208
- let h;
209
- const d = (r) => {
210
- let f = l[r];
211
- return f === void 0 && (f = this.stores[r]?.getVisibleData(a.from, a.to) ?? [], l[r] = f), f;
220
+ const { timeScale: i, yScale: o, scope: s } = t, { progress: l, range: a, width: f } = e, r = new Array(this.stores.length), m = new Array(this.stores.length);
221
+ let p;
222
+ const v = (n) => {
223
+ let u = r[n];
224
+ return u === void 0 && (u = this.stores[n]?.getVisibleData(a.from, a.to) ?? [], r[n] = u), u;
212
225
  };
213
226
  return {
214
- progress: n,
227
+ progress: l,
215
228
  range: a,
216
- width: u,
229
+ width: f,
217
230
  height: o.getMediaHeight() * s.verticalPixelRatio,
218
231
  stacking: this.options.stacking,
219
- timeToX: (r) => i.timeToBitmapXExact(r),
220
- xToTime: (r) => i.xToTime(r / s.horizontalPixelRatio),
221
- valueToY: (r) => o.valueToBitmapYExact(r),
232
+ timeToX: (n) => i.timeToBitmapXExact(n),
233
+ xToTime: (n) => i.xToTime(n / s.horizontalPixelRatio),
234
+ valueToY: (n) => o.valueToBitmapYExact(n),
235
+ lerpValue: (n, u, c) => o.lerpValue(n, u, c),
222
236
  layerCount: this.stores.length,
223
- layerData: d,
224
- layerMean: (r) => {
225
- let f = p[r];
226
- if (f === void 0) {
227
- let c = 0, y = 0;
228
- for (const R of d(r))
229
- Number.isFinite(R.value) && (c += R.value, y++);
230
- f = y > 0 ? c / y : null, p[r] = f;
231
- }
232
- return f;
237
+ layerData: v,
238
+ layerMean: (n) => {
239
+ let u = m[n];
240
+ return u === void 0 && (u = xt(v(n), o), m[n] = u), u;
233
241
  },
234
242
  primaryPath: () => {
235
- if (h === void 0) {
236
- h = null;
237
- for (let r = 0; r < this.stores.length; r++) {
238
- if (this.getLayerAlpha(r) <= 0 || !this.stores[r].isVisible()) continue;
239
- const f = d(r).filter((c) => Number.isFinite(c.value));
240
- if (!(f.length < 2)) {
241
- h = f.map((c) => ({
243
+ if (p === void 0) {
244
+ p = null;
245
+ for (let n = 0; n < this.stores.length; n++) {
246
+ if (this.getLayerAlpha(n) <= 0 || !this.stores[n].isVisible()) continue;
247
+ const u = v(n).filter((c) => o.isPlottable(c.value));
248
+ if (!(u.length < 2)) {
249
+ p = u.map((c) => ({
242
250
  x: i.timeToBitmapXExact(c.time),
243
251
  y: o.valueToBitmapYExact(c.value),
244
252
  time: c.time
@@ -247,7 +255,7 @@ class dt extends at {
247
255
  }
248
256
  }
249
257
  }
250
- return h;
258
+ return p;
251
259
  }
252
260
  };
253
261
  }
@@ -258,24 +266,23 @@ class dt extends at {
258
266
  * animates the whole geometry.
259
267
  */
260
268
  effectiveValue(t, e, i, o) {
261
- const s = super.effectiveValue(t, e, i, o), n = this.historyWave.active ? this.historyDirectives?.value : void 0, a = this.historyRange;
262
- if (n !== void 0 && a !== null && i < a.to) {
263
- const d = a.to - a.from, r = d > 0 ? Math.min(1, Math.max(0, (a.to - i) / d)) : 0;
264
- return n({ layerIndex: e, time: i, value: s, position: r });
269
+ const s = super.effectiveValue(t, e, i, o), l = this.historyWave.active ? this.historyDirectives?.value : void 0, a = this.historyRange;
270
+ if (l !== void 0 && a !== null && i < a.to) {
271
+ const v = a.to - a.from, n = v > 0 ? Math.min(1, Math.max(0, (a.to - i) / v)) : 0;
272
+ return l({ layerIndex: e, time: i, value: s, position: n });
265
273
  }
266
- const u = this.introWave.active ? this.introDirectives?.value : void 0;
267
- if (u === void 0) return s;
268
- const l = t.timeScale.getRange(), p = l.to - l.from, h = p > 0 ? Math.min(1, Math.max(0, (i - l.from) / p)) : 0;
269
- return u({ layerIndex: e, time: i, value: s, position: h });
274
+ const f = this.introWave.active ? this.introDirectives?.value : void 0;
275
+ if (f === void 0) return s;
276
+ const r = t.timeScale.getRange(), m = r.to - r.from, p = m > 0 ? Math.min(1, Math.max(0, (i - r.from) / m)) : 0;
277
+ return f({ layerIndex: e, time: i, value: s, position: p });
270
278
  }
271
279
  /**
272
280
  * Extends the base last-value query with the 'grow' entrance's value-space
273
- * equivalent of {@link chainedTailPositions}'s eased position lerp — the Y
274
- * scale is affine, so lerping the *value* by the same eased progress and
275
- * mapping it through `yScale` afterward lands on the identical pixel the
276
- * renderer paints. Without this, a tooltip/YLabel query would report a
277
- * freshly-appended point's raw value the instant it lands, `entryMs`
278
- * before the marker visually arrives there.
281
+ * equivalent of {@link chainedTailPositions}'s eased position lerp — the
282
+ * value lerps along the Y axis by the same eased progress, so mapping it
283
+ * through `yScale` lands on the identical pixel the renderer paints. Without
284
+ * this, a tooltip/YLabel query would report a freshly-appended point's raw
285
+ * value the instant it lands, `entryMs` before the marker visually arrives there.
279
286
  */
280
287
  snapshotValue(t, e, i) {
281
288
  const o = super.snapshotValue(t, e, i);
@@ -291,17 +298,22 @@ class dt extends at {
291
298
  if (i.length === 0) return null;
292
299
  const o = this.stores[t].getAll(), s = o.length - 1 - i.length;
293
300
  if (s < 0) return null;
294
- const n = o[s];
295
- if (!Number.isFinite(n.value)) return null;
296
- let a = e(n.time, n.value);
297
- const u = /* @__PURE__ */ new Map();
298
- for (let l = 0; l < i.length; l++) {
299
- const p = o[s + 1 + l];
300
- if (!Number.isFinite(p.value)) return null;
301
- const h = U(i[l].progress), d = e(p.time, p.value), r = Y(a, d, h);
302
- u.set(p.time, r), a = r;
301
+ const l = o[s];
302
+ if (!Number.isFinite(l.value)) return null;
303
+ let a = e(l.time, l.value);
304
+ const f = /* @__PURE__ */ new Map();
305
+ for (let r = 0; r < i.length; r++) {
306
+ const m = o[s + 1 + r];
307
+ if (!Number.isFinite(m.value)) return null;
308
+ const p = U(i[r].progress), v = e(m.time, m.value), n = this.axisLerp(a, v, p);
309
+ f.set(m.time, n), a = n;
303
310
  }
304
- return u;
311
+ return f;
312
+ }
313
+ /** `lerp` along the last rendered Y axis — plain before the first render. */
314
+ axisLerp(t, e, i) {
315
+ const o = this.lastYScale;
316
+ return o === null ? N(t, e, i) : o.lerpValue(t, e, i);
305
317
  }
306
318
  /**
307
319
  * Glowing pulse dots riding the intro's head anchors — the line reads as
@@ -311,22 +323,22 @@ class dt extends at {
311
323
  */
312
324
  drawIntroHeads(t, e, i) {
313
325
  if (this.options.stacking !== "off") return;
314
- const o = Math.min(1, i / J), s = Math.min(1, (1 - i) / J), n = Math.max(0, Math.min(o, s));
315
- if (n <= 0) return;
326
+ const o = Math.min(1, i / J), s = Math.min(1, (1 - i) / J), l = Math.max(0, Math.min(o, s));
327
+ if (l <= 0) return;
316
328
  const { scope: a } = t;
317
- for (const u of e)
318
- for (let l = 0; l < this.stores.length; l++) {
319
- const p = this.getLayerAlpha(l);
320
- if (p <= 0 || !this.stores[l].isVisible()) continue;
321
- const h = this.introHeadAnchor(t, l, u);
322
- h !== null && this.drawPulse({
329
+ for (const f of e)
330
+ for (let r = 0; r < this.stores.length; r++) {
331
+ const m = this.getLayerAlpha(r);
332
+ if (m <= 0 || !this.stores[r].isVisible()) continue;
333
+ const p = this.introHeadAnchor(t, r, f);
334
+ p !== null && this.drawPulse({
323
335
  ctx: a.context,
324
- x: h.x,
325
- y: h.y,
326
- color: this.resolveLayerColor(l, h.value),
336
+ x: p.x,
337
+ y: p.y,
338
+ color: this.resolveLayerColor(r, p.value),
327
339
  pixelRatio: a.horizontalPixelRatio,
328
340
  phase: i * 2,
329
- alpha: n * p
341
+ alpha: l * m
330
342
  });
331
343
  }
332
344
  }
@@ -342,26 +354,30 @@ class dt extends at {
342
354
  * visible range, not the data span) and jumps back on settle.
343
355
  */
344
356
  introHeadAnchor(t, e, i) {
345
- const { timeScale: o, yScale: s } = t, n = o.getRange(), a = this.stores[e].getVisibleData(n.from, n.to);
357
+ const { timeScale: o, yScale: s } = t, l = o.getRange(), a = this.stores[e].getVisibleData(l.from, l.to);
346
358
  if (a.length === 0) return null;
347
- const u = this.stores[e].last();
348
- if (u !== void 0 && i.time >= u.time) {
349
- if (!Number.isFinite(u.value)) return null;
350
- const h = this.trailingEndpoint(t, e);
351
- return h === null ? null : { x: h.x, y: h.y, value: u.value };
359
+ const f = this.stores[e].last();
360
+ if (f !== void 0 && i.time >= f.time) {
361
+ if (!s.isPlottable(f.value)) return null;
362
+ const p = this.trailingEndpoint(t, e);
363
+ return p === null ? null : { x: p.x, y: p.y, value: f.value };
352
364
  }
353
- const l = a[0];
354
- if (i.time <= l.time) {
355
- if (!Number.isFinite(l.value)) return null;
356
- const h = this.effectiveValue(t, e, l.time, l.value);
365
+ const r = a[0];
366
+ if (i.time <= r.time) {
367
+ if (!s.isPlottable(r.value)) return null;
368
+ const p = this.effectiveValue(t, e, r.time, r.value);
357
369
  return {
358
- x: o.timeToBitmapXExact(l.time),
359
- y: s.valueToBitmapYExact(h),
360
- value: l.value
370
+ x: o.timeToBitmapXExact(r.time),
371
+ y: s.valueToBitmapYExact(p),
372
+ value: r.value
361
373
  };
362
374
  }
363
- const p = j(a, i.time, (h) => this.effectiveValue(t, e, h.time, h.value));
364
- return p === null ? null : { x: i.x, y: s.valueToBitmapYExact(p), value: p };
375
+ const m = j(a, i.time, {
376
+ resolve: (p) => this.effectiveValue(t, e, p.time, p.value),
377
+ // Along the axis, so the dot stays on the straight segment the stroke draws.
378
+ lerp: (p, v, n) => !s.isPlottable(p) || !s.isPlottable(v) ? Number.NaN : s.lerpValue(p, v, n)
379
+ });
380
+ return m === null || !s.isPlottable(m) ? null : { x: i.x, y: s.valueToBitmapYExact(m), value: m };
365
381
  }
366
382
  /**
367
383
  * Rendered positions of the layer's still-unsettled trailing points, keyed
@@ -386,33 +402,43 @@ class dt extends at {
386
402
  * it (see `renderStacked`'s `valueMaps` comment for the full rationale).
387
403
  */
388
404
  stackedValueAt(t, e, i) {
389
- const o = this.options.stacking === "percent", s = (this.options.entryAnimation ?? "grow") === "grow", n = new Array(this.stores.length), a = (h) => {
405
+ const o = this.options.stacking === "percent", s = (this.options.entryAnimation ?? "grow") === "grow", l = new Array(this.stores.length), a = (n) => {
390
406
  if (!s) return null;
391
- const d = n[h];
392
- if (d !== void 0) return d;
393
- const r = this.chainedTailValues(h, (f, c) => this.effectiveValue(t, h, f, c));
394
- return n[h] = r, r;
395
- }, u = (h) => {
396
- const d = this.getLayerAlpha(h);
397
- if (d <= 0) return 0;
398
- const r = this.stores[h].getAll();
399
- if (r.length === 0 || i < r[0].time) return 0;
400
- const f = a(h), c = j(
401
- r,
402
- i,
403
- (y) => f?.get(y.time) ?? this.effectiveValue(t, h, y.time, y.value)
404
- );
405
- return c === null ? 0 : c * d;
407
+ const u = l[n];
408
+ if (u !== void 0) return u;
409
+ const c = this.chainedTailValues(n, (y, k) => this.effectiveValue(t, n, y, k));
410
+ return l[n] = c, c;
411
+ }, f = (n) => {
412
+ const u = this.stores[n].getAll();
413
+ if (u.length === 0 || i < u[0].time) return null;
414
+ const c = a(n);
415
+ return j(u, i, {
416
+ resolve: (y) => c?.get(y.time) ?? this.effectiveValue(t, n, y.time, y.value)
417
+ });
418
+ }, { yScale: r } = t;
419
+ if (r.getTransform() !== null && !o) {
420
+ const n = new et(r);
421
+ for (let u = 0; u <= e; u++) {
422
+ const c = this.getLayerAlpha(u), y = c > 0 ? f(u) : null;
423
+ y !== null && r.isPlottable(y) && n.push(y, c);
424
+ }
425
+ return n.edge;
426
+ }
427
+ const m = (n) => {
428
+ const u = this.getLayerAlpha(n);
429
+ if (u <= 0) return 0;
430
+ const c = f(n);
431
+ return c === null ? 0 : c * u;
406
432
  };
407
- let l = 0;
408
- if (o)
409
- for (let h = 0; h < this.stores.length; h++) l += u(h);
410
433
  let p = 0;
411
- for (let h = 0; h <= e; h++) {
412
- const d = u(h);
413
- p += o && l > 0 ? d / l * 100 : d;
434
+ if (o)
435
+ for (let n = 0; n < this.stores.length; n++) p += m(n);
436
+ let v = 0;
437
+ for (let n = 0; n <= e; n++) {
438
+ const u = m(n);
439
+ v += o && p > 0 ? u / p * 100 : u;
414
440
  }
415
- return p;
441
+ return v;
416
442
  }
417
443
  /**
418
444
  * Bitmap position for layer `li`'s stacked boundary at time `t`.
@@ -428,43 +454,43 @@ class dt extends at {
428
454
  stackedPositionAt(t, e, i) {
429
455
  const o = this.paintedStackVertex(t, e, i);
430
456
  if (o !== null) return o;
431
- const { timeScale: s, yScale: n } = t, a = n.valueToBitmapYExact(this.stackedValueAt(t, e, i)), u = s.timeToBitmapXExact(i), l = this.unsettledTail(e), p = this.stores[e].getAll(), h = p.length - 1 - l.length;
432
- if ((this.options.entryAnimation ?? "grow") !== "grow" || i !== p[p.length - 1]?.time || l.length === 0 || h < 0) return { x: u, y: a };
433
- let d = s.timeToBitmapXExact(p[h].time);
434
- for (let r = 0; r < l.length; r++)
435
- d = Y(d, s.timeToBitmapXExact(p[h + 1 + r].time), U(l[r].progress));
436
- return { x: d, y: a };
457
+ const { timeScale: s, yScale: l } = t, a = l.valueToBitmapYExact(this.stackedValueAt(t, e, i)), f = s.timeToBitmapXExact(i), r = this.unsettledTail(e), m = this.stores[e].getAll(), p = m.length - 1 - r.length;
458
+ if ((this.options.entryAnimation ?? "grow") !== "grow" || i !== m[m.length - 1]?.time || r.length === 0 || p < 0) return { x: f, y: a };
459
+ let v = s.timeToBitmapXExact(m[p].time);
460
+ for (let n = 0; n < r.length; n++)
461
+ v = N(v, s.timeToBitmapXExact(m[p + 1 + n].time), U(r[n].progress));
462
+ return { x: v, y: a };
437
463
  }
438
464
  /** Upper-edge vertex of layer `li` at column `t`, replayed from the last
439
465
  * stacked frame's data-space record against `ctx`'s scales. */
440
466
  paintedStackVertex(t, e, i) {
441
467
  const o = this.stackedEdges, s = o?.cumulative[e];
442
468
  if (o === null || s === void 0) return null;
443
- const { times: n, growChain: a, collapse: u } = o, l = pt(n, i);
444
- if (l < 0) return null;
445
- const { timeScale: p, yScale: h } = t, d = t.scope.bitmapSize.height, r = u[e] ?? 1, f = h.valueToBitmapYExact(s[l]), c = r >= 1 ? f : d + (f - d) * r, y = n.length - a.length;
446
- if (l < y) return { x: p.timeToBitmapXExact(i), y: c };
447
- let R = p.timeToBitmapXExact(n[y - 1]);
448
- for (let M = 0; M <= l - y; M++)
449
- R = Y(R, p.timeToBitmapXExact(n[y + M]), a[M]);
450
- return { x: R, y: c };
469
+ const { times: l, growChain: a, collapse: f } = o, r = vt(l, i);
470
+ if (r < 0) return null;
471
+ const { timeScale: m, yScale: p } = t, v = t.scope.bitmapSize.height, n = f[e] ?? 1, u = p.valueToBitmapYExact(s[r]), c = n >= 1 ? u : v + (u - v) * n, y = l.length - a.length;
472
+ if (r < y) return { x: m.timeToBitmapXExact(i), y: c };
473
+ let k = m.timeToBitmapXExact(l[y - 1]);
474
+ for (let w = 0; w <= r - y; w++)
475
+ k = N(k, m.timeToBitmapXExact(l[y + w]), a[w]);
476
+ return { x: k, y: c };
451
477
  }
452
478
  chainedTailPositions(t, e) {
453
479
  const i = this.unsettledTail(e);
454
480
  if (i.length === 0) return null;
455
481
  const o = this.stores[e].getAll(), s = o.length - 1 - i.length;
456
482
  if (s < 0) return null;
457
- const { timeScale: n, yScale: a } = t, u = o[s];
458
- if (!Number.isFinite(u.value)) return null;
459
- let l = n.timeToBitmapXExact(u.time), p = a.valueToBitmapYExact(this.effectiveValue(t, e, u.time, u.value));
460
- const h = /* @__PURE__ */ new Map();
461
- for (let d = 0; d < i.length; d++) {
462
- const r = o[s + 1 + d];
463
- if (!Number.isFinite(r.value)) return null;
464
- const f = U(i[d].progress), c = n.timeToBitmapXExact(r.time), y = a.valueToBitmapYExact(this.effectiveValue(t, e, r.time, r.value)), R = Y(l, c, f), M = Y(p, y, f);
465
- h.set(r.time, { x: R, y: M }), l = R, p = M;
483
+ const { timeScale: l, yScale: a } = t, f = o[s];
484
+ if (!a.isPlottable(f.value)) return null;
485
+ let r = l.timeToBitmapXExact(f.time), m = a.valueToBitmapYExact(this.effectiveValue(t, e, f.time, f.value));
486
+ const p = /* @__PURE__ */ new Map();
487
+ for (let v = 0; v < i.length; v++) {
488
+ const n = o[s + 1 + v];
489
+ if (!a.isPlottable(n.value)) return null;
490
+ const u = U(i[v].progress), c = l.timeToBitmapXExact(n.time), y = a.valueToBitmapYExact(this.effectiveValue(t, e, n.time, n.value)), k = N(r, c, u), w = N(m, y, u);
491
+ p.set(n.time, { x: k, y: w }), r = k, m = w;
466
492
  }
467
- return h;
493
+ return p;
468
494
  }
469
495
  /**
470
496
  * Bitmap coordinates for the trailing endpoint of a layer — i.e. where the
@@ -479,8 +505,8 @@ class dt extends at {
479
505
  trailingEndpoint(t, e) {
480
506
  const i = this.stores[e].last();
481
507
  if (!i) return null;
482
- const { timeScale: o, yScale: s } = t, n = o.timeToBitmapXExact(i.time), a = s.valueToBitmapYExact(this.effectiveValue(t, e, i.time, i.value));
483
- return (this.options.entryAnimation ?? "grow") !== "grow" ? { x: n, y: a } : this.chainedTailPositions(t, e)?.get(i.time) ?? { x: n, y: a };
508
+ const { timeScale: o, yScale: s } = t, l = o.timeToBitmapXExact(i.time), a = s.valueToBitmapYExact(this.effectiveValue(t, e, i.time, i.value));
509
+ return (this.options.entryAnimation ?? "grow") !== "grow" ? { x: l, y: a } : this.chainedTailPositions(t, e)?.get(i.time) ?? { x: l, y: a };
484
510
  }
485
511
  /**
486
512
  * Vertical stroke + area gradients for `options.threshold`, pinned to the
@@ -494,10 +520,10 @@ class dt extends at {
494
520
  buildThresholdPaint(t, e) {
495
521
  const i = this.options.threshold;
496
522
  if (!i) return null;
497
- const { scope: o, yScale: s } = t, { context: n } = o, a = o.bitmapSize.height, u = i.above, l = i.below ?? e, p = Math.min(1, Math.max(0, s.valueToBitmapYExact(i.value) / a)), h = Math.min(6 * o.verticalPixelRatio, a * 0.02) / a, d = Math.max(0, p - h), r = Math.min(1, p + h), f = n.createLinearGradient(0, 0, 0, a);
498
- f.addColorStop(0, u), f.addColorStop(d, u), f.addColorStop(r, l), f.addColorStop(1, l);
499
- const c = n.createLinearGradient(0, 0, 0, a);
500
- return c.addColorStop(0, W(u, 0.26)), c.addColorStop(d, W(u, 0.14)), c.addColorStop(r, W(l, 0.1)), c.addColorStop(1, W(l, 0.01)), { stroke: f, area: c };
523
+ const { scope: o, yScale: s } = t, { context: l } = o, a = o.bitmapSize.height, f = i.above, r = i.below ?? e, m = Math.min(1, Math.max(0, s.valueToBitmapYExact(i.value) / a)), p = Math.min(6 * o.verticalPixelRatio, a * 0.02) / a, v = Math.max(0, m - p), n = Math.min(1, m + p), u = l.createLinearGradient(0, 0, 0, a);
524
+ u.addColorStop(0, f), u.addColorStop(v, f), u.addColorStop(n, r), u.addColorStop(1, r);
525
+ const c = l.createLinearGradient(0, 0, 0, a);
526
+ return c.addColorStop(0, X(f, 0.26)), c.addColorStop(v, X(f, 0.14)), c.addColorStop(n, X(r, 0.1)), c.addColorStop(1, X(r, 0.01)), { stroke: u, area: c };
501
527
  }
502
528
  /**
503
529
  * Dot markers at each data point (`options.points`). Callers pass the same
@@ -510,224 +536,235 @@ class dt extends at {
510
536
  drawPointMarkers(t) {
511
537
  const e = this.options.points;
512
538
  if (!e?.visible) return;
513
- const { context: i, points: o, pixelRatio: s, color: n } = t;
539
+ const { context: i, points: o, pixelRatio: s, color: l } = t;
514
540
  if (o.length === 0) return;
515
541
  const a = Math.max(1, (e.radius ?? 3) * s);
516
542
  if (!(o.length > 1 && (o[o.length - 1].x - o[0].x) / (o.length - 1) < a * 3)) {
517
543
  i.beginPath();
518
- for (const u of o)
519
- i.moveTo(u.x + a, u.y), i.arc(u.x, u.y, a, 0, Math.PI * 2);
520
- i.fillStyle = e.color ?? n, i.fill();
544
+ for (const f of o)
545
+ i.moveTo(f.x + a, f.y), i.arc(f.x, f.y, a, 0, Math.PI * 2);
546
+ i.fillStyle = e.color ?? l, i.fill();
521
547
  }
522
548
  }
523
549
  /** Each layer drawn independently */
524
550
  renderOff(t) {
525
- const { scope: e, timeScale: i, yScale: o } = t, { context: s } = e, n = i.getRange(), { verticalPixelRatio: a } = e, u = this.options.strokeWidth > 0, l = Math.max(1, Math.round(this.options.strokeWidth * a)), p = this.options.entryAnimation ?? "grow", h = ct(this.options.linePainter ?? this.options.curve ?? "straight"), d = {
551
+ const { scope: e, timeScale: i, yScale: o } = t, { context: s } = e, l = i.getRange(), { verticalPixelRatio: a } = e, f = this.options.strokeWidth > 0, r = Math.max(1, Math.round(this.options.strokeWidth * a)), m = this.options.entryAnimation ?? "grow", p = mt(this.options.linePainter ?? this.options.curve ?? "straight"), v = {
526
552
  ctx: s,
527
553
  theme: t.theme,
528
554
  horizontalPixelRatio: e.horizontalPixelRatio,
529
555
  verticalPixelRatio: a
530
556
  };
531
- for (let r = 0; r < this.stores.length; r++) {
532
- const f = this.getLayerAlpha(r);
533
- if (f <= 0) continue;
534
- let c = this.stores[r].getVisibleData(n.from, n.to);
557
+ for (let n = 0; n < this.stores.length; n++) {
558
+ const u = this.getLayerAlpha(n);
559
+ if (u <= 0) continue;
560
+ let c = this.stores[n].getVisibleData(l.from, l.to);
535
561
  const y = e.mediaSize.width;
536
- if (c.length > y * 2 && (c = K(c, Math.round(y * 1.5))), c.length < 2) continue;
537
- const R = this.stores[r].last()?.value ?? c[c.length - 1].value, M = this.resolveLayerColor(r, R), V = this.buildThresholdPaint(t, M), C = c[c.length - 1], N = this.stores[r].last(), D = N !== void 0 && C.time === N.time, z = D ? this.entranceProgress(r, C.time) : 1, I = D && p === "fade" && z < 1, G = (D ? this.trailingEndpoint(t, r) : null) ?? {
538
- x: i.timeToBitmapXExact(C.time),
539
- y: o.valueToBitmapYExact(this.effectiveValue(t, r, C.time, C.value))
540
- }, H = G.x, _ = G.y, m = D && p === "grow" ? this.chainedTailPositions(t, r) : null, v = f < 1;
541
- (v || I) && (s.save(), v && (s.globalAlpha *= f), I && (s.globalAlpha *= z));
542
- const b = c.length - 1, T = [];
543
- let x = null;
544
- for (let S = 0; S < b; S++) {
545
- const B = c[S].value;
546
- if (!Number.isFinite(B)) {
547
- x = null;
562
+ if (c.length > y * 2 && (c = q(c, Math.round(y * 1.5))), c.length < 2) continue;
563
+ const k = this.stores[n].last()?.value ?? c[c.length - 1].value, w = this.resolveLayerColor(n, k), B = this.buildThresholdPaint(t, w), L = c[c.length - 1], z = this.stores[n].last(), D = z !== void 0 && L.time === z.time, F = D ? this.entranceProgress(n, L.time) : 1, C = D && m === "fade" && F < 1, O = (D ? this.trailingEndpoint(t, n) : null) ?? {
564
+ x: i.timeToBitmapXExact(L.time),
565
+ y: o.valueToBitmapYExact(this.effectiveValue(t, n, L.time, L.value))
566
+ }, W = O.x, I = O.y, $ = D && m === "grow" ? this.chainedTailPositions(t, n) : null, G = u < 1;
567
+ (G || C) && (s.save(), G && (s.globalAlpha *= u), C && (s.globalAlpha *= F));
568
+ const _ = c.length - 1, h = [];
569
+ let d = null;
570
+ for (let g = 0; g < _; g++) {
571
+ const S = c[g].value;
572
+ if (!o.isPlottable(S)) {
573
+ d = null;
548
574
  continue;
549
575
  }
550
- x || (x = [], T.push(x));
551
- const P = m?.get(c[S].time);
552
- if (P)
553
- x.push({ x: P.x, y: P.y });
576
+ d || (d = [], h.push(d));
577
+ const M = $?.get(c[g].time);
578
+ if (M)
579
+ d.push({ x: M.x, y: M.y });
554
580
  else {
555
- const w = o.valueToBitmapYExact(this.effectiveValue(t, r, c[S].time, B));
556
- x.push({ x: i.timeToBitmapXExact(c[S].time), y: w });
581
+ const Y = o.valueToBitmapYExact(this.effectiveValue(t, n, c[g].time, S));
582
+ d.push({ x: i.timeToBitmapXExact(c[g].time), y: Y });
557
583
  }
558
584
  }
559
- const k = c[b]?.value, L = Number.isFinite(H) && Number.isFinite(_) && Number.isFinite(k), A = p === "grow" && z < 1;
560
- let F = null;
561
- if (L && (x ? (x.push({ x: H, y: _ }), F = x) : T.push([{ x: H, y: _ }])), u && T.some((S) => S.length >= 2)) {
585
+ const b = c[_]?.value, A = Number.isFinite(W) && Number.isFinite(I) && o.isPlottable(b), P = m === "grow" && F < 1;
586
+ let T = null;
587
+ if (A && (d ? (d.push({ x: W, y: I }), T = d) : h.push([{ x: W, y: I }])), f && h.some((g) => g.length >= 2)) {
562
588
  s.beginPath();
563
- for (const S of T)
564
- S.length < 2 || h(d, { points: S, color: M, lineWidth: l, closing: !1, grew: A && S === F });
565
- s.strokeStyle = V ? V.stroke : M, s.lineWidth = l, s.lineJoin = "round", s.lineCap = "round", s.stroke();
589
+ for (const g of h)
590
+ g.length < 2 || p(v, { points: g, color: w, lineWidth: r, closing: !1, grew: P && g === T });
591
+ s.strokeStyle = B ? B.stroke : w, s.lineWidth = r, s.lineJoin = "round", s.lineCap = "round", s.stroke();
566
592
  }
567
- if (u) {
568
- const S = Math.max(1, l / 2);
569
- let B = !1;
570
- for (const P of T)
571
- P.length === 1 && (B || (s.beginPath(), B = !0), s.moveTo(P[0].x + S, P[0].y), s.arc(P[0].x, P[0].y, S, 0, Math.PI * 2));
572
- B && (s.fillStyle = M, s.fill());
593
+ if (f) {
594
+ const g = Math.max(1, r / 2);
595
+ let S = !1;
596
+ for (const M of h)
597
+ M.length === 1 && (S || (s.beginPath(), S = !0), s.moveTo(M[0].x + g, M[0].y), s.arc(M[0].x, M[0].y, g, 0, Math.PI * 2));
598
+ S && (s.fillStyle = w, s.fill());
573
599
  }
574
600
  if (this.options.area.visible && !this.introGhostPass) {
575
- const S = e.bitmapSize.height;
576
- let B;
577
- if (V)
578
- B = V.area;
601
+ const g = e.bitmapSize.height;
602
+ let S;
603
+ if (B)
604
+ S = B.area;
579
605
  else {
580
- const P = String(r), w = this.areaGradientCache.get(P);
581
- w && w.bottomY === S && w.color === M ? B = w.gradient : (B = s.createLinearGradient(0, 0, 0, S), B.addColorStop(0, W(M, 0.12)), B.addColorStop(1, W(M, 0.01)), this.areaGradientCache.set(P, { gradient: B, bottomY: S, color: M }));
606
+ const M = String(n), Y = this.areaGradientCache.get(M);
607
+ Y && Y.bottomY === g && Y.color === w ? S = Y.gradient : (S = s.createLinearGradient(0, 0, 0, g), S.addColorStop(0, X(w, 0.12)), S.addColorStop(1, X(w, 0.01)), this.areaGradientCache.set(M, { gradient: S, bottomY: g, color: w }));
582
608
  }
583
- s.fillStyle = B;
584
- for (const P of T)
585
- P.length < 2 || (s.beginPath(), h(d, { points: P, color: M, lineWidth: l, closing: !0, grew: A && P === F }), s.lineTo(P[P.length - 1].x, S), s.lineTo(P[0].x, S), s.closePath(), s.fill());
609
+ s.fillStyle = S;
610
+ for (const M of h)
611
+ M.length < 2 || (s.beginPath(), p(v, { points: M, color: w, lineWidth: r, closing: !0, grew: P && M === T }), s.lineTo(M[M.length - 1].x, g), s.lineTo(M[0].x, g), s.closePath(), s.fill());
586
612
  }
587
613
  if (this.options.points?.visible) {
588
- const S = [];
589
- for (const B of T)
590
- for (const P of B) S.push(P);
591
- this.drawPointMarkers({ context: s, points: S, pixelRatio: e.horizontalPixelRatio, color: M });
614
+ const g = [];
615
+ for (const S of h)
616
+ for (const M of S) g.push(M);
617
+ this.drawPointMarkers({ context: s, points: g, pixelRatio: e.horizontalPixelRatio, color: w });
592
618
  }
593
- (I || v) && s.restore();
619
+ (C || G) && s.restore();
594
620
  }
595
621
  }
596
622
  /** Stacked area rendering */
597
623
  renderStacked(t, e) {
598
- const { scope: i, timeScale: o, yScale: s } = t, { context: n } = i, a = o.getRange(), { verticalPixelRatio: u } = i, l = this.options.strokeWidth > 0, p = Math.max(1, Math.round(this.options.strokeWidth * u)), h = this.options.curve ?? "straight", d = i.mediaSize.width, r = this.stores.map((m, v) => {
599
- if (this.getLayerAlpha(v) <= 0) return [];
600
- let b = m.getVisibleData(a.from, a.to);
601
- return b.length > d * 2 && (b = K(b, Math.round(d * 1.5))), b;
602
- }), f = /* @__PURE__ */ new Set();
603
- for (const m of r)
604
- for (const v of m) f.add(v.time);
605
- const c = Array.from(f).sort((m, v) => m - v);
624
+ const { scope: i, timeScale: o, yScale: s } = t, { context: l } = i, a = o.getRange(), { verticalPixelRatio: f } = i, r = this.options.strokeWidth > 0, m = Math.max(1, Math.round(this.options.strokeWidth * f)), p = this.options.curve ?? "straight", v = i.mediaSize.width, n = this.stores.map((h, d) => {
625
+ if (this.getLayerAlpha(d) <= 0) return [];
626
+ let b = h.getVisibleData(a.from, a.to);
627
+ return b.length > v * 2 && (b = q(b, Math.round(v * 1.5))), b;
628
+ }), u = /* @__PURE__ */ new Set();
629
+ for (const h of n)
630
+ for (const d of h) u.add(d.time);
631
+ const c = Array.from(u).sort((h, d) => h - d);
606
632
  if (c.length < 2) {
607
633
  this.stackedEdges = null;
608
634
  return;
609
635
  }
610
- const y = this.options.entryAnimation ?? "grow", R = r.map((m, v) => {
636
+ const y = this.options.entryAnimation ?? "grow", k = n.map((h, d) => {
611
637
  const b = /* @__PURE__ */ new Map();
612
- if (m.length === 0) return b;
613
- const T = this.getLayerAlpha(v), x = m[0].time, k = y === "grow" ? this.chainedTailValues(v, (A, F) => this.effectiveValue(t, v, A, F)) : null, L = (A) => k?.get(A.time) ?? this.effectiveValue(t, v, A.time, A.value);
614
- for (const A of c) {
615
- if (A < x) continue;
616
- const F = j(m, A, L);
617
- F !== null && b.set(A, F * T);
638
+ if (h.length === 0) return b;
639
+ const A = h[0].time, P = y === "grow" ? this.chainedTailValues(d, (g, S) => this.effectiveValue(t, d, g, S)) : null, T = (g) => P?.get(g.time) ?? this.effectiveValue(t, d, g.time, g.value);
640
+ for (const g of c) {
641
+ if (g < A) continue;
642
+ const S = j(h, g, { resolve: T });
643
+ S !== null && b.set(g, S);
618
644
  }
619
645
  return b;
620
- }), M = Array.from({ length: this.stores.length }, () => new Array(c.length).fill(0));
621
- for (let m = 0; m < c.length; m++) {
622
- const v = c[m];
646
+ }), w = this.stores.map((h, d) => this.getLayerAlpha(d)), B = (h, d) => {
647
+ const b = k[h].get(d);
648
+ return b === void 0 ? void 0 : b * w[h];
649
+ }, L = s.getTransform() !== null && !e, z = Array.from({ length: this.stores.length }, () => new Array(c.length).fill(0));
650
+ for (let h = 0; h < c.length; h++) {
651
+ const d = c[h];
652
+ if (L) {
653
+ const P = new et(s);
654
+ for (let T = 0; T < this.stores.length; T++) {
655
+ const g = k[T].get(d);
656
+ g !== void 0 && s.isPlottable(g) && P.push(g, w[T]), z[T][h] = P.edge;
657
+ }
658
+ continue;
659
+ }
623
660
  let b = 0;
624
661
  if (e)
625
- for (let x = 0; x < this.stores.length; x++) {
626
- const k = R[x].get(v);
627
- Number.isFinite(k) && (b += k);
662
+ for (let P = 0; P < this.stores.length; P++) {
663
+ const T = B(P, d);
664
+ T !== void 0 && s.isPlottable(T) && (b += T);
628
665
  }
629
- let T = 0;
630
- for (let x = 0; x < this.stores.length; x++) {
631
- const k = R[x].get(v), L = Number.isFinite(k) ? k : 0;
632
- T += e && b > 0 ? L / b * 100 : L, M[x][m] = T;
666
+ let A = 0;
667
+ for (let P = 0; P < this.stores.length; P++) {
668
+ const T = B(P, d), g = T !== void 0 && s.isPlottable(T) ? T : 0;
669
+ A += e && b > 0 ? g / b * 100 : g, z[P][h] = A;
633
670
  }
634
671
  }
635
- const V = /* @__PURE__ */ new Map();
636
- for (let m = 0; m < c.length; m++) V.set(c[m], m);
637
- const C = new Array(this.stores.length).fill(1);
638
- for (let m = 0; m < this.stores.length; m++) {
639
- if (this.getLayerAlpha(m) <= 0) continue;
640
- const v = this.unsettledTail(m), b = v.length;
672
+ const D = /* @__PURE__ */ new Map();
673
+ for (let h = 0; h < c.length; h++) D.set(c[h], h);
674
+ const F = new Array(this.stores.length).fill(1);
675
+ for (let h = 0; h < this.stores.length; h++) {
676
+ if (this.getLayerAlpha(h) <= 0) continue;
677
+ const d = this.unsettledTail(h), b = d.length;
641
678
  if (b === 0) continue;
642
- let T = !0;
643
- for (let x = 0; x < b; x++)
644
- if (V.get(v[x].time) !== c.length - b + x) {
645
- T = !1;
679
+ let A = !0;
680
+ for (let P = 0; P < b; P++)
681
+ if (D.get(d[P].time) !== c.length - b + P) {
682
+ A = !1;
646
683
  break;
647
684
  }
648
- T && (C[m] = v[b - 1].progress);
685
+ A && (F[h] = d[b - 1].progress);
649
686
  }
650
- const N = [];
687
+ const C = [];
651
688
  if (y === "grow") {
652
- const m = r.map((v) => v.length - 1);
653
- for (let v = c.length - 1; v >= 1; v--) {
654
- const b = c[v];
655
- let T = 1, x = !1;
656
- for (let k = 0; k < r.length; k++) {
657
- if (this.getLayerAlpha(k) <= 0) continue;
658
- const L = r[k];
659
- for (; m[k] >= 0 && L[m[k]].time > b; ) m[k]--;
660
- if (m[k] < 0 || L[m[k]].time !== b) continue;
661
- const A = this.entranceProgress(k, b);
662
- (!x || A > T) && (T = A), x = !0;
689
+ const h = n.map((d) => d.length - 1);
690
+ for (let d = c.length - 1; d >= 1; d--) {
691
+ const b = c[d];
692
+ let A = 1, P = !1;
693
+ for (let T = 0; T < n.length; T++) {
694
+ if (this.getLayerAlpha(T) <= 0) continue;
695
+ const g = n[T];
696
+ for (; h[T] >= 0 && g[h[T]].time > b; ) h[T]--;
697
+ if (h[T] < 0 || g[h[T]].time !== b) continue;
698
+ const S = this.entranceProgress(T, b);
699
+ (!P || S > A) && (A = S), P = !0;
663
700
  }
664
- if (!x || T >= 1) break;
665
- N.unshift(U(T));
701
+ if (!P || A >= 1) break;
702
+ C.unshift(U(A));
666
703
  }
667
704
  }
668
- const D = (m, v) => {
669
- const b = v.length;
670
- if (!(b === 0 || m.length < b + 1))
671
- for (let T = 0; T < b; T++) {
672
- const x = m.length - b + T;
673
- m[x][0] = Y(m[x - 1][0], m[x][0], v[T]);
705
+ const O = (h, d) => {
706
+ const b = d.length;
707
+ if (!(b === 0 || h.length < b + 1))
708
+ for (let A = 0; A < b; A++) {
709
+ const P = h.length - b + A;
710
+ h[P][0] = N(h[P - 1][0], h[P][0], d[A]);
674
711
  }
675
- }, z = i.bitmapSize.height;
676
- let I = -1, G = -1;
677
- for (let m = 0; m < this.stores.length; m++)
678
- if (!(this.getLayerAlpha(m) <= 0))
712
+ }, W = i.bitmapSize.height;
713
+ let I = -1, $ = -1;
714
+ for (let h = 0; h < this.stores.length; h++)
715
+ if (!(this.getLayerAlpha(h) <= 0))
679
716
  if (I < 0)
680
- I = m;
717
+ I = h;
681
718
  else {
682
- G = m;
719
+ $ = h;
683
720
  break;
684
721
  }
685
- const H = I >= 0 ? this.getLayerAlpha(I) : 1, _ = r.map((m, v) => v === I ? Math.min(1, this.getLayerAlpha(v)) : 1);
686
- for (let m = this.stores.length - 1; m >= 0; m--) {
687
- const v = this.getLayerAlpha(m);
688
- if (v <= 0) continue;
689
- const b = this.stores[m].last()?.value ?? 0, T = this.resolveLayerColor(m, b), x = m === I, k = G >= 0 && m === G && H < 1, L = [];
690
- for (let w = 0; w < c.length; w++) {
691
- const X = m > 0 ? s.valueToBitmapYExact(M[m - 1][w]) : z;
692
- let O = X;
693
- x ? O = z : k && (O = X + (z - X) * (1 - H)), L.push([o.timeToBitmapXExact(c[w]), O]);
722
+ const G = I >= 0 ? this.getLayerAlpha(I) : 1, _ = n.map((h, d) => d === I ? Math.min(1, this.getLayerAlpha(d)) : 1);
723
+ for (let h = this.stores.length - 1; h >= 0; h--) {
724
+ const d = this.getLayerAlpha(h);
725
+ if (d <= 0) continue;
726
+ const b = this.stores[h].last()?.value ?? 0, A = this.resolveLayerColor(h, b), P = h === I, T = $ >= 0 && h === $ && G < 1, g = [];
727
+ for (let R = 0; R < c.length; R++) {
728
+ const V = h > 0 ? s.valueToBitmapYExact(z[h - 1][R]) : W;
729
+ let H = V;
730
+ P ? H = W : T && (H = V + (W - V) * (1 - G)), g.push([o.timeToBitmapXExact(c[R]), H]);
694
731
  }
695
- y === "grow" && D(L, N);
696
- const A = [];
697
- for (let w = 0; w < c.length; w++) {
698
- let X = s.valueToBitmapYExact(M[m][w]);
699
- x && v < 1 && (X = z + (X - z) * v), A.push([o.timeToBitmapXExact(c[w]), X]);
732
+ y === "grow" && O(g, C);
733
+ const S = [];
734
+ for (let R = 0; R < c.length; R++) {
735
+ let V = s.valueToBitmapYExact(z[h][R]);
736
+ P && d < 1 && (V = W + (V - W) * d), S.push([o.timeToBitmapXExact(c[R]), V]);
700
737
  }
701
- y === "grow" && D(A, N);
702
- const F = $(A), S = Q(F, h, y === "grow" && N.length > 0), B = y === "fade" && C[m] < 1;
703
- if (B && (n.save(), n.globalAlpha *= C[m]), this.options.area.visible && !this.introGhostPass) {
704
- let w = A[0][1], X = L[0][1];
705
- for (let E = 1; E < A.length; E++)
706
- A[E][1] < w && (w = A[E][1]);
707
- for (let E = 1; E < L.length; E++)
708
- L[E][1] > X && (X = L[E][1]);
709
- let O = W(T, 0.25);
710
- if (X > w + 0.5) {
711
- const E = n.createLinearGradient(0, w, 0, X);
712
- E.addColorStop(0, W(T, 0.25)), E.addColorStop(1, W(T, 0.05)), O = E;
738
+ y === "grow" && O(S, C);
739
+ const M = ot(S), Y = tt(M, p, y === "grow" && C.length > 0), K = y === "fade" && F[h] < 1;
740
+ if (K && (l.save(), l.globalAlpha *= F[h]), this.options.area.visible && !this.introGhostPass) {
741
+ let R = S[0][1], V = g[0][1];
742
+ for (let E = 1; E < S.length; E++)
743
+ S[E][1] < R && (R = S[E][1]);
744
+ for (let E = 1; E < g.length; E++)
745
+ g[E][1] > V && (V = g[E][1]);
746
+ let H = X(A, 0.25);
747
+ if (V > R + 0.5) {
748
+ const E = l.createLinearGradient(0, R, 0, V);
749
+ E.addColorStop(0, X(A, 0.25)), E.addColorStop(1, X(A, 0.05)), H = E;
713
750
  }
714
- if (n.beginPath(), n.moveTo(F[0].x, F[0].y), tt(n, S), x)
715
- for (let E = L.length - 1; E >= 0; E--)
716
- n.lineTo(L[E][0], L[E][1]);
751
+ if (l.beginPath(), l.moveTo(M[0].x, M[0].y), st(l, Y), P)
752
+ for (let E = g.length - 1; E >= 0; E--)
753
+ l.lineTo(g[E][0], g[E][1]);
717
754
  else {
718
- const E = $(L), rt = Q(E, h, y === "grow" && N.length > 0), q = E[E.length - 1];
719
- n.lineTo(q.x, q.y), ft(n, E, rt);
755
+ const E = ot(g), ct = tt(E, p, y === "grow" && C.length > 0), Z = E[E.length - 1];
756
+ l.lineTo(Z.x, Z.y), yt(l, E, ct);
720
757
  }
721
- n.closePath(), n.fillStyle = O, n.fill();
758
+ l.closePath(), l.fillStyle = H, l.fill();
722
759
  }
723
- const P = l && v < 1;
724
- if (P && (n.save(), n.globalAlpha *= v), l && (n.beginPath(), n.moveTo(F[0].x, F[0].y), tt(n, S), n.strokeStyle = T, n.lineWidth = p, n.lineJoin = "round", n.lineCap = "round", n.stroke()), P && n.restore(), this.options.points?.visible) {
725
- const w = v < 1;
726
- w && (n.save(), n.globalAlpha *= v), this.drawPointMarkers({ context: n, points: F, pixelRatio: i.horizontalPixelRatio, color: T }), w && n.restore();
760
+ const Q = r && d < 1;
761
+ if (Q && (l.save(), l.globalAlpha *= d), r && (l.beginPath(), l.moveTo(M[0].x, M[0].y), st(l, Y), l.strokeStyle = A, l.lineWidth = m, l.lineJoin = "round", l.lineCap = "round", l.stroke()), Q && l.restore(), this.options.points?.visible) {
762
+ const R = d < 1;
763
+ R && (l.save(), l.globalAlpha *= d), this.drawPointMarkers({ context: l, points: M, pixelRatio: i.horizontalPixelRatio, color: A }), R && l.restore();
727
764
  }
728
- B && n.restore();
765
+ K && l.restore();
729
766
  }
730
- this.stackedEdges = { times: c, cumulative: M, growChain: N, collapse: _ };
767
+ this.stackedEdges = { times: c, cumulative: z, growChain: C, collapse: _ };
731
768
  }
732
769
  /**
733
770
  * Overlay hook: draws crosshair nearest-point dots and last-point pulse dots.
@@ -735,54 +772,55 @@ class dt extends at {
735
772
  */
736
773
  drawOverlay(t) {
737
774
  this.tickAnimations(performance.now());
738
- const { scope: e, timeScale: i, yScale: o, crosshair: s, dataInterval: n } = t, a = e, u = this.options.pulseMs, l = u > 0 ? performance.now() / (u * 2 * Math.PI) % 1 : 0;
775
+ const { scope: e, timeScale: i, yScale: o, crosshair: s, dataInterval: l } = t, a = e, f = this.options.pulseMs, r = f > 0 ? performance.now() / (f * 2 * Math.PI) % 1 : 0;
739
776
  if (s) {
740
- const d = this.options.stacking, r = 4 * a.horizontalPixelRatio;
741
- for (let f = 0; f < this.stores.length; f++) {
742
- const c = this.getLayerAlpha(f);
777
+ const v = this.options.stacking, n = 4 * a.horizontalPixelRatio;
778
+ for (let u = 0; u < this.stores.length; u++) {
779
+ const c = this.getLayerAlpha(u);
743
780
  if (c <= 0) continue;
744
- const y = this.stores[f].findNearest(s.time, n);
745
- if (!y) continue;
746
- const R = this.resolveLayerColor(f, y.value), { x: M, y: V } = d === "off" ? {
781
+ const y = this.stores[u].findNearest(s.time, l);
782
+ if (!y || v === "off" && !o.isPlottable(y.value)) continue;
783
+ const k = this.resolveLayerColor(u, y.value), { x: w, y: B } = v === "off" ? {
747
784
  x: i.timeToBitmapXExact(y.time),
748
- y: o.valueToBitmapYExact(this.effectiveValue(t, f, y.time, y.value))
749
- } : this.stackedPositionAt(t, f, y.time), C = c < 1;
750
- C && (e.context.save(), e.context.globalAlpha *= c), e.context.save(), e.context.globalAlpha *= 0.25, e.context.beginPath(), e.context.arc(M, V, r + 3 * a.horizontalPixelRatio, 0, Math.PI * 2), e.context.fillStyle = R, e.context.fill(), e.context.restore(), e.context.beginPath(), e.context.arc(M, V, r, 0, Math.PI * 2), e.context.fillStyle = R, e.context.fill(), C && e.context.restore();
785
+ y: o.valueToBitmapYExact(this.effectiveValue(t, u, y.time, y.value))
786
+ } : this.stackedPositionAt(t, u, y.time), L = c < 1;
787
+ L && (e.context.save(), e.context.globalAlpha *= c), e.context.save(), e.context.globalAlpha *= 0.25, e.context.beginPath(), e.context.arc(w, B, n + 3 * a.horizontalPixelRatio, 0, Math.PI * 2), e.context.fillStyle = k, e.context.fill(), e.context.restore(), e.context.beginPath(), e.context.arc(w, B, n, 0, Math.PI * 2), e.context.fillStyle = k, e.context.fill(), L && e.context.restore();
751
788
  }
752
789
  }
753
- const p = this.introWave.active && this.introDirectives?.clip !== void 0;
754
- let h = 1;
755
- if (p && (h = Math.max(0, (this.introWave.linear() - (1 - J)) / J)), this.hasPulse && u > 0 && h > 0) {
756
- const d = this.options.stacking;
757
- for (let r = 0; r < this.stores.length; r++) {
758
- const f = this.getLayerAlpha(r);
759
- if (f <= 0) continue;
760
- const c = this.stores[r].last()?.value ?? 0, y = this.resolveLayerColor(r, c);
761
- if (d === "off") {
762
- const C = this.trailingEndpoint(t, r);
763
- if (!C) continue;
790
+ const m = this.introWave.active && this.introDirectives?.clip !== void 0;
791
+ let p = 1;
792
+ if (m && (p = Math.max(0, (this.introWave.linear() - (1 - J)) / J)), this.hasPulse && f > 0 && p > 0) {
793
+ const v = this.options.stacking;
794
+ for (let n = 0; n < this.stores.length; n++) {
795
+ const u = this.getLayerAlpha(n);
796
+ if (u <= 0) continue;
797
+ const c = this.stores[n].last()?.value ?? 0, y = this.resolveLayerColor(n, c);
798
+ if (v === "off") {
799
+ if (!o.isPlottable(c)) continue;
800
+ const L = this.trailingEndpoint(t, n);
801
+ if (!L) continue;
764
802
  this.drawPulse({
765
803
  ctx: e.context,
766
- x: C.x,
767
- y: C.y,
804
+ x: L.x,
805
+ y: L.y,
768
806
  color: y,
769
807
  pixelRatio: a.horizontalPixelRatio,
770
- phase: l,
771
- alpha: f * h
808
+ phase: r,
809
+ alpha: u * p
772
810
  });
773
811
  continue;
774
812
  }
775
- const R = this.stores[r].last();
776
- if (!R) continue;
777
- const { x: M, y: V } = this.stackedPositionAt(t, r, R.time);
813
+ const k = this.stores[n].last();
814
+ if (!k) continue;
815
+ const { x: w, y: B } = this.stackedPositionAt(t, n, k.time);
778
816
  this.drawPulse({
779
817
  ctx: e.context,
780
- x: M,
781
- y: V,
818
+ x: w,
819
+ y: B,
782
820
  color: y,
783
821
  pixelRatio: a.horizontalPixelRatio,
784
- phase: l,
785
- alpha: f * h
822
+ phase: r,
823
+ alpha: u * p
786
824
  });
787
825
  }
788
826
  }
@@ -793,22 +831,22 @@ class dt extends at {
793
831
  y: i,
794
832
  color: o,
795
833
  pixelRatio: s,
796
- phase: n,
834
+ phase: l,
797
835
  alpha: a = 1
798
836
  }) {
799
- const u = 3 * s, l = 0.4 + 0.6 * Math.abs(Math.sin(n * 2 * Math.PI)), p = u + 4 * s * l, h = a < 1;
800
- h && (t.save(), t.globalAlpha *= a), t.beginPath(), t.arc(e, i, p, 0, Math.PI * 2), t.fillStyle = W(o, l * 0.3), t.fill(), t.beginPath(), t.arc(e, i, u, 0, Math.PI * 2), t.fillStyle = o, t.fill(), h && t.restore();
837
+ const f = 3 * s, r = 0.4 + 0.6 * Math.abs(Math.sin(l * 2 * Math.PI)), m = f + 4 * s * r, p = a < 1;
838
+ p && (t.save(), t.globalAlpha *= a), t.beginPath(), t.arc(e, i, m, 0, Math.PI * 2), t.fillStyle = X(o, r * 0.3), t.fill(), t.beginPath(), t.arc(e, i, f, 0, Math.PI * 2), t.fillStyle = o, t.fill(), p && t.restore();
801
839
  }
802
840
  }
803
- const wt = {
841
+ const Bt = {
804
842
  type: "line",
805
- create: ({ theme: g, layerCount: t }, e) => new dt(t, {
806
- colors: t === 1 ? [g.line.color] : g.seriesColors.slice(0, t),
807
- strokeWidth: g.line.width,
843
+ create: ({ theme: x, layerCount: t }, e) => new bt(t, {
844
+ colors: t === 1 ? [x.line.color] : x.seriesColors.slice(0, t),
845
+ strokeWidth: x.line.width,
808
846
  ...e
809
847
  })
810
848
  };
811
849
  export {
812
- dt as LineRenderer,
813
- wt as LineSeriesDef
850
+ bt as LineRenderer,
851
+ Bt as LineSeriesDef
814
852
  };