@wick-charts/vue 0.6.0 → 0.6.1

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,40 +1,40 @@
1
- import { AnimationConfig as F, DEFAULT_LINE_PULSE as E } from "./animation/config.js";
2
- import { easeOutCubic as L } from "./animation/easing.js";
3
- import { createViewportEngine as N } from "./animation/viewport-engine.js";
4
- import { CanvasManager as W } from "./canvas-manager.js";
5
- import { resolveEdgeAnchorValue as O, drawEdgeIndicators as Y, resolveEdgeBoundary as B } from "./chart/edge-indicators.js";
6
- import { computeFitToData as X } from "./chart/fit-to-data.js";
7
- import { getLastValue as Z, getPreviousClose as _, getStackedLastValue as U } from "./chart/last-value.js";
8
- import { resolveMaxVisibleBars as $, resolvePadding as C, resolvePerfOptions as G, isSameHorizontalPadding as R } from "./chart/options.js";
9
- import { computePan as q, computeZoom as K } from "./chart/pan-zoom-math.js";
10
- import { StreamingCadence as j } from "./chart/streaming-cadence.js";
11
- import { computeStreamingTarget as J } from "./chart/streaming-target.js";
12
- import { resolvePaddingTime as M } from "./chart/viewport-padding.js";
13
- import { computeTargetYRange as Q, resolveBound as I } from "./chart/y-target.js";
14
- import { renderCrosshair as tt } from "./components/crosshair.js";
15
- import { renderGrid as it } from "./components/grid.js";
16
- import { renderMarker as et } from "./components/marker.js";
17
- import { renderReferenceLine as st } from "./components/reference-line.js";
18
- import { resolveTimeRegionColors as rt, renderTimeRegion as nt } from "./components/time-region.js";
19
- import { EventEmitter as at } from "./events.js";
20
- import { InteractionHandler as ht } from "./interactions/handler.js";
21
- import { RenderScheduler as P } from "./render-scheduler.js";
22
- import { XScale as ot } from "./scales/x-scale.js";
23
- import { YScale as lt } from "./scales/y-scale.js";
24
- import { resolveSeriesDefinition as ct } from "./series/definition.js";
25
- import { isTimeSeriesRenderer as S } from "./series/types.js";
26
- import { catppuccin as dt } from "./theme/themes/catppuccin.js";
27
- import { clamp as mt } from "./utils/math.js";
28
- import { normalizeTime as y, detectInterval as ut } from "./utils/time.js";
29
- const ft = 200, gt = 1500;
30
- let pt = 0, yt = 0, vt = 0, bt = 0;
31
- function H(f, t) {
32
- return f === t ? !0 : !f || !t || f.length !== t.length ? !1 : f.every((i, e) => i === t[e]);
1
+ import { AnimationConfig as O, DEFAULT_LINE_PULSE as N } from "./animation/config.js";
2
+ import { easeOutCubic as R } from "./animation/easing.js";
3
+ import { createViewportEngine as E } from "./animation/viewport-engine.js";
4
+ import { CanvasManager as Y } from "./canvas-manager.js";
5
+ import { resolveEdgeAnchorValue as X, drawEdgeIndicators as Z, resolveEdgeBoundary as $ } from "./chart/edge-indicators.js";
6
+ import { computeFitToData as _ } from "./chart/fit-to-data.js";
7
+ import { getLastValue as G, getPreviousClose as U, getStackedLastValue as K } from "./chart/last-value.js";
8
+ import { resolveFade as C, resolveMaxVisibleBars as j, resolvePadding as I, resolvePerfOptions as q, isSameHorizontalPadding as P } from "./chart/options.js";
9
+ import { computePan as J, computeZoom as Q } from "./chart/pan-zoom-math.js";
10
+ import { StreamingCadence as tt } from "./chart/streaming-cadence.js";
11
+ import { computeStreamingTarget as it } from "./chart/streaming-target.js";
12
+ import { resolvePaddingTime as H } from "./chart/viewport-padding.js";
13
+ import { computeTargetYRange as et, resolveBound as z } from "./chart/y-target.js";
14
+ import { renderCrosshair as st } from "./components/crosshair.js";
15
+ import { renderGrid as rt } from "./components/grid.js";
16
+ import { renderMarker as nt } from "./components/marker.js";
17
+ import { renderReferenceLine as at } from "./components/reference-line.js";
18
+ import { resolveTimeRegionColors as ht, renderTimeRegion as ot } from "./components/time-region.js";
19
+ import { EventEmitter as lt } from "./events.js";
20
+ import { InteractionHandler as ct } from "./interactions/handler.js";
21
+ import { RenderScheduler as V } from "./render-scheduler.js";
22
+ import { XScale as dt } from "./scales/x-scale.js";
23
+ import { YScale as mt } from "./scales/y-scale.js";
24
+ import { resolveSeriesDefinition as ut } from "./series/definition.js";
25
+ import { isTimeSeriesRenderer as x } from "./series/types.js";
26
+ import { catppuccin as ft } from "./theme/themes/catppuccin.js";
27
+ import { clamp as gt } from "./utils/math.js";
28
+ import { normalizeTime as v, detectInterval as pt } from "./utils/time.js";
29
+ const yt = 200, vt = 1500, bt = 48, xt = 12, A = 9;
30
+ let St = 0, kt = 0, wt = 0, At = 0;
31
+ function W(g, t) {
32
+ return g === t ? !0 : !g || !t || g.length !== t.length ? !1 : g.every((i, e) => i === t[e]);
33
33
  }
34
- function St(f, t) {
35
- return f === t ? !0 : !f || !t || f.length !== t.length ? !1 : f.every((i, e) => i === t[e]);
34
+ function Mt(g, t) {
35
+ return g === t ? !0 : !g || !t || g.length !== t.length ? !1 : g.every((i, e) => i === t[e]);
36
36
  }
37
- class qt extends at {
37
+ class ti extends lt {
38
38
  /** Canvas lifecycle and DPR-aware sizing. */
39
39
  #a;
40
40
  /** Schedules main-layer redraws (background, grid, series). */
@@ -46,7 +46,7 @@ class qt extends at {
46
46
  /** Maps price/value to vertical pixel coordinates. */
47
47
  yScale;
48
48
  /** Zoom, pan, crosshair — null when interactive=false. */
49
- #C;
49
+ #T;
50
50
  /** All registered series (candlestick, line, bar, pie). */
51
51
  #t = [];
52
52
  /** Point annotations (event markers) drawn on the overlay layer, kept out of the series model. */
@@ -63,12 +63,18 @@ class qt extends at {
63
63
  * later — which re-arms `getIntroFront()`'s global min — can't blink settled
64
64
  * markers / reference lines back out.
65
65
  */
66
- #tt = !1;
67
- #it = !1;
66
+ #rt = !1;
67
+ #nt = !1;
68
68
  /** Active visual theme (colors, fonts, grid style). */
69
69
  #n;
70
70
  /** Whether to render the background grid. */
71
- #O;
71
+ #V;
72
+ /** Resolved edge-fade zones — `right: null` tracks the live Y-axis width. */
73
+ #k;
74
+ /** Memoized destination-out mask gradients, one per edge, keyed by the
75
+ * zone's bitmap geometry so a resize / DPR change / `setFade` rebuilds
76
+ * them and steady frames reuse them. */
77
+ #w = { top: null, right: null, left: null, tail: null };
72
78
  /** Detected time interval between data points (milliseconds). */
73
79
  #r = 6e4;
74
80
  /** Current crosshair position, null when cursor is outside the chart. */
@@ -80,45 +86,45 @@ class qt extends at {
80
86
  * `time`/`y`; `'time'` (programmatic {@link setCrosshair}) keeps
81
87
  * `time`/`y` and re-projects the pixel position.
82
88
  */
83
- #Y = "pointer";
89
+ #X = "pointer";
84
90
  /** Whether the last overlay pass painted anything — gates the full-bitmap
85
91
  * clear so an empty overlay isn't cleared again every main frame. */
86
- #et = !1;
92
+ #at = !1;
87
93
  /** User-specified Y-axis bounds (auto, fixed, percentage). */
88
94
  #l = {};
89
95
  /** Cached series ID list — invalidated on add/remove. */
90
- #T = null;
96
+ #D = null;
91
97
  /** Axis visibility and sizing configuration. */
92
- #H = {};
98
+ #W = {};
93
99
  /** Host-declared state per edge — drives the edge-indicator overlay. */
94
- #S = { left: "idle", right: "idle" };
100
+ #x = { left: "idle", right: "idle" };
95
101
  /** Wall-clock start of a `loading` exit fade per side — set when the host
96
102
  * drops `loading` back to `idle`/`has-more`, so the indicator fades out
97
103
  * over {@link EDGE_EXIT_FADE_MS} instead of vanishing the same frame the
98
104
  * fetched data lands. `null` = no fade in flight. */
99
- #V = { left: null, right: null };
105
+ #B = { left: null, right: null };
100
106
  /** Cached boundary timestamps from the last `edgeReached` emission, by side. */
101
- #st = { left: null, right: null };
107
+ #ht = { left: null, right: null };
102
108
  /** Latest placeholder shapes a `loading` indicator reported per side —
103
109
  * the morph hand-off candidate consumed by {@link prependData}. */
104
- #B = { left: null, right: null };
110
+ #Z = { left: null, right: null };
105
111
  /** True after a prepend consumed a side's placeholder snapshot: the series'
106
112
  * reveal owns those pixels now, so the still-`loading` indicator is hidden
107
113
  * and the upcoming `loading → idle` transition skips its exit fade. Reset
108
114
  * by the next {@link setEdgeState} call. */
109
- #R = { left: !1, right: !1 };
115
+ #I = { left: !1, right: !1 };
110
116
  /** Host-supplied callback fired when the user releases a pan/zoom past a data edge. */
111
- #rt;
117
+ #ot;
112
118
  /** Per-side custom painter for the edge `loading` spinner. `null` falls back to the built-in dots. */
113
- #nt = { left: null, right: null };
119
+ #lt = { left: null, right: null };
114
120
  /** Nesting depth for batch updates. Suppresses recomputes while > 0. */
115
- #A = 0;
121
+ #M = 0;
116
122
  /** True when batched operations include data changes (triggers full onDataChanged on end). */
117
- #X = !1;
123
+ #$ = !1;
118
124
  /** True when batched operations include visibility changes (triggers Y-range + redraw on end). */
119
- #M = !1;
125
+ #P = !1;
120
126
  /** True when batched operations bumped overlay version (emits a single overlayChange on flush). */
121
- #Z = !1;
127
+ #_ = !1;
122
128
  /**
123
129
  * Monotonic counter bumped on any mutation that affects overlay output —
124
130
  * data, visibility, series options, theme. Used by snapshot helpers in
@@ -128,13 +134,13 @@ class qt extends at {
128
134
  *
129
135
  * @internal
130
136
  */
131
- #at = 0;
137
+ #ct = 0;
132
138
  get yAxisWidth() {
133
- const t = this.#H.y;
139
+ const t = this.#W.y;
134
140
  return t?.visible === !1 ? 0 : t?.width ?? 55;
135
141
  }
136
142
  get xAxisHeight() {
137
- const t = this.#H.x;
143
+ const t = this.#W.x;
138
144
  return t?.visible === !1 ? 0 : t?.height ?? 30;
139
145
  }
140
146
  /** Resolved animation config derived from `options.animations` at construction. */
@@ -153,7 +159,7 @@ class qt extends at {
153
159
  * longer than the producer's tick interval — the spring never quite
154
160
  * settles between ticks, so velocity carries continuously and the slide
155
161
  * doesn't pulse. */
156
- #D;
162
+ #R;
157
163
  /**
158
164
  * Mirrors `#dataReplaceSnapPending` for the engine signal that follows
159
165
  * inside the same `onDataChanged` call. `#dataReplaceSnapPending` is
@@ -163,9 +169,9 @@ class qt extends at {
163
169
  * field carries the decision across that gap. The closure also reads
164
170
  * `#dataStart` / `#dataEnd` directly for the timestamps.
165
171
  */
166
- #ht = !1;
172
+ #dt = !1;
167
173
  /** Earliest data timestamp registered across all series, `null` before any data has arrived. */
168
- #k = null;
174
+ #A = null;
169
175
  /** Latest data timestamp registered across all series, `null` before any data has arrived. */
170
176
  #i = null;
171
177
  /**
@@ -174,20 +180,20 @@ class qt extends at {
174
180
  * left of the tail keeps that offset as new bars arrive, instead of
175
181
  * snapping back to the natural-pin position every frame.
176
182
  */
177
- #z = null;
183
+ #F = null;
178
184
  /**
179
185
  * Warm-up window flag — `setVisibleRange({ from, bars })` arms it and
180
186
  * the streaming-target math suppresses pan ticks while the data hasn't
181
187
  * reached the right edge yet. Cleared by user interaction or once the
182
188
  * data fills the window.
183
189
  */
184
- #w = !1;
190
+ #L = !1;
185
191
  /**
186
192
  * Cap for fit-to-data. When the data span exceeds this, the fit anchors
187
193
  * the right edge and trims the left. Resolved once at construction from
188
194
  * `options.viewport.maxVisibleBars`.
189
195
  */
190
- #ot;
196
+ #mt;
191
197
  /**
192
198
  * Committed logical X range — the "where X should be" target. Engine
193
199
  * eases its visual toward this. Pan / zoom / setRange / fitContent /
@@ -196,7 +202,7 @@ class qt extends at {
196
202
  */
197
203
  #o = { from: 0, to: 0 };
198
204
  /** Padded Y range — engine's raw Y target plus pixel padding from `#padding`. */
199
- #F = { min: 0, max: 0 };
205
+ #O = { min: 0, max: 0 };
200
206
  /**
201
207
  * Auto-scroll flag — when `true`, streaming ticks slide X to track the
202
208
  * data tail. Pan flips this off when the gesture pushes the tail off
@@ -208,17 +214,17 @@ class qt extends at {
208
214
  #c;
209
215
  /** Cached chart width — passed by interactions on every call; kept for the rare
210
216
  * call that omits it (e.g. programmatic `chart.pan(...)` without explicit width). */
211
- #E = 0;
217
+ #N = 0;
212
218
  /** Active performance monitor, or `null` when instrumentation is disabled (the default). */
213
- #x;
219
+ #S;
214
220
  /** When true, `destroy()` tears down the monitor; false for caller-supplied monitors we must not destroy. */
215
- #_ = !1;
221
+ #G = !1;
216
222
  /** Visible HUD overlay (mounted by the perf config); non-null only when the caller requested one. */
217
223
  #U = null;
218
224
  constructor(t, i) {
219
- super(), i?.axis && (this.#H = i.axis, this.#l = { min: i.axis.y?.min, max: i.axis.y?.max }), this.#n = i?.theme ?? dt.theme, this.#O = i?.grid?.visible !== !1, this.#g = F.resolve(i?.animations), this.#ot = $(i?.viewport?.maxVisibleBars), this.#c = C(i?.padding), this.#D = new j();
225
+ super(), i?.axis && (this.#W = i.axis, this.#l = { min: i.axis.y?.min, max: i.axis.y?.max }), this.#n = i?.theme ?? ft.theme, this.#V = i?.grid?.visible !== !1, this.#k = C(i?.fade), this.#g = O.resolve(i?.animations), this.#mt = j(i?.viewport?.maxVisibleBars), this.#c = I(i?.padding), this.#R = new tt();
220
226
  const e = this.#g.axis.y, s = this.#g.axis.x;
221
- this.#s = N({
227
+ this.#s = E({
222
228
  initial: { yRange: { min: 0, max: 0 }, xRange: { from: 0, to: 0 } },
223
229
  y: {
224
230
  curve: e.curve,
@@ -233,25 +239,25 @@ class qt extends at {
233
239
  settleMs: s.settleMs,
234
240
  gestureMs: s.gestureMs
235
241
  },
236
- computeXTarget: () => this.#Rt(),
237
- computeYTarget: ({ xTarget: a }) => this.#gt(a),
242
+ computeXTarget: () => this.#Wt(),
243
+ computeYTarget: ({ xTarget: h }) => this.#xt(h),
238
244
  onWake: () => this.#e?.markDirty()
239
- }), this.#rt = i?.onEdgeReached, this.#N = i?.viewport?.initialRange;
240
- const r = G(i?.perf);
241
- this.#x = r.monitor, this.#_ = r.ownsMonitor, this.#a = new W(t, this.#x ?? void 0), this.timeScale = new ot(), this.yScale = new lt(), this.timeScale.setLocale(i?.locale), this.timeScale.setTimeZone(i?.timeZone);
245
+ }), this.#ot = i?.onEdgeReached, this.#E = i?.viewport?.initialRange;
246
+ const r = q(i?.perf);
247
+ this.#S = r.monitor, this.#G = r.ownsMonitor, this.#a = new Y(t, this.#S ?? void 0), this.timeScale = new dt(), this.yScale = new mt(), this.timeScale.setLocale(i?.locale), this.timeScale.setTimeZone(i?.timeZone);
242
248
  const n = this.#g.axis.ticksMs;
243
- this.timeScale.tickTracker.setFadeMs(n), this.yScale.tickTracker.setFadeMs(n), this.#e = new P((a) => this.#J(a)), this.#h = new P(
244
- (a) => this.#Q("overlay", a, () => this.renderOverlay(a))
245
- ), this.#x && r.hud && (this.#U = r.hud(t, this.#x));
246
- const h = i?.interactive !== !1;
247
- this.#C = h ? new ht(this.#a.canvas, this, this.timeScale, this.yScale) : null, this.#a.on("resize", () => {
248
- this.syncScales(), this.#J(), this.emit("viewportChange");
249
- }), this.syncScales(), this.#C?.on("crosshairMove", (a) => {
250
- this.#Y = "pointer", this.#d = a, this.#h.markDirty(), this.emit("crosshairMove", a), this.#G(a);
251
- }), this.#C?.on("click", (a) => {
252
- this.emit("pointClick", { ...a, spatialHit: this.#ft(a) });
253
- }), this.#C?.on("dblclick", (a) => {
254
- this.fitContent(), this.emit("pointDoubleClick", { ...a, spatialHit: this.#ft(a) });
249
+ this.timeScale.tickTracker.setFadeMs(n), this.yScale.tickTracker.setFadeMs(n), this.#e = new V((h) => this.#et(h)), this.#h = new V(
250
+ (h) => this.#st("overlay", h, () => this.renderOverlay(h))
251
+ ), this.#S && r.hud && (this.#U = r.hud(t, this.#S));
252
+ const a = i?.interactive !== !1;
253
+ this.#T = a ? new ct(this.#a.canvas, this, this.timeScale, this.yScale) : null, this.#a.on("resize", () => {
254
+ this.syncScales(), this.#et(), this.emit("viewportChange");
255
+ }), this.syncScales(), this.#T?.on("crosshairMove", (h) => {
256
+ this.#X = "pointer", this.#d = h, this.#h.markDirty(), this.emit("crosshairMove", h), this.#q(h);
257
+ }), this.#T?.on("click", (h) => {
258
+ this.emit("pointClick", { ...h, spatialHit: this.#bt(h) });
259
+ }), this.#T?.on("dblclick", (h) => {
260
+ this.fitContent(), this.emit("pointDoubleClick", { ...h, spatialHit: this.#bt(h) });
255
261
  });
