@wick-charts/vue 0.6.0 → 0.6.2

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.
@@ -1,74 +1,83 @@
1
- import { DEFAULT_HISTORY_REVEAL as tt, DEFAULT_LINE_INTRO as et, DEFAULT_LINE_PULSE as it, DEFAULT_LINE_SMOOTH as ot, DEFAULT_LINE_ENTRY as st } from "../animation/config.js";
2
- import { easeOutCubic as _ } from "../animation/easing.js";
3
- import { decimateLineData as j } from "../data/decimation.js";
4
- import { hexToRgba as C } from "../utils/color.js";
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";
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
5
  import { lerp as Y } from "../utils/math.js";
6
- import { BaseMultiLayerSeries as rt } from "./base-multi-layer.js";
7
- import { unfoldIntro as lt, backfillSweepIntro as at } from "./line-intro.js";
8
- import { buildCurveSegments as q } from "./painters/canvas-path.js";
9
- import { resolveLinePainter as ht } from "./painters/resolve.js";
10
- const ct = {
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 = {
11
11
  colors: ["#2962FF"],
12
12
  strokeWidth: 1,
13
13
  area: { visible: !0 },
14
14
  pulse: !0,
15
15
  stacking: "off",
16
16
  curve: "straight",
17
- entryMs: st,
18
- smoothMs: ot,
19
- pulseMs: it,
20
- introMs: et,
21
- historyRevealMs: tt
17
+ entryMs: nt,
18
+ smoothMs: st,
19
+ pulseMs: ot,
20
+ introMs: it,
21
+ historyRevealMs: et
22
22
  };
23
- function Q(v) {
24
- const t = v.areaFill, e = t !== void 0 && v.area === void 0 ? { visible: !!t } : v.area;
23
+ function Z(g) {
24
+ const t = g.areaFill, e = t !== void 0 && g.area === void 0 ? { visible: !!t } : g.area;
25
25
  return {
26
- ...v,
26
+ ...g,
27
27
  area: e,
28
- entryMs: v.entryMs === !1 ? 0 : v.entryMs ?? st,
29
- smoothMs: v.smoothMs === !1 ? 0 : v.smoothMs ?? ot,
30
- pulseMs: v.pulseMs === !1 ? 0 : v.pulseMs ?? it,
31
- introMs: v.introMs === !1 ? 0 : v.introMs ?? et,
32
- historyRevealMs: v.historyRevealMs === !1 ? 0 : v.historyRevealMs ?? tt
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
33
33
  };
34
34
  }
35
- function Z(v) {
36
- return v.map(([t, e]) => ({ x: t, y: e }));
35
+ function $(g) {
36
+ return g.map(([t, e]) => ({ x: t, y: e }));
37
37
  }
38
- const $ = 0.15, ut = at();
39
- function U(v, t, e) {
40
- if (v.length === 0) return null;
41
- if (t <= v[0].time) return Number.isFinite(v[0].value) ? e(v[0]) : null;
42
- const i = v[v.length - 1];
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
43
  if (t >= i.time) return Number.isFinite(i.value) ? e(i) : null;
44
- let s = 0, o = v.length - 1;
45
- for (; o - s > 1; ) {
46
- const a = s + o >> 1;
47
- v[a].time <= t ? s = a : o = a;
48
- }
49
- const n = v[s], r = v[o];
50
- if (!Number.isFinite(n.value) || !Number.isFinite(r.value)) return null;
51
- const l = r.time - n.time;
52
- return l <= 0 ? e(n) : Y(e(n), e(r), (t - n.time) / l);
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);
53
53
  }
54
- function K(v, t) {
54
+ function pt(g, t) {
55
+ let e = 0, i = g.length - 1;
56
+ for (; e <= i; ) {
57
+ const o = e + i >> 1;
58
+ if (g[o] === t) return o;
59
+ g[o] < t ? e = o + 1 : i = o - 1;
60
+ }
61
+ return -1;
62
+ }
63
+ function tt(g, t) {
55
64
  for (const e of t)
56
- e.kind === "line" ? v.lineTo(e.x, e.y) : v.bezierCurveTo(e.cp1x, e.cp1y, e.cp2x, e.cp2y, e.x, e.y);
65
+ e.kind === "line" ? g.lineTo(e.x, e.y) : g.bezierCurveTo(e.cp1x, e.cp1y, e.cp2x, e.cp2y, e.x, e.y);
57
66
  }
58
- function ft(v, t, e) {
67
+ function ft(g, t, e) {
59
68
  for (let i = e.length - 1; i >= 0; i--) {
60
- const s = e[i], o = i > 0 ? e[i - 1] : t[0];
61
- s.kind === "line" ? v.lineTo(o.x, o.y) : v.bezierCurveTo(s.cp2x, s.cp2y, s.cp1x, s.cp1y, o.x, o.y);
69
+ 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);
62
71
  }
63
72
  }
64
- class mt extends rt {
73
+ class dt extends at {
65
74
  kind = "line";
66
75
  areaGradientCache = /* @__PURE__ */ new Map();
67
76
  constructor(t, e) {
68
- super(t), this.options = Q({ ...ct, ...e });
77
+ super(t), this.options = Z({ ...ut, ...e });
69
78
  }
70
79
  updateOptions(t) {
71
- this.options = Q({ ...this.options, ...t });
80
+ this.options = Z({ ...this.options, ...t });
72
81
  }
73
82
  getStacking() {
74
83
  return this.options.stacking;
@@ -89,8 +98,8 @@ class mt extends rt {
89
98
  hasOverlayContentInRange(t, e) {
90
99
  for (let i = 0; i < this.stores.length; i++) {
91
100
  if (this.getLayerAlpha(i) <= 0) continue;
92
- const s = this.stores[i].last();
93
- if (s && s.time >= t) return !0;
101
+ const o = this.stores[i].last();
102
+ if (o && o.time >= t) return !0;
94
103
  }
95
104
  return !1;
96
105
  }
@@ -100,13 +109,13 @@ class mt extends rt {
100
109
  this.historyDirectives = null;
101
110
  const i = this.historyRange;
102
111
  if (this.historyWave.active && i !== null) {
103
- const r = this.options.historyReveal ?? ut;
104
- r !== "none" && (this.historyDirectives = r(this.buildHistoryFrame(t, i)));
112
+ const a = this.options.historyReveal ?? mt;
113
+ a !== "none" && (this.historyDirectives = a(this.buildHistoryFrame(t, i)));
105
114
  }
106
- const s = this.historyDirectives, o = s?.ghostAlpha ?? 0;
107
- o > 0 && (e.save(), e.globalAlpha *= o, this.introGhostPass = !0, this.renderBody(t), this.introGhostPass = !1, e.restore());
108
- const n = this.applyHistoryClip(t, s, i);
109
- this.introWave.active ? this.renderWithIntro(t) : (this.introDirectives = null, this.renderBody(t)), n && e.restore(), s?.heads !== void 0 && s.heads.length > 0 && this.drawIntroHeads(t, s.heads, this.historyWave.linear());
115
+ const o = this.historyDirectives, s = o?.ghostAlpha ?? 0;
116
+ 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());
110
119
  }
111
120
  /**
112
121
  * Initial-load intro pass: the resolved LineIntroFn describes this frame
@@ -116,14 +125,14 @@ class mt extends rt {
116
125
  renderWithIntro(t) {
117
126
  const e = this.resolveIntro()(this.buildIntroFrame(t));
118
127
  this.introDirectives = e;
119
- const { context: i } = t.scope, { width: s, height: o } = t.scope.bitmapSize, n = e.ghostAlpha ?? 0;
128
+ const { context: i } = t.scope, { width: o, height: s } = t.scope.bitmapSize, n = e.ghostAlpha ?? 0;
120
129
  n > 0 && (i.save(), i.globalAlpha *= n, this.introGhostPass = !0, this.renderBody(t), this.introGhostPass = !1, i.restore());
121
- const r = e.clip, l = r !== void 0 && (r.fromX !== void 0 || r.toX !== void 0);
122
- if (l) {
123
- const a = r.fromX ?? 0, p = r.toX ?? s;
124
- i.save(), i.beginPath(), i.rect(a, 0, Math.max(0, p - a), o), i.clip();
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();
125
134
  }
126
- this.renderBody(t), l && i.restore(), e.heads !== void 0 && e.heads.length > 0 && this.drawIntroHeads(t, e.heads, this.introWave.linear());
135
+ this.renderBody(t), u && i.restore(), e.heads !== void 0 && e.heads.length > 0 && this.drawIntroHeads(t, e.heads, this.introWave.linear());
127
136
  }
128
137
  /**
129
138
  * Apply the history reveal's clip directive, mapped from reveal space
@@ -132,14 +141,22 @@ class mt extends rt {
132
141
  * small pad keeps the stroke cap at the reveal front from being shaved.
133
142
  */
134
143
  applyHistoryClip(t, e, i) {
135
- const s = e?.clip;
136
- if (s === void 0 || i === null || s.fromX === void 0 && s.toX === void 0) return !1;
137
- const { context: o } = t.scope, { width: n, height: r } = t.scope.bitmapSize, l = t.timeScale.timeToBitmapX(i.to), a = Math.abs(l - t.timeScale.timeToBitmapX(i.from)), p = Math.max(2, (this.options.strokeWidth ?? 1) * t.scope.horizontalPixelRatio), f = s.fromX ?? 0, y = s.toX ?? a;
138
- return o.save(), o.beginPath(), o.rect(l - y - p, 0, Math.max(0, y - f + p), r), o.rect(l, 0, Math.max(0, n - l), r), o.clip(), !0;
144
+ const o = e?.clip;
145
+ 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;
139
148
  }
140
149
  renderBody(t) {
141
- this.options.stacking === "off" ? this.renderOff(t) : this.renderStacked(t, this.options.stacking === "percent");
150
+ this.options.stacking === "off" ? (this.stackedEdges = null, this.renderOff(t)) : this.renderStacked(t, this.options.stacking === "percent");
142
151
  }
152
+ /**
153
+ * What the stacked pass drew this frame, in data space — shared columns,
154
+ * their eased cumulative per layer, and the per-column grow chain. Lets the
155
+ * overlay's dots reproduce the painted geometry against its own scales
156
+ * instead of re-deriving the entrance from a different chain.
157
+ * `null` when the stacked path didn't run.
158
+ */
159
+ stackedEdges = null;
143
160
  /** True while a ghost pre-pass is drawing — skips the area fill so the
144
161
  * translucent pass shows only the stroke skeleton. */
145
162
  introGhostPass = !1;
@@ -181,54 +198,56 @@ class mt extends rt {
181
198
  return this.buildFrame(t, {
182
199
  progress: this.historyWave.linear(),
183
200
  range: e,
184
- width: Math.abs(t.timeScale.timeToBitmapX(e.to) - t.timeScale.timeToBitmapX(e.from))
201
+ width: Math.abs(
202
+ t.timeScale.timeToBitmapXExact(e.to) - t.timeScale.timeToBitmapXExact(e.from)
203
+ )
185
204
  });
186
205
  }
187
206
  buildFrame(t, e) {
188
- const { timeScale: i, yScale: s, scope: o } = t, { progress: n, range: r, width: l } = e, a = new Array(this.stores.length), p = new Array(this.stores.length);
189
- let f;
190
- const y = (h) => {
191
- let m = a[h];
192
- return m === void 0 && (m = this.stores[h]?.getVisibleData(r.from, r.to) ?? [], a[h] = m), m;
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;
193
212
  };
194
213
  return {
195
214
  progress: n,
196
- range: r,
197
- width: l,
198
- height: s.getMediaHeight() * o.verticalPixelRatio,
215
+ range: a,
216
+ width: u,
217
+ height: o.getMediaHeight() * s.verticalPixelRatio,
199
218
  stacking: this.options.stacking,
200
- timeToX: (h) => i.timeToBitmapX(h),
201
- xToTime: (h) => i.xToTime(h / o.horizontalPixelRatio),
202
- valueToY: (h) => s.valueToBitmapY(h),
219
+ timeToX: (r) => i.timeToBitmapXExact(r),
220
+ xToTime: (r) => i.xToTime(r / s.horizontalPixelRatio),
221
+ valueToY: (r) => o.valueToBitmapYExact(r),
203
222
  layerCount: this.stores.length,
204
- layerData: y,
205
- layerMean: (h) => {
206
- let m = p[h];
207
- if (m === void 0) {
208
- let u = 0, A = 0;
209
- for (const R of y(h))
210
- Number.isFinite(R.value) && (u += R.value, A++);
211
- m = A > 0 ? u / A : null, p[h] = m;
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;
212
231
  }
213
- return m;
232
+ return f;
214
233
  },
215
234
  primaryPath: () => {
216
- if (f === void 0) {
217
- f = null;
218
- for (let h = 0; h < this.stores.length; h++) {
219
- if (this.getLayerAlpha(h) <= 0 || !this.stores[h].isVisible()) continue;
220
- const m = y(h).filter((u) => Number.isFinite(u.value));
221
- if (!(m.length < 2)) {
222
- f = m.map((u) => ({
223
- x: i.timeToBitmapX(u.time),
224
- y: s.valueToBitmapY(u.value),
225
- time: u.time
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) => ({
242
+ x: i.timeToBitmapXExact(c.time),
243
+ y: o.valueToBitmapYExact(c.value),
244
+ time: c.time
226
245
  }));
227
246
  break;
228
247
  }
229
248
  }
230
249
  }
231
- return f;
250
+ return h;
232
251
  }
233
252
  };
234
253
  }
@@ -238,16 +257,16 @@ class mt extends rt {
238
257
  * overlay pulse) already flows through `effectiveValue`, so one override
239
258
  * animates the whole geometry.
240
259
  */
241
- effectiveValue(t, e, i, s) {
242
- const o = super.effectiveValue(t, e, i, s), n = this.historyWave.active ? this.historyDirectives?.value : void 0, r = this.historyRange;
243
- if (n !== void 0 && r !== null && i < r.to) {
244
- const y = r.to - r.from, h = y > 0 ? Math.min(1, Math.max(0, (r.to - i) / y)) : 0;
245
- return n({ layerIndex: e, time: i, value: o, position: h });
260
+ 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 });
246
265
  }
247
- const l = this.introWave.active ? this.introDirectives?.value : void 0;
248
- if (l === void 0) return o;
249
- const a = t.timeScale.getRange(), p = a.to - a.from, f = p > 0 ? Math.min(1, Math.max(0, (i - a.from) / p)) : 0;
250
- return l({ layerIndex: e, time: i, value: o, position: f });
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 });
251
270
  }
252
271
  /**
253
272
  * Extends the base last-value query with the 'grow' entrance's value-space
@@ -259,26 +278,30 @@ class mt extends rt {
259
278
  * before the marker visually arrives there.
260
279
  */
261
280
  snapshotValue(t, e, i) {
262
- const s = super.snapshotValue(t, e, i);
263
- return (this.options.entryAnimation ?? "grow") !== "grow" ? s : this.chainedTailValues(t)?.get(e) ?? s;
264
- }
265
- /** Value-space counterpart of {@link chainedTailPositions} — see {@link snapshotValue}. */
266
- chainedTailValues(t) {
267
- const e = this.unsettledTail(t);
268
- if (e.length === 0) return null;
269
- const i = this.stores[t].getAll(), s = i.length - 1 - e.length;
281
+ const o = super.snapshotValue(t, e, i);
282
+ return (this.options.entryAnimation ?? "grow") !== "grow" ? o : this.chainedTailValues(t)?.get(e) ?? o;
283
+ }
284
+ /**
285
+ * Value-space counterpart of {@link chainedTailPositions} — see {@link snapshotValue}.
286
+ * `resolve` lets the stacked renderer feed its ctx-aware `effectiveValue`
287
+ * in; query paths, which have no render context, keep the `liveValue` default.
288
+ */
289
+ chainedTailValues(t, e = (i, o) => this.liveValue(t, i, o)) {
290
+ const i = this.unsettledTail(t);
291
+ if (i.length === 0) return null;
292
+ const o = this.stores[t].getAll(), s = o.length - 1 - i.length;
270
293
  if (s < 0) return null;
271
- const o = i[s];
272
- if (!Number.isFinite(o.value)) return null;
273
- let n = this.liveValue(t, o.time, o.value);
274
- const r = /* @__PURE__ */ new Map();
275
- for (let l = 0; l < e.length; l++) {
276
- const a = i[s + 1 + l];
277
- if (!Number.isFinite(a.value)) return null;
278
- const p = _(e[l].progress), f = this.liveValue(t, a.time, a.value), y = Y(n, f, p);
279
- r.set(a.time, y), n = y;
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;
280
303
  }
281
- return r;
304
+ return u;
282
305
  }
283
306
  /**
284
307
  * Glowing pulse dots riding the intro's head anchors — the line reads as
@@ -288,20 +311,20 @@ class mt extends rt {
288
311
  */
289
312
  drawIntroHeads(t, e, i) {
290
313
  if (this.options.stacking !== "off") return;
291
- const s = Math.min(1, i / $), o = Math.min(1, (1 - i) / $), n = Math.max(0, Math.min(s, o));
314
+ const o = Math.min(1, i / J), s = Math.min(1, (1 - i) / J), n = Math.max(0, Math.min(o, s));
292
315
  if (n <= 0) return;
293
- const { scope: r } = t;
294
- for (const l of e)
295
- for (let a = 0; a < this.stores.length; a++) {
296
- const p = this.getLayerAlpha(a);
297
- if (p <= 0 || !this.stores[a].isVisible()) continue;
298
- const f = this.introHeadAnchor(t, a, l);
299
- f !== null && this.drawPulse({
300
- ctx: r.context,
301
- x: f.x,
302
- y: f.y,
303
- color: this.resolveLayerColor(a, f.value),
304
- pixelRatio: r.horizontalPixelRatio,
316
+ 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({
323
+ ctx: a.context,
324
+ x: h.x,
325
+ y: h.y,
326
+ color: this.resolveLayerColor(l, h.value),
327
+ pixelRatio: a.horizontalPixelRatio,
305
328
  phase: i * 2,
306
329
  alpha: n * p
307
330
  });
@@ -319,22 +342,26 @@ class mt extends rt {
319
342
  * visible range, not the data span) and jumps back on settle.
320
343
  */
321
344
  introHeadAnchor(t, e, i) {
322
- const { timeScale: s, yScale: o } = t, n = s.getRange(), r = this.stores[e].getVisibleData(n.from, n.to);
323
- if (r.length === 0) return null;
324
- const l = this.stores[e].last();
325
- if (l !== void 0 && i.time >= l.time) {
326
- if (!Number.isFinite(l.value)) return null;
327
- const f = this.trailingEndpoint(t, e);
328
- return f === null ? null : { x: f.x, y: f.y, value: l.value };
345
+ const { timeScale: o, yScale: s } = t, n = o.getRange(), a = this.stores[e].getVisibleData(n.from, n.to);
346
+ 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 };
329
352
  }
330
- const a = r[0];
331
- if (i.time <= a.time) {
332
- if (!Number.isFinite(a.value)) return null;
333
- const f = this.effectiveValue(t, e, a.time, a.value);
334
- return { x: s.timeToBitmapX(a.time), y: o.valueToBitmapY(f), value: a.value };
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);
357
+ return {
358
+ x: o.timeToBitmapXExact(l.time),
359
+ y: s.valueToBitmapYExact(h),
360
+ value: l.value
361
+ };
335
362
  }
336
- const p = U(r, i.time, (f) => this.effectiveValue(t, e, f.time, f.value));
337
- return p === null ? null : { x: i.x, y: o.valueToBitmapY(p), value: p };
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 };
338
365
  }
339
366
  /**
340
367
  * Rendered positions of the layer's still-unsettled trailing points, keyed
@@ -359,61 +386,85 @@ class mt extends rt {
359
386
  * it (see `renderStacked`'s `valueMaps` comment for the full rationale).
360
387
  */
361
388
  stackedValueAt(t, e, i) {
362
- const s = this.options.stacking === "percent", o = (l) => {
363
- const a = this.getLayerAlpha(l);
364
- if (a <= 0) return 0;
365
- const p = this.stores[l].getAll();
366
- if (p.length === 0 || i < p[0].time) return 0;
367
- const f = U(p, i, (y) => this.effectiveValue(t, l, y.time, y.value));
368
- return f === null ? 0 : f * a;
389
+ const o = this.options.stacking === "percent", s = (this.options.entryAnimation ?? "grow") === "grow", n = new Array(this.stores.length), a = (h) => {
390
+ 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;
369
406
  };
370
- let n = 0;
371
- if (s)
372
- for (let l = 0; l < this.stores.length; l++) n += o(l);
373
- let r = 0;
374
- for (let l = 0; l <= e; l++) {
375
- const a = o(l);
376
- r += s && n > 0 ? a / n * 100 : a;
407
+ let l = 0;
408
+ if (o)
409
+ for (let h = 0; h < this.stores.length; h++) l += u(h);
410
+ 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;
377
414
  }
378
- return r;
415
+ return p;
379
416
  }
380
417
  /**
381
- * Bitmap position for layer `li`'s stacked boundary at time `t`, chain-
382
- * lerped through that layer's own still-unsettled trailing entries when
383
- * `t` is its current live tip — a single dot has no shared edge to tear,
384
- * so (unlike `renderStacked`'s polygon boundaries) gating off the layer's
385
- * own entrance state is enough. Falls back to the raw settled position
386
- * for historical points or when the 'grow' entrance is disabled.
418
+ * Bitmap position for layer `li`'s stacked boundary at time `t`.
419
+ *
420
+ * Reads back the vertex {@link renderStacked} actually painted this frame
421
+ * whenever `t` is one of its columns. The stacked entrance is driven by a
422
+ * *shared* per-column chain (columns are common to every layer), which this
423
+ * layer's own entrance state cannot reconstruct — deriving it here is what
424
+ * left the pulse dots hanging a column ahead of the stroke on a ragged
425
+ * feed. Falls back to the raw settled position off-column (decimated
426
+ * history, or before the first stacked frame).
387
427
  */
388
428
  stackedPositionAt(t, e, i) {
389
- const { timeScale: s, yScale: o } = t, n = s.timeToBitmapX(i), r = o.valueToBitmapY(this.stackedValueAt(t, e, i)), l = this.stores[e].last()?.time;
390
- if ((this.options.entryAnimation ?? "grow") !== "grow" || i !== l) return { x: n, y: r };
391
- const a = this.unsettledTail(e), p = this.stores[e].getAll(), f = p.length - 1 - a.length;
392
- if (a.length === 0 || f < 0) return { x: n, y: r };
393
- const y = p[f];
394
- let h = s.timeToBitmapX(y.time), m = o.valueToBitmapY(this.stackedValueAt(t, e, y.time));
395
- for (let u = 0; u < a.length; u++) {
396
- const A = p[f + 1 + u], R = _(a[u].progress), M = s.timeToBitmapX(A.time), I = o.valueToBitmapY(this.stackedValueAt(t, e, A.time));
397
- h = Y(h, M, R), m = Y(m, I, R);
398
- }
399
- return { x: h, y: m };
429
+ const o = this.paintedStackVertex(t, e, i);
430
+ 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 };
437
+ }
438
+ /** Upper-edge vertex of layer `li` at column `t`, replayed from the last
439
+ * stacked frame's data-space record against `ctx`'s scales. */
440
+ paintedStackVertex(t, e, i) {
441
+ const o = this.stackedEdges, s = o?.cumulative[e];
442
+ 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 };
400
451
  }
401
452
  chainedTailPositions(t, e) {
402
453
  const i = this.unsettledTail(e);
403
454
  if (i.length === 0) return null;
404
- const s = this.stores[e].getAll(), o = s.length - 1 - i.length;
405
- if (o < 0) return null;
406
- const { timeScale: n, yScale: r } = t, l = s[o];
407
- if (!Number.isFinite(l.value)) return null;
408
- let a = n.timeToBitmapX(l.time), p = r.valueToBitmapY(this.effectiveValue(t, e, l.time, l.value));
409
- const f = /* @__PURE__ */ new Map();
410
- for (let y = 0; y < i.length; y++) {
411
- const h = s[o + 1 + y];
412
- if (!Number.isFinite(h.value)) return null;
413
- const m = _(i[y].progress), u = n.timeToBitmapX(h.time), A = r.valueToBitmapY(this.effectiveValue(t, e, h.time, h.value)), R = Y(a, u, m), M = Y(p, A, m);
414
- f.set(h.time, { x: R, y: M }), a = R, p = M;
455
+ const o = this.stores[e].getAll(), s = o.length - 1 - i.length;
456
+ 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;
415
466
  }
416
- return f;
467
+ return h;
417
468
  }
418
469
  /**
419
470
  * Bitmap coordinates for the trailing endpoint of a layer — i.e. where the
@@ -428,8 +479,8 @@ class mt extends rt {
428
479
  trailingEndpoint(t, e) {
429
480
  const i = this.stores[e].last();
430
481
  if (!i) return null;
431
- const { timeScale: s, yScale: o } = t, n = s.timeToBitmapX(i.time), r = o.valueToBitmapY(this.effectiveValue(t, e, i.time, i.value));
432
- return (this.options.entryAnimation ?? "grow") !== "grow" ? { x: n, y: r } : this.chainedTailPositions(t, e)?.get(i.time) ?? { x: n, y: r };
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 };
433
484
  }
434
485
  /**
435
486
  * Vertical stroke + area gradients for `options.threshold`, pinned to the
@@ -443,10 +494,10 @@ class mt extends rt {
443
494
  buildThresholdPaint(t, e) {
444
495
  const i = this.options.threshold;
445
496
  if (!i) return null;
446
- const { scope: s, yScale: o } = t, { context: n } = s, r = s.bitmapSize.height, l = i.above, a = i.below ?? e, p = Math.min(1, Math.max(0, o.valueToBitmapY(i.value) / r)), f = Math.min(6 * s.verticalPixelRatio, r * 0.02) / r, y = Math.max(0, p - f), h = Math.min(1, p + f), m = n.createLinearGradient(0, 0, 0, r);
447
- m.addColorStop(0, l), m.addColorStop(y, l), m.addColorStop(h, a), m.addColorStop(1, a);
448
- const u = n.createLinearGradient(0, 0, 0, r);
449
- return u.addColorStop(0, C(l, 0.26)), u.addColorStop(y, C(l, 0.14)), u.addColorStop(h, C(a, 0.1)), u.addColorStop(1, C(a, 0.01)), { stroke: m, area: u };
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 };
450
501
  }
451
502
  /**
452
503
  * Dot markers at each data point (`options.points`). Callers pass the same
@@ -459,215 +510,224 @@ class mt extends rt {
459
510
  drawPointMarkers(t) {
460
511
  const e = this.options.points;
461
512
  if (!e?.visible) return;
462
- const { context: i, points: s, pixelRatio: o, color: n } = t;
463
- if (s.length === 0) return;
464
- const r = Math.max(1, (e.radius ?? 3) * o);
465
- if (!(s.length > 1 && (s[s.length - 1].x - s[0].x) / (s.length - 1) < r * 3)) {
513
+ const { context: i, points: o, pixelRatio: s, color: n } = t;
514
+ if (o.length === 0) return;
515
+ const a = Math.max(1, (e.radius ?? 3) * s);
516
+ if (!(o.length > 1 && (o[o.length - 1].x - o[0].x) / (o.length - 1) < a * 3)) {
466
517
  i.beginPath();
467
- for (const l of s)
468
- i.moveTo(l.x + r, l.y), i.arc(l.x, l.y, r, 0, Math.PI * 2);
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);
469
520
  i.fillStyle = e.color ?? n, i.fill();
470
521
  }
471
522
  }
472
523
  /** Each layer drawn independently */
473
524
  renderOff(t) {
474
- const { scope: e, timeScale: i, yScale: s } = t, { context: o } = e, n = i.getRange(), { verticalPixelRatio: r } = e, l = this.options.strokeWidth > 0, a = Math.max(1, Math.round(this.options.strokeWidth * r)), p = this.options.entryAnimation ?? "grow", f = ht(this.options.linePainter ?? this.options.curve ?? "straight"), y = {
475
- ctx: o,
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 = {
526
+ ctx: s,
476
527
  theme: t.theme,
477
528
  horizontalPixelRatio: e.horizontalPixelRatio,
478
- verticalPixelRatio: r
529
+ verticalPixelRatio: a
479
530
  };
480
- for (let h = 0; h < this.stores.length; h++) {
481
- const m = this.getLayerAlpha(h);
482
- if (m <= 0) continue;
483
- let u = this.stores[h].getVisibleData(n.from, n.to);
484
- const A = e.mediaSize.width;
485
- if (u.length > A * 2 && (u = j(u, Math.round(A * 1.5))), u.length < 2) continue;
486
- const R = this.stores[h].last()?.value ?? u[u.length - 1].value, M = this.resolveLayerColor(h, R), I = this.buildThresholdPaint(t, M), F = u[u.length - 1], z = this.stores[h].last(), D = z !== void 0 && F.time === z.time, N = D ? this.entranceProgress(h, F.time) : 1, W = D && p === "fade" && N < 1, E = (D ? this.trailingEndpoint(t, h) : null) ?? {
487
- x: i.timeToBitmapX(F.time),
488
- y: s.valueToBitmapY(this.effectiveValue(t, h, F.time, F.value))
489
- }, G = E.x, c = E.y, x = D && p === "grow" ? this.chainedTailPositions(t, h) : null, b = m < 1;
490
- (b || W) && (o.save(), b && (o.globalAlpha *= m), W && (o.globalAlpha *= N));
491
- const S = u.length - 1, d = [];
492
- let T = null;
493
- for (let P = 0; P < S; P++) {
494
- const B = u[P].value;
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);
535
+ 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;
495
546
  if (!Number.isFinite(B)) {
496
- T = null;
547
+ x = null;
497
548
  continue;
498
549
  }
499
- T || (T = [], d.push(T));
500
- const g = x?.get(u[P].time);
501
- if (g)
502
- T.push({ x: g.x, y: g.y });
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 });
503
554
  else {
504
- const L = s.valueToBitmapY(this.effectiveValue(t, h, u[P].time, B));
505
- T.push({ x: i.timeToBitmapX(u[P].time), y: L });
555
+ const w = o.valueToBitmapYExact(this.effectiveValue(t, r, c[S].time, B));
556
+ x.push({ x: i.timeToBitmapXExact(c[S].time), y: w });
506
557
  }
507
558
  }
508
- const k = u[S]?.value, V = Number.isFinite(G) && Number.isFinite(c) && Number.isFinite(k), X = p === "grow" && N < 1;
509
- let H = null;
510
- if (V && (T ? (T.push({ x: G, y: c }), H = T) : d.push([{ x: G, y: c }])), l && d.some((P) => P.length >= 2)) {
511
- o.beginPath();
512
- for (const P of d)
513
- P.length < 2 || f(y, { points: P, color: M, lineWidth: a, closing: !1, grew: X && P === H });
514
- o.strokeStyle = I ? I.stroke : M, o.lineWidth = a, o.lineJoin = "round", o.lineCap = "round", o.stroke();
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)) {
562
+ 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();
515
566
  }
516
- if (l) {
517
- const P = Math.max(1, a / 2);
567
+ if (u) {
568
+ const S = Math.max(1, l / 2);
518
569
  let B = !1;
519
- for (const g of d)
520
- g.length === 1 && (B || (o.beginPath(), B = !0), o.moveTo(g[0].x + P, g[0].y), o.arc(g[0].x, g[0].y, P, 0, Math.PI * 2));
521
- B && (o.fillStyle = M, o.fill());
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());
522
573
  }
523
574
  if (this.options.area.visible && !this.introGhostPass) {
524
- const P = e.bitmapSize.height;
575
+ const S = e.bitmapSize.height;
525
576
  let B;
526
- if (I)
527
- B = I.area;
577
+ if (V)
578
+ B = V.area;
528
579
  else {
529
- const g = String(h), L = this.areaGradientCache.get(g);
530
- L && L.bottomY === P && L.color === M ? B = L.gradient : (B = o.createLinearGradient(0, 0, 0, P), B.addColorStop(0, C(M, 0.12)), B.addColorStop(1, C(M, 0.01)), this.areaGradientCache.set(g, { gradient: B, bottomY: P, color: M }));
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 }));
531
582
  }
