@wick-charts/vue 0.8.0 → 0.8.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.
Files changed (48) hide show
  1. package/README.md +2 -0
  2. package/dist/BandSeries.vue.js +43 -32
  3. package/dist/BarSeries.vue.js +44 -33
  4. package/dist/CandlestickSeries.vue.js +24 -23
  5. package/dist/ChartContainer.vue.js +1 -1
  6. package/dist/HeatmapSeries.vue.js +21 -20
  7. package/dist/LineSeries.vue.js +43 -32
  8. package/dist/PieSeries.vue.js +25 -24
  9. package/dist/composables.js +63 -36
  10. package/dist/core/dist/axis/dom-labels.js +64 -53
  11. package/dist/core/dist/chart/badge-animator.js +38 -28
  12. package/dist/core/dist/chart/options.js +1 -1
  13. package/dist/core/dist/chart/y-target.js +38 -32
  14. package/dist/core/dist/chart.js +852 -709
  15. package/dist/core/dist/data/decimation.js +52 -51
  16. package/dist/core/dist/data/store.js +38 -20
  17. package/dist/core/dist/data/sync.js +97 -59
  18. package/dist/core/dist/navigator/controller.js +11 -11
  19. package/dist/core/dist/perf/perf-hud.js +3 -3
  20. package/dist/core/dist/scales/tick-tracker.js +2 -1
  21. package/dist/core/dist/scales/time-ticks.js +99 -0
  22. package/dist/core/dist/scales/x-scale.js +33 -27
  23. package/dist/core/dist/series/band.js +83 -83
  24. package/dist/core/dist/series/bar.js +240 -211
  25. package/dist/core/dist/series/base-multi-layer.js +288 -240
  26. package/dist/core/dist/series/candlestick.js +168 -168
  27. package/dist/core/dist/series/line.js +545 -455
  28. package/dist/core/dist/snapshots.js +109 -86
  29. package/dist/core/dist/utils/point.js +4 -0
  30. package/dist/core/dist/utils/time.js +42 -26
  31. package/dist/index.d.ts +67 -28
  32. package/dist/ui/InfoBar.vue.js +69 -69
  33. package/dist/ui/NumberFlow.vue.js +36 -27
  34. package/dist/ui/Tooltip.vue.js +128 -131
  35. package/dist/ui/YLabel.vue.js +47 -47
  36. package/package.json +2 -2
  37. package/src/BandSeries.vue +20 -5
  38. package/src/BarSeries.vue +20 -5
  39. package/src/CandlestickSeries.vue +5 -4
  40. package/src/ChartContainer.vue +15 -9
  41. package/src/HeatmapSeries.vue +5 -4
  42. package/src/LineSeries.vue +20 -5
  43. package/src/PieSeries.vue +6 -5
  44. package/src/composables.ts +64 -1
  45. package/src/ui/InfoBar.vue +11 -3
  46. package/src/ui/NumberFlow.vue +17 -3
  47. package/src/ui/Tooltip.vue +23 -12
  48. package/src/ui/YLabel.vue +28 -27
@@ -1,10 +1,11 @@
1
- import { clamp as d } from "../utils/math.js";
1
+ import { clamp as f } from "../utils/math.js";
2
2
  import { crispCenterOffset as v } from "../utils/pixel-grid.js";
3
- import { formatTime as g, niceTimeIntervals as p } from "../utils/time.js";
3
+ import { formatTime as p, niceTimeIntervals as g } from "../utils/time.js";
4
4
  import { AxisTickTracker as I } from "./tick-tracker.js";