256
262
  }
257
263
  /**
@@ -267,8 +273,8 @@ class qt extends at {
267
273
  * render instead of N.
268
274
  */
269
275
  #p() {
270
- if (this.#at++, this.#A > 0) {
271
- this.#Z = !0;
276
+ if (this.#ct++, this.#M > 0) {
277
+ this.#_ = !0;
272
278
  return;
273
279
  }
274
280
  this.emit("overlayChange");
@@ -282,39 +288,39 @@ class qt extends at {
282
288
  * @internal
283
289
  */
284
290
  getOverlayVersion() {
285
- return this.#at;
291
+ return this.#ct;
286
292
  }
287
293
  /**
288
294
  * Return a series ID: use the provided hint if it's non-empty and not already taken,
289
295
  * otherwise generate a new auto ID. Auto-generated IDs never collide with each other
290
296
  * or with user-provided IDs because they use a monotonically increasing counter.
291
297
  */
292
- #bt(t) {
298
+ #Tt(t) {
293
299
  if (t && !this.#t.some((e) => e.id === t))
294
300
  return t;
295
301
  let i;
296
302
  do
297
- i = `series_${++pt}`;
303
+ i = `series_${++St}`;
298
304
  while (this.#t.some((e) => e.id === i));
299
305
  return i;
300
306
  }
301
307
  addSeries(t, i = {}) {
302
- const e = typeof t == "string" ? ct(t) : t;
308
+ const e = typeof t == "string" ? ut(t) : t;
303
309
  if (!e)
304
310
  throw new Error(
305
311
  `[wick-charts] Unknown series type '${String(t)}'. The string form of addSeries resolves through the series registry — call registerBuiltinSeries() once at startup, or pass the definition directly: chart.addSeries(LineSeriesDef, options).`
306
312
  );
307
- const { layers: s, id: r, label: n, labels: h, ...a } = i, l = s ?? 1, o = {
313
+ const { layers: s, id: r, label: n, labels: a, ...h } = i, l = s ?? 1, o = {
308
314
  ...this.#g.defaults(e.type),
309
- ...a,
315
+ ...h,
310
316
  ...this.#g.overrides(e.type)
311
- }, u = e.create({ theme: this.#n, layerCount: l }, o), d = h ?? (typeof n == "string" ? [n] : void 0), c = this.#bt(r);
312
- return u.onDataChanged?.(() => this.onDataChanged()), this.#t.push({ id: c, labels: d, renderer: u, visible: !0 }), this.#T = null, this.emit("seriesChange"), this.#p(), c;
317
+ }, u = e.create({ theme: this.#n, layerCount: l }, o), c = a ?? (typeof n == "string" ? [n] : void 0), d = this.#Tt(r);
318
+ return u.onDataChanged?.(() => this.onDataChanged()), this.#t.push({ id: d, labels: c, renderer: u, visible: !0 }), this.#D = null, this.#j(), this.emit("seriesChange"), this.#p(), d;
313
319
  }
314
320
  /** Remove a series by ID and clean up its resources. */
315
321
  removeSeries(t) {
316
322
  const i = this.#t.findIndex((e) => e.id === t);
317
- i >= 0 && (this.#t[i].renderer.dispose(), this.#t.splice(i, 1), this.#T = null, this.#e.markDirty(), this.emit("seriesChange"), this.#p());
323
+ i >= 0 && (this.#t[i].renderer.dispose(), this.#t.splice(i, 1), this.#D = null, this.#j(), this.#e.markDirty(), this.emit("seriesChange"), this.#p());
318
324
  }
319
325
  // --- Markers (point annotations) -----------------------------------------
320
326
  /**
@@ -327,13 +333,13 @@ class qt extends at {
327
333
  * appear in series queries.
328
334
  */
329
335
  addMarker(t) {
330
- const i = `marker_${++yt}`;
331
- return this.#m.push(this.#lt(i, t)), this.#h.markDirty(), i;
336
+ const i = `marker_${++kt}`;
337
+ return this.#m.push(this.#ut(i, t)), this.#h.markDirty(), i;
332
338
  }
333
339
  /** Replace a marker's config in place. No-op when the id is unknown. */
334
340
  updateMarker(t, i) {
335
341
  const e = this.#m.findIndex((s) => s.id === t);
336
- e !== -1 && (this.#m[e] = this.#lt(t, i), this.#h.markDirty());
342
+ e !== -1 && (this.#m[e] = this.#ut(t, i), this.#h.markDirty());
337
343
  }
338
344
  /** Remove a marker by id. No-op when the id is unknown. */
339
345
  removeMarker(t) {
@@ -344,10 +350,10 @@ class qt extends at {
344
350
  getMarkers() {
345
351
  return this.#m;
346
352
  }
347
- #lt(t, i) {
353
+ #ut(t, i) {
348
354
  return {
349
355
  id: t,
350
- time: y(i.time),
356
+ time: v(i.time),
351
357
  value: i.value,
352
358
  seriesId: i.seriesId,
353
359
  shape: i.shape ?? "dot",
@@ -357,14 +363,14 @@ class qt extends at {
357
363
  };
358
364
  }
359
365
  /** Resolve a marker's Y value: explicit `value`, else snapped to its series at `time`. Null when neither resolves. */
360
- #St(t) {
366
+ #Dt(t) {
361
367
  if (t.value !== void 0 && Number.isFinite(t.value)) return t.value;
362
368
  if (t.seriesId === void 0) return null;
363
369
  const i = this.getDataAtTime(t.seriesId, t.time);
364
370
  return i ? "close" in i ? i.close : i.value : null;
365
371
  }
366
372
  /** Resolve a marker's color: explicit `color`, else the series color, else the theme line color. */
367
- #xt(t) {
373
+ #Rt(t) {
368
374
  if (t.color !== void 0) return t.color;
369
375
  if (t.seriesId !== void 0) {
370
376
  const i = this.getSeriesColor(t.seriesId);
@@ -372,24 +378,24 @@ class qt extends at {
372
378
  }
373
379
  return this.#n.line.color;
374
380
  }
375
- #kt(t, i, e) {
381
+ #Ct(t, i, e) {
376
382
  if (this.#m.length === 0) return;
377
- const s = performance.now() / (E * 2 * Math.PI) % 1, r = this.#$();
383
+ const s = performance.now() / (N * 2 * Math.PI) % 1, r = this.#K();
378
384
  for (const n of this.#m) {
379
- const h = this.#St(n);
380
- if (h === null) continue;
381
- const a = this.#mt(r, n.time);
382
- if (a <= 0) continue;
385
+ const a = this.#Dt(n);
386
+ if (a === null) continue;
387
+ const h = this.#pt(r, n.time);
388
+ if (h <= 0) continue;
383
389
  const l = t.context.globalAlpha;
384
- a < 1 && (t.context.globalAlpha = l * a), et({
390
+ h < 1 && (t.context.globalAlpha = l * h), nt({
385
391
  scope: t,
386
392
  timeScale: this.timeScale,
387
393
  yScale: this.yScale,
388
394
  theme: this.#n,
389
395
  marker: {
390
396
  time: n.time,
391
- value: h,
392
- color: this.#xt(n),
397
+ value: a,
398
+ color: this.#Rt(n),
393
399
  shape: n.shape,
394
400
  pulse: n.pulse,
395
401
  label: n.label
@@ -397,7 +403,7 @@ class qt extends at {
397
403
  phase: s,
398
404
  plotWidth: i,
399
405
  plotHeight: e
400
- }), a < 1 && (t.context.globalAlpha = l);
406
+ }), h < 1 && (t.context.globalAlpha = l);
401
407
  }
402
408
  }
403
409
  // --- Time regions (shaded bands) -----------------------------------------
@@ -413,13 +419,13 @@ class qt extends at {
413
419
  * legend.
414
420
  */
415
421
  addRegion(t) {
416
- const i = `region_${++vt}`;
417
- return this.#b.push(this.#ct(i, t)), this.#e.markDirty(), i;
422
+ const i = `region_${++wt}`;
423
+ return this.#b.push(this.#ft(i, t)), this.#e.markDirty(), i;
418
424
  }
419
425
  /** Replace a region's config in place. No-op when the id is unknown. */
420
426
  updateRegion(t, i) {
421
427
  const e = this.#b.findIndex((s) => s.id === t);
422
- e !== -1 && (this.#b[e] = this.#ct(t, i), this.#e.markDirty());
428
+ e !== -1 && (this.#b[e] = this.#ft(t, i), this.#e.markDirty());
423
429
  }
424
430
  /** Remove a region by id. No-op when the id is unknown. */
425
431
  removeRegion(t) {
@@ -430,22 +436,22 @@ class qt extends at {
430
436
  getRegions() {
431
437
  return this.#b;
432
438
  }
433
- #ct(t, i) {
434
- const { to: e } = i, s = e === void 0 || e === "now" ? null : y(e);
439
+ #ft(t, i) {
440
+ const { to: e } = i, s = e === void 0 || e === "now" ? null : v(e);
435
441
  return {
436
442
  id: t,
437
- from: y(i.from),
443
+ from: v(i.from),
438
444
  to: s,
439
445
  fill: i.fill,
440
446
  color: i.color,
441
447
  label: i.label
442
448
  };
443
449
  }
444
- #At(t, i, e) {
450
+ #It(t, i, e) {
445
451
  if (this.#b.length !== 0)
446
452
  for (const s of this.#b) {
447
- const { color: r, fill: n } = rt(s, this.#n);
448
- nt({
453
+ const { color: r, fill: n } = ht(s, this.#n);
454
+ ot({
449
455
  scope: t,
450
456
  timeScale: this.timeScale,
451
457
  theme: this.#n,
@@ -467,13 +473,13 @@ class qt extends at {
467
473
  * legend.
468
474
  */
469
475
  addLine(t) {
470
- const i = `line_${++bt}`;
471
- return this.#y.push(this.#dt(i, t)), this.#h.markDirty(), i;
476
+ const i = `line_${++At}`;
477
+ return this.#y.push(this.#gt(i, t)), this.#h.markDirty(), i;
472
478
  }
473
479
  /** Replace a reference line's config in place. No-op when the id is unknown. */
474
480
  updateLine(t, i) {
475
481
  const e = this.#y.findIndex((s) => s.id === t);
476
- e !== -1 && (this.#y[e] = this.#dt(t, i), this.#h.markDirty());
482
+ e !== -1 && (this.#y[e] = this.#gt(t, i), this.#h.markDirty());
477
483
  }
478
484
  /** Remove a reference line by id. No-op when the id is unknown. */
479
485
  removeLine(t) {
@@ -484,7 +490,7 @@ class qt extends at {
484
490
  getLines() {
485
491
  return this.#y;
486
492
  }
487
- #dt(t, i) {
493
+ #gt(t, i) {
488
494
  const { time: e, value: s } = i, r = {
489
495
  id: t,
490
496
  color: i.color,
@@ -492,16 +498,16 @@ class qt extends at {
492
498
  style: i.style ?? "dashed",
493
499
  width: i.width ?? 1
494
500
  };
495
- return e !== void 0 ? { ...r, orientation: "vertical", coord: y(e) } : { ...r, orientation: "horizontal", coord: s ?? Number.NaN };
501
+ return e !== void 0 ? { ...r, orientation: "vertical", coord: v(e) } : { ...r, orientation: "horizontal", coord: s ?? Number.NaN };
496
502
  }
497
- #wt(t, i, e) {
503
+ #Pt(t, i, e) {
498
504
  if (this.#y.length === 0) return;
499
- const s = this.#$();
505
+ const s = this.#K();
500
506
  for (const r of this.#y) {
501
- const n = s >= 1 ? 1 : r.orientation === "vertical" ? this.#mt(s, r.coord) : L(s);
507
+ const n = s >= 1 ? 1 : r.orientation === "vertical" ? this.#pt(s, r.coord) : R(s);
502
508
  if (n <= 0) continue;
503
- const h = t.context.globalAlpha;
504
- n < 1 && (t.context.globalAlpha = h * n), st({
509
+ const a = t.context.globalAlpha;
510
+ n < 1 && (t.context.globalAlpha = a * n), at({
505
511
  scope: t,
506
512
  timeScale: this.timeScale,
507
513
  yScale: this.yScale,
@@ -516,7 +522,7 @@ class qt extends at {
516
522
  },
517
523
  plotWidth: i,
518
524
  plotHeight: e
519
- }), n < 1 && (t.context.globalAlpha = h);
525
+ }), n < 1 && (t.context.globalAlpha = a);
520
526
  }
521
527
  }
522
528
  /**
@@ -554,10 +560,10 @@ class qt extends at {
554
560
  * has actually been observed in progress, so an annotation drawn on a chart
555
561
  * that has no data yet still rides the reveal once data arrives.
556
562
  */
557
- #$() {
558
- if (this.#it) return 1;
563
+ #K() {
564
+ if (this.#nt) return 1;
559
565
  const t = this.getIntroFront();
560
- return t < 1 ? (this.#tt = !0, t) : (this.#tt && (this.#it = !0), 1);
566
+ return t < 1 ? (this.#rt = !0, t) : (this.#rt && (this.#nt = !0), 1);
561
567
  }
562
568
  /**
563
569
  * Entrance alpha for an overlay pinned at `time`, given the intro reveal
@@ -565,10 +571,10 @@ class qt extends at {
565
571
  * then fades in over a short band — so annotations surface in step with the
566
572
  * series drawing past them. `1` once the intro has settled.
567
573
  */
568
- #mt(t, i) {
574
+ #pt(t, i) {
569
575
  if (t >= 1) return 1;
570
576
  const { from: e, to: s } = this.timeScale.getRange(), r = s - e, n = r > 0 ? (i - e) / r : 0;
571
- return mt((t - n) / 0.12, 0, 1);
577
+ return gt((t - n) / 0.12, 0, 1);
572
578
  }
573
579
  /**
574
580
  * Replace all data for a series.
@@ -581,7 +587,7 @@ class qt extends at {
581
587
  */
582
588
  setSeriesData(t, i, e) {
583
589
  const s = this.#t.find((r) => r.id === t);
584
- s && (this.#q = !0, s.renderer.setData(i, e));
590
+ s && (this.#J = !0, s.renderer.setData(i, e));
585
591
  }
586
592
  /** Append a new data point to the end of a series (real-time tick). */
587
593
  appendData(t, i, e) {
@@ -604,8 +610,8 @@ class qt extends at {
604
610
  prependData(t, i, e) {
605
611
  const s = this.#t.find((n) => n.id === t);
606
612
  if (s === void 0 || s.renderer.prependPoints === void 0) return;
607
- const r = this.#B.left;
608
- r !== null && s.renderer.setHistoryHandoff !== void 0 && performance.now() - r.at < gt && (s.renderer.setHistoryHandoff(r.bars), this.#R.left = !0, this.#V.left = null, this.#B.left = null, this.#h.markDirty()), s.renderer.prependPoints(i, e);
613
+ const r = this.#Z.left;
614
+ r !== null && s.renderer.setHistoryHandoff !== void 0 && performance.now() - r.at < vt && (s.renderer.setHistoryHandoff(r.bars), this.#I.left = !0, this.#B.left = null, this.#Z.left = null, this.#h.markDirty()), s.renderer.prependPoints(i, e);
609
615
  }
610
616
  /** Update the last data point of a series in place (e.g. live candle update). */
611
617
  updateData(t, i, e) {
@@ -633,27 +639,27 @@ class qt extends at {
633
639
  if (!e) return;
634
640
  const s = e.labels, r = e.renderer.getLayerColors().slice(), n = this.#g.overrides(e.renderer.kind);
635
641
  e.renderer.updateOptions({ ...i, ...n }), "label" in i && typeof i.label == "string" && (e.labels = [i.label]), this.#e.markDirty();
636
- const h = e.renderer.getLayerColors(), a = r.length !== h.length || r.some((o, u) => o !== h[u]), l = !H(s, e.labels);
637
- (a || l) && this.#p();
642
+ const a = e.renderer.getLayerColors(), h = r.length !== a.length || r.some((o, u) => o !== a[u]), l = !W(s, e.labels);
643
+ (h || l) && this.#p();
638
644
  }
639
645
  /**
640
646
  * Batch multiple updates: suppress recomputes until `fn` returns. Exceptions
641
647
  * inside `fn` still flush the batch so counters don't leak across calls.
642
648
  */
643
649
  batch(t) {
644
- this.#A++;
650
+ this.#M++;
645
651
  try {
646
652
  t();
647
653
  } finally {
648
- if (--this.#A <= 0) {
649
- if (this.#A = 0, this.#X)
650
- this.#X = !1, this.#M = !1, this.onDataChanged();
651
- else if (this.#M) {
652
- this.#M = !1, this.#f = !0;
654
+ if (--this.#M <= 0) {
655
+ if (this.#M = 0, this.#$)
656
+ this.#$ = !1, this.#P = !1, this.onDataChanged();
657
+ else if (this.#P) {
658
+ this.#P = !1, this.#f = !0;
653
659
  const i = performance.now();
654
660
  this.#s.onAxisReconfig(i), this.#v(i), this.#e.markDirty();
655
661
  }
656
- this.#Z && (this.#Z = !1, this.emit("overlayChange"));
662
+ this.#_ && (this.#_ = !1, this.emit("overlayChange"));
657
663
  }
658
664
  }
659
665
  }
@@ -667,10 +673,10 @@ class qt extends at {
667
673
  setSeriesVisible(t, i) {
668
674
  const e = this.#t.find((n) => n.id === t);
669
675
  if (!e || e.visible === i) return;
670
- e.visible = i, this.#p();
676
+ e.visible = i, this.#p(), this.#j();
671
677
  const s = this.#g.toggleMs;
672
- if (e.renderer.setAlpha?.(i ? 1 : 0, s), this.#e.markDirty(), this.#A > 0) {
673
- this.#M = !0;
678
+ if (e.renderer.setAlpha?.(i ? 1 : 0, s), this.#e.markDirty(), this.#M > 0) {
679
+ this.#P = !0;
674
680
  return;
675
681
  }
676
682
  this.#f = !0;
@@ -701,12 +707,12 @@ class qt extends at {
701
707
  * layer's geometry on screen until the engine's Y ease settles.
702
708
  */
703
709
  setLayerVisible(t, i, e) {
704
- const s = this.#t.find((h) => h.id === t);
710
+ const s = this.#t.find((a) => a.id === t);
705
711
  if (!s || s.renderer.getLayerCount() <= 1 || s.renderer.isLayerVisible(i) === e) return;
706
712
  s.renderer.setLayerVisible(i, e), this.#p();
707
713
  const r = this.#g.toggleMs;
708
- if (s.renderer.setLayerAlpha?.(i, e ? 1 : 0, r), this.#e.markDirty(), this.#A > 0) {
709
- this.#M = !0;
714
+ if (s.renderer.setLayerAlpha?.(i, e ? 1 : 0, r), this.#e.markDirty(), this.#M > 0) {
715
+ this.#P = !0;
710
716
  return;
711
717
  }
712
718
  this.#f = !0;
@@ -721,7 +727,7 @@ class qt extends at {
721
727
  const { first: t, last: i } = this.getDataBounds();
722
728
  if (t === void 0 || i === void 0) return;
723
729
  const e = this.#a.size.media.width - this.yAxisWidth;
724
- this.#P(t, i, e), this.#W({ xEase: !0 });
730
+ this.#z(t, i, e), this.#Y({ xEase: !0 });
725
731
  }
726
732
  getVisibleRange() {
727
733
  return this.#o.from === 0 && this.#o.to === 0 ? this.#s.getAnimationState().xRange : this.#o;
@@ -732,7 +738,7 @@ class qt extends at {
732
738
  * tracking and is cheaper than recomputing from series stores.
733
739
  */
734
740
  getDataRange() {
735
- return this.#k === null || this.#i === null ? null : { from: this.#k, to: this.#i };
741
+ return this.#A === null || this.#i === null ? null : { from: this.#A, to: this.#i };
736
742
  }
737
743
  /**
738
744
  * Imperatively set the visible time range. Three forms:
@@ -761,29 +767,29 @@ class qt extends at {
761
767
  setVisibleRange(t, i) {
762
768
  if (typeof t == "number") {
763
769
  if (!Number.isInteger(t) || t < 2) return;
764
- const { first: n, last: h } = this.getDataBounds();
765
- if (n === void 0 || h === void 0) return;
766
- const a = Math.max(n, h - (t - 1) * this.#r), l = this.#a.size.media.width - this.yAxisWidth;
767
- this.#P(a, h, l), this.#W();
770
+ const { first: n, last: a } = this.getDataBounds();
771
+ if (n === void 0 || a === void 0) return;
772
+ const h = Math.max(n, a - (t - 1) * this.#r), l = this.#a.size.media.width - this.yAxisWidth;
773
+ this.#z(h, a, l), this.#Y();
768
774
  return;
769
775
  }
770
776
  if ("bars" in t) {
771
777
  if (!Number.isInteger(t.bars) || t.bars < 2) return;
772
- const n = y(t.from), h = n + t.bars * this.#r;
773
- this.#u = this.#i !== null && this.#i >= n && this.#i <= h, this.#L({ from: n, to: h }, { emitChange: !0 }), this.#w = !0, this.#W();
778
+ const n = v(t.from), a = n + t.bars * this.#r;
779
+ this.#u = this.#i !== null && this.#i >= n && this.#i <= a, this.#C({ from: n, to: a }, { emitChange: !0 }), this.#L = !0, this.#Y();
774
780
  return;
775
781
  }
776
- const e = y(t.from), s = y(t.to);
777
- this.#u = this.#i !== null && this.#i >= e && this.#i <= s, this.#w = !1;
778
- const r = this.#L({ from: e, to: s }, { emitChange: !0 });
782
+ const e = v(t.from), s = v(t.to);
783
+ this.#u = this.#i !== null && this.#i >= e && this.#i <= s, this.#L = !1;
784
+ const r = this.#C({ from: e, to: s }, { emitChange: !0 });
779
785
  if (i?.gesture) {
780
- r && this.#Mt();
786
+ r && this.#Bt();
781
787
  return;
782
788
  }
783
- this.#W();
789
+ this.#Y();
784
790
  }
785
791
  getYRange() {
786
- return this.#F;
792
+ return this.#O;
787
793
  }
788
794
  getCrosshairPosition() {
789
795
  return this.#d;
@@ -836,24 +842,24 @@ class qt extends at {
836
842
  else if (e !== null)
837
843
  s = e.y;
838
844
  else {
839
- const h = this.#F;
840
- s = (h.min + h.max) / 2;
845
+ const a = this.#O;
846
+ s = (a.min + a.max) / 2;
841
847
  }
842
848
  if (!Number.isFinite(s) || e !== null && e.time === i && e.y === s) return;
843
849
  const r = this.timeScale.timeToX(i), n = this.yScale.valueToY(s);
844
- this.#Y = "time", this.#d = { mediaX: r, mediaY: n, time: i, y: s }, this.#h.markDirty(), this.emit("crosshairMove", this.#d);
850
+ this.#X = "time", this.#d = { mediaX: r, mediaY: n, time: i, y: s }, this.#h.markDirty(), this.emit("crosshairMove", this.#d);
845
851
  }
846
852
  /** Get the last visible value and whether the absolute last point is on screen. */
847
853
  getLastValue(t) {
848
- return Z(t, this.#t, this.#s.getAnimationState().xRange);
854
+ return G(t, this.#t, this.#s.getAnimationState().xRange);
849
855
  }
850
856
  /** Get the second-to-last value, useful for computing change. */
851
857
  getPreviousClose(t) {
852
- return _(t, this.#t);
858
+ return U(t, this.#t);
853
859
  }
854
860
  getLastData(t) {
855
861
  const i = this.#t.find((e) => e.id === t);
856
- return !i || !S(i.renderer) ? null : i.renderer.getLastDataPoint();
862
+ return !i || !x(i.renderer) ? null : i.renderer.getLastDataPoint();
857
863
  }
858
864
  /** Find the data point closest to the given timestamp within one data interval. */
859
865
  getDataAtTime(t, i) {
@@ -871,7 +877,7 @@ class qt extends at {
871
877
  return e?.visible ? e.renderer.getLayerSnapshots?.(i, this.#r) ?? null : null;
872
878
  }
873
879
  getSeriesIds() {
874
- return this.#T || (this.#T = this.#t.map((t) => t.id)), this.#T.slice();
880
+ return this.#D || (this.#D = this.#t.map((t) => t.id)), this.#D.slice();
875
881
  }
876
882
  /**
877
883
  * True if any visible series has a time axis (line / bar / candlestick).
@@ -879,12 +885,31 @@ class qt extends at {
879
885
  * has no meaningful x/y coordinate system, so the dashed hairlines would
880
886
  * just be visual noise.
881
887
  */
882
- #Tt() {
888
+ #yt() {
883
889
  for (const t of this.#t)
884
- if (t.visible && S(t.renderer))
890
+ if (t.visible && x(t.renderer))
885
891
  return !0;
886
892
  return !1;
887
893
  }
894
+ /**
895
+ * Whether pan/zoom gestures currently apply — true when any visible series
896
+ * has a time axis. Part of the {@link PanZoomTarget} surface: on a
897
+ * spatial-only chart (pie, heatmap) the interaction layer stops capturing
898
+ * wheel and touch events, so the page scrolls normally under the cursor.
899
+ */
900
+ canPanZoom() {
901
+ return this.#yt();
902
+ }
903
+ /**
904
+ * Push the current pan/zoom capability into the interaction layer (canvas
905
+ * `touch-action`). Wheel and mouse gates read {@link canPanZoom} live, but
906
+ * the CSS must be correct *before* a touch gesture starts — call this from
907
+ * every mutation that can flip {@link canPanZoom}: series add/remove and
908
+ * series visibility.
909
+ */
910
+ #j() {
911
+ this.#T?.syncPanZoomMode();
912
+ }
888
913
  /**
889
914
  * Filter `getSeriesIds()` by renderer type. A concrete kind (`'pie'`,
890
915
  * `'heatmap'`, a custom kind, …) returns series of that exact kind;
@@ -899,19 +924,19 @@ class qt extends at {
899
924
  getSeriesIdsByType(t, i) {
900
925
  const e = i?.visibleOnly === !0, s = i?.singleLayerOnly === !0, r = [];
901
926
  for (const n of this.#t) {
902
- if (!(t === "time" ? S(n.renderer) : n.renderer.kind === t)) continue;
903
- const h = n.renderer.getLayerCount();
904
- if (!(s && h > 1)) {
927
+ if (!(t === "time" ? x(n.renderer) : n.renderer.kind === t)) continue;
928
+ const a = n.renderer.getLayerCount();
929
+ if (!(s && a > 1)) {
905
930
  if (e) {
906
931
  if (!n.visible) continue;
907
- if (h > 1) {
908
- let a = !1;
909
- for (let l = 0; l < h; l++)
932
+ if (a > 1) {
933
+ let h = !1;
934
+ for (let l = 0; l < a; l++)
910
935
  if (n.renderer.isLayerVisible(l)) {
911
- a = !0;
936
+ h = !0;
912
937
  break;
913
938
  }
914
- if (!a) continue;
939
+ if (!h) continue;
915
940
  }
916
941
  }
917
942
  r.push(n.id);
@@ -926,7 +951,7 @@ class qt extends at {
926
951
  * Returns `null` for unknown ids or empty series.
927
952
  */
928
953
  getStackedLastValue(t) {
929
- return U(t, this.#t, this.#s.getAnimationState().xRange);
954
+ return K(t, this.#t, this.#s.getAnimationState().xRange);
930
955
  }
931
956
  /**
932
957
  * Stacked value at an arbitrary `time` — the cumulative stack top at that
@@ -983,7 +1008,7 @@ class qt extends at {
983
1008
  */
984
1009
  setSeriesLabels(t, i) {
985
1010
  const e = this.#t.find((s) => s.id === t);
986
- !e || H(e.labels, i) || (e.labels = i, this.#p());
1011
+ !e || W(e.labels, i) || (e.labels = i, this.#p());
987
1012
  }
988
1013
  /**
989
1014
  * Set the per-layer color overrides carried in `data` (sparse — `undefined`
@@ -994,7 +1019,7 @@ class qt extends at {
994
1019
  */
995
1020
  setLayerColors(t, i) {
996
1021
  const e = this.#t.find((s) => s.id === t);
997
- !e || St(e.colorOverrides, i) || (e.colorOverrides = i, e.renderer.setColorOverrides?.(i), this.#e.markDirty(), this.#p());
1022
+ !e || Mt(e.colorOverrides, i) || (e.colorOverrides = i, e.renderer.setColorOverrides?.(i), this.#e.markDirty(), this.#p());
998
1023
  }
999
1024
  /** Get per-layer colors for a series. Returns null for single-layer non-bar/line series. */
1000
1025
  getSeriesLayers(t) {
@@ -1041,7 +1066,7 @@ class qt extends at {
1041
1066
  /** Update axis configuration and re-render. */
1042
1067
  setAxis(t) {
1043
1068
  const i = this.yAxisWidth, e = this.xAxisHeight;
1044
- this.#H = t, this.#l = { min: t.y?.min, max: t.y?.max }, this.#f = !0;
1069
+ this.#W = t, this.#l = { min: t.y?.min, max: t.y?.max }, this.#f = !0;
1045
1070
  const s = performance.now();
1046
1071
  this.#s.onAxisReconfig(s), this.#v(s), (this.yAxisWidth !== i || this.xAxisHeight !== e) && this.syncScales(), this.#e.markDirty();
1047
1072
  }
@@ -1085,13 +1110,13 @@ class qt extends at {
1085
1110
  */
1086
1111
  setPadding(t) {
1087
1112
  const i = this.#c;
1088
- this.#c = C(t);
1089
- const e = this.#c, s = !R(i.left, e.left) || !R(i.right, e.right), r = i.top !== e.top || i.bottom !== e.bottom;
1113
+ this.#c = I(t);
1114
+ const e = this.#c, s = !P(i.left, e.left) || !P(i.right, e.right), r = i.top !== e.top || i.bottom !== e.bottom;
1090
1115
  if (s) {
1091
- const { first: n, last: h } = this.getDataBounds();
1092
- if (n !== void 0 && h !== void 0) {
1093
- const a = this.#a.size.media.width - this.yAxisWidth;
1094
- this.#P(n, h, a);
1116
+ const { first: n, last: a } = this.getDataBounds();
1117
+ if (n !== void 0 && a !== void 0) {
1118
+ const h = this.#a.size.media.width - this.yAxisWidth;
1119
+ this.#z(n, a, h);
1095
1120
  }
1096
1121
  }
1097
1122
  if (s || r) {
@@ -1103,7 +1128,18 @@ class qt extends at {
1103
1128
  }
1104
1129
  /** Show or hide the background grid. Takes effect on the next render frame. */
1105
1130
  setGrid(t) {
1106
- this.#O = t.visible, this.#e.markDirty();
1131
+ this.#V = t.visible, this.#e.markDirty();
1132
+ }
1133
+ /**
1134
+ * Set or clear the edge fade masks (see {@link ChartOptions.fade}).
1135
+ * Content the main layer draws inside a zone dissolves toward that edge.
1136
+ * `right` omitted re-arms its default (track the Y-axis width); pass
1137
+ * `{ top: 0, right: 0, left: 0 }` to turn every mask off. Takes effect on
1138
+ * the next render frame.
1139
+ */
1140
+ setFade(t) {
1141
+ const i = C(t), e = this.#k;
1142
+ i.top === e.top && i.right === e.right && i.left === e.left || (this.#k = i, this.#e.markDirty());
1107
1143
  }
1108
1144
  /**
1109
1145
  * Set the visual state for one side of the chart. Typically called in
@@ -1115,23 +1151,23 @@ class qt extends at {
1115
1151
  * symmetry and currently renders identically to `idle`.
1116
1152
  */
1117
1153
  setEdgeState(t, i) {
1118
- if (this.#S[t] === i) return;
1119
- const e = this.#S[t] === "loading", s = this.#R[t];
1120
- this.#R[t] = !1, this.#V[t] = e && !s && (i === "idle" || i === "has-more") ? performance.now() : null, this.#S[t] = i, this.#h.markDirty();
1154
+ if (this.#x[t] === i) return;
1155
+ const e = this.#x[t] === "loading", s = this.#I[t];
1156
+ this.#I[t] = !1, this.#B[t] = e && !s && (i === "idle" || i === "has-more") ? performance.now() : null, this.#x[t] = i, this.#h.markDirty();
1121
1157
  }
1122
1158
  /** Read the current host-declared state for a given edge. */
1123
1159
  getEdgeState(t) {
1124
- return this.#S[t];
1160
+ return this.#x[t];
1125
1161
  }
1126
1162
  /**
1127
1163
  * Alpha for a side's `loading` exit fade, or `null` when none is in
1128
1164
  * flight. Self-cleaning: an elapsed fade clears its start stamp.
1129
1165
  */
1130
- #ut(t) {
1131
- const i = this.#V[t];
1166
+ #vt(t) {
1167
+ const i = this.#B[t];
1132
1168
  if (i === null) return null;
1133
- const e = (performance.now() - i) / ft;
1134
- return e >= 1 ? (this.#V[t] = null, null) : 1 - L(Math.max(0, e));
1169
+ const e = (performance.now() - i) / yt;
1170
+ return e >= 1 ? (this.#B[t] = null, null) : 1 - R(Math.max(0, e));
1135
1171
  }
1136
1172
  /**
1137
1173
  * Swap the painter used for a side's `loading` spinner — the same
@@ -1140,7 +1176,7 @@ class qt extends at {
1140
1176
  * immediately if that side is currently in the `loading` state.
1141
1177
  */
1142
1178
  setEdgeIndicator(t, i) {
1143
- this.#nt[t] = i, this.#S[t] === "loading" && this.#h.markDirty();
1179
+ this.#lt[t] = i, this.#x[t] === "loading" && this.#h.markDirty();
1144
1180
  }
1145
1181
  /**
1146
1182
  * Resolve the boundary point's Y position and series kind on the primary
@@ -1150,14 +1186,14 @@ class qt extends at {
1150
1186
  * `open` (the value immediately preceding the boundary); `right` from the
1151
1187
  * last visible candle's `close`.
1152
1188
  */
1153
- #Dt(t, i) {
1189
+ #Ht(t, i) {
1154
1190
  const e = this.getSeriesIdsByType("time", { visibleOnly: !0, singleLayerOnly: !0 })[0] ?? this.getSeriesIdsByType("time", { visibleOnly: !0 })[0];
1155
1191
  if (!e) return null;
1156
1192
  const s = this.getDataAtTime(e, i);
1157
1193
  if (!s) return null;
1158
1194
  const r = this.#t.find((n) => n.id === e);
1159
1195
  return r ? {
1160
- valueY: this.yScale.valueToY(O(t, s)),
1196
+ valueY: this.yScale.valueToY(X(t, s)),
1161
1197
  seriesKind: r.renderer.kind
1162
1198
  } : null;
1163
1199
  }
@@ -1167,7 +1203,7 @@ class qt extends at {
1167
1203
  * placeholder shapes to match the real bars that will render once data
1168
1204
  * lands. `null` when the viewport has no meaningful span yet.
1169
1205
  */
1170
- #Lt() {
1206
+ #zt() {
1171
1207
  const t = this.timeScale.barWidthMedia(this.#r);
1172
1208
  return Number.isFinite(t) && t > 0 ? t : null;
1173
1209
  }
@@ -1186,20 +1222,20 @@ class qt extends at {
1186
1222
  * probed, not kind-gated: a kind check here silently kills hover for the
1187
1223
  * next spatial renderer.
1188
1224
  */
1189
- #G(t) {
1225
+ #q(t) {
1190
1226
  const i = this.#a.size, e = this.#c, s = {
1191
1227
  top: e.top * i.verticalPixelRatio,
1192
1228
  bottom: e.bottom * i.verticalPixelRatio
1193
1229
  };
1194
1230
  let r = !1, n = null;
1195
- for (const h of this.#t) {
1196
- if (!h.renderer.hitTest || !h.renderer.setHoverIndex) continue;
1197
- let a = -1;
1231
+ for (const a of this.#t) {
1232
+ if (!a.renderer.hitTest || !a.renderer.setHoverIndex) continue;
1233
+ let h = -1;
1198
1234
  if (t) {
1199
1235
  const l = t.mediaX * i.horizontalPixelRatio, o = t.mediaY * i.verticalPixelRatio;
1200
- a = h.renderer.hitTest(l, o, i.bitmap.width, i.bitmap.height, s);
1236
+ h = a.renderer.hitTest(l, o, i.bitmap.width, i.bitmap.height, s);
1201
1237
  }
1202
- h.renderer.setHoverIndex(a) && (r = !0), a >= 0 && !n && (n = { seriesId: h.id, index: a, info: h.renderer.getHoverInfo?.(this.#n) ?? null });
1238
+ a.renderer.setHoverIndex(h) && (r = !0), h >= 0 && !n && (n = { seriesId: a.id, index: h, info: a.renderer.getHoverInfo?.(this.#n) ?? null });
1203
1239
  }
1204
1240
  r && (this.#e.markDirty(), this.emit("seriesHover", n));
1205
1241
  }
@@ -1210,15 +1246,15 @@ class qt extends at {
1210
1246
  * Returns the first spatial series (pie, heatmap, or a custom spatial kind)
1211
1247
  * whose `hitTest` claims the position, or `null` if none does.
1212
1248
  */
1213
- #ft(t) {
1249
+ #bt(t) {
1214
1250
  const i = this.#a.size, e = this.#c, s = {
1215
1251
  top: e.top * i.verticalPixelRatio,
1216
1252
  bottom: e.bottom * i.verticalPixelRatio
1217
1253
  }, r = t.mediaX * i.horizontalPixelRatio, n = t.mediaY * i.verticalPixelRatio;
1218
- for (const h of this.#t) {
1219
- if (!h.renderer.hitTest) continue;
1220
- const a = h.renderer.hitTest(r, n, i.bitmap.width, i.bitmap.height, s);
1221
- if (a >= 0) return { seriesId: h.id, index: a };
1254
+ for (const a of this.#t) {
1255
+ if (!a.renderer.hitTest) continue;
1256
+ const h = a.renderer.hitTest(r, n, i.bitmap.width, i.bitmap.height, s);
1257
+ if (h >= 0) return { seriesId: a.id, index: h };
1222
1258
  }
1223
1259
  return null;
1224
1260
  }
@@ -1242,40 +1278,40 @@ class qt extends at {
1242
1278
  * viewport didn't move, the re-derived values are bit-identical and the
1243
1279
  * method exits without emitting.
1244
1280
  */
1245
- #Ct() {
1281
+ #Vt() {
1246
1282
  const t = this.#d;
1247
1283
  if (t === null) return;
1248
- const { from: i, to: e } = this.timeScale.getRange(), s = this.yScale.getRange(), r = Math.abs(e - i) * 1e-9, n = Math.abs(s.max - s.min) * 1e-9, h = 1e-6;
1249
- let a;
1250
- if (this.#Y === "pointer") {
1284
+ const { from: i, to: e } = this.timeScale.getRange(), s = this.yScale.getRange(), r = Math.abs(e - i) * 1e-9, n = Math.abs(s.max - s.min) * 1e-9, a = 1e-6;
1285
+ let h;
1286
+ if (this.#X === "pointer") {
1251
1287
  const l = this.timeScale.xToTime(t.mediaX), o = this.yScale.yToValue(t.mediaY);
1252
1288
  if (!Number.isFinite(l) || !Number.isFinite(o) || Math.abs(l - t.time) <= r && Math.abs(o - t.y) <= n) return;
1253
- a = { mediaX: t.mediaX, mediaY: t.mediaY, time: l, y: o };
1289
+ h = { mediaX: t.mediaX, mediaY: t.mediaY, time: l, y: o };
1254
1290
  } else {
1255
1291
  if (t.time < i || t.time > e) {
1256
- this.#d = null, this.#h.markDirty(), this.emit("crosshairMove", null), this.#G(null);
1292
+ this.#d = null, this.#h.markDirty(), this.emit("crosshairMove", null), this.#q(null);
1257
1293
  return;
1258
1294
  }
1259
1295
  const l = this.timeScale.timeToX(t.time), o = this.yScale.valueToY(t.y);
1260
- if (!Number.isFinite(l) || !Number.isFinite(o) || Math.abs(l - t.mediaX) <= h && Math.abs(o - t.mediaY) <= h) return;
1261
- a = { mediaX: l, mediaY: o, time: t.time, y: t.y };
1296
+ if (!Number.isFinite(l) || !Number.isFinite(o) || Math.abs(l - t.mediaX) <= a && Math.abs(o - t.mediaY) <= a) return;
1297
+ h = { mediaX: l, mediaY: o, time: t.time, y: t.y };
1262
1298
  }
1263
- this.#d = a, this.#h.markDirty(), this.emit("crosshairMove", a), this.#G(a);
1299
+ this.#d = h, this.#h.markDirty(), this.emit("crosshairMove", h), this.#q(h);
1264
1300
  }
1265
1301
  /** Tear down the chart: cancel animations, remove listeners, and detach the canvas. */
1266
1302
  destroy() {
1267
1303
  for (const t of this.#t) t.renderer.dispose();
1268
- this.#t = [], this.#m = [], this.#b = [], this.#y = [], this.#T = null, this.#e.destroy(), this.#h.destroy(), this.#C?.destroy(), this.#a.destroy(), this.#U?.destroy(), this.#U = null, this.#_ && this.#x?.destroy(), this.#x = null, this.#_ = !1, this.removeAllListeners();
1304
+ this.#t = [], this.#m = [], this.#b = [], this.#y = [], this.#D = null, this.#e.destroy(), this.#h.destroy(), this.#T?.destroy(), this.#a.destroy(), this.#U?.destroy(), this.#U = null, this.#G && this.#S?.destroy(), this.#S = null, this.#G = !1, this.removeAllListeners();
1269
1305
  }
1270
1306
  /** The attached performance monitor, or `null` when instrumentation is disabled. */
1271
1307
  getPerfMonitor() {
1272
- return this.#x;
1308
+ return this.#S;
1273
1309
  }
1274
1310
  /** Compute the earliest and latest timestamps across all series. */
1275
1311
  getDataBounds() {
1276
1312
  let t, i;
1277
1313
  for (const e of this.#t) {
1278
- if (!e.visible || !S(e.renderer)) continue;
1314
+ if (!e.visible || !x(e.renderer)) continue;
1279
1315
  const s = e.renderer.getTimeBounds();
1280
1316
  s !== null && ((t === void 0 || s.first < t) && (t = s.first), (i === void 0 || s.last > i) && (i = s.last));
1281
1317
  }
@@ -1284,28 +1320,28 @@ class qt extends at {
1284
1320
  /** Set by `setSeriesData`/bulk-replace paths so the next `onDataChanged`
1285
1321
  * snaps the Y range (instead of easing) and `yScale.getRange()` reflects
1286
1322
  * the new domain synchronously. Cleared by `onDataChanged` after each run. */
1287
- #q = !1;
1323
+ #J = !1;
1288
1324
  onDataChanged() {
1289
- if (this.#A > 0) {
1290
- this.#X = !0;
1325
+ if (this.#M > 0) {
1326
+ this.#$ = !0;
1291
1327
  return;
1292
1328
  }
1293
1329
  this.updateDataInterval();
1294
1330
  const { first: t, last: i } = this.getDataBounds();
1295
- t !== void 0 && (this.#k = t), i !== void 0 && (this.#z = this.#i, this.#i = i);
1296
- const e = this.#q;
1297
- this.#q = !1;
1331
+ t !== void 0 && (this.#A = t), i !== void 0 && (this.#F = this.#i, this.#i = i);
1332
+ const e = this.#J;
1333
+ this.#J = !1;
1298
1334
  const s = !this.#f && t !== void 0;
1299
- e && (this.yScale.tickTracker.reset(), this.timeScale.tickTracker.reset()), this.#ht = e;
1335
+ e && (this.yScale.tickTracker.reset(), this.timeScale.tickTracker.reset()), this.#dt = e;
1300
1336
  const r = performance.now();
1301
- e || s ? (this.#D.seed(r), this.#s.onDataReplaced(r)) : this.#s.onPointAppended(r), this.#s.lastXTarget !== null && (this.#I = !0), t !== void 0 && (this.#f = !0), this.#v(r), this.syncScales(), s ? this.#J() : this.#e.markDirty(), this.emit("dataUpdate"), this.#p();
1337
+ e || s ? (this.#R.seed(r), this.#s.onDataReplaced(r)) : this.#s.onPointAppended(r), this.#s.lastXTarget !== null && (this.#H = !0), t !== void 0 && (this.#f = !0), this.#v(r), this.syncScales(), s ? this.#et() : this.#e.markDirty(), this.emit("dataUpdate"), this.#p();
1302
1338
  }
1303
1339
  updateDataInterval() {
1304
1340
  for (const t of this.#t) {
1305
- if (!S(t.renderer)) continue;
1341
+ if (!x(t.renderer)) continue;
1306
1342
  const i = t.renderer.sampleTimes(20);
1307
1343
  if (i.length >= 2) {
1308
- this.#r = ut(i);
1344
+ this.#r = pt(i);
1309
1345
  break;
1310
1346
  }
1311
1347
  }
@@ -1321,22 +1357,22 @@ class qt extends at {
1321
1357
  * range — without this guard the engine would ease from `{0,0}` into
1322
1358
  * the new target and the very first frame would render with a
1323
1359
  * zero-width X domain. */
1324
- #I = !1;
1360
+ #H = !1;
1325
1361
  /**
1326
1362
  * One-shot `setVisibleRange` argument applied on the first data arrival.
1327
1363
  * Captured at chart construction from {@link ChartOptions.viewport.initialRange};
1328
1364
  * cleared the moment it's consumed so subsequent data swaps don't snap
1329
1365
  * back to the initial window.
1330
1366
  */
1331
- #N;
1367
+ #E;
1332
1368
  /** Last Y bounds the engine resolved into {@link AnimationState.yRange}.
1333
1369
  * Used by {@link renderMain} to detect Y movement frame-to-frame so
1334
1370
  * `viewportChange` only emits when the Y range actually shifted — DOM
1335
1371
  * axis labels subscribe to that event and re-renders on every tick are
1336
1372
  * expensive. Initialised to NaN so the first real Y emit always passes
1337
1373
  * the change check. */
1338
- #K = Number.NaN;
1339
- #j = Number.NaN;
1374
+ #Q = Number.NaN;
1375
+ #tt = Number.NaN;
1340
1376
  /**
1341
1377
  * Sample the visible data window and return the resolved Y bounds, or
1342
1378
  * `null` when no series has data inside the X destination range.
@@ -1345,11 +1381,11 @@ class qt extends at {
1345
1381
  * converge together. Clears {@link #yInited} on empty so the next emit
1346
1382
  * with valid data lands as an instant snap.
1347
1383
  */
1348
- #gt(t) {
1349
- const i = t ?? this.#o, e = this.#l.min !== void 0 && this.#l.min !== "auto" && typeof this.#l.min != "number" || this.#l.max !== void 0 && this.#l.max !== "auto" && typeof this.#l.max != "number" ? [] : null, s = Q(i, this.#t, e);
1384
+ #xt(t) {
1385
+ const i = t ?? this.#o, e = this.#l.min !== void 0 && this.#l.min !== "auto" && typeof this.#l.min != "number" || this.#l.max !== void 0 && this.#l.max !== "auto" && typeof this.#l.max != "number" ? [] : null, s = et(i, this.#t, e);
1350
1386
  if (s === null)
1351
1387
  return this.#f = !1, null;
1352
- const r = I(this.#l.min, s.min, s.max, e ?? [], "min"), n = I(this.#l.max, s.max, s.min, e ?? [], "max");
1388
+ const r = z(this.#l.min, s.min, s.max, e ?? [], "min"), n = z(this.#l.max, s.max, s.min, e ?? [], "max");
1353
1389
  return { min: r, max: n };
1354
1390
  }
1355
1391
  /**
@@ -1370,29 +1406,29 @@ class qt extends at {
1370
1406
  * - **autoscroll off** → `null` (no X retarget; user has panned away
1371
1407
  * from the tail).
1372
1408
  */
1373
- #Rt() {
1374
- if (this.#k === null || this.#i === null) return null;
1409
+ #Wt() {
1410
+ if (this.#A === null || this.#i === null) return null;
1375
1411
  const { from: t, to: i } = this.#o, e = t === 0 && i === 0, s = this.#a.size.media.width - this.yAxisWidth;
1376
1412
  if (e) {
1377
- if (this.#P(this.#k, this.#i, s), this.#N !== void 0 && (this.setVisibleRange(this.#N), this.#N = void 0, !this.#u && this.#i !== null)) {
1413
+ if (this.#z(this.#A, this.#i, s), this.#E !== void 0 && (this.setVisibleRange(this.#E), this.#E = void 0, !this.#u && this.#i !== null)) {
1378
1414
  const { to: n } = this.#o;
1379
1415
  this.#i >= n && this.#i - n <= this.#r * 1.5 && (this.#u = !0);
1380
1416
  }
1381
1417
  return this.#o;
1382
1418
  }
1383
1419
  if (!this.#u) return null;
1384
- if (this.#ht)
1385
- return this.#P(this.#k, this.#i, s), this.#o;
1386
- const r = J({
1420
+ if (this.#dt)
1421
+ return this.#z(this.#A, this.#i, s), this.#o;
1422
+ const r = it({
1387
1423
  currentLogical: this.#o,
1388
1424
  lastTime: this.#i,
1389
- prevDataEnd: this.#z,
1425
+ prevDataEnd: this.#F,
1390
1426
  dataInterval: this.#r,
1391
1427
  paddingRight: this.#c.right,
1392
1428
  chartWidth: s,
1393
- holdUntilFilled: this.#w
1429
+ holdUntilFilled: this.#L
1394
1430
  });
1395
- return r.releaseHold && (this.#w = !1), r.reengageAutoScroll && (this.#u = !0), r.newLogical === null ? null : (this.#D.observe(performance.now()), this.#s.setXSettleMs(this.#D.pickSettleMs(this.#g.axis.x.settleMs)), this.#L(r.newLogical, { emitChange: !1, skipValidation: !0 }), this.#z = this.#i, r.newLogical);
1431
+ return r.releaseHold && (this.#L = !1), r.reengageAutoScroll && (this.#u = !0), r.newLogical === null ? null : (this.#R.observe(performance.now()), this.#s.setXSettleMs(this.#R.pickSettleMs(this.#g.axis.x.settleMs)), this.#C(r.newLogical, { emitChange: !1, skipValidation: !0 }), this.#F = this.#i, r.newLogical);
1396
1432
  }
1397
1433
  /**
1398
1434
  * Fit the viewport's logical X range around a data span. Mirrors the
@@ -1400,16 +1436,16 @@ class qt extends at {
1400
1436
  * forces autoscroll on (data tail is in the new window by construction),
1401
1437
  * commits the new range via `viewport.setRange` (which emits `change`).
1402
1438
  */
1403
- #P(t, i, e) {
1404
- const s = this.#c, r = X({
1439
+ #z(t, i, e) {
1440
+ const s = this.#c, r = _({
1405
1441
  firstTime: t,
1406
1442
  lastTime: i,
1407
1443
  dataInterval: this.#r,
1408
- maxVisibleBars: this.#ot,
1444
+ maxVisibleBars: this.#mt,
1409
1445
  chartWidth: e,
1410
1446
  padding: { left: s.left, right: s.right }
1411
1447
  });
1412
- this.#w = !1, this.#u = !0, this.#L(r, { emitChange: !0 });
1448
+ this.#L = !1, this.#u = !0, this.#C(r, { emitChange: !0 });
1413
1449
  }
1414
1450
  /**
1415
1451
  * Commit a programmatic zoom — `fitContent` or `setVisibleRange`. Reads
@@ -1425,12 +1461,12 @@ class qt extends at {
1425
1461
  * passes `xEase: true` so X eases instead — viewport and axis converge
1426
1462
  * on the same frame.
1427
1463
  */
1428
- #W(t) {
1464
+ #Y(t) {
1429
1465
  const i = this.#o;
1430
1466
  if (i.to <= i.from) return;
1431
1467
  const e = performance.now();
1432
- if (!this.#I || !this.#f) {
1433
- this.#pt(e);
1468
+ if (!this.#H || !this.#f) {
1469
+ this.#St(e);
1434
1470
  return;
1435
1471
  }
1436
1472
  this.#s.onProgrammaticZoom({ xTarget: i, xEase: t?.xEase }, e), this.#v(e);
@@ -1447,12 +1483,12 @@ class qt extends at {
1447
1483
  * instead of lagging on the long sticky contract. First paint still snaps
1448
1484
  * (same as the programmatic path) so synchronous readers see final values.
1449
1485
  */
1450
- #Mt() {
1486
+ #Bt() {
1451
1487
  const t = this.#o;
1452
1488
  if (t.to <= t.from) return;
1453
1489
  const i = performance.now();
1454
- if (!this.#I || !this.#f) {
1455
- this.#pt(i);
1490
+ if (!this.#H || !this.#f) {
1491
+ this.#St(i);
1456
1492
  return;
1457
1493
  }
1458
1494
  this.#s.onPanZoom({ xTarget: t, yAuto: !0 }, i), this.#v(i);
@@ -1464,9 +1500,9 @@ class qt extends at {
1464
1500
  * commits — both must snap before the chart has painted once so a
1465
1501
  * synchronous `getYRange()` / `getVisibleRange()` read sees final values.
1466
1502
  */
1467
- #pt(t) {
1468
- const i = this.#o, e = this.#gt(i);
1469
- this.#I = !0, e !== null && (this.#f = !0), this.#s.snap({ x: i, y: e ?? void 0 }, t), this.#v(t);
1503
+ #St(t) {
1504
+ const i = this.#o, e = this.#xt(i);
1505
+ this.#H = !0, e !== null && (this.#f = !0), this.#s.snap({ x: i, y: e ?? void 0 }, t), this.#v(t);
1470
1506
  }
1471
1507
  /**
1472
1508
  * Validate and commit a new logical X range. Mirrors the old
@@ -1486,7 +1522,7 @@ class qt extends at {
1486
1522
  * see `setVisibleRange`'s gesture path, where a per-frame echo would
1487
1523
  * otherwise re-arm and stall the in-flight Y ease.
1488
1524
  */
1489
- #L(t, i) {
1525
+ #C(t, i) {
1490
1526
  const { from: e, to: s } = t;
1491
1527
  return !Number.isFinite(e) || !Number.isFinite(s) || s <= e || !i.skipValidation && (s - e) / this.#r < 2 || this.#o.from === e && this.#o.to === s ? !1 : (this.#o = { from: e, to: s }, i.emitChange && (this.syncScales(), this.#e?.markDirty(), this.emit("viewportChange")), !0);
1492
1528
  }
@@ -1496,11 +1532,11 @@ class qt extends at {
1496
1532
  * symmetric pad top / bottom from `#padding`, suppressed on the side
1497
1533
  * that has an explicit (fixed) axis bound.
1498
1534
  */
1499
- #yt(t, i, e, s, r) {
1500
- const n = i - t, h = e > 0 ? this.#c.top / e * n : 0, a = e > 0 ? this.#c.bottom / e * n : 0;
1501
- this.#F = {
1502
- min: s ? t : t - a,
1503
- max: r ? i : i + h
1535
+ #kt(t, i, e, s, r) {
1536
+ const n = i - t, a = e > 0 ? this.#c.top / e * n : 0, h = e > 0 ? this.#c.bottom / e * n : 0;
1537
+ this.#O = {
1538
+ min: s ? t : t - h,
1539
+ max: r ? i : i + a
1504
1540
  };
1505
1541
  }
1506
1542
  /**
@@ -1513,18 +1549,18 @@ class qt extends at {
1513
1549
  * as a gesture for visual easing. Public so consumers can drive pan
1514
1550
  * programmatically.
1515
1551
  */
1516
- pan(t, i = this.#E) {
1517
- i > 0 && (this.#E = i), this.#w = !1;
1518
- const e = q({
1552
+ pan(t, i = this.#N) {
1553
+ i > 0 && (this.#N = i), this.#L = !1;
1554
+ const e = J({
1519
1555
  currentLogical: this.#o,
1520
1556
  timeDelta: t,
1521
1557
  chartWidth: i,
1522
1558
  dataInterval: this.#r,
1523
1559
  padding: { left: this.#c.left, right: this.#c.right },
1524
- dataStart: this.#k,
1560
+ dataStart: this.#A,
1525
1561
  dataEnd: this.#i
1526
1562
  });
1527
- e.newLogical !== null && (this.#u = !e.autoScrollOff, this.#L(e.newLogical, { emitChange: !0 }), e.edgeReached !== null && (this.#st[e.edgeReached.side] = e.edgeReached.boundaryTime, this.#rt?.(e.edgeReached)), this.#D.pause(), this.#vt());
1563
+ e.newLogical !== null && (this.#u = !e.autoScrollOff, this.#C(e.newLogical, { emitChange: !0 }), e.edgeReached !== null && (this.#ht[e.edgeReached.side] = e.edgeReached.boundaryTime, this.#ot?.(e.edgeReached)), this.#R.pause(), this.#wt());
1528
1564
  }
1529
1565
  /**
1530
1566
  * Zoom around a time anchor. `factor < 1` zooms in, `> 1` zooms out.
@@ -1541,35 +1577,35 @@ class qt extends at {
1541
1577
  * and produce a visible jump). Cursor-anchored zoom is intentionally
1542
1578
  * sacrificed in follow-live mode — pan first to inspect history.
1543
1579
  */
1544
- zoomAt(t, i, e = this.#E) {
1545
- e > 0 && (this.#E = e), this.#w = !1;
1546
- const s = K({
1580
+ zoomAt(t, i, e = this.#N) {
1581
+ e > 0 && (this.#N = e), this.#L = !1;
1582
+ const s = Q({
1547
1583
  currentLogical: this.#o,
1548
1584
  centerTime: t,
1549
1585
  factor: i,
1550
1586
  chartWidth: e,
1551
1587
  dataInterval: this.#r,
1552
1588
  padding: { left: this.#c.left, right: this.#c.right },
1553
- dataStart: this.#k,
1589
+ dataStart: this.#A,
1554
1590
  dataEnd: this.#i
1555
1591
  });
1556
1592
  if (s.newLogical === null) return;
1557
1593
  let r = s.newLogical;
1558
1594
  if (this.#u && this.#i !== null) {
1559
- const n = r.to - r.from, h = M(this.#c.right, n, this.#r, e), a = this.#i + h;
1560
- r = { from: a - n, to: a }, this.#z = this.#i;
1595
+ const n = r.to - r.from, a = H(this.#c.right, n, this.#r, e), h = this.#i + a;
1596
+ r = { from: h - n, to: h }, this.#F = this.#i;
1561
1597
  }
1562
- this.#L(r, { emitChange: !0 }), this.#D.pause(), this.#vt();
1598
+ this.#C(r, { emitChange: !0 }), this.#R.pause(), this.#wt();
1563
1599
  }
1564
1600
  /**
1565
1601
  * Common tail for `pan` / `zoomAt`: routes the just-committed `#logical`
1566
1602
  * to the engine as a gesture so the X spring retargets and the Y spring
1567
1603
  * eases over `animations.axis.y.gesture`.
1568
1604
  */
1569
- #vt() {
1605
+ #wt() {
1570
1606
  const t = this.#o;
1571
1607
  if (t.to <= t.from) return;
1572
- this.#I = !0, this.#f = !0;
1608
+ this.#H = !0, this.#f = !0;
1573
1609
  const i = performance.now();
1574
1610
  this.#s.onPanZoom({ xTarget: t, yAuto: !0 }, i), this.#v(i);
1575
1611
  }
@@ -1590,7 +1626,7 @@ class qt extends at {
1590
1626
  const i = this.#s.tick(t), e = this.#a.size;
1591
1627
  if (e.media.width === 0 || e.media.height === 0) return;
1592
1628
  const s = this.#l.min !== void 0 && this.#l.min !== "auto", r = this.#l.max !== void 0 && this.#l.max !== "auto", n = e.media.height - this.xAxisHeight;
1593
- this.#yt(i.yRange.min, i.yRange.max, n, s, r), this.#K = i.yRange.min, this.#j = i.yRange.max, this.syncScales();
1629
+ this.#kt(i.yRange.min, i.yRange.max, n, s, r), this.#Q = i.yRange.min, this.#tt = i.yRange.max, this.syncScales();
1594
1630
  }
1595
1631
  /**
1596
1632
  * Lightweight scale sync: updates timeScale/yScale from current viewport state
@@ -1606,7 +1642,7 @@ class qt extends at {
1606
1642
  i,
1607
1643
  t.horizontalPixelRatio,
1608
1644
  this.#r
1609
- ), this.yScale.update(this.#F, e, t.verticalPixelRatio);
1645
+ ), this.yScale.update(this.#O, e, t.verticalPixelRatio);
1610
1646
  }
1611
1647
  /** Expensive: background, grid, all series. Only on data/viewport/resize change. */
1612
1648
  renderMain(t) {
@@ -1614,64 +1650,231 @@ class qt extends at {
1614
1650
  if (i.media.width === 0 || i.media.height === 0) return;
1615
1651
  const e = typeof t == "number" ? t : performance.now(), s = this.#s.tick(e);
1616
1652
  s.animating && this.#e.markDirty();
1617
- const r = s.yRange.min, n = s.yRange.max, h = r !== this.#K || n !== this.#j;
1618
- if (h) {
1619
- const d = this.#l.min !== void 0 && this.#l.min !== "auto", c = this.#l.max !== void 0 && this.#l.max !== "auto", p = i.media.height - this.xAxisHeight;
1620
- this.#yt(r, n, p, d, c), this.#K = r, this.#j = n;
1653
+ const r = s.yRange.min, n = s.yRange.max, a = r !== this.#Q || n !== this.#tt;
1654
+ if (a) {
1655
+ const c = this.#l.min !== void 0 && this.#l.min !== "auto", d = this.#l.max !== void 0 && this.#l.max !== "auto", p = i.media.height - this.xAxisHeight;
1656
+ this.#kt(r, n, p, c, d), this.#Q = r, this.#tt = n;
1621
1657
  }
1622
- if (this.syncScales(), this.#Ct(), this.#i !== null && !this.#u) {
1623
- const d = this.#s.lastXTarget ?? this.#o, c = d.to - d.from;
1624
- if (c > 0) {
1625
- const p = this.#a.size.media.width - this.yAxisWidth, v = M(this.#c.right, c, this.#r, p), m = this.#r * 0.5;
1626
- Math.abs(d.to - (this.#i + v)) < m && (this.#u = !0);
1658
+ if (this.syncScales(), this.#Vt(), this.#i !== null && !this.#u) {
1659
+ const c = this.#s.lastXTarget ?? this.#o, d = c.to - c.from;
1660
+ if (d > 0) {
1661
+ const p = this.#a.size.media.width - this.yAxisWidth, f = H(this.#c.right, d, this.#r, p), m = this.#r * 0.5;
1662
+ Math.abs(c.to - (this.#i + f)) < m && (this.#u = !0);
1627
1663
  }
1628
1664
  }
1629
- h && this.emit("viewportChange");
1630
- let a = !1, l = !1;
1631
- this.#a.useMainLayer((d) => {
1632
- const { context: c, bitmapSize: p } = d, v = (i.media.width - this.yAxisWidth) * i.horizontalPixelRatio, m = (i.media.height - this.xAxisHeight) * i.verticalPixelRatio;
1633
- c.clearRect(0, 0, p.width, p.height), c.save(), c.beginPath(), c.rect(0, 0, v, m), c.clip(), this.yScale.tickTracker.setCurrentTicks(this.yScale.niceTickValues()), this.timeScale.tickTracker.setCurrentTicks(this.timeScale.niceTickValues(this.#r).ticks), this.yScale.tickTracker.tick(e), this.timeScale.tickTracker.tick(e);
1634
- const g = this.yScale.tickTracker.snapshot(), k = this.timeScale.tickTracker.snapshot();
1635
- a = g.isAnimating, l = k.isAnimating, (g.isAnimating || k.isAnimating || s.animating) && this.emit("tickFrame"), this.#O && it({
1636
- scope: d,
1665
+ a && this.emit("viewportChange");
1666
+ let h = !1, l = !1;
1667
+ this.#a.useMainLayer((c) => {
1668
+ const { context: d, bitmapSize: p } = c, f = (i.media.width - this.yAxisWidth) * i.horizontalPixelRatio, m = (i.media.height - this.xAxisHeight) * i.verticalPixelRatio;
1669
+ d.clearRect(0, 0, p.width, p.height), d.save(), d.beginPath();
1670
+ const y = this.#it(c, f);
1671
+ d.rect(0, 0, f + y.intrusion, m), d.clip(), this.yScale.tickTracker.setCurrentTicks(this.yScale.niceTickValues()), this.timeScale.tickTracker.setCurrentTicks(this.timeScale.niceTickValues(this.#r).ticks), this.yScale.tickTracker.tick(e), this.timeScale.tickTracker.tick(e);
1672
+ const w = this.yScale.tickTracker.snapshot(), S = this.timeScale.tickTracker.snapshot();
1673
+ h = w.isAnimating, l = S.isAnimating, (w.isAnimating || S.isAnimating || s.animating) && this.emit("tickFrame"), this.#V && rt({
1674
+ scope: c,
1637
1675
  timeScale: this.timeScale,
1638
1676
  yScale: this.yScale,
1639
1677
  theme: this.#n,
1640
- yTicks: g,
1641
- timeTicks: k
1642
- }), this.#At(d, v, m);
1643
- const A = this.#c, V = { top: A.top, bottom: A.bottom }, w = this.#x;
1678
+ yTicks: w,
1679
+ timeTicks: S
1680
+ }), this.#It(c, f, m);
1681
+ const M = this.#c, B = { top: M.top, bottom: M.bottom }, L = this.#S;
1644
1682
  for (const b of this.#t) {
1645
- const x = b.renderer.getAlpha?.() ?? (b.visible ? 1 : 0);
1646
- if (x <= 0) continue;
1683
+ const k = b.renderer.getAlpha?.() ?? (b.visible ? 1 : 0);
1684
+ if (k <= 0) continue;
1647
1685
  const T = {
1648
- scope: d,
1686
+ scope: c,
1649
1687
  timeScale: this.timeScale,
1650
1688
  yScale: this.yScale,
1651
1689
  theme: this.#n,
1652
1690
  dataInterval: this.#r,
1653
- padding: V,
1691
+ padding: B,
1654
1692
  state: s,
1655
1693
  seriesId: b.id
1656
- }, D = c.globalAlpha;
1657
- if (x < 1 && (c.globalAlpha = D * x), w) {
1658
- const z = performance.now();
1659
- b.renderer.render(T), w.recordSeries(b.id, performance.now() - z, e);
1694
+ }, D = d.globalAlpha;
1695
+ if (k < 1 && (d.globalAlpha = D * k), L) {
1696
+ const F = performance.now();
1697
+ b.renderer.render(T), L.recordSeries(b.id, performance.now() - F, e);
1660
1698
  } else
1661
1699
  b.renderer.render(T);
1662
- x < 1 && (c.globalAlpha = D);
1700
+ k < 1 && (d.globalAlpha = D);
1663
1701
  }
1664
- c.restore();
1665
- }), this.#$();
1702
+ d.restore(), this.#Ft({
1703
+ scope: c,
1704
+ paneBitmapWidth: f,
1705
+ paneBitmapHeight: m,
1706
+ timeTicks: S
1707
+ }), this.#At(c, m), this.#Lt(c, f);
1708
+ }), this.#K();
1666
1709
  let o = !1;
1667
- for (const d of this.#t)
1668
- if (d.renderer.needsAnimation) {
1710
+ for (const c of this.#t)
1711
+ if (c.renderer.needsAnimation) {
1669
1712
  o = !0, this.#e.markDirty();
1670
1713
  break;
1671
1714
  }
1672
- const u = a || l;
1715
+ const u = h || l;
1673
1716
  !s.animating && !o && !u && (this.yScale.tickTracker.markArmed(), this.timeScale.tickTracker.markArmed());
1674
1717
  }
1718
+ /**
1719
+ * Erase the main layer's alpha across the top fade zone so content
1720
+ * dissolves as it approaches the top edge. `destination-out` multiplies
1721
+ * the already-painted pixels by the mask's inverse alpha — an *erase*, not
1722
+ * a paint-over — so the container background behind the canvas (solid or
1723
+ * CSS gradient) shows through untouched.
1724
+ */
1725
+ #At(t, i) {
1726
+ if (this.#k.top <= 0) return;
1727
+ const e = Math.min(Math.round(this.#k.top * t.verticalPixelRatio), Math.round(i));
1728
+ if (e < 1) return;
1729
+ const { context: s } = t;
1730
+ s.save(), s.globalCompositeOperation = "destination-out", s.fillStyle = this.#Nt(s, e), s.fillRect(0, 0, t.bitmapSize.width, e), s.restore();
1731
+ }
1732
+ /**
1733
+ * Run the vertical gridlines a short stub past the pane floor, dissolving
1734
+ * to transparent on the way to the time-axis labels — the bottom-edge
1735
+ * mirror of the horizontal gridlines melting under the Y-axis column.
1736
+ * Drawn outside the pane clip (the stubs live below the pane, where
1737
+ * nothing else paints) and faded with the same destination-out ramp the
1738
+ * edge masks use, so the taper stays correct over any background.
1739
+ */
1740
+ #Ft(t) {
1741
+ if (!this.#V || this.xAxisHeight === 0) return;
1742
+ const { scope: i, paneBitmapWidth: e, paneBitmapHeight: s, timeTicks: r } = t, { context: n, horizontalPixelRatio: a, verticalPixelRatio: h } = i, l = Math.round(s), o = Math.round(A * h);
1743
+ if (o < 1) return;
1744
+ const u = this.#n.grid;
1745
+ n.save(), n.strokeStyle = u.color, u.style === "dashed" ? n.setLineDash([4 * a, 4 * a]) : u.style === "dotted" && n.setLineDash([1 * a, 3 * a]), n.lineDashOffset = l;
1746
+ const c = Math.max(1, Math.round(a)), d = c % 2 === 1 ? 0.5 : 0;
1747
+ n.lineWidth = c;
1748
+ const p = Math.round(e);
1749
+ for (const { value: f, opacity: m } of r.entries) {
1750
+ if (m <= 0.01) continue;
1751
+ const y = Math.round(this.timeScale.timeToBitmapX(f)) + d;
1752
+ y < 0 || y > p || (n.globalAlpha = m, n.beginPath(), n.moveTo(y, l), n.lineTo(y, l + o), n.stroke());
1753
+ }
1754
+ n.restore(), this.#Mt(i, s);
1755
+ }
1756
+ /**
1757
+ * Erase ramp over the below-pane overrun strip — the gridline tail stubs
1758
+ * on the main layer, the crosshair's overrun on the overlay. Nothing
1759
+ * erased at the pane floor, total at the strip's bottom edge, so whatever
1760
+ * crosses the floor tapers out short of the time-axis labels.
1761
+ */
1762
+ #Mt(t, i) {
1763
+ if (this.xAxisHeight === 0) return;
1764
+ const e = Math.round(i), s = Math.round(A * t.verticalPixelRatio);
1765
+ if (s < 1) return;
1766
+ const { context: r } = t;
1767
+ r.save(), r.globalCompositeOperation = "destination-out", r.fillStyle = this.#Yt({ context: r, start: e, height: s }), r.fillRect(0, e, t.bitmapSize.width, s), r.restore();
1768
+ }
1769
+ /**
1770
+ * Crosshair hairlines with the same edge melt the main layer runs: the
1771
+ * pane clip widens by the right-fade intrusion and by a gridline-tail's
1772
+ * overrun below the floor, then the shared erase ramps dissolve the
1773
+ * overhangs — the vertical line tapers toward the time-axis labels in
1774
+ * step with the gridline stubs and the horizontal line rides under the
1775
+ * Y-axis column toward its label instead of stopping dead at the pane
1776
+ * edge. Erases alpha (destination-out), so it must run while the
1777
+ * crosshair is the only content on the layer.
1778
+ */
1779
+ #Ot(t) {
1780
+ const i = this.#d;
1781
+ if (i === null) return;
1782
+ const { scope: e, chartBitmapWidth: s, chartBitmapHeight: r } = t, { context: n } = e, a = this.#it(e, s), h = this.xAxisHeight > 0 ? Math.round(A * e.verticalPixelRatio) : 0;
1783
+ n.save(), n.beginPath(), n.rect(0, 0, s + a.intrusion, r + h), n.clip(), st({
1784
+ scope: e,
1785
+ bitmapX: i.mediaX * e.horizontalPixelRatio,
1786
+ bitmapY: i.mediaY * e.verticalPixelRatio,
1787
+ theme: this.#n,
1788
+ pane: { width: s, height: r }
1789
+ }), n.restore(), this.#Mt(e, r), this.#At(e, r), this.#Lt(e, s);
1790
+ }
1791
+ /**
1792
+ * Horizontal companions to {@link #applyTopFade}: dissolve content that
1793
+ * rides under the Y-axis column on the right (the pane clip is widened by
1794
+ * the same zone) and, when configured, content leaving through the left
1795
+ * pane edge. Same destination-out erase — background-safe over gradients.
1796
+ * Runs the full bitmap height so the below-pane gridline tail stubs melt
1797
+ * at the edges in step with their lines above.
1798
+ */
1799
+ #Lt(t, i) {
1800
+ const { context: e } = t, s = t.bitmapSize.height, r = this.#it(t, i);
1801
+ r.width >= 1 && (e.save(), e.globalCompositeOperation = "destination-out", e.fillStyle = this.#Et({ context: e, start: r.start, width: r.width }), e.fillRect(r.start, 0, r.width, s), e.restore());
1802
+ const n = Math.min(Math.round(this.#k.left * t.horizontalPixelRatio), Math.round(i));
1803
+ n >= 1 && (e.save(), e.globalCompositeOperation = "destination-out", e.fillStyle = this.#Xt(e, n), e.fillRect(0, 0, n, s), e.restore());
1804
+ }
1805
+ /**
1806
+ * Bitmap geometry of the right fade zone. The ramp finishes just inside
1807
+ * the Y-axis column — {@link RIGHT_FADE_END_GAP_PX} past the pane edge,
1808
+ * still short of where the right-anchored label glyphs start — so content
1809
+ * is fully erased before it can cross any axis text. Everything wider
1810
+ * spills backward into the pane as the soft lead-in. `width: 0` (axis
1811
+ * hidden, or `right: 0`) means no zone; `intrusion` is what the pane clip
1812
+ * extends by (content past the ramp is total-erased anyway, so the clip
1813
+ * stops with the ramp).
1814
+ */
1815
+ #it(t, i) {
1816
+ const e = { start: 0, width: 0, intrusion: 0 }, s = Math.max(0, Math.round(t.bitmapSize.width - i));
1817
+ if (s === 0) return e;
1818
+ const r = t.horizontalPixelRatio, n = Math.min(Math.round(xt * r), s), a = this.#k.right === null ? n + Math.round(bt * r) : Math.round(this.#k.right * r);
1819
+ if (a < 1) return e;
1820
+ const h = i + n, l = Math.min(a, h);
1821
+ return { start: h - l, width: l, intrusion: n };
1822
+ }
1823
+ /** Memoized mask gradient — rebuilt only when the bitmap zone height
1824
+ * changes (resize, DPR change, `setFade`). Ease-out ramp (`1 - t²`):
1825
+ * near-total erasure across the upper half keeps a floating header
1826
+ * legible, then a soft tail into full opacity at the zone's bottom. */
1827
+ #Nt(t, i) {
1828
+ const e = this.#w.top;
1829
+ if (e !== null && e.height === i) return e.gradient;
1830
+ const s = t.createLinearGradient(0, 0, 0, i);
1831
+ for (let r = 0; r <= 4; r++) {
1832
+ const n = r / 4;
1833
+ s.addColorStop(n, `rgba(0, 0, 0, ${1 - n * n})`);
1834
+ }
1835
+ return this.#w.top = { height: i, gradient: s }, s;
1836
+ }
1837
+ /** Right-zone mask — erase grows from 0 at the ramp's inner start to
1838
+ * total at its outer end on an ease-in (`s³`): zero slope *and* zero
1839
+ * curvature at the entry, so the in-pane lead-in barely dims the newest
1840
+ * candles at rest and the aggressive erasing all happens deep under the
1841
+ * axis column. Nine stops keep the piecewise interpolation smooth across
1842
+ * the zone. */
1843
+ #Et(t) {
1844
+ const i = this.#w.right;
1845
+ if (i !== null && i.start === t.start && i.width === t.width) return i.gradient;
1846
+ const e = t.context.createLinearGradient(t.start, 0, t.start + t.width, 0);
1847
+ for (let s = 0; s <= 8; s++) {
1848
+ const r = s / 8;
1849
+ e.addColorStop(r, `rgba(0, 0, 0, ${r * r * r})`);
1850
+ }
1851
+ return this.#w.right = { start: t.start, width: t.width, gradient: e }, e;
1852
+ }
1853
+ /** Erase ramp for the gridline tail stubs — nothing erased at the pane
1854
+ * floor, total at the stub tip, ease-in (`t²`) so a stub holds strength
1855
+ * briefly before melting away short of the label glyphs. */
1856
+ #Yt(t) {
1857
+ const i = this.#w.tail;
1858
+ if (i !== null && i.start === t.start && i.height === t.height) return i.gradient;
1859
+ const e = t.context.createLinearGradient(0, t.start, 0, t.start + t.height);
1860
+ for (let s = 0; s <= 4; s++) {
1861
+ const r = s / 4;
1862
+ e.addColorStop(r, `rgba(0, 0, 0, ${r * r})`);
1863
+ }
1864
+ return this.#w.tail = { start: t.start, height: t.height, gradient: e }, e;
1865
+ }
1866
+ /** Left-zone mask — mirror of the top ramp: total erase at the canvas
1867
+ * edge, fully opaque at the zone's inner boundary. */
1868
+ #Xt(t, i) {
1869
+ const e = this.#w.left;
1870
+ if (e !== null && e.width === i) return e.gradient;
1871
+ const s = t.createLinearGradient(0, 0, i, 0);
1872
+ for (let r = 0; r <= 4; r++) {
1873
+ const n = r / 4;
1874
+ s.addColorStop(n, `rgba(0, 0, 0, ${1 - n * n})`);
1875
+ }
1876
+ return this.#w.left = { width: i, gradient: s }, s;
1877
+ }
1675
1878
  /**
1676
1879
  * Paint a full frame: the main layer, then the overlay synchronously on
1677
1880
  * top so both land in the same browser paint. The overlay scheduler's
@@ -1681,13 +1884,13 @@ class qt extends at {
1681
1884
  * `markDirty` calls made *during* `renderOverlay` (pulse, edge spinner)
1682
1885
  * land after the consume and re-arm cleanly for the next frame.
1683
1886
  */
1684
- #J(t) {
1685
- this.#Q("main", t, () => this.renderMain(t)), this.#h.consume(), this.#Q("overlay", t, () => this.renderOverlay(t));
1887
+ #et(t) {
1888
+ this.#st("main", t, () => this.renderMain(t)), this.#h.consume(), this.#st("overlay", t, () => this.renderOverlay(t));
1686
1889
  }
1687
1890
  /** Run a layer's paint, booking duration + draw calls to the perf monitor
1688
1891
  * when one is attached — keeps overlay time out of the `main` samples. */
1689
- #Q(t, i, e) {
1690
- const s = this.#x;
1892
+ #st(t, i, e) {
1893
+ const s = this.#S;
1691
1894
  if (!s) {
1692
1895
  e();
1693
1896
  return;
@@ -1708,21 +1911,18 @@ class qt extends at {
1708
1911
  }
1709
1912
  this.#m.some((o) => o.pulse) && (e = !0);
1710
1913
  const s = {
1711
- left: this.#R.left && this.#S.left === "loading" ? "idle" : this.#S.left,
1712
- right: this.#R.right && this.#S.right === "loading" ? "idle" : this.#S.right
1914
+ left: this.#I.left && this.#x.left === "loading" ? "idle" : this.#x.left,
1915
+ right: this.#I.right && this.#x.right === "loading" ? "idle" : this.#x.right
1713
1916
  }, r = {
1714
- left: this.#ut("left"),
1715
- right: this.#ut("right")
1716
- }, n = r.left !== null || r.right !== null, h = s.left === "loading" || s.right === "loading" || n, a = s.left !== "idle" || s.right !== "idle" || n, l = !!this.#d || e || a || this.#m.length > 0 || this.#y.length > 0;
1717
- if (!(!l && !this.#et)) {
1718
- if (this.#et = l, this.#a.useOverlayLayer((o) => {
1917
+ left: this.#vt("left"),
1918
+ right: this.#vt("right")
1919
+ }, n = r.left !== null || r.right !== null, a = s.left === "loading" || s.right === "loading" || n, h = s.left !== "idle" || s.right !== "idle" || n, l = !!this.#d || e || h || this.#m.length > 0 || this.#y.length > 0;
1920
+ if (!(!l && !this.#at)) {
1921
+ if (this.#at = l, this.#a.useOverlayLayer((o) => {
1719
1922
  if (!l) return;
1720
- const u = (i.media.width - this.yAxisWidth) * i.horizontalPixelRatio, d = (i.media.height - this.xAxisHeight) * i.verticalPixelRatio;
1721
- if (o.context.save(), o.context.beginPath(), o.context.rect(0, 0, u, d), o.context.clip(), this.#d && this.#Tt()) {
1722
- const m = this.#d.mediaX * i.horizontalPixelRatio, g = this.#d.mediaY * i.verticalPixelRatio;
1723
- tt(o, m, g, this.#n);
1724
- }
1725
- const c = this.#c, p = { top: c.top, bottom: c.bottom }, v = this.#s.getAnimationState();
1923
+ const u = (i.media.width - this.yAxisWidth) * i.horizontalPixelRatio, c = (i.media.height - this.xAxisHeight) * i.verticalPixelRatio;
1924
+ this.#d && this.#yt() && this.#Ot({ scope: o, chartBitmapWidth: u, chartBitmapHeight: c }), o.context.save(), o.context.beginPath(), o.context.rect(0, 0, u, c), o.context.clip();
1925
+ const d = this.#c, p = { top: d.top, bottom: d.bottom }, f = this.#s.getAnimationState();
1726
1926
  for (const m of this.#t)
1727
1927
  m.visible && m.renderer.drawOverlay?.({
1728
1928
  scope: o,
@@ -1732,10 +1932,10 @@ class qt extends at {
1732
1932
  dataInterval: this.#r,
1733
1933
  padding: p,
1734
1934
  crosshair: this.#d,
1735
- state: v,
1935
+ state: f,
1736
1936
  seriesId: m.id
1737
1937
  });
1738
- this.#wt(o, u, d), this.#kt(o, u, d), a && Y({
1938
+ this.#Pt(o, u, c), this.#Ct(o, u, c), h && Z({
1739
1939
  scope: o,
1740
1940
  chartMediaWidth: i.media.width - this.yAxisWidth,
1741
1941
  chartMediaHeight: i.media.height - this.xAxisHeight,
@@ -1743,35 +1943,35 @@ class qt extends at {
1743
1943
  theme: this.#n,
1744
1944
  edgeStates: s,
1745
1945
  edgeExitFades: r,
1746
- edgeIndicatorFns: this.#nt,
1747
- resolveBoundary: (m) => B(m, this.#st[m], this.getDataBounds()),
1748
- resolveEdgeAnchor: (m, g) => this.#Dt(m, g),
1749
- resolveEdgeBarSpacing: () => this.#Lt(),
1750
- reportPlaceholders: (m, g) => {
1751
- this.#B[m] = { bars: g, at: performance.now() };
1946
+ edgeIndicatorFns: this.#lt,
1947
+ resolveBoundary: (m) => $(m, this.#ht[m], this.getDataBounds()),
1948
+ resolveEdgeAnchor: (m, y) => this.#Ht(m, y),
1949
+ resolveEdgeBarSpacing: () => this.#zt(),
1950
+ reportPlaceholders: (m, y) => {
1951
+ this.#Z[m] = { bars: y, at: performance.now() };
1752
1952
  }
1753
1953
  }), o.context.restore();
1754
1954
  }), e) {
1755
1955
  const { from: o, to: u } = this.timeScale.getRange();
1756
- let d = !1;
1757
- for (const c of this.#t)
1758
- if (!(!c.visible || !c.renderer.overlayNeedsAnimation) && (c.renderer.hasOverlayContentInRange?.(o, u) ?? !0)) {
1759
- d = !0;
1956
+ let c = !1;
1957
+ for (const d of this.#t)
1958
+ if (!(!d.visible || !d.renderer.overlayNeedsAnimation) && (d.renderer.hasOverlayContentInRange?.(o, u) ?? !0)) {
1959
+ c = !0;
1760
1960
  break;
1761
1961
  }
1762
- if (!d) {
1763
- for (const c of this.#m)
1764
- if (c.pulse && c.time >= o && c.time <= u) {
1765
- d = !0;
1962
+ if (!c) {
1963
+ for (const d of this.#m)
1964
+ if (d.pulse && d.time >= o && d.time <= u) {
1965
+ c = !0;
1766
1966
  break;
1767
1967
  }
1768
1968
  }
1769
- d && this.#h.markDirty();
1969
+ c && this.#h.markDirty();
1770
1970
  }
1771
- h && this.#h.markDirty();
1971
+ a && this.#h.markDirty();
1772
1972
  }
1773
1973
  }
1774
1974
  }
1775
1975
  export {
1776
- qt as ChartInstance
1976
+ ti as ChartInstance
1777
1977
  };