532
- o.fillStyle = B;
533
- for (const g of d)
534
- g.length < 2 || (o.beginPath(), f(y, { points: g, color: M, lineWidth: a, closing: !0, grew: X && g === H }), o.lineTo(g[g.length - 1].x, P), o.lineTo(g[0].x, P), o.closePath(), o.fill());
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());
535
586
  }
536
587
  if (this.options.points?.visible) {
537
- const P = [];
538
- for (const B of d)
539
- for (const g of B) P.push(g);
540
- this.drawPointMarkers({ context: o, points: P, pixelRatio: e.horizontalPixelRatio, color: M });
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 });
541
592
  }
542
- (W || b) && o.restore();
593
+ (I || v) && s.restore();
543
594
  }
544
595
  }
545
596
  /** Stacked area rendering */
546
597
  renderStacked(t, e) {
547
- const { scope: i, timeScale: s, yScale: o } = t, { context: n } = i, r = s.getRange(), { verticalPixelRatio: l } = i, a = this.options.strokeWidth > 0, p = Math.max(1, Math.round(this.options.strokeWidth * l)), f = this.options.curve ?? "straight", y = i.mediaSize.width, h = this.stores.map((c, x) => {
548
- if (this.getLayerAlpha(x) <= 0) return [];
549
- let b = c.getVisibleData(r.from, r.to);
550
- return b.length > y * 2 && (b = j(b, Math.round(y * 1.5))), b;
551
- }), m = /* @__PURE__ */ new Set();
552
- for (const c of h)
553
- for (const x of c) m.add(x.time);
554
- const u = Array.from(m).sort((c, x) => c - x);
555
- if (u.length < 2) return;
556
- const A = h.map((c, x) => {
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);
606
+ if (c.length < 2) {
607
+ this.stackedEdges = null;
608
+ return;
609
+ }
610
+ const y = this.options.entryAnimation ?? "grow", R = r.map((m, v) => {
557
611
  const b = /* @__PURE__ */ new Map();
558
- if (c.length === 0) return b;
559
- const S = this.getLayerAlpha(x), d = c[0].time;
560
- for (const T of u) {
561
- if (T < d) continue;
562
- const k = U(c, T, (V) => this.effectiveValue(t, x, V.time, V.value));
563
- k !== null && b.set(T, k * S);
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);
564
618
  }
565
619
  return b;
566
- }), R = Array.from({ length: this.stores.length }, () => new Array(u.length).fill(0));
567
- for (let c = 0; c < u.length; c++) {
568
- const x = u[c];
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];
569
623
  let b = 0;
570
624
  if (e)
571
- for (let d = 0; d < this.stores.length; d++) {
572
- const T = A[d].get(x);
573
- Number.isFinite(T) && (b += T);
625
+ for (let x = 0; x < this.stores.length; x++) {
626
+ const k = R[x].get(v);
627
+ Number.isFinite(k) && (b += k);
574
628
  }
575
- let S = 0;
576
- for (let d = 0; d < this.stores.length; d++) {
577
- const T = A[d].get(x), k = Number.isFinite(T) ? T : 0;
578
- S += e && b > 0 ? k / b * 100 : k, R[d][c] = S;
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;
579
633
  }
580
634
  }
581
- const M = this.options.entryAnimation ?? "grow", I = /* @__PURE__ */ new Map();
582
- for (let c = 0; c < u.length; c++) I.set(u[c], c);
583
- const F = new Array(this.stores.length).fill(1);
584
- for (let c = 0; c < this.stores.length; c++) {
585
- if (this.getLayerAlpha(c) <= 0) continue;
586
- const x = this.unsettledTail(c), b = x.length;
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;
587
641
  if (b === 0) continue;
588
- let S = !0;
589
- for (let d = 0; d < b; d++)
590
- if (I.get(x[d].time) !== u.length - b + d) {
591
- S = !1;
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;
592
646
  break;
593
647
  }
594
- S && (F[c] = x[b - 1].progress);
648
+ T && (C[m] = v[b - 1].progress);
595
649
  }
596
- const z = [];
597
- if (M === "grow")
598
- for (let c = u.length - 1; c >= 0; c--) {
599
- const x = u[c];
600
- let b = 1, S = !1;
601
- for (let d = 0; d < this.stores.length; d++) {
602
- if (this.getLayerAlpha(d) <= 0 || this.entries[d]?.get(x) === void 0) continue;
603
- const T = this.entranceProgress(d, x);
604
- T >= 1 || (S = !0, T < b && (b = T));
650
+ const N = [];
651
+ 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;
605
663
  }
606
- if (!S) break;
607
- z.unshift(_(b));
664
+ if (!x || T >= 1) break;
665
+ N.unshift(U(T));
608
666
  }
609
- const D = (c, x) => {
610
- const b = x.length;
611
- if (!(b === 0 || c.length < b + 1))
612
- for (let S = 0; S < b; S++) {
613
- const d = c.length - b + S, T = c[d - 1], k = c[d];
614
- c[d] = [Y(T[0], k[0], x[S]), Y(T[1], k[1], x[S])];
667
+ }
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]);
615
674
  }