5
- import { pickNiceCeiling as b, pickNiceFloor as k } from "./y-scale.js";
6
- const o = 50, y = 80, h = 0.3, u = 0.2;
7
- class W {
5
+ import { timeTicks as k } from "./time-ticks.js";
6
+ import { pickNiceCeiling as b, pickNiceFloor as y } from "./y-scale.js";
7
+ const o = 50, T = 80, h = 0.3, u = 0.2;
8
+ class w {
8
9
  /**
9
10
  * Shared fade state for time ticks. Grid lines (canvas) and DOM tick labels
10
11
  * read opacity from the same tracker, so a tick fading in/out looks
@@ -44,20 +45,20 @@ class W {
44
45
  return this.labelCountHintValue;
45
46
  }
46
47
  get minLabelSpacing() {
47
- return this.minSpacingValue ?? y;
48
+ return this.minSpacingValue ?? T;
48
49
  }
49
50
  update(t, i, s, e) {
50
51
  if (this.from = t.from, this.to = t.to, this.width = i, this.pixelRatio = s, this.type === "time" && e !== void 0 && e > 0) {
51
- const r = c(e);
52
+ const r = m(e);
52
53
  this.lastBucketKey !== null && this.lastBucketKey !== r && this.resetHysteresis(), this.lastBucketKey = r, this.dataInterval = e;
53
54
  }
54
55
  this.resolveInterval();
55
56
  }
56
57
  setLabelCount(t) {
57
- this.labelCountHintValue = M(t), this.resetHysteresis(), this.resolveInterval();
58
+ this.labelCountHintValue = x(t), this.resetHysteresis(), this.resolveInterval();
58
59
  }
59
60
  setMinSpacing(t) {
60
- this.minSpacingValue = x(t), this.resetHysteresis(), this.resolveInterval();
61
+ this.minSpacingValue = V(t), this.resetHysteresis(), this.resolveInterval();
61
62
  }
62
63
  setFormat(t) {
63
64
  this.customFormat = t;
@@ -83,8 +84,8 @@ class W {
83
84
  /** Band spacing on a category axis; an omitted or invalid side takes its default. */
84
85
  setBandPadding(t) {
85
86
  this.bandPadding = {
86
- inner: m({ value: t?.inner, fallback: h, max: 1 }),
87
- outer: m({ value: t?.outer, fallback: u, max: 1 / 0 })
87
+ inner: c({ value: t?.inner, fallback: h, max: 1 }),
88
+ outer: c({ value: t?.outer, fallback: u, max: 1 / 0 })
88
89
  };
89
90
  }
90
91
  getBandPadding() {
@@ -110,7 +111,7 @@ class W {
110
111
  */
111
112
  snapToBand(t) {
112
113
  const i = this.categories.length;
113
- return this.type !== "category" || i === 0 ? t : d(Math.round(t), 0, i - 1);
114
+ return this.type !== "category" || i === 0 ? t : f(Math.round(t), 0, i - 1);
114
115
  }
115
116
  /**
116
117
  * An internal coordinate in the axis domain: the category name at that
@@ -151,7 +152,7 @@ class W {
151
152
  */
152
153
  formatX(t, i) {
153
154
  const s = this.domainValue(t);
154
- return this.customFormat ? this.customFormat(s, i) : this.type === "category" ? String(s) : this.type === "numeric" ? T({ value: t, step: i, locale: this.localeValue }) : g(t, i, { locale: this.localeValue, timeZone: this.timeZoneValue });
155
+ return this.customFormat ? this.customFormat(s, i) : this.type === "category" ? String(s) : this.type === "numeric" ? M({ value: t, step: i, locale: this.localeValue }) : p(t, i, { locale: this.localeValue, timeZone: this.timeZoneValue });
155
156
  }
156
157
  /**
157
158
  * Format a data point's X for a tooltip or info-bar header. Like
@@ -197,7 +198,9 @@ class W {
197
198
  return Math.max(1, Math.round(this.barWidthMedia(t) * this.pixelRatio));
198
199
  }
199
200
  /**
200
- * Evenly spaced "nice" tick times. Resolution uses the cached
201
+ * "Nice" tick values. A time axis puts them on calendar boundaries in the
202
+ * installed time zone (Jan 1, the 1st of a month, midnight), so their gaps
203
+ * vary; `tickInterval` is the tier's nominal span. Resolution uses the cached
201
204
  * `dataInterval` set by `update()`; callers that bypass `update()` can
202
205
  * still pass it here for back-compat.
203
206
  */
@@ -209,11 +212,14 @@ class W {
209
212
  }
210
213
  if (this.type === "category") return this.bandTicks();
211
214
  if (this.type === "time" && this.dataInterval !== t) {
212
- const a = c(t);
215
+ const a = m(t);
213
216
  this.lastBucketKey !== null && this.lastBucketKey !== a && this.resetHysteresis(), this.lastBucketKey = a, this.dataInterval = t, this.resolveInterval();
214
217
  }
215
218
  if (this.resolvedInterval == null) return { ticks: [], tickInterval: 0 };
216
- const i = this.resolvedInterval, s = Math.ceil(this.from / i) * i, e = Math.max(0, Math.min(o, Math.floor((this.to - s) / i) + 1)), r = [];
219
+ const i = this.resolvedInterval;
220
+ if (this.type === "time")
221
+ return { ticks: k({ from: this.from, to: this.to, interval: i, timeZone: this.timeZoneValue, max: o }), tickInterval: i };
222
+ const s = Math.ceil(this.from / i) * i, e = Math.max(0, Math.min(o, Math.floor((this.to - s) / i) + 1)), r = [];
217
223
  for (let a = 0; a < e; a++) r.push(s + a * i);
218
224
  return { ticks: r, tickInterval: i };
219
225
  }
@@ -244,7 +250,7 @@ class W {
244
250
  this.resolvedInterval = null;
245
251
  return;
246
252
  }
247
- const t = p(this.dataInterval), i = this.to - this.from, s = i / this.width * this.minLabelSpacing;
253
+ const t = g(this.dataInterval), i = this.to - this.from, s = i / this.width * this.minLabelSpacing;
248
254
  let e;
249
255
  if (this.labelCountHint != null) {
250
256
  const l = Math.max(1, this.labelCountHint);
@@ -252,8 +258,8 @@ class W {
252
258
  } else
253
259
  e = s;
254
260
  if (this.lastInterval != null && this.lastWant != null && t.includes(this.lastInterval)) {
255
- const l = e >= this.lastWant * 0.8 && e <= this.lastWant * 1.25, f = this.lastInterval >= s;
256
- if (l && f) {
261
+ const l = e >= this.lastWant * 0.8 && e <= this.lastWant * 1.25, d = this.lastInterval >= s;
262
+ if (l && d) {
257
263
  this.resolvedInterval = this.lastInterval;
258
264
  return;
259
265
  }
@@ -289,7 +295,7 @@ class W {
289
295
  }
290
296
  let r = b(e);
291
297
  if (this.labelCountHint != null && this.countTicks(r) < this.labelCountHint) {
292
- const a = k(e);
298
+ const a = y(e);
293
299
  a >= i && (r = a);
294
300
  }
295
301
  this.resolvedInterval = r, this.lastInterval = r, this.lastWant = e;
@@ -300,23 +306,23 @@ class W {
300
306
  return Math.max(0, Math.floor((this.to - i) / t) + 1);
301
307
  }
302
308
  }
303
- function c(n) {
309
+ function m(n) {
304
310
  return n < 6e4 ? 0 : n < 36e5 ? 1 : n < 864e5 ? 2 : 3;
305
311
  }
306
- function T(n) {
307
- const { value: t, step: i, locale: s } = n, e = Number.isFinite(i) && i > 0 ? -Math.floor(Math.log10(i)) : 2, r = d(e, 0, 20);
312
+ function M(n) {
313
+ const { value: t, step: i, locale: s } = n, e = Number.isFinite(i) && i > 0 ? -Math.floor(Math.log10(i)) : 2, r = f(e, 0, 20);
308
314
  return t.toLocaleString(s ?? "en-US", { maximumFractionDigits: r });
309
315
  }
310
- function m(n) {
316
+ function c(n) {
311
317
  const { value: t, fallback: i, max: s } = n;
312
318
  return t === void 0 || !Number.isFinite(t) || t < 0 ? i : Math.min(t, s);
313
319
  }
314
- function M(n) {
320
+ function x(n) {
315
321
  return typeof n == "number" && Number.isFinite(n) && n >= 2 ? Math.floor(n) : null;
316
322
  }
317
- function x(n) {
323
+ function V(n) {
318
324
  return typeof n == "number" && Number.isFinite(n) && n > 0 ? n : null;
319
325
  }
320
326
  export {
321
- W as XScale
327
+ w as XScale
322
328
  };
@@ -2,15 +2,15 @@ import { Animator as I } from "../animation/animator.js";
2
2
  import { DEFAULT_HISTORY_REVEAL as z, DEFAULT_BAND_INTRO as F, DEFAULT_BAND_SMOOTH as O, DEFAULT_BAND_ENTRY as _ } from "../animation/config.js";
3
3
  import { easeOutCubic as Y } from "../animation/easing.js";
4
4
  import { IntroWave as N } from "../animation/intro-wave.js";
5
- import { ScalarSpring as S } from "../animation/scalar-spring.js";
5
+ import { ScalarSpring as A } from "../animation/scalar-spring.js";
6
6
  import { decimateBandData as $ } from "../data/decimation.js";
7
7
  import { TimeSeriesStore as H } from "../data/store.js";
8
8
  import { resolveColor as U, hexToRgba as T } from "../utils/color.js";
9
9
  import { lerp as L } from "../utils/math.js";
10
- import { normalizeTime as W } from "../utils/time.js";
11
- import { unfoldIntro as J, scaleMean as j, backfillSweepIntro as G } from "./line-intro.js";
12
- import { buildCurveSegments as B, replaySegmentsForward as R, replaySegmentsReversed as Q } from "./painters/canvas-path.js";
13
- const Z = {
10
+ import { sliceSample as W, normalizeTime as J } from "../utils/time.js";
11
+ import { unfoldIntro as j, scaleMean as G, backfillSweepIntro as Z } from "./line-intro.js";
12
+ import { buildCurveSegments as B, replaySegmentsForward as R, replaySegmentsReversed as q } from "./painters/canvas-path.js";
13
+ const K = {
14
14
  colors: ["#2962FF"],
15
15
  fill: void 0,
16
16
  stroke: { visible: !0, width: 1, color: void 0 },
@@ -22,11 +22,11 @@ const Z = {
22
22
  historyRevealMs: z,
23
23
  introAnimation: void 0,
24
24
  historyReveal: void 0
25
- }, q = 0.4, K = 0.04, E = 0.6, tt = G();
25
+ }, Q = 0.4, tt = 0.04, E = 0.6, et = Z();
26
26
  function k(a, t) {
27
27
  return a === !1 ? 0 : a ?? t;
28
28
  }
29
- function V(a, t) {
29
+ function C(a, t) {
30
30
  const i = t.stroke;
31
31
  return {
32
32
  colors: t.colors ?? a.colors,
@@ -46,12 +46,12 @@ function V(a, t) {
46
46
  historyReveal: "historyReveal" in t ? t.historyReveal : a.historyReveal
47
47
  };
48
48
  }
49
- const et = (a, t, i) => a + (t - a) * i;
49
+ const it = (a, t, i) => a + (t - a) * i;
50
50
  function P(a) {
51
51
  return a <= 0 ? 0 : a >= 1 ? 1 : a;
52
52
  }
53
- function A(a) {
54
- const t = W(a.time), { low: i, high: e } = a;
53
+ function S(a) {
54
+ const t = J(a.time), { low: i, high: e } = a;
55
55
  return !Number.isFinite(i) || !Number.isFinite(e) ? { ...a, time: t, low: Number.NaN, high: Number.NaN } : { ...a, time: t, low: Math.min(i, e), high: Math.max(i, e) };
56
56
  }
57
57
  function b(a) {
@@ -60,25 +60,25 @@ function b(a) {
60
60
  function x(a) {
61
61
  return { low: a.low, high: a.high };
62
62
  }
63
- function it(a) {
63
+ function ot(a) {
64
64
  const { upperSegs: t, lowerSegs: i } = a;
65
65
  for (let e = 0; e < t.length; e++) {
66
66
  const o = t[e], s = i[e];
67
67
  if (o.kind !== "bezier" || s.kind !== "bezier") continue;
68
- const n = C(o.cp1y, s.cp1y), l = C(o.cp2y, s.cp2y);
68
+ const n = V(o.cp1y, s.cp1y), l = V(o.cp2y, s.cp2y);
69
69
  t[e] = { ...o, cp1y: n.top, cp2y: l.top }, i[e] = { ...s, cp1y: n.bottom, cp2y: l.bottom };
70
70
  }
71
71
  }
72
- function C(a, t) {
72
+ function V(a, t) {
73
73
  if (a <= t) return { top: a, bottom: t };
74
74
  const i = (a + t) / 2;
75
75
  return { top: i, bottom: i };
76
76
  }
77
- class ot {
77
+ class st {
78
78
  store = new H();
79
79
  /** Entrance start wall-time per appended point, keyed by point time. */
80
80
  entries = /* @__PURE__ */ new Map();
81
- alpha = new I({ initial: 1, duration: 0, lerp: et });
81
+ alpha = new I({ initial: 1, duration: 0, lerp: it });
82
82
  /** Displayed edges of the last point; the chase moves them toward the stored ones. */
83
83
  displayedLast = null;
84
84
  chase = null;
@@ -91,7 +91,7 @@ class ot {
91
91
  /** Per-point eases started by `morphData`, keyed by point time; pruned on settle. */
92
92
  morphs = /* @__PURE__ */ new Map();
93
93
  }
94
- class st {
94
+ class nt {
95
95
  kind = "band";
96
96
  #e;
97
97
  #t;
@@ -109,10 +109,10 @@ class st {
109
109
  /** True while a ghost pre-pass draws — edges only, no fill. */
110
110
  #c = !1;
111
111
  constructor(t, i) {
112
- this.#t = Array.from({ length: Math.max(1, t) }, () => new ot()), this.#e = V(Z, i ?? {});
112
+ this.#t = Array.from({ length: Math.max(1, t) }, () => new st()), this.#e = C(K, i ?? {});
113
113
  }
114
114
  updateOptions(t) {
115
- this.#e = V(this.#e, t);
115
+ this.#e = C(this.#e, t);
116
116
  }
117
117
  applyTheme(t) {
118
118
  this.updateOptions({ colors: X(t, this.#t.length) });
@@ -121,8 +121,8 @@ class st {
121
121
  setData(t, i = 0) {
122
122
  const e = this.#t[i];
123
123
  if (!e) return;
124
- const o = this.#t.some((l) => l.store.length > 0), s = (t ?? []).map(A);
125
- e.store.setData(s), !o && s.length > 0 && this.#i.arm(this.#e.introMs);
124
+ const o = this.#t.some((l) => l.store.length > 0), s = (t ?? []).map(S);
125
+ !o && s.length > 0 && this.#i.arm(this.#e.introMs), e.store.setData(s);
126
126
  const n = e.store.last();
127
127
  e.displayedLast = n ? x(n) : null, e.chase = null, e.pinned = null, e.morphs.clear(), e.entries.clear(), this.#o.finish(), this.#s = null;
128
128
  }
@@ -141,7 +141,7 @@ class st {
141
141
  const o = /* @__PURE__ */ new Map();
142
142
  for (const h of e.store.getAll())
143
143
  o.set(h.time, this.#u(e, h));
144
- const s = (t ?? []).map(A);
144
+ const s = (t ?? []).map(S);
145
145
  e.store.setData(s);
146
146
  const n = this.#e.smoothMs, l = this.#e.entryAnimation !== "none" && this.#e.entryMs > 0, r = /* @__PURE__ */ new Map();
147
147
  for (const h of s) {
@@ -152,8 +152,8 @@ class st {
152
152
  }
153
153
  if (u.low === h.low && u.high === h.high || n <= 0 || b(h) || !Number.isFinite(u.low)) continue;
154
154
  const g = e.morphs.get(h.time) ?? {
155
- low: new S(u.low),
156
- high: new S(u.high)
155
+ low: new A(u.low),
156
+ high: new A(u.high)
157
157
  };
158
158
  g.low.target !== h.low && g.low.retarget(h.low, { settleMs: n }), g.high.target !== h.high && g.high.retarget(h.high, { settleMs: n }), r.set(h.time, g);
159
159
  }
@@ -167,7 +167,7 @@ class st {
167
167
  appendPoint(t, i = 0) {
168
168
  const e = this.#t[i];
169
169
  if (!e) return;
170
- const o = A(t), s = e.store.last(), n = e.store.length;
170
+ const o = S(t), s = e.store.last(), n = e.store.length;
171
171
  e.store.append(o);
172
172
  const l = e.store.length > n;
173
173
  e.chase !== null && s !== void 0 && l && (e.pinned = { time: s.time, chase: e.chase }), e.displayedLast = x(o), e.chase = null, this.#e.entryAnimation !== "none" && this.#e.entryMs > 0 && e.entries.set(o.time, performance.now());
@@ -175,11 +175,11 @@ class st {
175
175
  prependPoints(t, i = 0) {
176
176
  const e = this.#t[i];
177
177
  if (!e || t.length === 0) return;
178
- const o = t.map(A), s = e.store.first()?.time;
179
- e.store.prepend(o), this.#A(o[0]?.time, s);
178
+ const o = t.map(S), s = e.store.first()?.time;
179
+ e.store.prepend(o), this.#S(o[0]?.time, s);
180
180
  }
181
181
  /** While a reveal is in flight only the range grows — a restart would hide half-revealed points again. */
182
- #A(t, i) {
182
+ #S(t, i) {
183
183
  const e = this.#e.historyRevealMs;
184
184
  if (!(this.#e.historyReveal === "none" || e <= 0) && !(t === void 0 || i === void 0)) {
185
185
  if (this.#o.active && this.#s !== null) {
@@ -192,7 +192,7 @@ class st {
192
192
  updateLastPoint(t, i = 0) {
193
193
  const e = this.#t[i];
194
194
  if (!e) return;
195
- const o = A(t), s = e.store.last()?.time;
195
+ const o = S(t), s = e.store.last()?.time;
196
196
  e.store.updateLast(o);
197
197
  const n = s === void 0 ? void 0 : e.morphs.get(s);
198
198
  s !== void 0 && n !== void 0 && (e.morphs.delete(s), e.displayedLast = { low: n.low.current, high: n.high.current }, e.chase = n);
@@ -203,7 +203,7 @@ class st {
203
203
  }
204
204
  if (e.chase === null) {
205
205
  const r = e.displayedLast, c = r !== null && Number.isFinite(r.low) ? r : x(o);
206
- e.chase = { low: new S(c.low), high: new S(c.high) };
206
+ e.chase = { low: new A(c.low), high: new A(c.high) };
207
207
  }
208
208
  e.chase.low.retarget(o.low, { settleMs: l }), e.chase.high.retarget(o.high, { settleMs: l });
209
209
  }
@@ -239,9 +239,9 @@ class st {
239
239
  #g(t) {
240
240
  this.#i.tick(t), this.#o.tick(t);
241
241
  for (const i of this.#t)
242
- i.alpha.tick(t), this.#S(i, t), this.#T(i, t);
242
+ i.alpha.tick(t), this.#A(i, t), this.#T(i, t);
243
243
  }
244
- #S(t, i) {
244
+ #A(t, i) {
245
245
  const e = t.chase;
246
246
  if (e !== null) {
247
247
  const s = e.low.tick(i), n = e.high.tick(i);
@@ -350,7 +350,7 @@ class st {
350
350
  * link grows from the previous link's rendered spot, so a feed faster than
351
351
  * `entryMs` keeps every head unfurling instead of snapping older ones.
352
352
  */
353
- #v(t, i) {
353
+ #w(t, i) {
354
354
  if (this.#e.entryAnimation !== "grow") return null;
355
355
  const e = this.#t[i], o = this.#k(e);
356
356
  if (o.length === 0) return null;
@@ -363,12 +363,12 @@ class st {
363
363
  for (let p = 0; p < o.length; p++) {
364
364
  const h = s[n + 1 + p], u = this.#l(t, i, h);
365
365
  if (u === null) return null;
366
- const g = Y(o[p].progress), w = {
366
+ const g = Y(o[p].progress), v = {
367
367
  x: L(c.x, u.x, g),
368
368
  top: L(c.top, u.top, g),
369
369
  bottom: L(c.bottom, u.bottom, g)
370
370
  };
371
- r.set(h.time, w), c = w;
371
+ r.set(h.time, v), c = v;
372
372
  }
373
373
  return r;
374
374
  }
@@ -379,17 +379,17 @@ class st {
379
379
  this.#n = null;
380
380
  const e = this.#s;
381
381
  if (this.#o.active && e !== null) {
382
- const n = this.#e.historyReveal ?? tt;
383
- n !== "none" && (this.#n = n(this.#C(t, e)));
382
+ const n = this.#e.historyReveal ?? et;
383
+ n !== "none" && (this.#n = n(this.#V(t, e)));
384
384
  }
385
385
  const o = this.#n;
386
- this.#w(t, o?.ghostAlpha ?? 0);
386
+ this.#v(t, o?.ghostAlpha ?? 0);
387
387
  const s = this.#D(t, o, e);
388
388
  this.#i.active ? this.#R(t) : (this.#a = null, this.#m(t)), s && i.restore();
389
389
  }
390
390
  #R(t) {
391
- const i = (this.#e.introAnimation ?? this.#P())(this.#V(t));
392
- this.#a = i, this.#w(t, i.ghostAlpha ?? 0);
391
+ const i = (this.#e.introAnimation ?? this.#P())(this.#C(t));
392
+ this.#a = i, this.#v(t, i.ghostAlpha ?? 0);
393
393
  const { context: e } = t.scope, { width: o, height: s } = t.scope.bitmapSize, n = i.clip, l = n !== void 0 && (n.fromX !== void 0 || n.toX !== void 0);
394
394
  if (l) {
395
395
  const r = n.fromX ?? 0, c = n.toX ?? o;
@@ -398,10 +398,10 @@ class st {
398
398
  this.#m(t), l && e.restore();
399
399
  }
400
400
  #P() {
401
- return this.#h === null && (this.#h = J()), this.#h;
401
+ return this.#h === null && (this.#h = j()), this.#h;
402
402
  }
403
403
  /** Edges-only skeleton under the main pass, so a clip reveal never reads as an empty chart. */
404
- #w(t, i) {
404
+ #v(t, i) {
405
405
  if (i <= 0) return;
406
406
  const { context: e } = t.scope;
407
407
  e.save(), e.globalAlpha *= i, this.#c = !0, this.#m(t), this.#c = !1, e.restore();
@@ -423,16 +423,16 @@ class st {
423
423
  const { scope: s, timeScale: n } = t, l = n.getRange();
424
424
  let r = e.store.getVisibleData(l.from, l.to);
425
425
  if (r.length > s.mediaSize.width * 2 && (r = $(r, Math.round(s.mediaSize.width * 1.5))), r.length === 0) return;
426
- const c = r[r.length - 1], p = this.#y(e, r), h = p ? this.#v(t, i) : null, u = this.#B(t, { layerIndex: i, data: r, grown: h });
426
+ const c = r[r.length - 1], p = this.#y(e, r), h = p ? this.#w(t, i) : null, u = this.#B(t, { layerIndex: i, data: r, grown: h });
427
427
  if (u.length === 0) return;
428
- const g = p ? this.#d(e, c.time) : 1, w = p && !b(c) && this.#e.entryAnimation === "fade" && g < 1 ? nt(u) : null, { context: m } = s;
428
+ const g = p ? this.#d(e, c.time) : 1, v = p && !b(c) && this.#e.entryAnimation === "fade" && g < 1 ? rt(u) : null, { context: m } = s;
429
429
  m.save(), o < 1 && (m.globalAlpha *= o);
430
- const f = this.#r(i), v = { ctx: t, runs: u, color: f, growing: h !== null };
431
- if (w === null)
432
- this.#p(v);
430
+ const f = this.#r(i), w = { ctx: t, runs: u, color: f, growing: h !== null };
431
+ if (v === null)
432
+ this.#p(w);
433
433
  else {
434
434
  const { width: d, height: y } = s.bitmapSize;
435
- m.save(), m.beginPath(), m.rect(0, 0, w, y), m.clip(), this.#p(v), m.restore(), m.save(), m.beginPath(), m.rect(w, 0, Math.max(0, d - w), y), m.clip(), m.globalAlpha *= g, this.#p(v), m.restore();
435
+ m.save(), m.beginPath(), m.rect(0, 0, v, y), m.clip(), this.#p(w), m.restore(), m.save(), m.beginPath(), m.rect(v, 0, Math.max(0, d - v), y), m.clip(), m.globalAlpha *= g, this.#p(w), m.restore();
436
436
  }
437
437
  m.restore();
438
438
  }
@@ -466,24 +466,24 @@ class st {
466
466
  p.push(f[0]);
467
467
  continue;
468
468
  }
469
- const v = s && m === e.length - 1, d = f.map((M) => ({ x: M.x, y: M.top })), y = f.map((M) => ({ x: M.x, y: M.bottom })), D = {
469
+ const w = s && m === e.length - 1, d = f.map((M) => ({ x: M.x, y: M.top })), y = f.map((M) => ({ x: M.x, y: M.bottom })), D = {
470
470
  upper: d,
471
471
  lower: y,
472
- upperSegs: B(d, r, v),
473
- lowerSegs: B(y, r, v)
472
+ upperSegs: B(d, r, w),
473
+ lowerSegs: B(y, r, w)
474
474
  };
475
- it(D), c.push(D);
475
+ ot(D), c.push(D);
476
476
  }
477
477
  if (!this.#c && c.length > 0) {
478
478
  n.fillStyle = this.#E({ context: n, paths: c, color: o });
479
479
  for (const m of c) {
480
480
  n.beginPath(), n.moveTo(m.upper[0].x, m.upper[0].y), R(n, m.upperSegs);
481
481
  const f = m.lower[m.lower.length - 1];
482
- n.lineTo(f.x, f.y), Q(n, m.lower, m.lowerSegs), n.closePath(), n.fill();
482
+ n.lineTo(f.x, f.y), q(n, m.lower, m.lowerSegs), n.closePath(), n.fill();
483
483
  }
484
484
  }
485
- const h = this.#e.stroke, u = h.color ?? T(o, E), g = Math.max(1, Math.round(h.width * l)), w = h.visible && h.width > 0;
486
- if (w && c.length > 0) {
485
+ const h = this.#e.stroke, u = h.color ?? T(o, E), g = Math.max(1, Math.round(h.width * l)), v = h.visible && h.width > 0;
486
+ if (v && c.length > 0) {
487
487
  n.beginPath();
488
488
  for (const m of c)
489
489
  n.moveTo(m.upper[0].x, m.upper[0].y), R(n, m.upperSegs), n.moveTo(m.lower[0].x, m.lower[0].y), R(n, m.lowerSegs);
@@ -493,7 +493,7 @@ class st {
493
493
  n.beginPath();
494
494
  for (const m of p)
495
495
  n.moveTo(m.x, m.top), n.lineTo(m.x, m.bottom);
496
- n.strokeStyle = w ? u : T(o, E), n.lineWidth = g, n.lineCap = "round", n.stroke();
496
+ n.strokeStyle = v ? u : T(o, E), n.lineWidth = g, n.lineCap = "round", n.stroke();
497
497
  }
498
498
  }
499
499
  /** A gradient fill spans the layer's drawn extent this frame; a degenerate extent paints solid. */
@@ -501,8 +501,8 @@ class st {
501
501
  const { context: i, paths: e, color: o } = t, s = this.#e.fill;
502
502
  if (typeof s == "string") return s;
503
503
  const [n, l] = s ?? [
504
- T(o, q),
505
- T(o, K)
504
+ T(o, Q),
505
+ T(o, tt)
506
506
  ];
507
507
  let r = 1 / 0, c = -1 / 0;
508
508
  for (const h of e) {
@@ -516,7 +516,7 @@ class st {
516
516
  return p.addColorStop(0, n), p.addColorStop(1, l), p;
517
517
  }
518
518
  // --- Intro frames ---------------------------------------------------------
519
- #V(t) {
519
+ #C(t) {
520
520
  return this.#b(t, {
521
521
  progress: this.#i.linear(),
522
522
  range: t.timeScale.getRange(),
@@ -524,7 +524,7 @@ class st {
524
524
  width: t.timeScale.getMediaWidth() * t.scope.horizontalPixelRatio
525
525
  });
526
526
  }
527
- #C(t, i) {
527
+ #V(t, i) {
528
528
  const { timeScale: e } = t;
529
529
  return this.#b(t, {
530
530
  progress: this.#o.linear(),
@@ -541,26 +541,26 @@ class st {
541
541
  const { timeScale: e, yScale: o, scope: s } = t, { progress: n, range: l, width: r } = i, c = this.#t.length, p = new Array(c), h = new Array(c);
542
542
  let u;
543
543
  const g = (f) => {
544
- const v = p[f];
545
- if (v !== void 0) return v;
544
+ const w = p[f];
545
+ if (w !== void 0) return w;
546
546
  const d = (this.#t[f]?.store.getVisibleData(l.from, l.to) ?? []).map((y) => ({
547
547
  time: y.time,
548
548
  value: b(y) ? Number.NaN : o.lerpValue(y.low, y.high, 0.5)
549
549
  }));
550
550
  return p[f] = d, d;
551
- }, w = (f) => {
552
- const v = h[f];
553
- if (v !== void 0) return v;
554
- const d = j(g(f), o);
551
+ }, v = (f) => {
552
+ const w = h[f];
553
+ if (w !== void 0) return w;
554
+ const d = G(g(f), o);
555
555
  return h[f] = d, d;
556
556
  }, m = () => {
557
557
  if (u !== void 0) return u;
558
558
  u = null;
559
559
  for (let f = 0; f < c; f++) {
560
560
  if (this.getLayerAlpha(f) <= 0 || !this.isLayerVisible(f)) continue;
561
- const v = g(f).filter((d) => o.isPlottable(d.value));
562
- if (!(v.length < 2)) {
563
- u = v.map((d) => ({
561
+ const w = g(f).filter((d) => o.isPlottable(d.value));
562
+ if (!(w.length < 2)) {
563
+ u = w.map((d) => ({
564
564
  x: e.timeToBitmapXExact(d.time),
565
565
  y: o.valueToBitmapYExact(d.value),
566
566
  time: d.time
@@ -579,10 +579,10 @@ class st {
579
579
  timeToX: (f) => e.timeToBitmapXExact(f),
580
580
  xToTime: (f) => e.xToTime(f / s.horizontalPixelRatio),
581
581
  valueToY: (f) => o.valueToBitmapYExact(f),
582
- lerpValue: (f, v, d) => o.lerpValue(f, v, d),
582
+ lerpValue: (f, w, d) => o.lerpValue(f, w, d),
583
583
  layerCount: c,
584
584
  layerData: g,
585
- layerMean: w,
585
+ layerMean: v,
586
586
  primaryPath: m
587
587
  };
588
588
  }
@@ -602,15 +602,15 @@ class st {
602
602
  if (u === null) continue;
603
603
  const g = this.#r(r);
604
604
  o.save(), o.globalAlpha *= p, o.fillStyle = g;
605
- for (const w of [u.top, u.bottom])
606
- o.save(), o.globalAlpha *= 0.25, o.beginPath(), o.arc(u.x, w, l, 0, Math.PI * 2), o.fill(), o.restore(), o.beginPath(), o.arc(u.x, w, n, 0, Math.PI * 2), o.fill();
605
+ for (const v of [u.top, u.bottom])
606
+ o.save(), o.globalAlpha *= 0.25, o.beginPath(), o.arc(u.x, v, l, 0, Math.PI * 2), o.fill(), o.restore(), o.beginPath(), o.arc(u.x, v, n, 0, Math.PI * 2), o.fill();
607
607
  o.restore();
608
608
  }
609
609
  }
610
610
  /** The hovered sample where the fill draws it: an entering tail point sits on its grown head. */
611
611
  #X(t, i, e) {
612
612
  const o = this.#t[i], s = t.timeScale.getRange(), n = o.store.getVisibleData(s.from, s.to);
613
- return (this.#y(o, n) ? this.#v(t, i) : null)?.get(e.time) ?? this.#l(t, i, e);
613
+ return (this.#y(o, n) ? this.#w(t, i) : null)?.get(e.time) ?? this.#l(t, i, e);
614
614
  }
615
615
  // --- Data queries ---------------------------------------------------------
616
616
  /** A sample as a query reports it: the drawn (live-chased) edges, `null` for a gap. */
@@ -670,11 +670,11 @@ class st {
670
670
  const t = this.#t[0].store.getAll();
671
671
  return t.length < 2 ? null : t[t.length - 2];
672
672
  }
673
- sampleTimes(t) {
674
- for (const i of this.#t) {
675
- const e = i.store.getAll();
676
- if (e.length !== 0)
677
- return e.slice(0, t).map((o) => o.time);
673
+ sampleTimes(t, i = "start") {
674
+ for (const e of this.#t) {
675
+ const o = e.store.getAll();
676
+ if (o.length !== 0)
677
+ return W(o, { maxCount: t, from: i }).map((s) => s.time);
678
678
  }
679
679
  return [];
680
680
  }
@@ -708,16 +708,16 @@ class st {
708
708
  function X(a, t) {
709
709
  return t === 1 ? [a.bands.upper] : a.seriesColors.slice(0, t);
710
710
  }
711
- function nt(a) {
711
+ function rt(a) {
712
712
  const t = a[a.length - 1];
713
713
  return t.length < 2 ? null : Math.round(t[t.length - 2].x);
714
714
  }
715
- const wt = {
715
+ const yt = {
716
716
  type: "band",
717
717
  xTypes: ["time", "numeric", "category"],
718
- create: ({ theme: a, layerCount: t }, i) => new st(t, { colors: X(a, t), ...i })
718
+ create: ({ theme: a, layerCount: t }, i) => new nt(t, { colors: X(a, t), ...i })
719
719
  };
720
720
  export {
721
- st as BandRenderer,
722
- wt as BandSeriesDef
721
+ nt as BandRenderer,
722
+ yt as BandSeriesDef
723
723
  };