@wick-charts/vue 0.5.1 → 0.6.0
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.
- package/README.md +18 -3
- package/dist/BarSeries.vue.js +26 -20
- package/dist/CandlestickSeries.vue.js +30 -24
- package/dist/ChartContainer.vue.js +88 -65
- package/dist/HeatmapSeries.vue.js +40 -0
- package/dist/HeatmapSeries.vue2.js +4 -0
- package/dist/LineSeries.vue.js +26 -20
- package/dist/PieSeries.vue.js +24 -18
- package/dist/core/dist/animation/animator.js +21 -21
- package/dist/core/dist/animation/config.js +114 -87
- package/dist/core/dist/animation/easing.js +3 -1
- package/dist/core/dist/animation/intro-wave.js +68 -0
- package/dist/core/dist/axis/dom-labels.js +13 -14
- package/dist/core/dist/chart/badge-animator.js +56 -0
- package/dist/core/dist/chart/edge-indicators.js +28 -13
- package/dist/core/dist/chart/last-value.js +18 -17
- package/dist/core/dist/chart/y-target.js +13 -12
- package/dist/core/dist/chart.js +679 -452
- package/dist/core/dist/components/annotation-chip.js +28 -0
- package/dist/core/dist/components/edge-indicator.js +58 -26
- package/dist/core/dist/components/loading-indicator.js +46 -0
- package/dist/core/dist/components/marker.js +49 -31
- package/dist/core/dist/components/reference-line.js +27 -36
- package/dist/core/dist/components/time-region.js +30 -28
- package/dist/core/dist/data/store.js +38 -19
- package/dist/core/dist/data/sync.js +60 -38
- package/dist/core/dist/heatmap-tooltip.js +16 -0
- package/dist/core/dist/interactions/handler.js +67 -43
- package/dist/core/dist/perf/perf-hud.js +5 -5
- package/dist/core/dist/scales/x-scale.js +85 -37
- package/dist/core/dist/scales/y-scale.js +38 -27
- package/dist/core/dist/series/bar-intro.js +18 -0
- package/dist/core/dist/series/bar.js +337 -205
- package/dist/core/dist/series/base-multi-layer.js +224 -96
- package/dist/core/dist/series/candlestick-intro.js +57 -0
- package/dist/core/dist/series/candlestick.js +454 -276
- package/dist/core/dist/series/heatmap.js +387 -0
- package/dist/core/dist/series/line-intro.js +85 -0
- package/dist/core/dist/series/line.js +590 -282
- package/dist/core/dist/series/painters/builtins.js +2 -2
- package/dist/core/dist/series/pie.js +396 -259
- package/dist/core/dist/series/register-builtins.js +8 -7
- package/dist/core/dist/series/types.js +6 -0
- package/dist/core/dist/series/wave-intro.js +26 -0
- package/dist/core/dist/theme/create.js +69 -63
- package/dist/core/dist/theme/themes/mint-breeze.js +2 -2
- package/dist/core/dist/theme/themes/sand-dune.js +2 -2
- package/dist/core/dist/utils/color.js +109 -34
- package/dist/core/dist/utils/deep-equal.js +18 -0
- package/dist/core/dist/utils/time.js +25 -19
- package/dist/index.d.ts +1405 -123
- package/dist/index.js +177 -130
- package/dist/ui/Crosshair.vue.js +20 -21
- package/dist/ui/HeatmapTooltip.vue.js +96 -0
- package/dist/ui/HeatmapTooltip.vue2.js +4 -0
- package/dist/ui/InfoBar.vue.js +46 -47
- package/dist/ui/Legend.vue.js +80 -79
- package/dist/ui/PieLegend.vue.js +5 -5
- package/dist/ui/PieTooltip.vue.js +77 -67
- package/dist/ui/Tooltip.vue.js +60 -60
- package/dist/ui/YAxis.vue.js +2 -2
- package/dist/ui/YLabel.vue.js +94 -61
- package/package.json +2 -2
- package/src/BarSeries.vue +23 -7
- package/src/CandlestickSeries.vue +23 -7
- package/src/ChartContainer.vue +134 -12
- package/src/HeatmapSeries.vue +69 -0
- package/src/LineSeries.vue +23 -7
- package/src/PieSeries.vue +22 -6
- package/src/index.ts +84 -3
- package/src/ui/Crosshair.vue +1 -2
- package/src/ui/HeatmapTooltip.vue +144 -0
- package/src/ui/InfoBar.vue +1 -2
- package/src/ui/Legend.vue +13 -0
- package/src/ui/Marker.vue +1 -1
- package/src/ui/PieTooltip.vue +10 -0
- package/src/ui/ReferenceLine.vue +2 -2
- package/src/ui/TimeRegion.vue +2 -2
- package/src/ui/Tooltip.vue +2 -2
- package/src/ui/YLabel.vue +123 -8
package/dist/core/dist/chart.js
CHANGED
|
@@ -1,62 +1,76 @@
|
|
|
1
|
-
import { AnimationConfig as
|
|
2
|
-
import {
|
|
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";
|
|
3
4
|
import { CanvasManager as W } from "./canvas-manager.js";
|
|
4
|
-
import { drawEdgeIndicators as
|
|
5
|
-
import { computeFitToData as
|
|
6
|
-
import { getLastValue as
|
|
7
|
-
import { resolveMaxVisibleBars as
|
|
8
|
-
import { computePan as
|
|
9
|
-
import { StreamingCadence as
|
|
10
|
-
import { computeStreamingTarget as
|
|
11
|
-
import { resolvePaddingTime as
|
|
12
|
-
import { computeTargetYRange as
|
|
13
|
-
import { renderCrosshair as
|
|
14
|
-
import { renderGrid as
|
|
15
|
-
import { renderMarker as
|
|
16
|
-
import { renderReferenceLine as
|
|
17
|
-
import { resolveTimeRegionColors as
|
|
18
|
-
import { EventEmitter as
|
|
19
|
-
import { InteractionHandler as
|
|
20
|
-
import { RenderScheduler as
|
|
21
|
-
import { XScale as
|
|
22
|
-
import { YScale as
|
|
23
|
-
import { resolveSeriesDefinition as
|
|
24
|
-
import {
|
|
25
|
-
import {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
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]);
|
|
29
33
|
}
|
|
30
|
-
function
|
|
31
|
-
return
|
|
34
|
+
function St(f, t) {
|
|
35
|
+
return f === t ? !0 : !f || !t || f.length !== t.length ? !1 : f.every((i, e) => i === t[e]);
|
|
32
36
|
}
|
|
33
|
-
class
|
|
37
|
+
class qt extends at {
|
|
34
38
|
/** Canvas lifecycle and DPR-aware sizing. */
|
|
35
|
-
#
|
|
39
|
+
#a;
|
|
36
40
|
/** Schedules main-layer redraws (background, grid, series). */
|
|
37
|
-
#
|
|
41
|
+
#e;
|
|
38
42
|
/** Schedules overlay redraws (crosshair). */
|
|
39
|
-
#
|
|
43
|
+
#h;
|
|
40
44
|
/** Maps time values to horizontal pixel coordinates. */
|
|
41
45
|
timeScale;
|
|
42
46
|
/** Maps price/value to vertical pixel coordinates. */
|
|
43
47
|
yScale;
|
|
44
48
|
/** Zoom, pan, crosshair — null when interactive=false. */
|
|
45
|
-
#
|
|
49
|
+
#C;
|
|
46
50
|
/** All registered series (candlestick, line, bar, pie). */
|
|
47
51
|
#t = [];
|
|
48
52
|
/** Point annotations (event markers) drawn on the overlay layer, kept out of the series model. */
|
|
49
53
|
#m = [];
|
|
50
54
|
/** Time-region bands drawn on the main layer behind the series, kept out of the series model. */
|
|
51
|
-
#
|
|
55
|
+
#b = [];
|
|
52
56
|
/** Reference lines (horizontal threshold / vertical event) drawn on the overlay layer, kept out of the series model. */
|
|
53
|
-
#
|
|
57
|
+
#y = [];
|
|
58
|
+
/**
|
|
59
|
+
* Overlay-intro latch. Annotations ride the *initial* reveal, then stay put.
|
|
60
|
+
* `#overlayIntroSeen` flips once we've actually watched an intro in progress
|
|
61
|
+
* (guards against latching on an empty chart before any data arrives);
|
|
62
|
+
* `#overlayIntroSettled` freezes the front at `1` afterward so a series added
|
|
63
|
+
* later — which re-arms `getIntroFront()`'s global min — can't blink settled
|
|
64
|
+
* markers / reference lines back out.
|
|
65
|
+
*/
|
|
66
|
+
#tt = !1;
|
|
67
|
+
#it = !1;
|
|
54
68
|
/** Active visual theme (colors, fonts, grid style). */
|
|
55
|
-
#
|
|
69
|
+
#n;
|
|
56
70
|
/** Whether to render the background grid. */
|
|
57
|
-
#
|
|
71
|
+
#O;
|
|
58
72
|
/** Detected time interval between data points (milliseconds). */
|
|
59
|
-
#
|
|
73
|
+
#r = 6e4;
|
|
60
74
|
/** Current crosshair position, null when cursor is outside the chart. */
|
|
61
75
|
#d = null;
|
|
62
76
|
/**
|
|
@@ -66,30 +80,45 @@ class Ot extends st {
|
|
|
66
80
|
* `time`/`y`; `'time'` (programmatic {@link setCrosshair}) keeps
|
|
67
81
|
* `time`/`y` and re-projects the pixel position.
|
|
68
82
|
*/
|
|
69
|
-
#
|
|
83
|
+
#Y = "pointer";
|
|
70
84
|
/** Whether the last overlay pass painted anything — gates the full-bitmap
|
|
71
85
|
* clear so an empty overlay isn't cleared again every main frame. */
|
|
72
|
-
#
|
|
86
|
+
#et = !1;
|
|
73
87
|
/** User-specified Y-axis bounds (auto, fixed, percentage). */
|
|
74
|
-
#
|
|
88
|
+
#l = {};
|
|
75
89
|
/** Cached series ID list — invalidated on add/remove. */
|
|
76
|
-
#
|
|
90
|
+
#T = null;
|
|
77
91
|
/** Axis visibility and sizing configuration. */
|
|
78
|
-
#
|
|
92
|
+
#H = {};
|
|
79
93
|
/** Host-declared state per edge — drives the edge-indicator overlay. */
|
|
80
|
-
#
|
|
94
|
+
#S = { left: "idle", right: "idle" };
|
|
95
|
+
/** Wall-clock start of a `loading` exit fade per side — set when the host
|
|
96
|
+
* drops `loading` back to `idle`/`has-more`, so the indicator fades out
|
|
97
|
+
* over {@link EDGE_EXIT_FADE_MS} instead of vanishing the same frame the
|
|
98
|
+
* fetched data lands. `null` = no fade in flight. */
|
|
99
|
+
#V = { left: null, right: null };
|
|
81
100
|
/** Cached boundary timestamps from the last `edgeReached` emission, by side. */
|
|
82
|
-
#
|
|
101
|
+
#st = { left: null, right: null };
|
|
102
|
+
/** Latest placeholder shapes a `loading` indicator reported per side —
|
|
103
|
+
* the morph hand-off candidate consumed by {@link prependData}. */
|
|
104
|
+
#B = { left: null, right: null };
|
|
105
|
+
/** True after a prepend consumed a side's placeholder snapshot: the series'
|
|
106
|
+
* reveal owns those pixels now, so the still-`loading` indicator is hidden
|
|
107
|
+
* and the upcoming `loading → idle` transition skips its exit fade. Reset
|
|
108
|
+
* by the next {@link setEdgeState} call. */
|
|
109
|
+
#R = { left: !1, right: !1 };
|
|
83
110
|
/** Host-supplied callback fired when the user releases a pan/zoom past a data edge. */
|
|
84
|
-
#
|
|
111
|
+
#rt;
|
|
112
|
+
/** Per-side custom painter for the edge `loading` spinner. `null` falls back to the built-in dots. */
|
|
113
|
+
#nt = { left: null, right: null };
|
|
85
114
|
/** Nesting depth for batch updates. Suppresses recomputes while > 0. */
|
|
86
|
-
#
|
|
115
|
+
#A = 0;
|
|
87
116
|
/** True when batched operations include data changes (triggers full onDataChanged on end). */
|
|
88
|
-
#
|
|
117
|
+
#X = !1;
|
|
89
118
|
/** True when batched operations include visibility changes (triggers Y-range + redraw on end). */
|
|
90
|
-
#
|
|
119
|
+
#M = !1;
|
|
91
120
|
/** True when batched operations bumped overlay version (emits a single overlayChange on flush). */
|
|
92
|
-
#
|
|
121
|
+
#Z = !1;
|
|
93
122
|
/**
|
|
94
123
|
* Monotonic counter bumped on any mutation that affects overlay output —
|
|
95
124
|
* data, visibility, series options, theme. Used by snapshot helpers in
|
|
@@ -99,17 +128,17 @@ class Ot extends st {
|
|
|
99
128
|
*
|
|
100
129
|
* @internal
|
|
101
130
|
*/
|
|
102
|
-
#
|
|
131
|
+
#at = 0;
|
|
103
132
|
get yAxisWidth() {
|
|
104
|
-
const t = this.#
|
|
133
|
+
const t = this.#H.y;
|
|
105
134
|
return t?.visible === !1 ? 0 : t?.width ?? 55;
|
|
106
135
|
}
|
|
107
136
|
get xAxisHeight() {
|
|
108
|
-
const t = this.#
|
|
137
|
+
const t = this.#H.x;
|
|
109
138
|
return t?.visible === !1 ? 0 : t?.height ?? 30;
|
|
110
139
|
}
|
|
111
140
|
/** Resolved animation config derived from `options.animations` at construction. */
|
|
112
|
-
#
|
|
141
|
+
#g;
|
|
113
142
|
/**
|
|
114
143
|
* Single source of truth for the chart's X / Y viewport animation.
|
|
115
144
|
* Push-model API: chart emits intent signals (`onPointAppended`,
|
|
@@ -118,7 +147,7 @@ class Ot extends st {
|
|
|
118
147
|
* matching targets back through `computeXTarget` / `computeYTarget`
|
|
119
148
|
* closures supplied at construction.
|
|
120
149
|
*/
|
|
121
|
-
#
|
|
150
|
+
#s;
|
|
122
151
|
/** EMA-smoothed real-wall-clock cadence between streaming appends. The
|
|
123
152
|
* X spring's `setSettleMs` is fed from this so the settle time stays just
|
|
124
153
|
* longer than the producer's tick interval — the spring never quite
|
|
@@ -134,31 +163,31 @@ class Ot extends st {
|
|
|
134
163
|
* field carries the decision across that gap. The closure also reads
|
|
135
164
|
* `#dataStart` / `#dataEnd` directly for the timestamps.
|
|
136
165
|
*/
|
|
137
|
-
#
|
|
166
|
+
#ht = !1;
|
|
138
167
|
/** Earliest data timestamp registered across all series, `null` before any data has arrived. */
|
|
139
168
|
#k = null;
|
|
140
169
|
/** Latest data timestamp registered across all series, `null` before any data has arrived. */
|
|
141
|
-
#
|
|
170
|
+
#i = null;
|
|
142
171
|
/**
|
|
143
172
|
* Previous {@link #dataEnd} value. Streaming-target math reads it to
|
|
144
173
|
* preserve any pan offset across ticks: a user who panned a few bars
|
|
145
174
|
* left of the tail keeps that offset as new bars arrive, instead of
|
|
146
175
|
* snapping back to the natural-pin position every frame.
|
|
147
176
|
*/
|
|
148
|
-
#
|
|
177
|
+
#z = null;
|
|
149
178
|
/**
|
|
150
179
|
* Warm-up window flag — `setVisibleRange({ from, bars })` arms it and
|
|
151
180
|
* the streaming-target math suppresses pan ticks while the data hasn't
|
|
152
181
|
* reached the right edge yet. Cleared by user interaction or once the
|
|
153
182
|
* data fills the window.
|
|
154
183
|
*/
|
|
155
|
-
#
|
|
184
|
+
#w = !1;
|
|
156
185
|
/**
|
|
157
186
|
* Cap for fit-to-data. When the data span exceeds this, the fit anchors
|
|
158
187
|
* the right edge and trims the left. Resolved once at construction from
|
|
159
188
|
* `options.viewport.maxVisibleBars`.
|
|
160
189
|
*/
|
|
161
|
-
#
|
|
190
|
+
#ot;
|
|
162
191
|
/**
|
|
163
192
|
* Committed logical X range — the "where X should be" target. Engine
|
|
164
193
|
* eases its visual toward this. Pan / zoom / setRange / fitContent /
|
|
@@ -167,29 +196,29 @@ class Ot extends st {
|
|
|
167
196
|
*/
|
|
168
197
|
#o = { from: 0, to: 0 };
|
|
169
198
|
/** Padded Y range — engine's raw Y target plus pixel padding from `#padding`. */
|
|
170
|
-
#
|
|
199
|
+
#F = { min: 0, max: 0 };
|
|
171
200
|
/**
|
|
172
201
|
* Auto-scroll flag — when `true`, streaming ticks slide X to track the
|
|
173
202
|
* data tail. Pan flips this off when the gesture pushes the tail off
|
|
174
203
|
* screen; chart's per-frame autoscroll check re-engages it when a
|
|
175
204
|
* follow-up pan brings the tail back into view.
|
|
176
205
|
*/
|
|
177
|
-
#
|
|
206
|
+
#u = !0;
|
|
178
207
|
/** Resolved viewport padding (top/bottom px + left/right pixels-or-intervals). */
|
|
179
208
|
#c;
|
|
180
209
|
/** Cached chart width — passed by interactions on every call; kept for the rare
|
|
181
210
|
* call that omits it (e.g. programmatic `chart.pan(...)` without explicit width). */
|
|
182
|
-
#
|
|
211
|
+
#E = 0;
|
|
183
212
|
/** Active performance monitor, or `null` when instrumentation is disabled (the default). */
|
|
184
|
-
#
|
|
213
|
+
#x;
|
|
185
214
|
/** When true, `destroy()` tears down the monitor; false for caller-supplied monitors we must not destroy. */
|
|
186
|
-
#
|
|
215
|
+
#_ = !1;
|
|
187
216
|
/** Visible HUD overlay (mounted by the perf config); non-null only when the caller requested one. */
|
|
188
|
-
#
|
|
217
|
+
#U = null;
|
|
189
218
|
constructor(t, i) {
|
|
190
|
-
super(), i?.axis && (this.#
|
|
191
|
-
const e = this.#
|
|
192
|
-
this.#
|
|
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();
|
|
220
|
+
const e = this.#g.axis.y, s = this.#g.axis.x;
|
|
221
|
+
this.#s = N({
|
|
193
222
|
initial: { yRange: { min: 0, max: 0 }, xRange: { from: 0, to: 0 } },
|
|
194
223
|
y: {
|
|
195
224
|
curve: e.curve,
|
|
@@ -197,28 +226,32 @@ class Ot extends st {
|
|
|
197
226
|
stickyMs: e.stickyMs,
|
|
198
227
|
stickyFloorMs: e.stickyFloorMs,
|
|
199
228
|
gestureMs: e.gestureMs,
|
|
200
|
-
toggleMs: this.#
|
|
229
|
+
toggleMs: this.#g.toggleMs
|
|
201
230
|
},
|
|
202
231
|
x: {
|
|
203
232
|
curve: s.curve,
|
|
204
233
|
settleMs: s.settleMs,
|
|
205
234
|
gestureMs: s.gestureMs
|
|
206
235
|
},
|
|
207
|
-
computeXTarget: () => this.#
|
|
208
|
-
computeYTarget: ({ xTarget:
|
|
209
|
-
onWake: () => this.#
|
|
210
|
-
}), this.#
|
|
211
|
-
const r =
|
|
212
|
-
this.#
|
|
213
|
-
const n = this.#
|
|
214
|
-
this.timeScale.tickTracker.setFadeMs(n), this.yScale.tickTracker.setFadeMs(n), this.#
|
|
215
|
-
(
|
|
216
|
-
), this.#
|
|
217
|
-
const
|
|
218
|
-
this.#
|
|
219
|
-
this.syncScales(), this.#
|
|
220
|
-
}), this.syncScales(), this.#
|
|
221
|
-
this.#
|
|
236
|
+
computeXTarget: () => this.#Rt(),
|
|
237
|
+
computeYTarget: ({ xTarget: a }) => this.#gt(a),
|
|
238
|
+
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);
|
|
242
|
+
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) });
|
|
222
255
|
});
|
|
223
256
|
}
|
|
224
257
|
/**
|
|
@@ -233,9 +266,9 @@ class Ot extends st {
|
|
|
233
266
|
* `setSeriesVisible` / `setLayerVisible` calls — produce one overlay
|
|
234
267
|
* render instead of N.
|
|
235
268
|
*/
|
|
236
|
-
#
|
|
237
|
-
if (this.#
|
|
238
|
-
this.#
|
|
269
|
+
#p() {
|
|
270
|
+
if (this.#at++, this.#A > 0) {
|
|
271
|
+
this.#Z = !0;
|
|
239
272
|
return;
|
|
240
273
|
}
|
|
241
274
|
this.emit("overlayChange");
|
|
@@ -249,39 +282,39 @@ class Ot extends st {
|
|
|
249
282
|
* @internal
|
|
250
283
|
*/
|
|
251
284
|
getOverlayVersion() {
|
|
252
|
-
return this.#
|
|
285
|
+
return this.#at;
|
|
253
286
|
}
|
|
254
287
|
/**
|
|
255
288
|
* Return a series ID: use the provided hint if it's non-empty and not already taken,
|
|
256
289
|
* otherwise generate a new auto ID. Auto-generated IDs never collide with each other
|
|
257
290
|
* or with user-provided IDs because they use a monotonically increasing counter.
|
|
258
291
|
*/
|
|
259
|
-
#
|
|
292
|
+
#bt(t) {
|
|
260
293
|
if (t && !this.#t.some((e) => e.id === t))
|
|
261
294
|
return t;
|
|
262
295
|
let i;
|
|
263
296
|
do
|
|
264
|
-
i = `series_${++
|
|
297
|
+
i = `series_${++pt}`;
|
|
265
298
|
while (this.#t.some((e) => e.id === i));
|
|
266
299
|
return i;
|
|
267
300
|
}
|
|
268
301
|
addSeries(t, i = {}) {
|
|
269
|
-
const e = typeof t == "string" ?
|
|
302
|
+
const e = typeof t == "string" ? ct(t) : t;
|
|
270
303
|
if (!e)
|
|
271
304
|
throw new Error(
|
|
272
305
|
`[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).`
|
|
273
306
|
);
|
|
274
|
-
const { layers: s, id: r, label: n, labels:
|
|
275
|
-
...this.#
|
|
276
|
-
...
|
|
277
|
-
...this.#
|
|
278
|
-
}, u = e.create({ theme: this.#
|
|
279
|
-
return u.onDataChanged?.(() => this.onDataChanged()), this.#t.push({ id: c, labels: d, renderer: u, visible: !0 }), this.#
|
|
307
|
+
const { layers: s, id: r, label: n, labels: h, ...a } = i, l = s ?? 1, o = {
|
|
308
|
+
...this.#g.defaults(e.type),
|
|
309
|
+
...a,
|
|
310
|
+
...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;
|
|
280
313
|
}
|
|
281
314
|
/** Remove a series by ID and clean up its resources. */
|
|
282
315
|
removeSeries(t) {
|
|
283
316
|
const i = this.#t.findIndex((e) => e.id === t);
|
|
284
|
-
i >= 0 && (this.#t[i].renderer.dispose(), this.#t.splice(i, 1), this.#
|
|
317
|
+
i >= 0 && (this.#t[i].renderer.dispose(), this.#t.splice(i, 1), this.#T = null, this.#e.markDirty(), this.emit("seriesChange"), this.#p());
|
|
285
318
|
}
|
|
286
319
|
// --- Markers (point annotations) -----------------------------------------
|
|
287
320
|
/**
|
|
@@ -294,27 +327,27 @@ class Ot extends st {
|
|
|
294
327
|
* appear in series queries.
|
|
295
328
|
*/
|
|
296
329
|
addMarker(t) {
|
|
297
|
-
const i = `marker_${++
|
|
298
|
-
return this.#m.push(this.#
|
|
330
|
+
const i = `marker_${++yt}`;
|
|
331
|
+
return this.#m.push(this.#lt(i, t)), this.#h.markDirty(), i;
|
|
299
332
|
}
|
|
300
333
|
/** Replace a marker's config in place. No-op when the id is unknown. */
|
|
301
334
|
updateMarker(t, i) {
|
|
302
335
|
const e = this.#m.findIndex((s) => s.id === t);
|
|
303
|
-
e !== -1 && (this.#m[e] = this.#
|
|
336
|
+
e !== -1 && (this.#m[e] = this.#lt(t, i), this.#h.markDirty());
|
|
304
337
|
}
|
|
305
338
|
/** Remove a marker by id. No-op when the id is unknown. */
|
|
306
339
|
removeMarker(t) {
|
|
307
340
|
const i = this.#m.findIndex((e) => e.id === t);
|
|
308
|
-
i !== -1 && (this.#m.splice(i, 1), this.#
|
|
341
|
+
i !== -1 && (this.#m.splice(i, 1), this.#h.markDirty());
|
|
309
342
|
}
|
|
310
343
|
/** Read-only snapshot of the registered markers (normalized). Mutate via add / update / removeMarker. */
|
|
311
344
|
getMarkers() {
|
|
312
345
|
return this.#m;
|
|
313
346
|
}
|
|
314
|
-
#
|
|
347
|
+
#lt(t, i) {
|
|
315
348
|
return {
|
|
316
349
|
id: t,
|
|
317
|
-
time:
|
|
350
|
+
time: y(i.time),
|
|
318
351
|
value: i.value,
|
|
319
352
|
seriesId: i.seriesId,
|
|
320
353
|
shape: i.shape ?? "dot",
|
|
@@ -324,41 +357,47 @@ class Ot extends st {
|
|
|
324
357
|
};
|
|
325
358
|
}
|
|
326
359
|
/** Resolve a marker's Y value: explicit `value`, else snapped to its series at `time`. Null when neither resolves. */
|
|
327
|
-
#
|
|
360
|
+
#St(t) {
|
|
328
361
|
if (t.value !== void 0 && Number.isFinite(t.value)) return t.value;
|
|
329
362
|
if (t.seriesId === void 0) return null;
|
|
330
363
|
const i = this.getDataAtTime(t.seriesId, t.time);
|
|
331
364
|
return i ? "close" in i ? i.close : i.value : null;
|
|
332
365
|
}
|
|
333
366
|
/** Resolve a marker's color: explicit `color`, else the series color, else the theme line color. */
|
|
334
|
-
#
|
|
367
|
+
#xt(t) {
|
|
335
368
|
if (t.color !== void 0) return t.color;
|
|
336
369
|
if (t.seriesId !== void 0) {
|
|
337
370
|
const i = this.getSeriesColor(t.seriesId);
|
|
338
371
|
if (i !== null) return i;
|
|
339
372
|
}
|
|
340
|
-
return this.#
|
|
373
|
+
return this.#n.line.color;
|
|
341
374
|
}
|
|
342
|
-
#
|
|
375
|
+
#kt(t, i, e) {
|
|
343
376
|
if (this.#m.length === 0) return;
|
|
344
|
-
const
|
|
345
|
-
for (const
|
|
346
|
-
const
|
|
347
|
-
|
|
377
|
+
const s = performance.now() / (E * 2 * Math.PI) % 1, r = this.#$();
|
|
378
|
+
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;
|
|
383
|
+
const l = t.context.globalAlpha;
|
|
384
|
+
a < 1 && (t.context.globalAlpha = l * a), et({
|
|
348
385
|
scope: t,
|
|
349
386
|
timeScale: this.timeScale,
|
|
350
387
|
yScale: this.yScale,
|
|
351
|
-
theme: this.#
|
|
388
|
+
theme: this.#n,
|
|
352
389
|
marker: {
|
|
353
|
-
time:
|
|
354
|
-
value:
|
|
355
|
-
color: this.#
|
|
356
|
-
shape:
|
|
357
|
-
pulse:
|
|
358
|
-
label:
|
|
390
|
+
time: n.time,
|
|
391
|
+
value: h,
|
|
392
|
+
color: this.#xt(n),
|
|
393
|
+
shape: n.shape,
|
|
394
|
+
pulse: n.pulse,
|
|
395
|
+
label: n.label
|
|
359
396
|
},
|
|
360
|
-
phase:
|
|
361
|
-
|
|
397
|
+
phase: s,
|
|
398
|
+
plotWidth: i,
|
|
399
|
+
plotHeight: e
|
|
400
|
+
}), a < 1 && (t.context.globalAlpha = l);
|
|
362
401
|
}
|
|
363
402
|
}
|
|
364
403
|
// --- Time regions (shaded bands) -----------------------------------------
|
|
@@ -374,42 +413,42 @@ class Ot extends st {
|
|
|
374
413
|
* legend.
|
|
375
414
|
*/
|
|
376
415
|
addRegion(t) {
|
|
377
|
-
const i = `region_${++
|
|
378
|
-
return this.#
|
|
416
|
+
const i = `region_${++vt}`;
|
|
417
|
+
return this.#b.push(this.#ct(i, t)), this.#e.markDirty(), i;
|
|
379
418
|
}
|
|
380
419
|
/** Replace a region's config in place. No-op when the id is unknown. */
|
|
381
420
|
updateRegion(t, i) {
|
|
382
|
-
const e = this.#
|
|
383
|
-
e !== -1 && (this.#
|
|
421
|
+
const e = this.#b.findIndex((s) => s.id === t);
|
|
422
|
+
e !== -1 && (this.#b[e] = this.#ct(t, i), this.#e.markDirty());
|
|
384
423
|
}
|
|
385
424
|
/** Remove a region by id. No-op when the id is unknown. */
|
|
386
425
|
removeRegion(t) {
|
|
387
|
-
const i = this.#
|
|
388
|
-
i !== -1 && (this.#
|
|
426
|
+
const i = this.#b.findIndex((e) => e.id === t);
|
|
427
|
+
i !== -1 && (this.#b.splice(i, 1), this.#e.markDirty());
|
|
389
428
|
}
|
|
390
429
|
/** Read-only snapshot of the registered regions (normalized). Mutate via add / update / removeRegion. */
|
|
391
430
|
getRegions() {
|
|
392
|
-
return this.#
|
|
431
|
+
return this.#b;
|
|
393
432
|
}
|
|
394
|
-
#
|
|
395
|
-
const { to: e } = i, s = e === void 0 || e === "now" ? null :
|
|
433
|
+
#ct(t, i) {
|
|
434
|
+
const { to: e } = i, s = e === void 0 || e === "now" ? null : y(e);
|
|
396
435
|
return {
|
|
397
436
|
id: t,
|
|
398
|
-
from:
|
|
437
|
+
from: y(i.from),
|
|
399
438
|
to: s,
|
|
400
439
|
fill: i.fill,
|
|
401
440
|
color: i.color,
|
|
402
441
|
label: i.label
|
|
403
442
|
};
|
|
404
443
|
}
|
|
405
|
-
#
|
|
406
|
-
if (this.#
|
|
407
|
-
for (const s of this.#
|
|
408
|
-
const { color: r, fill: n } =
|
|
409
|
-
|
|
444
|
+
#At(t, i, e) {
|
|
445
|
+
if (this.#b.length !== 0)
|
|
446
|
+
for (const s of this.#b) {
|
|
447
|
+
const { color: r, fill: n } = rt(s, this.#n);
|
|
448
|
+
nt({
|
|
410
449
|
scope: t,
|
|
411
450
|
timeScale: this.timeScale,
|
|
412
|
-
theme: this.#
|
|
451
|
+
theme: this.#n,
|
|
413
452
|
region: { from: s.from, to: s.to, fill: n, color: r, label: s.label },
|
|
414
453
|
plotWidth: i,
|
|
415
454
|
plotHeight: e
|
|
@@ -428,24 +467,24 @@ class Ot extends st {
|
|
|
428
467
|
* legend.
|
|
429
468
|
*/
|
|
430
469
|
addLine(t) {
|
|
431
|
-
const i = `line_${++
|
|
432
|
-
return this.#
|
|
470
|
+
const i = `line_${++bt}`;
|
|
471
|
+
return this.#y.push(this.#dt(i, t)), this.#h.markDirty(), i;
|
|
433
472
|
}
|
|
434
473
|
/** Replace a reference line's config in place. No-op when the id is unknown. */
|
|
435
474
|
updateLine(t, i) {
|
|
436
|
-
const e = this.#
|
|
437
|
-
e !== -1 && (this.#
|
|
475
|
+
const e = this.#y.findIndex((s) => s.id === t);
|
|
476
|
+
e !== -1 && (this.#y[e] = this.#dt(t, i), this.#h.markDirty());
|
|
438
477
|
}
|
|
439
478
|
/** Remove a reference line by id. No-op when the id is unknown. */
|
|
440
479
|
removeLine(t) {
|
|
441
|
-
const i = this.#
|
|
442
|
-
i !== -1 && (this.#
|
|
480
|
+
const i = this.#y.findIndex((e) => e.id === t);
|
|
481
|
+
i !== -1 && (this.#y.splice(i, 1), this.#h.markDirty());
|
|
443
482
|
}
|
|
444
483
|
/** Read-only snapshot of the registered reference lines (normalized). Mutate via add / update / removeLine. */
|
|
445
484
|
getLines() {
|
|
446
|
-
return this.#
|
|
485
|
+
return this.#y;
|
|
447
486
|
}
|
|
448
|
-
#
|
|
487
|
+
#dt(t, i) {
|
|
449
488
|
const { time: e, value: s } = i, r = {
|
|
450
489
|
id: t,
|
|
451
490
|
color: i.color,
|
|
@@ -453,27 +492,32 @@ class Ot extends st {
|
|
|
453
492
|
style: i.style ?? "dashed",
|
|
454
493
|
width: i.width ?? 1
|
|
455
494
|
};
|
|
456
|
-
return e !== void 0 ? { ...r, orientation: "vertical", coord:
|
|
457
|
-
}
|
|
458
|
-
#
|
|
459
|
-
if (this.#
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
495
|
+
return e !== void 0 ? { ...r, orientation: "vertical", coord: y(e) } : { ...r, orientation: "horizontal", coord: s ?? Number.NaN };
|
|
496
|
+
}
|
|
497
|
+
#wt(t, i, e) {
|
|
498
|
+
if (this.#y.length === 0) return;
|
|
499
|
+
const s = this.#$();
|
|
500
|
+
for (const r of this.#y) {
|
|
501
|
+
const n = s >= 1 ? 1 : r.orientation === "vertical" ? this.#mt(s, r.coord) : L(s);
|
|
502
|
+
if (n <= 0) continue;
|
|
503
|
+
const h = t.context.globalAlpha;
|
|
504
|
+
n < 1 && (t.context.globalAlpha = h * n), st({
|
|
505
|
+
scope: t,
|
|
506
|
+
timeScale: this.timeScale,
|
|
507
|
+
yScale: this.yScale,
|
|
508
|
+
theme: this.#n,
|
|
509
|
+
line: {
|
|
510
|
+
orientation: r.orientation,
|
|
511
|
+
coord: r.coord,
|
|
512
|
+
color: r.color ?? this.#n.line.color,
|
|
513
|
+
style: r.style,
|
|
514
|
+
width: r.width,
|
|
515
|
+
label: r.label
|
|
516
|
+
},
|
|
517
|
+
plotWidth: i,
|
|
518
|
+
plotHeight: e
|
|
519
|
+
}), n < 1 && (t.context.globalAlpha = h);
|
|
520
|
+
}
|
|
477
521
|
}
|
|
478
522
|
/**
|
|
479
523
|
* Read-only snapshot of the chart's X / Y viewport animation. The same
|
|
@@ -482,7 +526,49 @@ class Ot extends st {
|
|
|
482
526
|
* underlying animator mutates between frames.
|
|
483
527
|
*/
|
|
484
528
|
getAnimationState() {
|
|
485
|
-
return this.#
|
|
529
|
+
return this.#s.getAnimationState();
|
|
530
|
+
}
|
|
531
|
+
/**
|
|
532
|
+
* Reveal-front position in `[0, 1]` of any in-flight initial-load intro.
|
|
533
|
+
* With a `seriesId`, that series' own front; without, the minimum across
|
|
534
|
+
* every visible time series — overlays wait for the slowest reveal. `1`
|
|
535
|
+
* whenever nothing is introing. Overlay components (the Y-label badge,
|
|
536
|
+
* annotations) read this to reveal their entrance in step with the draw.
|
|
537
|
+
*/
|
|
538
|
+
getIntroFront(t) {
|
|
539
|
+
if (t !== void 0)
|
|
540
|
+
return this.#t.find((e) => e.id === t)?.renderer.getIntroFront?.() ?? 1;
|
|
541
|
+
let i = 1;
|
|
542
|
+
for (const e of this.#t) {
|
|
543
|
+
if (!e.visible) continue;
|
|
544
|
+
const s = e.renderer.getIntroFront?.();
|
|
545
|
+
s !== void 0 && s < i && (i = s);
|
|
546
|
+
}
|
|
547
|
+
return i;
|
|
548
|
+
}
|
|
549
|
+
/**
|
|
550
|
+
* Reveal front for annotations (markers / reference lines). The same as
|
|
551
|
+
* {@link getIntroFront}() during the initial reveal, but latched to `1` once
|
|
552
|
+
* that first reveal has settled — so introducing another series afterward
|
|
553
|
+
* doesn't re-hide overlays that already surfaced. Latches only after an intro
|
|
554
|
+
* has actually been observed in progress, so an annotation drawn on a chart
|
|
555
|
+
* that has no data yet still rides the reveal once data arrives.
|
|
556
|
+
*/
|
|
557
|
+
#$() {
|
|
558
|
+
if (this.#it) return 1;
|
|
559
|
+
const t = this.getIntroFront();
|
|
560
|
+
return t < 1 ? (this.#tt = !0, t) : (this.#tt && (this.#it = !0), 1);
|
|
561
|
+
}
|
|
562
|
+
/**
|
|
563
|
+
* Entrance alpha for an overlay pinned at `time`, given the intro reveal
|
|
564
|
+
* `front`. Transparent until the sweep reaches the element's normalized X,
|
|
565
|
+
* then fades in over a short band — so annotations surface in step with the
|
|
566
|
+
* series drawing past them. `1` once the intro has settled.
|
|
567
|
+
*/
|
|
568
|
+
#mt(t, i) {
|
|
569
|
+
if (t >= 1) return 1;
|
|
570
|
+
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);
|
|
486
572
|
}
|
|
487
573
|
/**
|
|
488
574
|
* Replace all data for a series.
|
|
@@ -495,13 +581,32 @@ class Ot extends st {
|
|
|
495
581
|
*/
|
|
496
582
|
setSeriesData(t, i, e) {
|
|
497
583
|
const s = this.#t.find((r) => r.id === t);
|
|
498
|
-
s && (this
|
|
584
|
+
s && (this.#q = !0, s.renderer.setData(i, e));
|
|
499
585
|
}
|
|
500
586
|
/** Append a new data point to the end of a series (real-time tick). */
|
|
501
587
|
appendData(t, i, e) {
|
|
502
588
|
const s = this.#t.find((r) => r.id === t);
|
|
503
589
|
s === void 0 || s.renderer.appendPoint === void 0 || s.renderer.appendPoint(i, e);
|
|
504
590
|
}
|
|
591
|
+
/**
|
|
592
|
+
* Prepend older points to the front of a series — the "load more history on
|
|
593
|
+
* scroll" path. Unlike {@link setSeriesData}, this deliberately does NOT set
|
|
594
|
+
* `#dataReplaceSnapPending`: the visible window and the data inside it don't
|
|
595
|
+
* change, so the viewport must stay put (X) and the Y axis eases if newly
|
|
596
|
+
* revealed history shifts the range — instead of the full-span re-fit and
|
|
597
|
+
* instant dual-axis snap a bulk `setSeriesData` replace would force. Routes
|
|
598
|
+
* through the streaming `onPointAppended` engine signal via `onDataChanged`.
|
|
599
|
+
*
|
|
600
|
+
* `points` must be sorted ascending and sit strictly before the current
|
|
601
|
+
* first point; the sync reconciler guarantees this before calling here.
|
|
602
|
+
* No-op if the renderer doesn't support prepend.
|
|
603
|
+
*/
|
|
604
|
+
prependData(t, i, e) {
|
|
605
|
+
const s = this.#t.find((n) => n.id === t);
|
|
606
|
+
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);
|
|
609
|
+
}
|
|
505
610
|
/** Update the last data point of a series in place (e.g. live candle update). */
|
|
506
611
|
updateData(t, i, e) {
|
|
507
612
|
this.#t.find((s) => s.id === t)?.renderer.updateLastPoint?.(i, e);
|
|
@@ -526,29 +631,29 @@ class Ot extends st {
|
|
|
526
631
|
updateSeriesOptions(t, i) {
|
|
527
632
|
const e = this.#t.find((o) => o.id === t);
|
|
528
633
|
if (!e) return;
|
|
529
|
-
const s = e.labels, r = e.renderer.getLayerColors().slice(), n = this.#
|
|
530
|
-
e.renderer.updateOptions({ ...i, ...n }), "label" in i && typeof i.label == "string" && (e.labels = [i.label]), this.#
|
|
531
|
-
const
|
|
532
|
-
(
|
|
634
|
+
const s = e.labels, r = e.renderer.getLayerColors().slice(), n = this.#g.overrides(e.renderer.kind);
|
|
635
|
+
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();
|
|
533
638
|
}
|
|
534
639
|
/**
|
|
535
640
|
* Batch multiple updates: suppress recomputes until `fn` returns. Exceptions
|
|
536
641
|
* inside `fn` still flush the batch so counters don't leak across calls.
|
|
537
642
|
*/
|
|
538
643
|
batch(t) {
|
|
539
|
-
this.#
|
|
644
|
+
this.#A++;
|
|
540
645
|
try {
|
|
541
646
|
t();
|
|
542
647
|
} finally {
|
|
543
|
-
if (--this.#
|
|
544
|
-
if (this.#
|
|
545
|
-
this.#
|
|
546
|
-
else if (this.#
|
|
547
|
-
this.#
|
|
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;
|
|
548
653
|
const i = performance.now();
|
|
549
|
-
this.#
|
|
654
|
+
this.#s.onAxisReconfig(i), this.#v(i), this.#e.markDirty();
|
|
550
655
|
}
|
|
551
|
-
this.#
|
|
656
|
+
this.#Z && (this.#Z = !1, this.emit("overlayChange"));
|
|
552
657
|
}
|
|
553
658
|
}
|
|
554
659
|
}
|
|
@@ -562,15 +667,15 @@ class Ot extends st {
|
|
|
562
667
|
setSeriesVisible(t, i) {
|
|
563
668
|
const e = this.#t.find((n) => n.id === t);
|
|
564
669
|
if (!e || e.visible === i) return;
|
|
565
|
-
e.visible = i, this.#
|
|
566
|
-
const s = this.#
|
|
567
|
-
if (e.renderer.setAlpha?.(i ? 1 : 0, s), this.#
|
|
568
|
-
this.#
|
|
670
|
+
e.visible = i, this.#p();
|
|
671
|
+
const s = this.#g.toggleMs;
|
|
672
|
+
if (e.renderer.setAlpha?.(i ? 1 : 0, s), this.#e.markDirty(), this.#A > 0) {
|
|
673
|
+
this.#M = !0;
|
|
569
674
|
return;
|
|
570
675
|
}
|
|
571
|
-
this.#
|
|
676
|
+
this.#f = !0;
|
|
572
677
|
const r = performance.now();
|
|
573
|
-
this.#
|
|
678
|
+
this.#s.onSeriesVisibilityChanged(r), this.#v(r);
|
|
574
679
|
}
|
|
575
680
|
/**
|
|
576
681
|
* Whether streaming ticks slide the visible range to track the data tail.
|
|
@@ -580,7 +685,7 @@ class Ot extends st {
|
|
|
580
685
|
* containing the tail.
|
|
581
686
|
*/
|
|
582
687
|
getAutoScroll() {
|
|
583
|
-
return this.#
|
|
688
|
+
return this.#u;
|
|
584
689
|
}
|
|
585
690
|
isSeriesVisible(t) {
|
|
586
691
|
return this.#t.find((i) => i.id === t)?.visible ?? !0;
|
|
@@ -596,17 +701,17 @@ class Ot extends st {
|
|
|
596
701
|
* layer's geometry on screen until the engine's Y ease settles.
|
|
597
702
|
*/
|
|
598
703
|
setLayerVisible(t, i, e) {
|
|
599
|
-
const s = this.#t.find((
|
|
704
|
+
const s = this.#t.find((h) => h.id === t);
|
|
600
705
|
if (!s || s.renderer.getLayerCount() <= 1 || s.renderer.isLayerVisible(i) === e) return;
|
|
601
|
-
s.renderer.setLayerVisible(i, e), this.#
|
|
602
|
-
const r = this.#
|
|
603
|
-
if (s.renderer.setLayerAlpha?.(i, e ? 1 : 0, r), this.#
|
|
604
|
-
this.#
|
|
706
|
+
s.renderer.setLayerVisible(i, e), this.#p();
|
|
707
|
+
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;
|
|
605
710
|
return;
|
|
606
711
|
}
|
|
607
|
-
this.#
|
|
712
|
+
this.#f = !0;
|
|
608
713
|
const n = performance.now();
|
|
609
|
-
this.#
|
|
714
|
+
this.#s.onSeriesVisibilityChanged(n), this.#v(n);
|
|
610
715
|
}
|
|
611
716
|
isLayerVisible(t, i) {
|
|
612
717
|
return this.#t.find((e) => e.id === t)?.renderer.isLayerVisible(i) ?? !0;
|
|
@@ -615,11 +720,11 @@ class Ot extends st {
|
|
|
615
720
|
fitContent() {
|
|
616
721
|
const { first: t, last: i } = this.getDataBounds();
|
|
617
722
|
if (t === void 0 || i === void 0) return;
|
|
618
|
-
const e = this.#
|
|
619
|
-
this.#
|
|
723
|
+
const e = this.#a.size.media.width - this.yAxisWidth;
|
|
724
|
+
this.#P(t, i, e), this.#W({ xEase: !0 });
|
|
620
725
|
}
|
|
621
726
|
getVisibleRange() {
|
|
622
|
-
return this.#o.from === 0 && this.#o.to === 0 ? this.#
|
|
727
|
+
return this.#o.from === 0 && this.#o.to === 0 ? this.#s.getAnimationState().xRange : this.#o;
|
|
623
728
|
}
|
|
624
729
|
/**
|
|
625
730
|
* Return the full span of registered data, or `null` before any data has
|
|
@@ -627,7 +732,7 @@ class Ot extends st {
|
|
|
627
732
|
* tracking and is cheaper than recomputing from series stores.
|
|
628
733
|
*/
|
|
629
734
|
getDataRange() {
|
|
630
|
-
return this.#k === null || this.#
|
|
735
|
+
return this.#k === null || this.#i === null ? null : { from: this.#k, to: this.#i };
|
|
631
736
|
}
|
|
632
737
|
/**
|
|
633
738
|
* Imperatively set the visible time range. Three forms:
|
|
@@ -656,29 +761,29 @@ class Ot extends st {
|
|
|
656
761
|
setVisibleRange(t, i) {
|
|
657
762
|
if (typeof t == "number") {
|
|
658
763
|
if (!Number.isInteger(t) || t < 2) return;
|
|
659
|
-
const { first: n, last:
|
|
660
|
-
if (n === void 0 ||
|
|
661
|
-
const
|
|
662
|
-
this.#
|
|
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();
|
|
663
768
|
return;
|
|
664
769
|
}
|
|
665
770
|
if ("bars" in t) {
|
|
666
771
|
if (!Number.isInteger(t.bars) || t.bars < 2) return;
|
|
667
|
-
const n =
|
|
668
|
-
this.#
|
|
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();
|
|
669
774
|
return;
|
|
670
775
|
}
|
|
671
|
-
const e =
|
|
672
|
-
this.#
|
|
673
|
-
const r = this.#
|
|
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 });
|
|
674
779
|
if (i?.gesture) {
|
|
675
|
-
r && this.#
|
|
780
|
+
r && this.#Mt();
|
|
676
781
|
return;
|
|
677
782
|
}
|
|
678
|
-
this.#
|
|
783
|
+
this.#W();
|
|
679
784
|
}
|
|
680
785
|
getYRange() {
|
|
681
|
-
return this.#
|
|
786
|
+
return this.#F;
|
|
682
787
|
}
|
|
683
788
|
getCrosshairPosition() {
|
|
684
789
|
return this.#d;
|
|
@@ -719,7 +824,7 @@ class Ot extends st {
|
|
|
719
824
|
setCrosshair(t) {
|
|
720
825
|
if (t === null) {
|
|
721
826
|
if (this.#d === null) return;
|
|
722
|
-
this.#d = null, this.#
|
|
827
|
+
this.#d = null, this.#h.markDirty(), this.emit("crosshairMove", null);
|
|
723
828
|
return;
|
|
724
829
|
}
|
|
725
830
|
const { time: i } = t;
|
|
@@ -731,29 +836,29 @@ class Ot extends st {
|
|
|
731
836
|
else if (e !== null)
|
|
732
837
|
s = e.y;
|
|
733
838
|
else {
|
|
734
|
-
const
|
|
735
|
-
s = (
|
|
839
|
+
const h = this.#F;
|
|
840
|
+
s = (h.min + h.max) / 2;
|
|
736
841
|
}
|
|
737
842
|
if (!Number.isFinite(s) || e !== null && e.time === i && e.y === s) return;
|
|
738
843
|
const r = this.timeScale.timeToX(i), n = this.yScale.valueToY(s);
|
|
739
|
-
this.#
|
|
844
|
+
this.#Y = "time", this.#d = { mediaX: r, mediaY: n, time: i, y: s }, this.#h.markDirty(), this.emit("crosshairMove", this.#d);
|
|
740
845
|
}
|
|
741
846
|
/** Get the last visible value and whether the absolute last point is on screen. */
|
|
742
847
|
getLastValue(t) {
|
|
743
|
-
return
|
|
848
|
+
return Z(t, this.#t, this.#s.getAnimationState().xRange);
|
|
744
849
|
}
|
|
745
850
|
/** Get the second-to-last value, useful for computing change. */
|
|
746
851
|
getPreviousClose(t) {
|
|
747
|
-
return
|
|
852
|
+
return _(t, this.#t);
|
|
748
853
|
}
|
|
749
854
|
getLastData(t) {
|
|
750
855
|
const i = this.#t.find((e) => e.id === t);
|
|
751
|
-
return !i || i.renderer
|
|
856
|
+
return !i || !S(i.renderer) ? null : i.renderer.getLastDataPoint();
|
|
752
857
|
}
|
|
753
858
|
/** Find the data point closest to the given timestamp within one data interval. */
|
|
754
859
|
getDataAtTime(t, i) {
|
|
755
860
|
const e = this.#t.find((s) => s.id === t);
|
|
756
|
-
return e ? e.renderer.getDataAtTime?.(i, this.#
|
|
861
|
+
return e ? e.renderer.getDataAtTime?.(i, this.#r) ?? null : null;
|
|
757
862
|
}
|
|
758
863
|
/**
|
|
759
864
|
* Get all layers' data at a given time for multi-layer series (Bar/Line
|
|
@@ -763,25 +868,28 @@ class Ot extends st {
|
|
|
763
868
|
*/
|
|
764
869
|
getLayerSnapshots(t, i) {
|
|
765
870
|
const e = this.#t.find((s) => s.id === t);
|
|
766
|
-
return e?.visible ? e.renderer.getLayerSnapshots?.(i, this.#
|
|
871
|
+
return e?.visible ? e.renderer.getLayerSnapshots?.(i, this.#r) ?? null : null;
|
|
767
872
|
}
|
|
768
873
|
getSeriesIds() {
|
|
769
|
-
return this.#
|
|
874
|
+
return this.#T || (this.#T = this.#t.map((t) => t.id)), this.#T.slice();
|
|
770
875
|
}
|
|
771
876
|
/**
|
|
772
|
-
* True if any visible series
|
|
773
|
-
* to gate crosshair rendering — a
|
|
774
|
-
* coordinate system, so the dashed hairlines would
|
|
877
|
+
* True if any visible series has a time axis (line / bar / candlestick).
|
|
878
|
+
* Used to gate crosshair rendering — a spatial-only chart (pie, heatmap)
|
|
879
|
+
* has no meaningful x/y coordinate system, so the dashed hairlines would
|
|
880
|
+
* just be visual noise.
|
|
775
881
|
*/
|
|
776
|
-
#
|
|
882
|
+
#Tt() {
|
|
777
883
|
for (const t of this.#t)
|
|
778
|
-
if (t.visible && t.renderer
|
|
884
|
+
if (t.visible && S(t.renderer))
|
|
779
885
|
return !0;
|
|
780
886
|
return !1;
|
|
781
887
|
}
|
|
782
888
|
/**
|
|
783
|
-
* Filter `getSeriesIds()` by renderer type. `'pie'
|
|
784
|
-
* `'
|
|
889
|
+
* Filter `getSeriesIds()` by renderer type. A concrete kind (`'pie'`,
|
|
890
|
+
* `'heatmap'`, a custom kind, …) returns series of that exact kind;
|
|
891
|
+
* `'time'` returns every time-axis series (line/bar/candlestick and any
|
|
892
|
+
* custom time-series kind).
|
|
785
893
|
*
|
|
786
894
|
* - `opts.visibleOnly` — exclude series with `isSeriesVisible=false`; for
|
|
787
895
|
* multi-layer series also exclude when every layer is hidden.
|
|
@@ -791,20 +899,19 @@ class Ot extends st {
|
|
|
791
899
|
getSeriesIdsByType(t, i) {
|
|
792
900
|
const e = i?.visibleOnly === !0, s = i?.singleLayerOnly === !0, r = [];
|
|
793
901
|
for (const n of this.#t) {
|
|
794
|
-
|
|
795
|
-
if (t === "pie" && !a || t === "time" && a) continue;
|
|
902
|
+
if (!(t === "time" ? S(n.renderer) : n.renderer.kind === t)) continue;
|
|
796
903
|
const h = n.renderer.getLayerCount();
|
|
797
904
|
if (!(s && h > 1)) {
|
|
798
905
|
if (e) {
|
|
799
906
|
if (!n.visible) continue;
|
|
800
907
|
if (h > 1) {
|
|
801
|
-
let
|
|
802
|
-
for (let
|
|
803
|
-
if (n.renderer.isLayerVisible(
|
|
804
|
-
|
|
908
|
+
let a = !1;
|
|
909
|
+
for (let l = 0; l < h; l++)
|
|
910
|
+
if (n.renderer.isLayerVisible(l)) {
|
|
911
|
+
a = !0;
|
|
805
912
|
break;
|
|
806
913
|
}
|
|
807
|
-
if (!
|
|
914
|
+
if (!a) continue;
|
|
808
915
|
}
|
|
809
916
|
}
|
|
810
917
|
r.push(n.id);
|
|
@@ -819,7 +926,22 @@ class Ot extends st {
|
|
|
819
926
|
* Returns `null` for unknown ids or empty series.
|
|
820
927
|
*/
|
|
821
928
|
getStackedLastValue(t) {
|
|
822
|
-
return
|
|
929
|
+
return U(t, this.#t, this.#s.getAnimationState().xRange);
|
|
930
|
+
}
|
|
931
|
+
/**
|
|
932
|
+
* Stacked value at an arbitrary `time` — the cumulative stack top at that
|
|
933
|
+
* sample, sharing a basis with {@link getStackedLastValue}. Falls back to the
|
|
934
|
+
* nearest raw sample (close / value) for renderers without a stacked concept
|
|
935
|
+
* (Candlestick, single-layer Line/Bar). Returns `null` for unknown ids or
|
|
936
|
+
* when no sample sits near `time`. Used by the YLabel intro count-up start.
|
|
937
|
+
*/
|
|
938
|
+
getStackedValueAtTime(t, i) {
|
|
939
|
+
const e = this.#t.find((n) => n.id === t);
|
|
940
|
+
if (!e) return null;
|
|
941
|
+
const s = e.renderer.getStackedValueAtTime?.(i, this.#r);
|
|
942
|
+
if (s != null) return s;
|
|
943
|
+
const r = e.renderer.getDataAtTime?.(i, this.#r);
|
|
944
|
+
return r ? "close" in r ? r.close : r.value : null;
|
|
823
945
|
}
|
|
824
946
|
/**
|
|
825
947
|
* Per-layer last snapshots with each layer's own `time`. Returns `null`
|
|
@@ -843,7 +965,7 @@ class Ot extends st {
|
|
|
843
965
|
/** Get the primary display color for a series. */
|
|
844
966
|
getSeriesColor(t) {
|
|
845
967
|
const i = this.#t.find((e) => e.id === t);
|
|
846
|
-
return i ? i.renderer.getLayerColors()[0] ?? this.#
|
|
968
|
+
return i ? i.renderer.getLayerColors()[0] ?? this.#n.line.color : null;
|
|
847
969
|
}
|
|
848
970
|
/** The series' primary name (first layer). Used for single-layer overlays. */
|
|
849
971
|
getSeriesLabel(t) {
|
|
@@ -861,7 +983,7 @@ class Ot extends st {
|
|
|
861
983
|
*/
|
|
862
984
|
setSeriesLabels(t, i) {
|
|
863
985
|
const e = this.#t.find((s) => s.id === t);
|
|
864
|
-
!e ||
|
|
986
|
+
!e || H(e.labels, i) || (e.labels = i, this.#p());
|
|
865
987
|
}
|
|
866
988
|
/**
|
|
867
989
|
* Set the per-layer color overrides carried in `data` (sparse — `undefined`
|
|
@@ -872,7 +994,7 @@ class Ot extends st {
|
|
|
872
994
|
*/
|
|
873
995
|
setLayerColors(t, i) {
|
|
874
996
|
const e = this.#t.find((s) => s.id === t);
|
|
875
|
-
!e ||
|
|
997
|
+
!e || St(e.colorOverrides, i) || (e.colorOverrides = i, e.renderer.setColorOverrides?.(i), this.#e.markDirty(), this.#p());
|
|
876
998
|
}
|
|
877
999
|
/** Get per-layer colors for a series. Returns null for single-layer non-bar/line series. */
|
|
878
1000
|
getSeriesLayers(t) {
|
|
@@ -885,29 +1007,43 @@ class Ot extends st {
|
|
|
885
1007
|
}
|
|
886
1008
|
/** Get all slices with computed colors and percentages. Returns null for series without slice data (e.g. candlestick, line, bar). */
|
|
887
1009
|
getSliceInfo(t) {
|
|
888
|
-
return this.#t.find((i) => i.id === t)?.renderer.getSliceInfo?.(this.#
|
|
1010
|
+
return this.#t.find((i) => i.id === t)?.renderer.getSliceInfo?.(this.#n) ?? null;
|
|
889
1011
|
}
|
|
890
1012
|
/** Get hover info (label/value/percent/color) for the currently hovered element, or null. */
|
|
891
1013
|
getHoverInfo(t) {
|
|
892
|
-
return this.#t.find((i) => i.id === t)?.renderer.getHoverInfo?.(this.#
|
|
1014
|
+
return this.#t.find((i) => i.id === t)?.renderer.getHoverInfo?.(this.#n) ?? null;
|
|
893
1015
|
}
|
|
894
1016
|
/** Apply a new theme and update series colors where appropriate. */
|
|
895
1017
|
setTheme(t) {
|
|
896
|
-
const i = this.#
|
|
897
|
-
this.#
|
|
1018
|
+
const i = this.#n;
|
|
1019
|
+
this.#n = t;
|
|
898
1020
|
for (const e of this.#t)
|
|
899
1021
|
e.renderer.applyTheme(t, i);
|
|
900
|
-
this.#
|
|
1022
|
+
this.#e.markDirty(), this.#p();
|
|
901
1023
|
}
|
|
902
1024
|
getTheme() {
|
|
903
|
-
return this.#
|
|
1025
|
+
return this.#n;
|
|
1026
|
+
}
|
|
1027
|
+
/** BCP 47 locale applied to the built-in time-axis / tooltip / crosshair formatting. */
|
|
1028
|
+
setLocale(t) {
|
|
1029
|
+
this.timeScale.setLocale(t), this.#p();
|
|
1030
|
+
}
|
|
1031
|
+
getLocale() {
|
|
1032
|
+
return this.timeScale.getLocale();
|
|
1033
|
+
}
|
|
1034
|
+
/** IANA timezone applied to the same built-in date-time formatting. */
|
|
1035
|
+
setTimeZone(t) {
|
|
1036
|
+
this.timeScale.setTimeZone(t), this.#p();
|
|
1037
|
+
}
|
|
1038
|
+
getTimeZone() {
|
|
1039
|
+
return this.timeScale.getTimeZone();
|
|
904
1040
|
}
|
|
905
1041
|
/** Update axis configuration and re-render. */
|
|
906
1042
|
setAxis(t) {
|
|
907
1043
|
const i = this.yAxisWidth, e = this.xAxisHeight;
|
|
908
|
-
this.#
|
|
1044
|
+
this.#H = t, this.#l = { min: t.y?.min, max: t.y?.max }, this.#f = !0;
|
|
909
1045
|
const s = performance.now();
|
|
910
|
-
this.#
|
|
1046
|
+
this.#s.onAxisReconfig(s), this.#v(s), (this.yAxisWidth !== i || this.xAxisHeight !== e) && this.syncScales(), this.#e.markDirty();
|
|
911
1047
|
}
|
|
912
1048
|
/**
|
|
913
1049
|
* Apply label-density knobs driven by `<YAxis labelCount=… minLabelSpacing=…>`
|
|
@@ -917,19 +1053,19 @@ class Ot extends st {
|
|
|
917
1053
|
*/
|
|
918
1054
|
setYAxisLabelDensity(t) {
|
|
919
1055
|
let i = !1;
|
|
920
|
-
"labelCount" in t && (this.yScale.setLabelCount(t.labelCount ?? null), i = !0), "minLabelSpacing" in t && (this.yScale.setMinSpacing(t.minLabelSpacing ?? null), i = !0), i && (this.syncScales(), this.emit("viewportChange"), this.#
|
|
1056
|
+
"labelCount" in t && (this.yScale.setLabelCount(t.labelCount ?? null), i = !0), "minLabelSpacing" in t && (this.yScale.setMinSpacing(t.minLabelSpacing ?? null), i = !0), i && (this.syncScales(), this.emit("viewportChange"), this.#e.markDirty());
|
|
921
1057
|
}
|
|
922
1058
|
/** Label-density knobs for the time axis — mirror of {@link setYAxisLabelDensity}. */
|
|
923
1059
|
setTimeAxisLabelDensity(t) {
|
|
924
1060
|
let i = !1;
|
|
925
|
-
"labelCount" in t && (this.timeScale.setLabelCount(t.labelCount ?? null), i = !0), "minLabelSpacing" in t && (this.timeScale.setMinSpacing(t.minLabelSpacing ?? null), i = !0), i && (this.syncScales(), this.emit("viewportChange"), this.#
|
|
1061
|
+
"labelCount" in t && (this.timeScale.setLabelCount(t.labelCount ?? null), i = !0), "minLabelSpacing" in t && (this.timeScale.setMinSpacing(t.minLabelSpacing ?? null), i = !0), i && (this.syncScales(), this.emit("viewportChange"), this.#e.markDirty());
|
|
926
1062
|
}
|
|
927
1063
|
getMediaSize() {
|
|
928
|
-
return this.#
|
|
1064
|
+
return this.#a.size.media;
|
|
929
1065
|
}
|
|
930
1066
|
/** Returns layout metrics for the chart area, Y axis, and time axis. */
|
|
931
1067
|
getLayout() {
|
|
932
|
-
const t = this.#
|
|
1068
|
+
const t = this.#a.size.media, i = this.yAxisWidth, e = this.xAxisHeight;
|
|
933
1069
|
return {
|
|
934
1070
|
chartArea: { x: 0, y: 0, width: t.width - i, height: t.height - e },
|
|
935
1071
|
yAxisWidth: i,
|
|
@@ -937,7 +1073,7 @@ class Ot extends st {
|
|
|
937
1073
|
};
|
|
938
1074
|
}
|
|
939
1075
|
getDataInterval() {
|
|
940
|
-
return this.#
|
|
1076
|
+
return this.#r;
|
|
941
1077
|
}
|
|
942
1078
|
/**
|
|
943
1079
|
* Update viewport padding at runtime. Refits the visible time range to
|
|
@@ -949,25 +1085,25 @@ class Ot extends st {
|
|
|
949
1085
|
*/
|
|
950
1086
|
setPadding(t) {
|
|
951
1087
|
const i = this.#c;
|
|
952
|
-
this.#c =
|
|
953
|
-
const e = this.#c, s = !
|
|
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;
|
|
954
1090
|
if (s) {
|
|
955
|
-
const { first: n, last:
|
|
956
|
-
if (n !== void 0 &&
|
|
957
|
-
const
|
|
958
|
-
this.#
|
|
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);
|
|
959
1095
|
}
|
|
960
1096
|
}
|
|
961
1097
|
if (s || r) {
|
|
962
|
-
this.#
|
|
1098
|
+
this.#f = !0;
|
|
963
1099
|
const n = performance.now();
|
|
964
|
-
this.#
|
|
1100
|
+
this.#s.onAxisReconfig(n), this.#v(n);
|
|
965
1101
|
}
|
|
966
|
-
this.syncScales(), this.#
|
|
1102
|
+
this.syncScales(), this.#e.markDirty(), r && this.emit("viewportChange");
|
|
967
1103
|
}
|
|
968
1104
|
/** Show or hide the background grid. Takes effect on the next render frame. */
|
|
969
1105
|
setGrid(t) {
|
|
970
|
-
this.#
|
|
1106
|
+
this.#O = t.visible, this.#e.markDirty();
|
|
971
1107
|
}
|
|
972
1108
|
/**
|
|
973
1109
|
* Set the visual state for one side of the chart. Typically called in
|
|
@@ -979,11 +1115,61 @@ class Ot extends st {
|
|
|
979
1115
|
* symmetry and currently renders identically to `idle`.
|
|
980
1116
|
*/
|
|
981
1117
|
setEdgeState(t, i) {
|
|
982
|
-
|
|
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();
|
|
983
1121
|
}
|
|
984
1122
|
/** Read the current host-declared state for a given edge. */
|
|
985
1123
|
getEdgeState(t) {
|
|
986
|
-
return this.#
|
|
1124
|
+
return this.#S[t];
|
|
1125
|
+
}
|
|
1126
|
+
/**
|
|
1127
|
+
* Alpha for a side's `loading` exit fade, or `null` when none is in
|
|
1128
|
+
* flight. Self-cleaning: an elapsed fade clears its start stamp.
|
|
1129
|
+
*/
|
|
1130
|
+
#ut(t) {
|
|
1131
|
+
const i = this.#V[t];
|
|
1132
|
+
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));
|
|
1135
|
+
}
|
|
1136
|
+
/**
|
|
1137
|
+
* Swap the painter used for a side's `loading` spinner — the same
|
|
1138
|
+
* pluggable-function contract as the series intro animations. `null`
|
|
1139
|
+
* (default) falls back to the built-in three-dot spinner. Takes effect
|
|
1140
|
+
* immediately if that side is currently in the `loading` state.
|
|
1141
|
+
*/
|
|
1142
|
+
setEdgeIndicator(t, i) {
|
|
1143
|
+
this.#nt[t] = i, this.#S[t] === "loading" && this.#h.markDirty();
|
|
1144
|
+
}
|
|
1145
|
+
/**
|
|
1146
|
+
* Resolve the boundary point's Y position and series kind on the primary
|
|
1147
|
+
* visible time series, for a custom edge indicator that wants to start
|
|
1148
|
+
* exactly where the real chart leaves off and match its shape (candle vs.
|
|
1149
|
+
* plain bar/line). `left` continues from the first visible candle's
|
|
1150
|
+
* `open` (the value immediately preceding the boundary); `right` from the
|
|
1151
|
+
* last visible candle's `close`.
|
|
1152
|
+
*/
|
|
1153
|
+
#Dt(t, i) {
|
|
1154
|
+
const e = this.getSeriesIdsByType("time", { visibleOnly: !0, singleLayerOnly: !0 })[0] ?? this.getSeriesIdsByType("time", { visibleOnly: !0 })[0];
|
|
1155
|
+
if (!e) return null;
|
|
1156
|
+
const s = this.getDataAtTime(e, i);
|
|
1157
|
+
if (!s) return null;
|
|
1158
|
+
const r = this.#t.find((n) => n.id === e);
|
|
1159
|
+
return r ? {
|
|
1160
|
+
valueY: this.yScale.valueToY(O(t, s)),
|
|
1161
|
+
seriesKind: r.renderer.kind
|
|
1162
|
+
} : null;
|
|
1163
|
+
}
|
|
1164
|
+
/**
|
|
1165
|
+
* Resolve the media-pixel spacing between adjacent bars at the chart's
|
|
1166
|
+
* current zoom level, for a custom edge indicator that wants to size its
|
|
1167
|
+
* placeholder shapes to match the real bars that will render once data
|
|
1168
|
+
* lands. `null` when the viewport has no meaningful span yet.
|
|
1169
|
+
*/
|
|
1170
|
+
#Lt() {
|
|
1171
|
+
const t = this.timeScale.barWidthMedia(this.#r);
|
|
1172
|
+
return Number.isFinite(t) && t > 0 ? t : null;
|
|
987
1173
|
}
|
|
988
1174
|
/**
|
|
989
1175
|
* Notify chart that a YLabel overlay is mounted / unmounted. Currently a
|
|
@@ -995,24 +1181,46 @@ class Ot extends st {
|
|
|
995
1181
|
}
|
|
996
1182
|
/**
|
|
997
1183
|
* Dispatch a crosshair move to every renderer that supports spatial hover
|
|
998
|
-
* (
|
|
1184
|
+
* (pie, heatmap — anything implementing hitTest/setHoverIndex). Any change
|
|
1185
|
+
* in hover index schedules a main-layer redraw. Keep this loop capability-
|
|
1186
|
+
* probed, not kind-gated: a kind check here silently kills hover for the
|
|
1187
|
+
* next spatial renderer.
|
|
999
1188
|
*/
|
|
1000
|
-
#
|
|
1001
|
-
const i = this.#
|
|
1189
|
+
#G(t) {
|
|
1190
|
+
const i = this.#a.size, e = this.#c, s = {
|
|
1002
1191
|
top: e.top * i.verticalPixelRatio,
|
|
1003
1192
|
bottom: e.bottom * i.verticalPixelRatio
|
|
1004
1193
|
};
|
|
1005
|
-
let r = !1;
|
|
1006
|
-
for (const
|
|
1007
|
-
if (!
|
|
1194
|
+
let r = !1, n = null;
|
|
1195
|
+
for (const h of this.#t) {
|
|
1196
|
+
if (!h.renderer.hitTest || !h.renderer.setHoverIndex) continue;
|
|
1008
1197
|
let a = -1;
|
|
1009
1198
|
if (t) {
|
|
1010
|
-
const
|
|
1011
|
-
a =
|
|
1199
|
+
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);
|
|
1012
1201
|
}
|
|
1013
|
-
|
|
1202
|
+
h.renderer.setHoverIndex(a) && (r = !0), a >= 0 && !n && (n = { seriesId: h.id, index: a, info: h.renderer.getHoverInfo?.(this.#n) ?? null });
|
|
1203
|
+
}
|
|
1204
|
+
r && (this.#e.markDirty(), this.emit("seriesHover", n));
|
|
1205
|
+
}
|
|
1206
|
+
/**
|
|
1207
|
+
* Read-only counterpart to {@link #updateHover} for `pointClick` — same
|
|
1208
|
+
* capability-probed `hitTest` scan, but doesn't touch `setHoverIndex` (a
|
|
1209
|
+
* click shouldn't move the hover state the last pointer move already set).
|
|
1210
|
+
* Returns the first spatial series (pie, heatmap, or a custom spatial kind)
|
|
1211
|
+
* whose `hitTest` claims the position, or `null` if none does.
|
|
1212
|
+
*/
|
|
1213
|
+
#ft(t) {
|
|
1214
|
+
const i = this.#a.size, e = this.#c, s = {
|
|
1215
|
+
top: e.top * i.verticalPixelRatio,
|
|
1216
|
+
bottom: e.bottom * i.verticalPixelRatio
|
|
1217
|
+
}, 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 };
|
|
1014
1222
|
}
|
|
1015
|
-
|
|
1223
|
+
return null;
|
|
1016
1224
|
}
|
|
1017
1225
|
/**
|
|
1018
1226
|
* Re-derive the crosshair after the viewport moved beneath it. A streaming
|
|
@@ -1034,40 +1242,40 @@ class Ot extends st {
|
|
|
1034
1242
|
* viewport didn't move, the re-derived values are bit-identical and the
|
|
1035
1243
|
* method exits without emitting.
|
|
1036
1244
|
*/
|
|
1037
|
-
#
|
|
1245
|
+
#Ct() {
|
|
1038
1246
|
const t = this.#d;
|
|
1039
1247
|
if (t === null) return;
|
|
1040
|
-
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,
|
|
1041
|
-
let
|
|
1042
|
-
if (this.#
|
|
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") {
|
|
1043
1251
|
const l = this.timeScale.xToTime(t.mediaX), o = this.yScale.yToValue(t.mediaY);
|
|
1044
1252
|
if (!Number.isFinite(l) || !Number.isFinite(o) || Math.abs(l - t.time) <= r && Math.abs(o - t.y) <= n) return;
|
|
1045
|
-
|
|
1253
|
+
a = { mediaX: t.mediaX, mediaY: t.mediaY, time: l, y: o };
|
|
1046
1254
|
} else {
|
|
1047
1255
|
if (t.time < i || t.time > e) {
|
|
1048
|
-
this.#d = null, this.#
|
|
1256
|
+
this.#d = null, this.#h.markDirty(), this.emit("crosshairMove", null), this.#G(null);
|
|
1049
1257
|
return;
|
|
1050
1258
|
}
|
|
1051
1259
|
const l = this.timeScale.timeToX(t.time), o = this.yScale.valueToY(t.y);
|
|
1052
|
-
if (!Number.isFinite(l) || !Number.isFinite(o) || Math.abs(l - t.mediaX) <=
|
|
1053
|
-
|
|
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 };
|
|
1054
1262
|
}
|
|
1055
|
-
this.#d =
|
|
1263
|
+
this.#d = a, this.#h.markDirty(), this.emit("crosshairMove", a), this.#G(a);
|
|
1056
1264
|
}
|
|
1057
1265
|
/** Tear down the chart: cancel animations, remove listeners, and detach the canvas. */
|
|
1058
1266
|
destroy() {
|
|
1059
1267
|
for (const t of this.#t) t.renderer.dispose();
|
|
1060
|
-
this.#t = [], this.#m = [], this.#
|
|
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();
|
|
1061
1269
|
}
|
|
1062
1270
|
/** The attached performance monitor, or `null` when instrumentation is disabled. */
|
|
1063
1271
|
getPerfMonitor() {
|
|
1064
|
-
return this.#
|
|
1272
|
+
return this.#x;
|
|
1065
1273
|
}
|
|
1066
1274
|
/** Compute the earliest and latest timestamps across all series. */
|
|
1067
1275
|
getDataBounds() {
|
|
1068
1276
|
let t, i;
|
|
1069
1277
|
for (const e of this.#t) {
|
|
1070
|
-
if (!e.visible || e.renderer
|
|
1278
|
+
if (!e.visible || !S(e.renderer)) continue;
|
|
1071
1279
|
const s = e.renderer.getTimeBounds();
|
|
1072
1280
|
s !== null && ((t === void 0 || s.first < t) && (t = s.first), (i === void 0 || s.last > i) && (i = s.last));
|
|
1073
1281
|
}
|
|
@@ -1076,28 +1284,28 @@ class Ot extends st {
|
|
|
1076
1284
|
/** Set by `setSeriesData`/bulk-replace paths so the next `onDataChanged`
|
|
1077
1285
|
* snaps the Y range (instead of easing) and `yScale.getRange()` reflects
|
|
1078
1286
|
* the new domain synchronously. Cleared by `onDataChanged` after each run. */
|
|
1079
|
-
|
|
1287
|
+
#q = !1;
|
|
1080
1288
|
onDataChanged() {
|
|
1081
|
-
if (this.#
|
|
1082
|
-
this.#
|
|
1289
|
+
if (this.#A > 0) {
|
|
1290
|
+
this.#X = !0;
|
|
1083
1291
|
return;
|
|
1084
1292
|
}
|
|
1085
1293
|
this.updateDataInterval();
|
|
1086
1294
|
const { first: t, last: i } = this.getDataBounds();
|
|
1087
|
-
t !== void 0 && (this.#k = t), i !== void 0 && (this.#
|
|
1088
|
-
const e = this
|
|
1089
|
-
this
|
|
1090
|
-
const s = !this.#
|
|
1091
|
-
e && (this.yScale.tickTracker.reset(), this.timeScale.tickTracker.reset()), this.#
|
|
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;
|
|
1298
|
+
const s = !this.#f && t !== void 0;
|
|
1299
|
+
e && (this.yScale.tickTracker.reset(), this.timeScale.tickTracker.reset()), this.#ht = e;
|
|
1092
1300
|
const r = performance.now();
|
|
1093
|
-
e || s ? (this.#D.seed(r), this.#
|
|
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();
|
|
1094
1302
|
}
|
|
1095
1303
|
updateDataInterval() {
|
|
1096
1304
|
for (const t of this.#t) {
|
|
1097
|
-
if (t.renderer
|
|
1305
|
+
if (!S(t.renderer)) continue;
|
|
1098
1306
|
const i = t.renderer.sampleTimes(20);
|
|
1099
1307
|
if (i.length >= 2) {
|
|
1100
|
-
this.#
|
|
1308
|
+
this.#r = ut(i);
|
|
1101
1309
|
break;
|
|
1102
1310
|
}
|
|
1103
1311
|
}
|
|
@@ -1107,13 +1315,13 @@ class Ot extends st {
|
|
|
1107
1315
|
* data regardless of the caller's requested kind. Also reset by paths
|
|
1108
1316
|
* that intentionally invalidate the current Y baseline (axis bound
|
|
1109
1317
|
* change, empty viewport). */
|
|
1110
|
-
#
|
|
1318
|
+
#f = !1;
|
|
1111
1319
|
/** Whether the engine's X slot has received its first emit. Pre-init X
|
|
1112
1320
|
* emits are forced to `instant` so first paint snaps to the fitted
|
|
1113
1321
|
* range — without this guard the engine would ease from `{0,0}` into
|
|
1114
1322
|
* the new target and the very first frame would render with a
|
|
1115
1323
|
* zero-width X domain. */
|
|
1116
|
-
#
|
|
1324
|
+
#I = !1;
|
|
1117
1325
|
/**
|
|
1118
1326
|
* One-shot `setVisibleRange` argument applied on the first data arrival.
|
|
1119
1327
|
* Captured at chart construction from {@link ChartOptions.viewport.initialRange};
|
|
@@ -1127,8 +1335,8 @@ class Ot extends st {
|
|
|
1127
1335
|
* axis labels subscribe to that event and re-renders on every tick are
|
|
1128
1336
|
* expensive. Initialised to NaN so the first real Y emit always passes
|
|
1129
1337
|
* the change check. */
|
|
1130
|
-
#
|
|
1131
|
-
#
|
|
1338
|
+
#K = Number.NaN;
|
|
1339
|
+
#j = Number.NaN;
|
|
1132
1340
|
/**
|
|
1133
1341
|
* Sample the visible data window and return the resolved Y bounds, or
|
|
1134
1342
|
* `null` when no series has data inside the X destination range.
|
|
@@ -1137,11 +1345,11 @@ class Ot extends st {
|
|
|
1137
1345
|
* converge together. Clears {@link #yInited} on empty so the next emit
|
|
1138
1346
|
* with valid data lands as an instant snap.
|
|
1139
1347
|
*/
|
|
1140
|
-
#
|
|
1141
|
-
const i = t ?? this.#o, e = this.#
|
|
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);
|
|
1142
1350
|
if (s === null)
|
|
1143
|
-
return this.#
|
|
1144
|
-
const r =
|
|
1351
|
+
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");
|
|
1145
1353
|
return { min: r, max: n };
|
|
1146
1354
|
}
|
|
1147
1355
|
/**
|
|
@@ -1162,24 +1370,29 @@ class Ot extends st {
|
|
|
1162
1370
|
* - **autoscroll off** → `null` (no X retarget; user has panned away
|
|
1163
1371
|
* from the tail).
|
|
1164
1372
|
*/
|
|
1165
|
-
#
|
|
1166
|
-
if (this.#k === null || this.#
|
|
1167
|
-
const { from: t, to: i } = this.#o, e = t === 0 && i === 0, s = this.#
|
|
1168
|
-
if (e)
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1373
|
+
#Rt() {
|
|
1374
|
+
if (this.#k === null || this.#i === null) return null;
|
|
1375
|
+
const { from: t, to: i } = this.#o, e = t === 0 && i === 0, s = this.#a.size.media.width - this.yAxisWidth;
|
|
1376
|
+
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)) {
|
|
1378
|
+
const { to: n } = this.#o;
|
|
1379
|
+
this.#i >= n && this.#i - n <= this.#r * 1.5 && (this.#u = !0);
|
|
1380
|
+
}
|
|
1381
|
+
return this.#o;
|
|
1382
|
+
}
|
|
1383
|
+
if (!this.#u) return null;
|
|
1384
|
+
if (this.#ht)
|
|
1385
|
+
return this.#P(this.#k, this.#i, s), this.#o;
|
|
1386
|
+
const r = J({
|
|
1174
1387
|
currentLogical: this.#o,
|
|
1175
|
-
lastTime: this.#
|
|
1176
|
-
prevDataEnd: this.#
|
|
1177
|
-
dataInterval: this.#
|
|
1388
|
+
lastTime: this.#i,
|
|
1389
|
+
prevDataEnd: this.#z,
|
|
1390
|
+
dataInterval: this.#r,
|
|
1178
1391
|
paddingRight: this.#c.right,
|
|
1179
1392
|
chartWidth: s,
|
|
1180
|
-
holdUntilFilled: this.#
|
|
1393
|
+
holdUntilFilled: this.#w
|
|
1181
1394
|
});
|
|
1182
|
-
return r.releaseHold && (this.#
|
|
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);
|
|
1183
1396
|
}
|
|
1184
1397
|
/**
|
|
1185
1398
|
* Fit the viewport's logical X range around a data span. Mirrors the
|
|
@@ -1187,16 +1400,16 @@ class Ot extends st {
|
|
|
1187
1400
|
* forces autoscroll on (data tail is in the new window by construction),
|
|
1188
1401
|
* commits the new range via `viewport.setRange` (which emits `change`).
|
|
1189
1402
|
*/
|
|
1190
|
-
#
|
|
1191
|
-
const s = this.#c, r =
|
|
1403
|
+
#P(t, i, e) {
|
|
1404
|
+
const s = this.#c, r = X({
|
|
1192
1405
|
firstTime: t,
|
|
1193
1406
|
lastTime: i,
|
|
1194
|
-
dataInterval: this.#
|
|
1195
|
-
maxVisibleBars: this.#
|
|
1407
|
+
dataInterval: this.#r,
|
|
1408
|
+
maxVisibleBars: this.#ot,
|
|
1196
1409
|
chartWidth: e,
|
|
1197
1410
|
padding: { left: s.left, right: s.right }
|
|
1198
1411
|
});
|
|
1199
|
-
this.#
|
|
1412
|
+
this.#w = !1, this.#u = !0, this.#L(r, { emitChange: !0 });
|
|
1200
1413
|
}
|
|
1201
1414
|
/**
|
|
1202
1415
|
* Commit a programmatic zoom — `fitContent` or `setVisibleRange`. Reads
|
|
@@ -1212,15 +1425,15 @@ class Ot extends st {
|
|
|
1212
1425
|
* passes `xEase: true` so X eases instead — viewport and axis converge
|
|
1213
1426
|
* on the same frame.
|
|
1214
1427
|
*/
|
|
1215
|
-
#
|
|
1428
|
+
#W(t) {
|
|
1216
1429
|
const i = this.#o;
|
|
1217
1430
|
if (i.to <= i.from) return;
|
|
1218
1431
|
const e = performance.now();
|
|
1219
|
-
if (!this.#
|
|
1220
|
-
this.#
|
|
1432
|
+
if (!this.#I || !this.#f) {
|
|
1433
|
+
this.#pt(e);
|
|
1221
1434
|
return;
|
|
1222
1435
|
}
|
|
1223
|
-
this.#
|
|
1436
|
+
this.#s.onProgrammaticZoom({ xTarget: i, xEase: t?.xEase }, e), this.#v(e);
|
|
1224
1437
|
}
|
|
1225
1438
|
/**
|
|
1226
1439
|
* Commit the current logical X to the engine on the *gesture* profile:
|
|
@@ -1234,15 +1447,15 @@ class Ot extends st {
|
|
|
1234
1447
|
* instead of lagging on the long sticky contract. First paint still snaps
|
|
1235
1448
|
* (same as the programmatic path) so synchronous readers see final values.
|
|
1236
1449
|
*/
|
|
1237
|
-
#
|
|
1450
|
+
#Mt() {
|
|
1238
1451
|
const t = this.#o;
|
|
1239
1452
|
if (t.to <= t.from) return;
|
|
1240
1453
|
const i = performance.now();
|
|
1241
|
-
if (!this.#
|
|
1242
|
-
this.#
|
|
1454
|
+
if (!this.#I || !this.#f) {
|
|
1455
|
+
this.#pt(i);
|
|
1243
1456
|
return;
|
|
1244
1457
|
}
|
|
1245
|
-
this.#
|
|
1458
|
+
this.#s.onPanZoom({ xTarget: t, yAuto: !0 }, i), this.#v(i);
|
|
1246
1459
|
}
|
|
1247
1460
|
/**
|
|
1248
1461
|
* First-paint snap: land both axes on the current logical X immediately
|
|
@@ -1251,9 +1464,9 @@ class Ot extends st {
|
|
|
1251
1464
|
* commits — both must snap before the chart has painted once so a
|
|
1252
1465
|
* synchronous `getYRange()` / `getVisibleRange()` read sees final values.
|
|
1253
1466
|
*/
|
|
1254
|
-
#
|
|
1255
|
-
const i = this.#o, e = this.#
|
|
1256
|
-
this.#
|
|
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);
|
|
1257
1470
|
}
|
|
1258
1471
|
/**
|
|
1259
1472
|
* Validate and commit a new logical X range. Mirrors the old
|
|
@@ -1273,9 +1486,9 @@ class Ot extends st {
|
|
|
1273
1486
|
* see `setVisibleRange`'s gesture path, where a per-frame echo would
|
|
1274
1487
|
* otherwise re-arm and stall the in-flight Y ease.
|
|
1275
1488
|
*/
|
|
1276
|
-
#
|
|
1489
|
+
#L(t, i) {
|
|
1277
1490
|
const { from: e, to: s } = t;
|
|
1278
|
-
return !Number.isFinite(e) || !Number.isFinite(s) || s <= e || !i.skipValidation && (s - e) / this.#
|
|
1491
|
+
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);
|
|
1279
1492
|
}
|
|
1280
1493
|
/**
|
|
1281
1494
|
* Apply pixel-padding to the engine's raw Y target and store the
|
|
@@ -1283,11 +1496,11 @@ class Ot extends st {
|
|
|
1283
1496
|
* symmetric pad top / bottom from `#padding`, suppressed on the side
|
|
1284
1497
|
* that has an explicit (fixed) axis bound.
|
|
1285
1498
|
*/
|
|
1286
|
-
#
|
|
1287
|
-
const n = i - t,
|
|
1288
|
-
this.#
|
|
1289
|
-
min: s ? t : t -
|
|
1290
|
-
max: r ? i : i +
|
|
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
|
|
1291
1504
|
};
|
|
1292
1505
|
}
|
|
1293
1506
|
/**
|
|
@@ -1300,18 +1513,18 @@ class Ot extends st {
|
|
|
1300
1513
|
* as a gesture for visual easing. Public so consumers can drive pan
|
|
1301
1514
|
* programmatically.
|
|
1302
1515
|
*/
|
|
1303
|
-
pan(t, i = this.#
|
|
1304
|
-
i > 0 && (this.#
|
|
1305
|
-
const e =
|
|
1516
|
+
pan(t, i = this.#E) {
|
|
1517
|
+
i > 0 && (this.#E = i), this.#w = !1;
|
|
1518
|
+
const e = q({
|
|
1306
1519
|
currentLogical: this.#o,
|
|
1307
1520
|
timeDelta: t,
|
|
1308
1521
|
chartWidth: i,
|
|
1309
|
-
dataInterval: this.#
|
|
1522
|
+
dataInterval: this.#r,
|
|
1310
1523
|
padding: { left: this.#c.left, right: this.#c.right },
|
|
1311
1524
|
dataStart: this.#k,
|
|
1312
|
-
dataEnd: this.#
|
|
1525
|
+
dataEnd: this.#i
|
|
1313
1526
|
});
|
|
1314
|
-
e.newLogical !== null && (this.#
|
|
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());
|
|
1315
1528
|
}
|
|
1316
1529
|
/**
|
|
1317
1530
|
* Zoom around a time anchor. `factor < 1` zooms in, `> 1` zooms out.
|
|
@@ -1328,37 +1541,37 @@ class Ot extends st {
|
|
|
1328
1541
|
* and produce a visible jump). Cursor-anchored zoom is intentionally
|
|
1329
1542
|
* sacrificed in follow-live mode — pan first to inspect history.
|
|
1330
1543
|
*/
|
|
1331
|
-
zoomAt(t, i, e = this.#
|
|
1332
|
-
e > 0 && (this.#
|
|
1333
|
-
const s =
|
|
1544
|
+
zoomAt(t, i, e = this.#E) {
|
|
1545
|
+
e > 0 && (this.#E = e), this.#w = !1;
|
|
1546
|
+
const s = K({
|
|
1334
1547
|
currentLogical: this.#o,
|
|
1335
1548
|
centerTime: t,
|
|
1336
1549
|
factor: i,
|
|
1337
1550
|
chartWidth: e,
|
|
1338
|
-
dataInterval: this.#
|
|
1551
|
+
dataInterval: this.#r,
|
|
1339
1552
|
padding: { left: this.#c.left, right: this.#c.right },
|
|
1340
1553
|
dataStart: this.#k,
|
|
1341
|
-
dataEnd: this.#
|
|
1554
|
+
dataEnd: this.#i
|
|
1342
1555
|
});
|
|
1343
1556
|
if (s.newLogical === null) return;
|
|
1344
1557
|
let r = s.newLogical;
|
|
1345
|
-
if (this.#
|
|
1346
|
-
const n = r.to - r.from,
|
|
1347
|
-
r = { from:
|
|
1558
|
+
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;
|
|
1348
1561
|
}
|
|
1349
|
-
this.#
|
|
1562
|
+
this.#L(r, { emitChange: !0 }), this.#D.pause(), this.#vt();
|
|
1350
1563
|
}
|
|
1351
1564
|
/**
|
|
1352
1565
|
* Common tail for `pan` / `zoomAt`: routes the just-committed `#logical`
|
|
1353
1566
|
* to the engine as a gesture so the X spring retargets and the Y spring
|
|
1354
1567
|
* eases over `animations.axis.y.gesture`.
|
|
1355
1568
|
*/
|
|
1356
|
-
#
|
|
1569
|
+
#vt() {
|
|
1357
1570
|
const t = this.#o;
|
|
1358
1571
|
if (t.to <= t.from) return;
|
|
1359
|
-
this.#
|
|
1572
|
+
this.#I = !0, this.#f = !0;
|
|
1360
1573
|
const i = performance.now();
|
|
1361
|
-
this.#
|
|
1574
|
+
this.#s.onPanZoom({ xTarget: t, yAuto: !0 }, i), this.#v(i);
|
|
1362
1575
|
}
|
|
1363
1576
|
/**
|
|
1364
1577
|
* Tick the engine at the given wall clock and push the resolved X / Y
|
|
@@ -1373,11 +1586,11 @@ class Ot extends st {
|
|
|
1373
1586
|
* `effectiveNow === startWall` and the prune step keeps zero-duration
|
|
1374
1587
|
* events long enough for the slot processor to snap them.
|
|
1375
1588
|
*/
|
|
1376
|
-
#
|
|
1377
|
-
const i = this.#
|
|
1589
|
+
#v(t) {
|
|
1590
|
+
const i = this.#s.tick(t), e = this.#a.size;
|
|
1378
1591
|
if (e.media.width === 0 || e.media.height === 0) return;
|
|
1379
|
-
const s = this.#
|
|
1380
|
-
this.#
|
|
1592
|
+
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();
|
|
1381
1594
|
}
|
|
1382
1595
|
/**
|
|
1383
1596
|
* Lightweight scale sync: updates timeScale/yScale from current viewport state
|
|
@@ -1385,78 +1598,78 @@ class Ot extends st {
|
|
|
1385
1598
|
* handler, so DOM axis components always read fresh coordinates on re-render.
|
|
1386
1599
|
*/
|
|
1387
1600
|
syncScales() {
|
|
1388
|
-
const t = this.#
|
|
1601
|
+
const t = this.#a.size;
|
|
1389
1602
|
if (t.media.width === 0 || t.media.height === 0) return;
|
|
1390
1603
|
const i = t.media.width - this.yAxisWidth, e = t.media.height - this.xAxisHeight;
|
|
1391
1604
|
this.timeScale.update(
|
|
1392
|
-
this.#
|
|
1605
|
+
this.#s.getAnimationState().xRange,
|
|
1393
1606
|
i,
|
|
1394
1607
|
t.horizontalPixelRatio,
|
|
1395
|
-
this.#
|
|
1396
|
-
), this.yScale.update(this.#
|
|
1608
|
+
this.#r
|
|
1609
|
+
), this.yScale.update(this.#F, e, t.verticalPixelRatio);
|
|
1397
1610
|
}
|
|
1398
1611
|
/** Expensive: background, grid, all series. Only on data/viewport/resize change. */
|
|
1399
1612
|
renderMain(t) {
|
|
1400
|
-
const i = this.#
|
|
1613
|
+
const i = this.#a.size;
|
|
1401
1614
|
if (i.media.width === 0 || i.media.height === 0) return;
|
|
1402
|
-
const e = typeof t == "number" ? t : performance.now(), s = this.#
|
|
1403
|
-
s.animating && this.#
|
|
1404
|
-
const r = s.yRange.min, n = s.yRange.max,
|
|
1405
|
-
if (
|
|
1406
|
-
const d = this.#
|
|
1407
|
-
this.#
|
|
1615
|
+
const e = typeof t == "number" ? t : performance.now(), s = this.#s.tick(e);
|
|
1616
|
+
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;
|
|
1408
1621
|
}
|
|
1409
|
-
if (this.syncScales(), this.#
|
|
1410
|
-
const d = this.#
|
|
1622
|
+
if (this.syncScales(), this.#Ct(), this.#i !== null && !this.#u) {
|
|
1623
|
+
const d = this.#s.lastXTarget ?? this.#o, c = d.to - d.from;
|
|
1411
1624
|
if (c > 0) {
|
|
1412
|
-
const
|
|
1413
|
-
Math.abs(d.to - (this.#
|
|
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);
|
|
1414
1627
|
}
|
|
1415
1628
|
}
|
|
1416
|
-
|
|
1417
|
-
let
|
|
1418
|
-
this.#
|
|
1419
|
-
const { context: c, bitmapSize:
|
|
1420
|
-
c.clearRect(0, 0,
|
|
1421
|
-
const
|
|
1422
|
-
|
|
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({
|
|
1423
1636
|
scope: d,
|
|
1424
1637
|
timeScale: this.timeScale,
|
|
1425
1638
|
yScale: this.yScale,
|
|
1426
|
-
theme: this.#
|
|
1427
|
-
yTicks:
|
|
1428
|
-
timeTicks:
|
|
1429
|
-
}), this.#
|
|
1430
|
-
const
|
|
1431
|
-
for (const
|
|
1432
|
-
const
|
|
1433
|
-
if (
|
|
1434
|
-
const
|
|
1639
|
+
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;
|
|
1644
|
+
for (const b of this.#t) {
|
|
1645
|
+
const x = b.renderer.getAlpha?.() ?? (b.visible ? 1 : 0);
|
|
1646
|
+
if (x <= 0) continue;
|
|
1647
|
+
const T = {
|
|
1435
1648
|
scope: d,
|
|
1436
1649
|
timeScale: this.timeScale,
|
|
1437
1650
|
yScale: this.yScale,
|
|
1438
|
-
theme: this.#
|
|
1439
|
-
dataInterval: this.#
|
|
1440
|
-
padding:
|
|
1651
|
+
theme: this.#n,
|
|
1652
|
+
dataInterval: this.#r,
|
|
1653
|
+
padding: V,
|
|
1441
1654
|
state: s,
|
|
1442
|
-
seriesId:
|
|
1443
|
-
},
|
|
1444
|
-
if (
|
|
1445
|
-
const
|
|
1446
|
-
|
|
1655
|
+
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);
|
|
1447
1660
|
} else
|
|
1448
|
-
|
|
1449
|
-
|
|
1661
|
+
b.renderer.render(T);
|
|
1662
|
+
x < 1 && (c.globalAlpha = D);
|
|
1450
1663
|
}
|
|
1451
1664
|
c.restore();
|
|
1452
|
-
});
|
|
1665
|
+
}), this.#$();
|
|
1453
1666
|
let o = !1;
|
|
1454
1667
|
for (const d of this.#t)
|
|
1455
1668
|
if (d.renderer.needsAnimation) {
|
|
1456
|
-
o = !0, this.#
|
|
1669
|
+
o = !0, this.#e.markDirty();
|
|
1457
1670
|
break;
|
|
1458
1671
|
}
|
|
1459
|
-
const u =
|
|
1672
|
+
const u = a || l;
|
|
1460
1673
|
!s.animating && !o && !u && (this.yScale.tickTracker.markArmed(), this.timeScale.tickTracker.markArmed());
|
|
1461
1674
|
}
|
|
1462
1675
|
/**
|
|
@@ -1468,13 +1681,13 @@ class Ot extends st {
|
|
|
1468
1681
|
* `markDirty` calls made *during* `renderOverlay` (pulse, edge spinner)
|
|
1469
1682
|
* land after the consume and re-arm cleanly for the next frame.
|
|
1470
1683
|
*/
|
|
1471
|
-
#
|
|
1472
|
-
this.#
|
|
1684
|
+
#J(t) {
|
|
1685
|
+
this.#Q("main", t, () => this.renderMain(t)), this.#h.consume(), this.#Q("overlay", t, () => this.renderOverlay(t));
|
|
1473
1686
|
}
|
|
1474
1687
|
/** Run a layer's paint, booking duration + draw calls to the perf monitor
|
|
1475
1688
|
* when one is attached — keeps overlay time out of the `main` samples. */
|
|
1476
|
-
#
|
|
1477
|
-
const s = this.#
|
|
1689
|
+
#Q(t, i, e) {
|
|
1690
|
+
const s = this.#x;
|
|
1478
1691
|
if (!s) {
|
|
1479
1692
|
e();
|
|
1480
1693
|
return;
|
|
@@ -1485,66 +1698,80 @@ class Ot extends st {
|
|
|
1485
1698
|
}
|
|
1486
1699
|
/** Cheap overlay: crosshair, nearest-point dots, pulse animation, edge indicator. */
|
|
1487
1700
|
renderOverlay(t) {
|
|
1488
|
-
const i = this.#
|
|
1701
|
+
const i = this.#a.size;
|
|
1489
1702
|
if (i.media.width === 0 || i.media.height === 0) return;
|
|
1490
1703
|
let e = !1;
|
|
1491
|
-
for (const
|
|
1492
|
-
if (
|
|
1704
|
+
for (const o of this.#t)
|
|
1705
|
+
if (o.visible && o.renderer.overlayNeedsAnimation) {
|
|
1493
1706
|
e = !0;
|
|
1494
1707
|
break;
|
|
1495
1708
|
}
|
|
1496
|
-
this.#m.some((
|
|
1497
|
-
const s =
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1709
|
+
this.#m.some((o) => o.pulse) && (e = !0);
|
|
1710
|
+
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
|
|
1713
|
+
}, 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) => {
|
|
1719
|
+
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);
|
|
1505
1724
|
}
|
|
1506
|
-
const
|
|
1507
|
-
for (const
|
|
1508
|
-
|
|
1509
|
-
scope:
|
|
1725
|
+
const c = this.#c, p = { top: c.top, bottom: c.bottom }, v = this.#s.getAnimationState();
|
|
1726
|
+
for (const m of this.#t)
|
|
1727
|
+
m.visible && m.renderer.drawOverlay?.({
|
|
1728
|
+
scope: o,
|
|
1510
1729
|
timeScale: this.timeScale,
|
|
1511
1730
|
yScale: this.yScale,
|
|
1512
|
-
theme: this.#
|
|
1513
|
-
dataInterval: this.#
|
|
1514
|
-
padding:
|
|
1731
|
+
theme: this.#n,
|
|
1732
|
+
dataInterval: this.#r,
|
|
1733
|
+
padding: p,
|
|
1515
1734
|
crosshair: this.#d,
|
|
1516
|
-
state:
|
|
1517
|
-
seriesId:
|
|
1735
|
+
state: v,
|
|
1736
|
+
seriesId: m.id
|
|
1518
1737
|
});
|
|
1519
|
-
this.#
|
|
1520
|
-
scope:
|
|
1738
|
+
this.#wt(o, u, d), this.#kt(o, u, d), a && Y({
|
|
1739
|
+
scope: o,
|
|
1740
|
+
chartMediaWidth: i.media.width - this.yAxisWidth,
|
|
1521
1741
|
chartMediaHeight: i.media.height - this.xAxisHeight,
|
|
1522
1742
|
timeScale: this.timeScale,
|
|
1523
|
-
theme: this.#
|
|
1524
|
-
edgeStates:
|
|
1525
|
-
|
|
1526
|
-
|
|
1743
|
+
theme: this.#n,
|
|
1744
|
+
edgeStates: s,
|
|
1745
|
+
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() };
|
|
1752
|
+
}
|
|
1753
|
+
}), o.context.restore();
|
|
1527
1754
|
}), e) {
|
|
1528
|
-
const { from:
|
|
1529
|
-
let
|
|
1530
|
-
for (const
|
|
1531
|
-
if (!(!
|
|
1532
|
-
|
|
1755
|
+
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;
|
|
1533
1760
|
break;
|
|
1534
1761
|
}
|
|
1535
|
-
if (!
|
|
1536
|
-
for (const
|
|
1537
|
-
if (
|
|
1538
|
-
|
|
1762
|
+
if (!d) {
|
|
1763
|
+
for (const c of this.#m)
|
|
1764
|
+
if (c.pulse && c.time >= o && c.time <= u) {
|
|
1765
|
+
d = !0;
|
|
1539
1766
|
break;
|
|
1540
1767
|
}
|
|
1541
1768
|
}
|
|
1542
|
-
|
|
1769
|
+
d && this.#h.markDirty();
|
|
1543
1770
|
}
|
|
1544
|
-
|
|
1771
|
+
h && this.#h.markDirty();
|
|
1545
1772
|
}
|
|
1546
1773
|
}
|
|
1547
1774
|
}
|
|
1548
1775
|
export {
|
|
1549
|
-
|
|
1776
|
+
qt as ChartInstance
|
|
1550
1777
|
};
|