616
- }, N = i.bitmapSize.height;
617
- let W = -1, E = -1;
618
- for (let c = 0; c < this.stores.length; c++)
619
- if (!(this.getLayerAlpha(c) <= 0))
620
- if (W < 0)
621
- W = c;
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))
679
+ if (I < 0)
680
+ I = m;
622
681
  else {
623
- E = c;
682
+ G = m;
624
683
  break;
625
684
  }
626
- const G = W >= 0 ? this.getLayerAlpha(W) : 1;
627
- for (let c = this.stores.length - 1; c >= 0; c--) {
628
- const x = this.getLayerAlpha(c);
629
- if (x <= 0) continue;
630
- const b = this.stores[c].last()?.value ?? 0, S = this.resolveLayerColor(c, b), d = c === W, T = E >= 0 && c === E && G < 1, k = [];
631
- for (let g = 0; g < u.length; g++) {
632
- const L = c > 0 ? o.valueToBitmapY(R[c - 1][g]) : N;
633
- let O = L;
634
- d ? O = N : T && (O = L + (N - L) * (1 - G)), k.push([s.timeToBitmapX(u[g]), O]);
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]);
635
694
  }
636
- M === "grow" && !d && D(k, z);
637
- const V = [];
638
- for (let g = 0; g < u.length; g++) {
639
- let L = o.valueToBitmapY(R[c][g]);
640
- d && x < 1 && (L = N + (L - N) * x), V.push([s.timeToBitmapX(u[g]), L]);
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]);
641
700
  }
642
- M === "grow" && D(V, z);
643
- const X = Z(V), H = q(X, f, M === "grow" && z.length > 0), P = M === "fade" && F[c] < 1;
644
- if (P && (n.save(), n.globalAlpha *= F[c]), this.options.area.visible && !this.introGhostPass) {
645
- let g = V[0][1], L = k[0][1];
646
- for (let w = 1; w < V.length; w++)
647
- V[w][1] < g && (g = V[w][1]);
648
- for (let w = 1; w < k.length; w++)
649
- k[w][1] > L && (L = k[w][1]);
650
- let O = C(S, 0.25);
651
- if (L > g + 0.5) {
652
- const w = n.createLinearGradient(0, g, 0, L);
653
- w.addColorStop(0, C(S, 0.25)), w.addColorStop(1, C(S, 0.05)), O = w;
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;
654
713
  }
655
- if (n.beginPath(), n.moveTo(X[0].x, X[0].y), K(n, H), d)
656
- for (let w = k.length - 1; w >= 0; w--)
657
- n.lineTo(k[w][0], k[w][1]);
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]);
658
717
  else {
659
- const w = Z(k), nt = q(w, f, M === "grow" && z.length > 0), J = w[w.length - 1];
660
- n.lineTo(J.x, J.y), ft(n, w, nt);
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);
661
720
  }
662
721
  n.closePath(), n.fillStyle = O, n.fill();
663
722
  }
664
- const B = a && x < 1;
665
- if (B && (n.save(), n.globalAlpha *= x), a && (n.beginPath(), n.moveTo(X[0].x, X[0].y), K(n, H), n.strokeStyle = S, n.lineWidth = p, n.lineJoin = "round", n.lineCap = "round", n.stroke()), B && n.restore(), this.options.points?.visible) {
666
- const g = x < 1;
667
- g && (n.save(), n.globalAlpha *= x), this.drawPointMarkers({ context: n, points: X, pixelRatio: i.horizontalPixelRatio, color: S }), g && n.restore();
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();
668
727
  }
669
- P && n.restore();
728
+ B && n.restore();
670
729
  }
730
+ this.stackedEdges = { times: c, cumulative: M, growChain: N, collapse: _ };
671
731
  }
672
732
  /**
673
733
  * Overlay hook: draws crosshair nearest-point dots and last-point pulse dots.
@@ -675,54 +735,54 @@ class mt extends rt {
675
735
  */
676
736
  drawOverlay(t) {
677
737
  this.tickAnimations(performance.now());
678
- const { scope: e, timeScale: i, yScale: s, crosshair: o, dataInterval: n } = t, r = e, l = this.options.pulseMs, a = l > 0 ? performance.now() / (l * 2 * Math.PI) % 1 : 0;
679
- if (o) {
680
- const y = this.options.stacking, h = 4 * r.horizontalPixelRatio;
681
- for (let m = 0; m < this.stores.length; m++) {
682
- const u = this.getLayerAlpha(m);
683
- if (u <= 0) continue;
684
- const A = this.stores[m].findNearest(o.time, n);
685
- if (!A) continue;
686
- const R = this.resolveLayerColor(m, A.value), { x: M, y: I } = y === "off" ? {
687
- x: i.timeToBitmapX(A.time),
688
- y: s.valueToBitmapY(this.effectiveValue(t, m, A.time, A.value))
689
- } : this.stackedPositionAt(t, m, A.time), F = u < 1;
690
- F && (e.context.save(), e.context.globalAlpha *= u), e.context.save(), e.context.globalAlpha *= 0.25, e.context.beginPath(), e.context.arc(M, I, h + 3 * r.horizontalPixelRatio, 0, Math.PI * 2), e.context.fillStyle = R, e.context.fill(), e.context.restore(), e.context.beginPath(), e.context.arc(M, I, h, 0, Math.PI * 2), e.context.fillStyle = R, e.context.fill(), F && e.context.restore();
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;
739
+ 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);
743
+ 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" ? {
747
+ 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();
691
751
  }
692
752
  }
693
753
  const p = this.introWave.active && this.introDirectives?.clip !== void 0;
694
- let f = 1;
695
- if (p && (f = Math.max(0, (this.introWave.linear() - (1 - $)) / $)), this.hasPulse && l > 0 && f > 0) {
696
- const y = this.options.stacking;
697
- for (let h = 0; h < this.stores.length; h++) {
698
- const m = this.getLayerAlpha(h);
699
- if (m <= 0) continue;
700
- const u = this.stores[h].last()?.value ?? 0, A = this.resolveLayerColor(h, u);
701
- if (y === "off") {
702
- const F = this.trailingEndpoint(t, h);
703
- if (!F) continue;
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;
704
764
  this.drawPulse({
705
765
  ctx: e.context,
706
- x: F.x,
707
- y: F.y,
708
- color: A,
709
- pixelRatio: r.horizontalPixelRatio,
710
- phase: a,
711
- alpha: m * f
766
+ x: C.x,
767
+ y: C.y,
768
+ color: y,
769
+ pixelRatio: a.horizontalPixelRatio,
770
+ phase: l,
771
+ alpha: f * h
712
772
  });
713
773
  continue;
714
774
  }
715
- const R = this.stores[h].last();
775
+ const R = this.stores[r].last();
716
776
  if (!R) continue;
717
- const { x: M, y: I } = this.stackedPositionAt(t, h, R.time);
777
+ const { x: M, y: V } = this.stackedPositionAt(t, r, R.time);
718
778
  this.drawPulse({
719
779
  ctx: e.context,
720
780
  x: M,
721
- y: I,
722
- color: A,
723
- pixelRatio: r.horizontalPixelRatio,
724
- phase: a,
725
- alpha: m * f
781
+ y: V,
782
+ color: y,
783
+ pixelRatio: a.horizontalPixelRatio,
784
+ phase: l,
785
+ alpha: f * h
726
786
  });
727
787
  }
728
788
  }
@@ -731,24 +791,24 @@ class mt extends rt {
731
791
  ctx: t,
732
792
  x: e,
733
793
  y: i,
734
- color: s,
735
- pixelRatio: o,
794
+ color: o,
795
+ pixelRatio: s,
736
796
  phase: n,
737
- alpha: r = 1
797
+ alpha: a = 1
738
798
  }) {
739
- const l = 3 * o, a = 0.4 + 0.6 * Math.abs(Math.sin(n * 2 * Math.PI)), p = l + 4 * o * a, f = r < 1;
740
- f && (t.save(), t.globalAlpha *= r), t.beginPath(), t.arc(e, i, p, 0, Math.PI * 2), t.fillStyle = C(s, a * 0.3), t.fill(), t.beginPath(), t.arc(e, i, l, 0, Math.PI * 2), t.fillStyle = s, t.fill(), f && t.restore();
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();
741
801
  }
742
802
  }
743
- const Pt = {
803
+ const wt = {
744
804
  type: "line",
745
- create: ({ theme: v, layerCount: t }, e) => new mt(t, {
746
- colors: t === 1 ? [v.line.color] : v.seriesColors.slice(0, t),
747
- strokeWidth: v.line.width,
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,
748
808
  ...e
749
809
  })
750
810
  };
751
811
  export {
752
- mt as LineRenderer,
753
- Pt as LineSeriesDef
812
+ dt as LineRenderer,
813
+ wt as LineSeriesDef
754
814
  };