@wick-charts/vue 0.8.0 → 0.8.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.
- package/README.md +2 -0
- package/dist/BandSeries.vue.js +40 -30
- package/dist/BarSeries.vue.js +39 -29
- package/dist/CandlestickSeries.vue.js +2 -2
- package/dist/ChartContainer.vue.js +1 -1
- package/dist/LineSeries.vue.js +40 -30
- package/dist/core/dist/chart/badge-animator.js +38 -28
- package/dist/core/dist/chart.js +801 -694
- package/dist/core/dist/data/sync.js +77 -50
- package/dist/core/dist/navigator/controller.js +11 -11
- package/dist/core/dist/scales/time-ticks.js +99 -0
- package/dist/core/dist/scales/x-scale.js +33 -27
- package/dist/core/dist/series/band.js +82 -82
- package/dist/core/dist/series/bar.js +1 -1
- package/dist/core/dist/series/base-multi-layer.js +182 -152
- package/dist/core/dist/series/candlestick.js +96 -96
- package/dist/core/dist/series/line.js +297 -292
- package/dist/core/dist/snapshots.js +39 -35
- package/dist/core/dist/utils/point.js +4 -0
- package/dist/core/dist/utils/time.js +42 -26
- package/dist/index.d.ts +45 -24
- package/dist/ui/InfoBar.vue.js +13 -13
- package/dist/ui/Tooltip.vue.js +11 -11
- package/dist/ui/YLabel.vue.js +47 -47
- package/package.json +2 -2
- package/src/BandSeries.vue +16 -3
- package/src/BarSeries.vue +16 -3
- package/src/ChartContainer.vue +14 -8
- package/src/LineSeries.vue +16 -3
- package/src/ui/YLabel.vue +28 -27
package/dist/core/dist/chart.js
CHANGED
|
@@ -1,100 +1,117 @@
|
|
|
1
|
-
import { Animator as
|
|
2
|
-
import { AnimationConfig as
|
|
3
|
-
import { easeOutCubic as
|
|
4
|
-
import { prefersReducedMotion as
|
|
5
|
-
import { createViewportEngine as
|
|
6
|
-
import { CanvasManager as
|
|
7
|
-
import { resolveEdgeAnchorValue as
|
|
8
|
-
import { computeFitToData as
|
|
9
|
-
import { getLastValue as
|
|
10
|
-
import { resolveFade as
|
|
11
|
-
import { computePan as
|
|
12
|
-
import { warnUnplottableBounds as
|
|
13
|
-
import { StreamingCadence as
|
|
14
|
-
import { computeStreamingTarget as
|
|
15
|
-
import { resolvePaddingTime as
|
|
16
|
-
import { assertSeriesFitsXAxis as
|
|
17
|
-
import { fromScaleSpace as
|
|
18
|
-
import { renderCrosshair as
|
|
19
|
-
import { renderGrid as
|
|
20
|
-
import { renderMarker as
|
|
21
|
-
import { renderReferenceLine as
|
|
22
|
-
import { resolveTimeRegionColors as
|
|
23
|
-
import { EventEmitter as
|
|
24
|
-
import { InteractionHandler as
|
|
25
|
-
import { RenderScheduler as
|
|
26
|
-
import { XScale as
|
|
27
|
-
import { YScale as
|
|
28
|
-
import { resolveSeriesDefinition as
|
|
29
|
-
import { isTimeSeriesRenderer as
|
|
30
|
-
import { catppuccin as
|
|
31
|
-
import { deepEqual as
|
|
32
|
-
import { clamp as
|
|
33
|
-
import { crispLineWidth as
|
|
34
|
-
import { pointValue as
|
|
35
|
-
import { normalizeTime as k, detectInterval as
|
|
36
|
-
const
|
|
37
|
-
function
|
|
1
|
+
import { Animator as ut } from "./animation/animator.js";
|
|
2
|
+
import { AnimationConfig as mt, DEFAULT_LINE_PULSE as ft } from "./animation/config.js";
|
|
3
|
+
import { easeOutCubic as E } from "./animation/easing.js";
|
|
4
|
+
import { prefersReducedMotion as gt } from "./animation/reduced-motion.js";
|
|
5
|
+
import { createViewportEngine as pt } from "./animation/viewport-engine.js";
|
|
6
|
+
import { CanvasManager as yt } from "./canvas-manager.js";
|
|
7
|
+
import { resolveEdgeAnchorValue as xt, drawEdgeIndicators as vt, resolveEdgeBoundary as St } from "./chart/edge-indicators.js";
|
|
8
|
+
import { computeFitToData as B } from "./chart/fit-to-data.js";
|
|
9
|
+
import { getLastValue as bt, getPreviousClose as kt, getStackedLastValue as Tt } from "./chart/last-value.js";
|
|
10
|
+
import { resolveFade as X, resolveMaxVisibleBars as wt, resolvePadding as Z, resolvePerfOptions as Mt, isSameHorizontalPadding as _ } from "./chart/options.js";
|
|
11
|
+
import { computePan as At, computeZoom as Pt } from "./chart/pan-zoom-math.js";
|
|
12
|
+
import { warnUnplottableBounds as L, assertStackingFitsScale as I, warnScaleSideTaken as Ct, warnUnknownScale as Lt, warnStackingOffScale as It, warnUnplottableValues as Dt } from "./chart/scale-guards.js";
|
|
13
|
+
import { StreamingCadence as Rt } from "./chart/streaming-cadence.js";
|
|
14
|
+
import { computeStreamingTarget as Vt } from "./chart/streaming-target.js";
|
|
15
|
+
import { resolvePaddingTime as G } from "./chart/viewport-padding.js";
|
|
16
|
+
import { assertSeriesFitsXAxis as Ht, warnXMisfit as Nt, warnXTimeMixed as Ft, warnTimeOnlyFeature as Wt, warnXTypeChange as Ot } from "./chart/x-guards.js";
|
|
17
|
+
import { fromScaleSpace as zt, computeTargetYRange as Yt, resolveYTarget as $t } from "./chart/y-target.js";
|
|
18
|
+
import { renderCrosshair as Et } from "./components/crosshair.js";
|
|
19
|
+
import { renderGrid as U } from "./components/grid.js";
|
|
20
|
+
import { renderMarker as Bt } from "./components/marker.js";
|
|
21
|
+
import { renderReferenceLine as Xt } from "./components/reference-line.js";
|
|
22
|
+
import { resolveTimeRegionColors as Zt, renderTimeRegion as _t } from "./components/time-region.js";
|
|
23
|
+
import { EventEmitter as Gt } from "./events.js";
|
|
24
|
+
import { InteractionHandler as Ut } from "./interactions/handler.js";
|
|
25
|
+
import { RenderScheduler as j } from "./render-scheduler.js";
|
|
26
|
+
import { XScale as jt } from "./scales/x-scale.js";
|
|
27
|
+
import { YScale as K, isPlottableOn as q } from "./scales/y-scale.js";
|
|
28
|
+
import { resolveSeriesDefinition as Kt } from "./series/definition.js";
|
|
29
|
+
import { isTimeSeriesRenderer as S } from "./series/types.js";
|
|
30
|
+
import { catppuccin as qt } from "./theme/themes/catppuccin.js";
|
|
31
|
+
import { deepEqual as Qt } from "./utils/deep-equal.js";
|
|
32
|
+
import { clamp as Jt } from "./utils/math.js";
|
|
33
|
+
import { crispLineWidth as te, crispCenterOffset as ee } from "./utils/pixel-grid.js";
|
|
34
|
+
import { pointValue as Q, isBandPoint as ie } from "./utils/point.js";
|
|
35
|
+
import { normalizeTime as k, detectInterval as D } from "./utils/time.js";
|
|
36
|
+
const se = 200, re = 1500, ne = 48, J = 12, R = 9, ae = ["left", "right"], oe = { entries: [], isAnimating: !1 }, he = [], le = ["left"], ce = ["right"], de = 55, tt = 2e3, et = 20;
|
|
37
|
+
function M(d) {
|
|
38
|
+
return Number.isInteger(d) && d >= 2;
|
|
39
|
+
}
|
|
40
|
+
function ue(d) {
|
|
41
|
+
if (typeof d == "number") return M(d) ? d : void 0;
|
|
42
|
+
if (!(d !== void 0 && "bars" in d && !M(d.bars)))
|
|
43
|
+
return d;
|
|
44
|
+
}
|
|
45
|
+
function me(d) {
|
|
46
|
+
return typeof d == "object" && "to" in d;
|
|
47
|
+
}
|
|
48
|
+
function it(d, t) {
|
|
38
49
|
return {
|
|
39
|
-
yScale:
|
|
50
|
+
yScale: d,
|
|
40
51
|
bounds: { min: t?.min, max: t?.max },
|
|
41
52
|
range: { min: 0, max: 0 },
|
|
42
53
|
prevMin: Number.NaN,
|
|
43
|
-
prevMax: Number.NaN
|
|
54
|
+
prevMax: Number.NaN,
|
|
55
|
+
paintedMin: Number.NaN,
|
|
56
|
+
paintedMax: Number.NaN
|
|
44
57
|
};
|
|
45
58
|
}
|
|
46
|
-
function
|
|
47
|
-
|
|
59
|
+
function st(d) {
|
|
60
|
+
const t = d.range.min !== d.paintedMin || d.range.max !== d.paintedMax;
|
|
61
|
+
return d.paintedMin = d.range.min, d.paintedMax = d.range.max, t;
|
|
62
|
+
}
|
|
63
|
+
function rt(d) {
|
|
64
|
+
return d === "left" ? "right" : "left";
|
|
48
65
|
}
|
|
49
|
-
function
|
|
50
|
-
return
|
|
66
|
+
function nt(d, t) {
|
|
67
|
+
return d === void 0 || d === "auto" ? !1 : !(typeof d == "number" && !t.isPlottable(d));
|
|
51
68
|
}
|
|
52
|
-
let
|
|
53
|
-
function
|
|
54
|
-
return
|
|
69
|
+
let fe = 0, ge = 0, pe = 0, ye = 0;
|
|
70
|
+
function at(d, t) {
|
|
71
|
+
return d === t ? !0 : !d || !t || d.length !== t.length ? !1 : d.every((e, i) => e === t[i]);
|
|
55
72
|
}
|
|
56
|
-
function
|
|
57
|
-
return
|
|
73
|
+
function ot(d) {
|
|
74
|
+
return S(d) ? d.stacking : void 0;
|
|
58
75
|
}
|
|
59
|
-
function
|
|
60
|
-
return
|
|
76
|
+
function xe(d, t) {
|
|
77
|
+
return d === t ? !0 : !d || !t || d.length !== t.length ? !1 : d.every((e, i) => e === t[i]);
|
|
61
78
|
}
|
|
62
|
-
class
|
|
79
|
+
class ti extends Gt {
|
|
63
80
|
/** Canvas lifecycle and DPR-aware sizing. */
|
|
64
|
-
#
|
|
81
|
+
#c;
|
|
65
82
|
/** Schedules main-layer redraws (background, grid, series). */
|
|
66
83
|
#i;
|
|
67
84
|
/** Schedules overlay redraws (crosshair). */
|
|
68
|
-
#
|
|
85
|
+
#d;
|
|
69
86
|
/** Maps time values to horizontal pixel coordinates. */
|
|
70
87
|
timeScale;
|
|
71
88
|
/** Maps price/value to vertical pixel coordinates — the default Y scale. */
|
|
72
89
|
yScale;
|
|
73
90
|
/** Default-scale Y state; `yScale` is its scale. */
|
|
74
|
-
#
|
|
91
|
+
#w;
|
|
75
92
|
/** Named Y scales from `options.scales`, in declaration order. */
|
|
76
|
-
#
|
|
93
|
+
#o = /* @__PURE__ */ new Map();
|
|
77
94
|
/** Copy of the `scales` option as last applied — `setScales` skips a deep-equal replay,
|
|
78
95
|
* and the copy keeps an in-place edit of the caller's object from comparing equal. */
|
|
79
|
-
#
|
|
96
|
+
#Lt = {};
|
|
80
97
|
/** Set when a named scale's range moved, so the crosshair re-emits for its axis label. */
|
|
81
|
-
#
|
|
98
|
+
#ot = !1;
|
|
82
99
|
/** Keys of dev warnings already printed, so each fires once. */
|
|
83
|
-
#
|
|
100
|
+
#It = /* @__PURE__ */ new Set();
|
|
84
101
|
/** What the X axis maps — read from `axis.x.type` once, at construction. */
|
|
85
|
-
#
|
|
102
|
+
#n;
|
|
86
103
|
/** Category axis: name → band index, in first-seen order across the series. */
|
|
87
104
|
#Y = /* @__PURE__ */ new Map();
|
|
88
105
|
/** Zoom, pan, crosshair — null when interactive=false. */
|
|
89
|
-
#
|
|
106
|
+
#N;
|
|
90
107
|
/** All registered series (candlestick, line, bar, pie). */
|
|
91
108
|
#t = [];
|
|
92
109
|
/** Point annotations (event markers) drawn on the overlay layer, kept out of the series model. */
|
|
93
110
|
#y = [];
|
|
94
111
|
/** Time-region bands drawn on the main layer behind the series, kept out of the series model. */
|
|
95
|
-
#
|
|
112
|
+
#M = [];
|
|
96
113
|
/** Reference lines (horizontal threshold / vertical event) drawn on the overlay layer, kept out of the series model. */
|
|
97
|
-
#
|
|
114
|
+
#S = [];
|
|
98
115
|
/**
|
|
99
116
|
* Overlay-intro latch. Annotations ride the *initial* reveal, then stay put.
|
|
100
117
|
* `#overlayIntroSeen` flips once we've actually watched an intro in progress
|
|
@@ -103,29 +120,29 @@ class _e extends Et {
|
|
|
103
120
|
* later — which re-arms `getIntroFront()`'s global min — can't blink settled
|
|
104
121
|
* markers / reference lines back out.
|
|
105
122
|
*/
|
|
106
|
-
#
|
|
107
|
-
#
|
|
123
|
+
#Dt = !1;
|
|
124
|
+
#Rt = !1;
|
|
108
125
|
/** Active visual theme (colors, fonts, grid style). */
|
|
109
|
-
#
|
|
126
|
+
#h;
|
|
110
127
|
/** Whether to render the background grid. */
|
|
111
|
-
#
|
|
128
|
+
#j;
|
|
112
129
|
/**
|
|
113
130
|
* Gridline layer opacity, multiplied into every per-tick fade: `0 → 1` on
|
|
114
131
|
* the opening reveal, `1 → 0` when {@link setGrid} hides the grid. The
|
|
115
132
|
* per-tick fades stay snapped during mount (see the tracker's arming), so
|
|
116
133
|
* this is what keeps `fitToData` tick churn from flickering the reveal.
|
|
117
134
|
*/
|
|
118
|
-
|
|
135
|
+
#$;
|
|
119
136
|
/** Resolved edge-fade zones — a `null` side is auto: the axis-column ramp on the Y-axis side, off on the other. */
|
|
120
137
|
#C;
|
|
121
138
|
/** See {@link headerHeight}. */
|
|
122
|
-
#
|
|
139
|
+
#ht = 0;
|
|
123
140
|
/** Memoized destination-out mask gradients, one per edge, keyed by the
|
|
124
141
|
* zone's bitmap geometry so a resize / DPR change / `setFade` rebuilds
|
|
125
142
|
* them and steady frames reuse them. */
|
|
126
|
-
#
|
|
143
|
+
#b = { top: null, axis: { left: null, right: null }, edge: { left: null, right: null }, tail: null, overhang: null };
|
|
127
144
|
/** Detected time interval between data points (milliseconds). */
|
|
128
|
-
#
|
|
145
|
+
#r = 6e4;
|
|
129
146
|
/** Current crosshair position, null when cursor is outside the chart. */
|
|
130
147
|
#f = null;
|
|
131
148
|
/**
|
|
@@ -135,12 +152,12 @@ class _e extends Et {
|
|
|
135
152
|
* `time`/`y`; `'time'` (programmatic {@link setCrosshair}) keeps
|
|
136
153
|
* `time`/`y` and re-projects the pixel position.
|
|
137
154
|
*/
|
|
138
|
-
#
|
|
155
|
+
#lt = "pointer";
|
|
139
156
|
/** Whether the last overlay pass painted anything — gates the full-bitmap
|
|
140
157
|
* clear so an empty overlay isn't cleared again every main frame. */
|
|
141
|
-
#
|
|
158
|
+
#Vt = !1;
|
|
142
159
|
/** Cached series ID list — invalidated on add/remove. */
|
|
143
|
-
#
|
|
160
|
+
#F = null;
|
|
144
161
|
/** Axis visibility and sizing configuration. */
|
|
145
162
|
#v = {};
|
|
146
163
|
/** Host-declared state per edge — drives the edge-indicator overlay. */
|
|
@@ -151,27 +168,27 @@ class _e extends Et {
|
|
|
151
168
|
* fetched data lands. `null` = no fade in flight. */
|
|
152
169
|
#K = { left: null, right: null };
|
|
153
170
|
/** Cached boundary timestamps from the last `edgeReached` emission, by side. */
|
|
154
|
-
#
|
|
171
|
+
#Ht = { left: null, right: null };
|
|
155
172
|
/** Latest placeholder shapes a `loading` indicator reported per side —
|
|
156
173
|
* the morph hand-off candidate consumed by {@link prependData}. */
|
|
157
|
-
#
|
|
174
|
+
#ct = { left: null, right: null };
|
|
158
175
|
/** True after a prepend consumed a side's placeholder snapshot: the series'
|
|
159
176
|
* reveal owns those pixels now, so the still-`loading` indicator is hidden
|
|
160
177
|
* and the upcoming `loading → idle` transition skips its exit fade. Reset
|
|
161
178
|
* by the next {@link setEdgeState} call. */
|
|
162
|
-
#
|
|
179
|
+
#E = { left: !1, right: !1 };
|
|
163
180
|
/** Host-supplied callback fired when the user releases a pan/zoom past a data edge. */
|
|
164
|
-
#
|
|
181
|
+
#Nt;
|
|
165
182
|
/** Per-side custom painter for the edge `loading` spinner. `null` falls back to the built-in dots. */
|
|
166
|
-
#
|
|
183
|
+
#Ft = { left: null, right: null };
|
|
167
184
|
/** Nesting depth for batch updates. Suppresses recomputes while > 0. */
|
|
168
185
|
#R = 0;
|
|
169
186
|
/** True when batched operations include data changes (triggers full onDataChanged on end). */
|
|
170
|
-
#
|
|
187
|
+
#dt = !1;
|
|
171
188
|
/** True when batched operations include visibility changes (triggers Y-range + redraw on end). */
|
|
172
|
-
#
|
|
189
|
+
#B = !1;
|
|
173
190
|
/** True when batched operations bumped overlay version (emits a single overlayChange on flush). */
|
|
174
|
-
#
|
|
191
|
+
#ut = !1;
|
|
175
192
|
/**
|
|
176
193
|
* Monotonic counter bumped on any mutation that affects overlay output —
|
|
177
194
|
* data, visibility, series options, theme. Used by snapshot helpers in
|
|
@@ -181,10 +198,10 @@ class _e extends Et {
|
|
|
181
198
|
*
|
|
182
199
|
* @internal
|
|
183
200
|
*/
|
|
184
|
-
#
|
|
201
|
+
#Wt = 0;
|
|
185
202
|
/** CSS px of the default Y-axis column. The default collapses to `0` on a spatial-only chart. */
|
|
186
203
|
get yAxisWidth() {
|
|
187
|
-
return this.#
|
|
204
|
+
return this.#q(this.#v.y);
|
|
188
205
|
}
|
|
189
206
|
/** Side of the plot area the default Y-axis column sits on. */
|
|
190
207
|
get yAxisPosition() {
|
|
@@ -204,33 +221,33 @@ class _e extends Et {
|
|
|
204
221
|
*/
|
|
205
222
|
getAxisColumnWidth(t) {
|
|
206
223
|
if (t === this.yAxisPosition && this.yAxisWidth > 0) return this.yAxisWidth;
|
|
207
|
-
for (const e of this.#
|
|
208
|
-
if (e.column === t) return this.#
|
|
224
|
+
for (const e of this.#o.values())
|
|
225
|
+
if (e.column === t) return this.#q(e.config);
|
|
209
226
|
return 0;
|
|
210
227
|
}
|
|
211
228
|
/** The named scale whose axis column sits on `side`, `null` when the default axis's does or none. */
|
|
212
229
|
getAxisColumnScale(t) {
|
|
213
|
-
for (const [e, i] of this.#
|
|
230
|
+
for (const [e, i] of this.#o)
|
|
214
231
|
if (i.column === t) return e;
|
|
215
232
|
return null;
|
|
216
233
|
}
|
|
217
234
|
/** Both Y-axis columns together — the plot area is the canvas width minus this. */
|
|
218
|
-
#
|
|
235
|
+
#k() {
|
|
219
236
|
return this.getAxisColumnWidth("left") + this.getAxisColumnWidth("right");
|
|
220
237
|
}
|
|
221
238
|
/** Column width a Y-axis config asks for; `0` when hidden, and by default on a spatial-only chart. */
|
|
222
|
-
#
|
|
223
|
-
return t?.visible === !1 ? 0 : t?.width !== void 0 ? t.width : this.#
|
|
239
|
+
#q(t) {
|
|
240
|
+
return t?.visible === !1 ? 0 : t?.width !== void 0 ? t.width : this.#it() ? 0 : de;
|
|
224
241
|
}
|
|
225
242
|
/** CSS px height of the floating Title / InfoBar header, `0` without one. A left
|
|
226
243
|
* axis shares its column with it, so tick labels fade out underneath. */
|
|
227
244
|
get headerHeight() {
|
|
228
|
-
return this.#
|
|
245
|
+
return this.#ht;
|
|
229
246
|
}
|
|
230
247
|
/** CSS px of the time-axis row. The default collapses to `0` on a spatial-only chart. */
|
|
231
248
|
get xAxisHeight() {
|
|
232
249
|
const t = this.#v.x;
|
|
233
|
-
return t?.visible === !1 ? 0 : t?.height !== void 0 ? t.height : this.#
|
|
250
|
+
return t?.visible === !1 ? 0 : t?.height !== void 0 ? t.height : this.#it() ? 0 : 30;
|
|
234
251
|
}
|
|
235
252
|
/** Resolved animation config derived from `options.animations` at construction. */
|
|
236
253
|
#g;
|
|
@@ -248,7 +265,7 @@ class _e extends Et {
|
|
|
248
265
|
* longer than the producer's tick interval — the spring never quite
|
|
249
266
|
* settles between ticks, so velocity carries continuously and the slide
|
|
250
267
|
* doesn't pulse. */
|
|
251
|
-
#
|
|
268
|
+
#W;
|
|
252
269
|
/**
|
|
253
270
|
* Mirrors `#dataReplaceSnapPending` for the engine signal that follows
|
|
254
271
|
* inside the same `onDataChanged` call. `#dataReplaceSnapPending` is
|
|
@@ -258,9 +275,9 @@ class _e extends Et {
|
|
|
258
275
|
* field carries the decision across that gap. The closure also reads
|
|
259
276
|
* `#dataStart` / `#dataEnd` directly for the timestamps.
|
|
260
277
|
*/
|
|
261
|
-
#
|
|
278
|
+
#Ot = !1;
|
|
262
279
|
/** Earliest data timestamp registered across all series, `null` before any data has arrived. */
|
|
263
|
-
#
|
|
280
|
+
#T = null;
|
|
264
281
|
/** Latest data timestamp registered across all series, `null` before any data has arrived. */
|
|
265
282
|
#s = null;
|
|
266
283
|
/**
|
|
@@ -269,7 +286,7 @@ class _e extends Et {
|
|
|
269
286
|
* left of the tail keeps that offset as new bars arrive, instead of
|
|
270
287
|
* snapping back to the natural-pin position every frame.
|
|
271
288
|
*/
|
|
272
|
-
#
|
|
289
|
+
#Q = null;
|
|
273
290
|
/**
|
|
274
291
|
* Warm-up window flag — `setVisibleRange({ from, bars })` arms it and
|
|
275
292
|
* the streaming-target math suppresses pan ticks while the data hasn't
|
|
@@ -282,14 +299,14 @@ class _e extends Et {
|
|
|
282
299
|
* the right edge and trims the left. Resolved once at construction from
|
|
283
300
|
* `options.viewport.maxVisibleBars`.
|
|
284
301
|
*/
|
|
285
|
-
#
|
|
302
|
+
#mt;
|
|
286
303
|
/**
|
|
287
304
|
* Committed logical X range — the "where X should be" target. Engine
|
|
288
305
|
* eases its visual toward this. Pan / zoom / setRange / fitContent /
|
|
289
306
|
* streaming-target writes go here. Initialized to `{0,0}` and treated
|
|
290
307
|
* as "uninitialized" by `#computeXTarget` until first paint.
|
|
291
308
|
*/
|
|
292
|
-
#
|
|
309
|
+
#a = { from: 0, to: 0 };
|
|
293
310
|
/**
|
|
294
311
|
* Auto-scroll flag — when `true`, streaming ticks slide X to track the
|
|
295
312
|
* data tail. Pan flips this off when the gesture pushes the tail off
|
|
@@ -298,20 +315,22 @@ class _e extends Et {
|
|
|
298
315
|
*/
|
|
299
316
|
#p = !0;
|
|
300
317
|
/** Resolved viewport padding (top/bottom px + left/right pixels-or-intervals). */
|
|
301
|
-
#
|
|
318
|
+
#l;
|
|
302
319
|
/** Cached chart width — passed by interactions on every call; kept for the rare
|
|
303
320
|
* call that omits it (e.g. programmatic `chart.pan(...)` without explicit width). */
|
|
304
321
|
#J = 0;
|
|
322
|
+
/** X range the last main paint drew. */
|
|
323
|
+
#tt = { from: Number.NaN, to: Number.NaN };
|
|
305
324
|
/** Active performance monitor, or `null` when instrumentation is disabled (the default). */
|
|
306
|
-
#
|
|
325
|
+
#P;
|
|
307
326
|
/** When true, `destroy()` tears down the monitor; false for caller-supplied monitors we must not destroy. */
|
|
308
|
-
#
|
|
327
|
+
#ft = !1;
|
|
309
328
|
/** Visible HUD overlay (mounted by the perf config); non-null only when the caller requested one. */
|
|
310
|
-
#
|
|
329
|
+
#gt = null;
|
|
311
330
|
constructor(t, e) {
|
|
312
|
-
super(), e?.axis && (this.#v = e.axis), this.#
|
|
331
|
+
super(), e?.axis && (this.#v = e.axis), this.#n = this.#v.x?.type ?? "time", this.#h = e?.theme ?? qt.theme, this.#j = e?.grid?.visible !== !1, this.#C = X(e?.fade), this.#g = mt.resolve(e?.animations), this.#mt = wt(e?.viewport?.maxVisibleBars), this.#l = Z(e?.padding), this.#W = new Rt();
|
|
313
332
|
const i = this.#g.axis.y, s = this.#g.axis.x;
|
|
314
|
-
this.#e =
|
|
333
|
+
this.#e = pt({
|
|
315
334
|
initial: { yRange: { min: 0, max: 0 }, xRange: { from: 0, to: 0 } },
|
|
316
335
|
y: {
|
|
317
336
|
curve: i.curve,
|
|
@@ -326,36 +345,36 @@ class _e extends Et {
|
|
|
326
345
|
settleMs: s.settleMs,
|
|
327
346
|
gestureMs: s.gestureMs
|
|
328
347
|
},
|
|
329
|
-
computeXTarget: () => this.#
|
|
330
|
-
computeYTarget: ({ xTarget: o, scale: h }) => this.#
|
|
348
|
+
computeXTarget: () => this.#De(),
|
|
349
|
+
computeYTarget: ({ xTarget: o, scale: h }) => this.#U(o, h),
|
|
331
350
|
onWake: () => this.#i?.markDirty()
|
|
332
|
-
}), e?.onEdgeReached && this.checkTimeOnlyFeature("onEdgeReached") && (this.#
|
|
333
|
-
const r =
|
|
334
|
-
this.#
|
|
351
|
+
}), e?.onEdgeReached && this.checkTimeOnlyFeature("onEdgeReached") && (this.#Nt = e.onEdgeReached), this.#H = ue(e?.viewport?.initialRange);
|
|
352
|
+
const r = Mt(e?.perf);
|
|
353
|
+
this.#P = r.monitor, this.#ft = r.ownsMonitor, this.#c = new yt(t, this.#P ?? void 0), this.timeScale = new jt(), this.timeScale.setType(this.#n), this.timeScale.setBandPadding(this.#v.x?.padding), this.yScale = new K(), this.#w = it(this.yScale, this.#v.y), this.yScale.setTransform(this.#v.y?.scale ?? null), L({ y: this.#v.y, isPlottable: this.#xt(void 0) }), this.timeScale.setLocale(e?.locale), this.timeScale.setTimeZone(e?.timeZone);
|
|
335
354
|
const n = this.#g.axis.ticksMs;
|
|
336
|
-
this.timeScale.tickTracker.setFadeMs(n), this.yScale.tickTracker.setFadeMs(n), this.#
|
|
355
|
+
this.timeScale.tickTracker.setFadeMs(n), this.yScale.tickTracker.setFadeMs(n), this.#Ut(e?.scales ?? {}), this.#Tt(), this.#$ = new ut({
|
|
337
356
|
initial: 0,
|
|
338
357
|
duration: this.#g.axis.gridMs,
|
|
339
358
|
lerp: (o, h, l) => o + (h - o) * l
|
|
340
|
-
}), this.#i = new
|
|
341
|
-
(o) => this.#
|
|
342
|
-
), this.#
|
|
359
|
+
}), this.#i = new j((o) => this.#Pt(o)), this.#d = new j(
|
|
360
|
+
(o) => this.#Ct("overlay", o, () => this.renderOverlay(o))
|
|
361
|
+
), this.#P && r.hud && (this.#gt = r.hud(t, this.#P));
|
|
343
362
|
const a = e?.interactive !== !1;
|
|
344
|
-
this.#
|
|
345
|
-
this.syncScales(), this.#
|
|
346
|
-
}), this.syncScales(), this.#
|
|
347
|
-
const h = o === null ? null : this.#
|
|
348
|
-
this.#
|
|
349
|
-
}), this.#
|
|
350
|
-
const h = this.#
|
|
351
|
-
this.emit("pointClick", { ...h, spatialHit: this.#
|
|
352
|
-
}), this.#
|
|
353
|
-
const h = this.#
|
|
354
|
-
this.fitContent(), this.emit("pointDoubleClick", { ...h, spatialHit: this.#
|
|
363
|
+
this.#N = a ? new Ut(this.#c.canvas, this, this.timeScale, this.yScale) : null, this.#c.on("resize", () => {
|
|
364
|
+
this.syncScales(), this.#Pt(), this.emit("viewportChange");
|
|
365
|
+
}), this.syncScales(), this.#N?.on("crosshairMove", (o) => {
|
|
366
|
+
const h = o === null ? null : this.#pt(o);
|
|
367
|
+
this.#lt = "pointer", this.#f = h, this.#d.markDirty(), this.emit("crosshairMove", h), this.#wt(h);
|
|
368
|
+
}), this.#N?.on("click", (o) => {
|
|
369
|
+
const h = this.#pt(o);
|
|
370
|
+
this.emit("pointClick", { ...h, spatialHit: this.#Kt(h) });
|
|
371
|
+
}), this.#N?.on("dblclick", (o) => {
|
|
372
|
+
const h = this.#pt(o);
|
|
373
|
+
this.fitContent(), this.emit("pointDoubleClick", { ...h, spatialHit: this.#Kt(h) });
|
|
355
374
|
});
|
|
356
375
|
}
|
|
357
376
|
/** A pointer position on a category axis snaps to the nearest band; `x` is the coordinate in the axis domain. */
|
|
358
|
-
#
|
|
377
|
+
#pt(t) {
|
|
359
378
|
const e = this.timeScale.snapToBand(t.time);
|
|
360
379
|
return { ...t, time: e, x: this.timeScale.domainValue(e) };
|
|
361
380
|
}
|
|
@@ -371,9 +390,9 @@ class _e extends Et {
|
|
|
371
390
|
* `setSeriesVisible` / `setLayerVisible` calls — produce one overlay
|
|
372
391
|
* render instead of N.
|
|
373
392
|
*/
|
|
374
|
-
#
|
|
375
|
-
if (this.#
|
|
376
|
-
this.#
|
|
393
|
+
#m() {
|
|
394
|
+
if (this.#Wt++, this.#R > 0) {
|
|
395
|
+
this.#ut = !0;
|
|
377
396
|
return;
|
|
378
397
|
}
|
|
379
398
|
this.emit("overlayChange");
|
|
@@ -387,59 +406,59 @@ class _e extends Et {
|
|
|
387
406
|
* @internal
|
|
388
407
|
*/
|
|
389
408
|
getOverlayVersion() {
|
|
390
|
-
return this.#
|
|
409
|
+
return this.#Wt;
|
|
391
410
|
}
|
|
392
411
|
/**
|
|
393
412
|
* Return a series ID: use the provided hint if it's non-empty and not already taken,
|
|
394
413
|
* otherwise generate a new auto ID. Auto-generated IDs never collide with each other
|
|
395
414
|
* or with user-provided IDs because they use a monotonically increasing counter.
|
|
396
415
|
*/
|
|
397
|
-
#
|
|
416
|
+
#ue(t) {
|
|
398
417
|
if (t && !this.#t.some((i) => i.id === t))
|
|
399
418
|
return t;
|
|
400
419
|
let e;
|
|
401
420
|
do
|
|
402
|
-
e = `series_${++
|
|
421
|
+
e = `series_${++fe}`;
|
|
403
422
|
while (this.#t.some((i) => i.id === e));
|
|
404
423
|
return e;
|
|
405
424
|
}
|
|
406
425
|
addSeries(t, e = {}) {
|
|
407
|
-
const i = typeof t == "string" ?
|
|
426
|
+
const i = typeof t == "string" ? Kt(t) : t;
|
|
408
427
|
if (!i)
|
|
409
428
|
throw new Error(
|
|
410
429
|
`[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).`
|
|
411
430
|
);
|
|
412
431
|
const { layers: s, id: r, label: n, labels: a, scale: o, ...h } = e, l = s ?? 1;
|
|
413
|
-
o === void 0 &&
|
|
432
|
+
o === void 0 && I({
|
|
414
433
|
seriesId: r ?? i.type,
|
|
415
434
|
stacking: h.stacking,
|
|
416
|
-
isPlottable: this.#
|
|
435
|
+
isPlottable: this.#xt(o)
|
|
417
436
|
});
|
|
418
|
-
const
|
|
437
|
+
const c = {
|
|
419
438
|
...this.#g.defaults(i.type),
|
|
420
439
|
...h,
|
|
421
440
|
...this.#g.overrides(i.type)
|
|
422
|
-
}, f = i.create({ theme: this.#
|
|
423
|
-
|
|
424
|
-
const
|
|
441
|
+
}, f = i.create({ theme: this.#h, layerCount: l }, c);
|
|
442
|
+
S(f) && Ht({ seriesType: i.type, axisType: this.#n, supported: i.xTypes ?? ["time"] });
|
|
443
|
+
const g = a ?? (typeof n == "string" ? [n] : void 0), u = this.#ue(r);
|
|
425
444
|
f.onDataChanged?.(() => this.onDataChanged());
|
|
426
|
-
const
|
|
445
|
+
const m = this.#Z();
|
|
427
446
|
return this.#t.push({
|
|
428
|
-
id:
|
|
429
|
-
labels:
|
|
447
|
+
id: u,
|
|
448
|
+
labels: g,
|
|
430
449
|
renderer: f,
|
|
431
450
|
visible: !0,
|
|
432
451
|
scale: o,
|
|
433
452
|
xKeys: { x: !1, time: !1 },
|
|
434
453
|
categoryPoints: []
|
|
435
|
-
}), this.#
|
|
454
|
+
}), this.#F = null, this.#rt(), this.#st(m), this.emit("seriesChange"), this.#m(), u;
|
|
436
455
|
}
|
|
437
456
|
/** Remove a series by ID and clean up its resources. */
|
|
438
457
|
removeSeries(t) {
|
|
439
458
|
const e = this.#t.findIndex((i) => i.id === t);
|
|
440
459
|
if (e >= 0) {
|
|
441
460
|
const i = this.#Z();
|
|
442
|
-
this.#t[e].renderer.dispose(), this.#t.splice(e, 1), this.#
|
|
461
|
+
this.#t[e].renderer.dispose(), this.#t.splice(e, 1), this.#F = null, this.#n === "category" && this.#Zt(), this.#rt(), this.#st(i), this.#i.markDirty(), this.emit("seriesChange"), this.#m();
|
|
443
462
|
}
|
|
444
463
|
}
|
|
445
464
|
// --- Markers (point annotations) -----------------------------------------
|
|
@@ -453,24 +472,24 @@ class _e extends Et {
|
|
|
453
472
|
* appear in series queries.
|
|
454
473
|
*/
|
|
455
474
|
addMarker(t) {
|
|
456
|
-
const e = `marker_${++
|
|
457
|
-
return this.#y.push(this.#
|
|
475
|
+
const e = `marker_${++ge}`;
|
|
476
|
+
return this.#y.push(this.#zt(e, t)), this.#d.markDirty(), e;
|
|
458
477
|
}
|
|
459
478
|
/** Replace a marker's config in place. No-op when the id is unknown. */
|
|
460
479
|
updateMarker(t, e) {
|
|
461
480
|
const i = this.#y.findIndex((s) => s.id === t);
|
|
462
|
-
i !== -1 && (this.#y[i] = this.#
|
|
481
|
+
i !== -1 && (this.#y[i] = this.#zt(t, e), this.#d.markDirty());
|
|
463
482
|
}
|
|
464
483
|
/** Remove a marker by id. No-op when the id is unknown. */
|
|
465
484
|
removeMarker(t) {
|
|
466
485
|
const e = this.#y.findIndex((i) => i.id === t);
|
|
467
|
-
e !== -1 && (this.#y.splice(e, 1), this.#
|
|
486
|
+
e !== -1 && (this.#y.splice(e, 1), this.#d.markDirty());
|
|
468
487
|
}
|
|
469
488
|
/** Read-only snapshot of the registered markers (normalized). Mutate via add / update / removeMarker. */
|
|
470
489
|
getMarkers() {
|
|
471
490
|
return this.#y;
|
|
472
491
|
}
|
|
473
|
-
#
|
|
492
|
+
#zt(t, e) {
|
|
474
493
|
return {
|
|
475
494
|
id: t,
|
|
476
495
|
time: k(e.time),
|
|
@@ -484,43 +503,43 @@ class _e extends Et {
|
|
|
484
503
|
};
|
|
485
504
|
}
|
|
486
505
|
/** The scale a marker's value maps through: its own `scale`, else its series' scale. */
|
|
487
|
-
#
|
|
506
|
+
#me(t) {
|
|
488
507
|
return t.scale !== void 0 || t.seriesId === void 0 ? this.getYScale(t.scale) : this.getYScale(this.getSeriesScale(t.seriesId));
|
|
489
508
|
}
|
|
490
509
|
/** Resolve a marker's Y value: explicit `value`, else snapped to its series at `time`. Null when neither resolves. */
|
|
491
|
-
#
|
|
510
|
+
#fe(t) {
|
|
492
511
|
if (t.value !== void 0 && Number.isFinite(t.value)) return t.value;
|
|
493
512
|
if (t.seriesId === void 0) return null;
|
|
494
513
|
const e = this.getDataAtTime(t.seriesId, t.time);
|
|
495
|
-
return e ?
|
|
514
|
+
return e ? Q(e) : null;
|
|
496
515
|
}
|
|
497
516
|
/** Resolve a marker's color: explicit `color`, else the series color, else the theme line color. */
|
|
498
|
-
#
|
|
517
|
+
#ge(t) {
|
|
499
518
|
if (t.color !== void 0) return t.color;
|
|
500
519
|
if (t.seriesId !== void 0) {
|
|
501
520
|
const e = this.getSeriesColor(t.seriesId);
|
|
502
521
|
if (e !== null) return e;
|
|
503
522
|
}
|
|
504
|
-
return this.#
|
|
523
|
+
return this.#h.line.color;
|
|
505
524
|
}
|
|
506
|
-
#
|
|
525
|
+
#pe(t, e, i) {
|
|
507
526
|
if (this.#y.length === 0) return;
|
|
508
|
-
const s = performance.now() / (
|
|
527
|
+
const s = performance.now() / (ft * 2 * Math.PI) % 1, r = this.#vt();
|
|
509
528
|
for (const n of this.#y) {
|
|
510
|
-
const a = this.#
|
|
529
|
+
const a = this.#fe(n);
|
|
511
530
|
if (a === null) continue;
|
|
512
|
-
const o = this.#
|
|
531
|
+
const o = this.#Bt(r, n.time);
|
|
513
532
|
if (o <= 0) continue;
|
|
514
533
|
const h = t.context.globalAlpha;
|
|
515
|
-
o < 1 && (t.context.globalAlpha = h * o),
|
|
534
|
+
o < 1 && (t.context.globalAlpha = h * o), Bt({
|
|
516
535
|
scope: t,
|
|
517
536
|
timeScale: this.timeScale,
|
|
518
|
-
yScale: this.#
|
|
519
|
-
theme: this.#
|
|
537
|
+
yScale: this.#me(n),
|
|
538
|
+
theme: this.#h,
|
|
520
539
|
marker: {
|
|
521
540
|
time: n.time,
|
|
522
541
|
value: a,
|
|
523
|
-
color: this.#
|
|
542
|
+
color: this.#ge(n),
|
|
524
543
|
shape: n.shape,
|
|
525
544
|
pulse: n.pulse,
|
|
526
545
|
label: n.label
|
|
@@ -544,24 +563,24 @@ class _e extends Et {
|
|
|
544
563
|
* legend.
|
|
545
564
|
*/
|
|
546
565
|
addRegion(t) {
|
|
547
|
-
const e = `region_${++
|
|
548
|
-
return this.checkTimeOnlyFeature("TimeRegion") && (this.#
|
|
566
|
+
const e = `region_${++pe}`;
|
|
567
|
+
return this.checkTimeOnlyFeature("TimeRegion") && (this.#M.push(this.#Yt(e, t)), this.#i.markDirty()), e;
|
|
549
568
|
}
|
|
550
569
|
/** Replace a region's config in place. No-op when the id is unknown. */
|
|
551
570
|
updateRegion(t, e) {
|
|
552
|
-
const i = this.#
|
|
553
|
-
i !== -1 && (this.#
|
|
571
|
+
const i = this.#M.findIndex((s) => s.id === t);
|
|
572
|
+
i !== -1 && (this.#M[i] = this.#Yt(t, e), this.#i.markDirty());
|
|
554
573
|
}
|
|
555
574
|
/** Remove a region by id. No-op when the id is unknown. */
|
|
556
575
|
removeRegion(t) {
|
|
557
|
-
const e = this.#
|
|
558
|
-
e !== -1 && (this.#
|
|
576
|
+
const e = this.#M.findIndex((i) => i.id === t);
|
|
577
|
+
e !== -1 && (this.#M.splice(e, 1), this.#i.markDirty());
|
|
559
578
|
}
|
|
560
579
|
/** Read-only snapshot of the registered regions (normalized). Mutate via add / update / removeRegion. */
|
|
561
580
|
getRegions() {
|
|
562
|
-
return this.#
|
|
581
|
+
return this.#M;
|
|
563
582
|
}
|
|
564
|
-
#
|
|
583
|
+
#Yt(t, e) {
|
|
565
584
|
const { to: i } = e, s = i === void 0 || i === "now" ? null : k(i);
|
|
566
585
|
return {
|
|
567
586
|
id: t,
|
|
@@ -572,14 +591,14 @@ class _e extends Et {
|
|
|
572
591
|
label: e.label
|
|
573
592
|
};
|
|
574
593
|
}
|
|
575
|
-
#
|
|
576
|
-
if (this.#
|
|
577
|
-
for (const s of this.#
|
|
578
|
-
const { color: r, fill: n } =
|
|
579
|
-
|
|
594
|
+
#ye(t, e, i) {
|
|
595
|
+
if (this.#M.length !== 0)
|
|
596
|
+
for (const s of this.#M) {
|
|
597
|
+
const { color: r, fill: n } = Zt(s, this.#h);
|
|
598
|
+
_t({
|
|
580
599
|
scope: t,
|
|
581
600
|
timeScale: this.timeScale,
|
|
582
|
-
theme: this.#
|
|
601
|
+
theme: this.#h,
|
|
583
602
|
region: { from: s.from, to: s.to, fill: n, color: r, label: s.label },
|
|
584
603
|
plotWidth: e,
|
|
585
604
|
plotHeight: i
|
|
@@ -598,22 +617,22 @@ class _e extends Et {
|
|
|
598
617
|
* legend.
|
|
599
618
|
*/
|
|
600
619
|
addLine(t) {
|
|
601
|
-
const e = `line_${++
|
|
602
|
-
return this.#
|
|
620
|
+
const e = `line_${++ye}`;
|
|
621
|
+
return this.#S.push(this.#$t(e, t)), this.#d.markDirty(), e;
|
|
603
622
|
}
|
|
604
623
|
/** Replace a reference line's config in place. No-op when the id is unknown. */
|
|
605
624
|
updateLine(t, e) {
|
|
606
|
-
const i = this.#
|
|
607
|
-
i !== -1 && (this.#
|
|
625
|
+
const i = this.#S.findIndex((s) => s.id === t);
|
|
626
|
+
i !== -1 && (this.#S[i] = this.#$t(t, e), this.#d.markDirty());
|
|
608
627
|
}
|
|
609
628
|
/** Remove a reference line by id. No-op when the id is unknown. */
|
|
610
629
|
removeLine(t) {
|
|
611
|
-
const e = this.#
|
|
612
|
-
e !== -1 && (this.#
|
|
630
|
+
const e = this.#S.findIndex((i) => i.id === t);
|
|
631
|
+
e !== -1 && (this.#S.splice(e, 1), this.#d.markDirty());
|
|
613
632
|
}
|
|
614
633
|
/** Read-only snapshot of the registered reference lines (normalized). Mutate via add / update / removeLine. */
|
|
615
634
|
getLines() {
|
|
616
|
-
return this.#
|
|
635
|
+
return this.#S;
|
|
617
636
|
}
|
|
618
637
|
#$t(t, e) {
|
|
619
638
|
const { time: i, value: s } = e, r = {
|
|
@@ -626,22 +645,22 @@ class _e extends Et {
|
|
|
626
645
|
};
|
|
627
646
|
return i !== void 0 ? { ...r, orientation: "vertical", coord: k(i) } : { ...r, orientation: "horizontal", coord: s ?? Number.NaN };
|
|
628
647
|
}
|
|
629
|
-
#
|
|
630
|
-
if (this.#
|
|
631
|
-
const s = this.#
|
|
632
|
-
for (const r of this.#
|
|
633
|
-
const n = s >= 1 ? 1 : r.orientation === "vertical" ? this.#
|
|
648
|
+
#xe(t, e, i) {
|
|
649
|
+
if (this.#S.length === 0) return;
|
|
650
|
+
const s = this.#vt();
|
|
651
|
+
for (const r of this.#S) {
|
|
652
|
+
const n = s >= 1 ? 1 : r.orientation === "vertical" ? this.#Bt(s, r.coord) : E(s);
|
|
634
653
|
if (n <= 0) continue;
|
|
635
654
|
const a = t.context.globalAlpha;
|
|
636
|
-
n < 1 && (t.context.globalAlpha = a * n),
|
|
655
|
+
n < 1 && (t.context.globalAlpha = a * n), Xt({
|
|
637
656
|
scope: t,
|
|
638
657
|
timeScale: this.timeScale,
|
|
639
658
|
yScale: this.getYScale(r.scale),
|
|
640
|
-
theme: this.#
|
|
659
|
+
theme: this.#h,
|
|
641
660
|
line: {
|
|
642
661
|
orientation: r.orientation,
|
|
643
662
|
coord: r.coord,
|
|
644
|
-
color: r.color ?? this.#
|
|
663
|
+
color: r.color ?? this.#h.line.color,
|
|
645
664
|
style: r.style,
|
|
646
665
|
width: r.width,
|
|
647
666
|
label: r.label
|
|
@@ -658,20 +677,20 @@ class _e extends Et {
|
|
|
658
677
|
* underlying animator mutates between frames.
|
|
659
678
|
*/
|
|
660
679
|
getAnimationState() {
|
|
661
|
-
return this.#
|
|
680
|
+
return this.#yt(this.#e.getAnimationState());
|
|
662
681
|
}
|
|
663
682
|
/** The engine animates Y in scale space (the scale's forward); readers outside it get values. */
|
|
664
|
-
#
|
|
683
|
+
#yt(t, e = this.yScale) {
|
|
665
684
|
const i = e.getTransform();
|
|
666
|
-
return i === null ? t : { ...t, yRange:
|
|
685
|
+
return i === null ? t : { ...t, yRange: zt(t.yRange, i) };
|
|
667
686
|
}
|
|
668
687
|
/** The animation state as a named scale's series see it: its own Y, in values. */
|
|
669
|
-
#
|
|
688
|
+
#Et(t, e) {
|
|
670
689
|
const i = this.#e.getScaleYRange(e) ?? t.yRange;
|
|
671
|
-
return this.#
|
|
690
|
+
return this.#yt({ ...t, yRange: i }, this.getYScale(e));
|
|
672
691
|
}
|
|
673
692
|
/** `isPlottable` of a scale (`undefined` = default), as a predicate for the guard helpers. */
|
|
674
|
-
#
|
|
693
|
+
#xt(t) {
|
|
675
694
|
const e = this.getYScale(t);
|
|
676
695
|
return (i) => e.isPlottable(i);
|
|
677
696
|
}
|
|
@@ -701,10 +720,10 @@ class _e extends Et {
|
|
|
701
720
|
* has actually been observed in progress, so an annotation drawn on a chart
|
|
702
721
|
* that has no data yet still rides the reveal once data arrives.
|
|
703
722
|
*/
|
|
704
|
-
#
|
|
705
|
-
if (this.#
|
|
723
|
+
#vt() {
|
|
724
|
+
if (this.#Rt) return 1;
|
|
706
725
|
const t = this.getIntroFront();
|
|
707
|
-
return t < 1 ? (this.#
|
|
726
|
+
return t < 1 ? (this.#Dt = !0, t) : (this.#Dt && (this.#Rt = !0), 1);
|
|
708
727
|
}
|
|
709
728
|
/**
|
|
710
729
|
* Entrance alpha for an overlay pinned at `time`, given the intro reveal
|
|
@@ -712,10 +731,10 @@ class _e extends Et {
|
|
|
712
731
|
* then fades in over a short band — so annotations surface in step with the
|
|
713
732
|
* series drawing past them. `1` once the intro has settled.
|
|
714
733
|
*/
|
|
715
|
-
#
|
|
734
|
+
#Bt(t, e) {
|
|
716
735
|
if (t >= 1) return 1;
|
|
717
736
|
const { from: i, to: s } = this.timeScale.getRange(), r = s - i, n = r > 0 ? (e - i) / r : 0;
|
|
718
|
-
return
|
|
737
|
+
return Jt((t - n) / 0.12, 0, 1);
|
|
719
738
|
}
|
|
720
739
|
/**
|
|
721
740
|
* Replace all data for a series.
|
|
@@ -732,24 +751,24 @@ class _e extends Et {
|
|
|
732
751
|
setSeriesData(t, e, i) {
|
|
733
752
|
const s = this.#t.find((a) => a.id === t);
|
|
734
753
|
if (!s) return;
|
|
735
|
-
const r = this.#
|
|
736
|
-
if (this.#
|
|
754
|
+
const r = this.#n === "category" && this.#kt(s);
|
|
755
|
+
if (this.#nt = !r, !this.#kt(s)) {
|
|
737
756
|
s.renderer.setData(e, i);
|
|
738
757
|
return;
|
|
739
758
|
}
|
|
740
|
-
const n = this.#
|
|
759
|
+
const n = this.#Xt(s, e ?? []);
|
|
741
760
|
if (!r) {
|
|
742
761
|
s.renderer.setData(n, i);
|
|
743
762
|
return;
|
|
744
763
|
}
|
|
745
|
-
this.#
|
|
764
|
+
this.#bt({ entry: s, layerIndex: i, mutate: () => n });
|
|
746
765
|
}
|
|
747
766
|
/** Append a new data point to the end of a series (real-time tick). */
|
|
748
767
|
appendData(t, e, i) {
|
|
749
768
|
const s = this.#t.find((n) => n.id === t);
|
|
750
769
|
if (s === void 0 || s.renderer.appendPoint === void 0) return;
|
|
751
770
|
const r = s.renderer.appendPoint.bind(s.renderer);
|
|
752
|
-
this.#
|
|
771
|
+
this.#St({
|
|
753
772
|
entry: s,
|
|
754
773
|
layerIndex: i,
|
|
755
774
|
points: [e],
|
|
@@ -763,19 +782,19 @@ class _e extends Et {
|
|
|
763
782
|
* category axis applies `mutateCategory` to the layer's input-order points
|
|
764
783
|
* instead, then re-sets the store from them.
|
|
765
784
|
*/
|
|
766
|
-
#
|
|
785
|
+
#St(t) {
|
|
767
786
|
const { entry: e, apply: i } = t;
|
|
768
|
-
if (!this.#
|
|
787
|
+
if (!this.#kt(e)) {
|
|
769
788
|
i(t.points.slice());
|
|
770
789
|
return;
|
|
771
790
|
}
|
|
772
|
-
const s = this.#
|
|
791
|
+
const s = this.#Xt(e, t.points);
|
|
773
792
|
if (s.length !== 0) {
|
|
774
|
-
if (this.#
|
|
793
|
+
if (this.#n === "numeric") {
|
|
775
794
|
i(s);
|
|
776
795
|
return;
|
|
777
796
|
}
|
|
778
|
-
this.#
|
|
797
|
+
this.#bt({
|
|
779
798
|
entry: e,
|
|
780
799
|
layerIndex: t.layerIndex,
|
|
781
800
|
mutate: (r) => t.mutateCategory(r, s)
|
|
@@ -783,35 +802,35 @@ class _e extends Et {
|
|
|
783
802
|
}
|
|
784
803
|
}
|
|
785
804
|
/** Replace a category layer's input-order points with `mutate`'s result and sync the categories and stores. */
|
|
786
|
-
#
|
|
805
|
+
#bt(t) {
|
|
787
806
|
const { entry: e } = t, i = t.layerIndex ?? 0;
|
|
788
|
-
e.categoryPoints[i] = t.mutate(e.categoryPoints[i] ?? []), this.#
|
|
807
|
+
e.categoryPoints[i] = t.mutate(e.categoryPoints[i] ?? []), this.#Zt({ entry: e, layerIndex: i });
|
|
789
808
|
}
|
|
790
809
|
/** Whether `entry`'s points go through the numeric / category ingest. */
|
|
791
|
-
#
|
|
792
|
-
return this.#
|
|
810
|
+
#kt(t) {
|
|
811
|
+
return this.#n !== "time" && S(t.renderer);
|
|
793
812
|
}
|
|
794
813
|
/**
|
|
795
814
|
* Points that fit the X axis, a numeric one with its `x` copied to `time`.
|
|
796
815
|
* The rest are skipped with a dev warning, as is a series mixing `x` and `time`.
|
|
797
816
|
*/
|
|
798
|
-
#
|
|
817
|
+
#Xt(t, e) {
|
|
799
818
|
const i = [];
|
|
800
819
|
for (const s of e) {
|
|
801
820
|
const r = s.x !== void 0;
|
|
802
|
-
if (r && (t.xKeys.x = !0), s.time !== void 0 && (t.xKeys.time = !0), !(this.#
|
|
803
|
-
this.#
|
|
821
|
+
if (r && (t.xKeys.x = !0), s.time !== void 0 && (t.xKeys.time = !0), !(this.#n === "category" ? typeof s.x == "string" : !r || typeof s.x == "number")) {
|
|
822
|
+
this.#V(
|
|
804
823
|
`x-misfit:${t.id}`,
|
|
805
|
-
() =>
|
|
824
|
+
() => Nt({ seriesId: t.id, axisType: this.#n, x: s.x })
|
|
806
825
|
);
|
|
807
826
|
continue;
|
|
808
827
|
}
|
|
809
|
-
i.push(r && this.#
|
|
828
|
+
i.push(r && this.#n === "numeric" ? { ...s, time: s.x } : s);
|
|
810
829
|
}
|
|
811
|
-
return t.xKeys.x && t.xKeys.time && this.#
|
|
830
|
+
return t.xKeys.x && t.xKeys.time && this.#V(`x-mixed:${t.id}`, () => Ft({ seriesId: t.id })), i;
|
|
812
831
|
}
|
|
813
832
|
/** Category points with `time` set to their band index. */
|
|
814
|
-
#
|
|
833
|
+
#ve(t) {
|
|
815
834
|
return t.map((e) => ({ ...e, time: this.#Y.get(e.x) }));
|
|
816
835
|
}
|
|
817
836
|
/**
|
|
@@ -819,7 +838,7 @@ class _e extends Et {
|
|
|
819
838
|
* order, then layers, then points in input order) — and re-set every store
|
|
820
839
|
* whose band indices moved, plus the `changed` layer.
|
|
821
840
|
*/
|
|
822
|
-
#
|
|
841
|
+
#Zt(t) {
|
|
823
842
|
const e = /* @__PURE__ */ new Set();
|
|
824
843
|
for (const a of this.#t)
|
|
825
844
|
for (const o of a.categoryPoints)
|
|
@@ -828,21 +847,21 @@ class _e extends Et {
|
|
|
828
847
|
const i = [...e], s = this.timeScale.getCategories(), r = i.length !== s.length || i.some((a, o) => a !== s[o]), n = this.#Y;
|
|
829
848
|
this.#Y = new Map(i.map((a, o) => [a, o])), this.timeScale.setCategories(i), this.batch(() => {
|
|
830
849
|
for (const a of this.#t)
|
|
831
|
-
this.#
|
|
850
|
+
this.#Se({ entry: a, previous: n, changed: t });
|
|
832
851
|
r && this.onDataChanged();
|
|
833
852
|
});
|
|
834
853
|
}
|
|
835
854
|
/** Re-set `entry`'s layers whose points moved band, or that `changed` names, from their input-order points. */
|
|
836
|
-
#
|
|
855
|
+
#Se(t) {
|
|
837
856
|
const { entry: e, previous: i, changed: s } = t;
|
|
838
857
|
for (let r = 0; r < e.categoryPoints.length; r++) {
|
|
839
858
|
const n = e.categoryPoints[r] ?? [], a = s?.entry === e && s.layerIndex === r, o = n.some(
|
|
840
|
-
(
|
|
859
|
+
(c) => i.get(c.x) !== this.#Y.get(c.x)
|
|
841
860
|
);
|
|
842
861
|
if (!a && !o) continue;
|
|
843
|
-
const h = this.#
|
|
844
|
-
const f = i.get(
|
|
845
|
-
return f !== void 0 && f !== this.#Y.get(
|
|
862
|
+
const h = this.#ve(n).sort((c, f) => c.time - f.time), l = n.some((c) => {
|
|
863
|
+
const f = i.get(c.x);
|
|
864
|
+
return f !== void 0 && f !== this.#Y.get(c.x);
|
|
846
865
|
});
|
|
847
866
|
a && !l && e.renderer.morphData !== void 0 ? e.renderer.morphData(h, r) : e.renderer.setData(h, r);
|
|
848
867
|
}
|
|
@@ -863,10 +882,10 @@ class _e extends Et {
|
|
|
863
882
|
prependData(t, e, i) {
|
|
864
883
|
const s = this.#t.find((a) => a.id === t);
|
|
865
884
|
if (s === void 0 || s.renderer.prependPoints === void 0) return;
|
|
866
|
-
const r = this.#
|
|
867
|
-
r !== null && s.renderer.setHistoryHandoff !== void 0 && performance.now() - r.at <
|
|
885
|
+
const r = this.#ct.left;
|
|
886
|
+
r !== null && s.renderer.setHistoryHandoff !== void 0 && performance.now() - r.at < re && (s.renderer.setHistoryHandoff(r.bars), this.#E.left = !0, this.#K.left = null, this.#ct.left = null, this.#d.markDirty());
|
|
868
887
|
const n = s.renderer.prependPoints.bind(s.renderer);
|
|
869
|
-
this.#
|
|
888
|
+
this.#St({
|
|
870
889
|
entry: s,
|
|
871
890
|
layerIndex: i,
|
|
872
891
|
points: e,
|
|
@@ -879,7 +898,7 @@ class _e extends Et {
|
|
|
879
898
|
const s = this.#t.find((n) => n.id === t);
|
|
880
899
|
if (s === void 0 || s.renderer.updateLastPoint === void 0) return;
|
|
881
900
|
const r = s.renderer.updateLastPoint.bind(s.renderer);
|
|
882
|
-
this.#
|
|
901
|
+
this.#St({
|
|
883
902
|
entry: s,
|
|
884
903
|
layerIndex: i,
|
|
885
904
|
points: [e],
|
|
@@ -904,11 +923,11 @@ class _e extends Et {
|
|
|
904
923
|
keepLast(t, e, i) {
|
|
905
924
|
const s = this.#t.find((r) => r.id === t);
|
|
906
925
|
if (s?.renderer.keepLast !== void 0) {
|
|
907
|
-
if (this.#
|
|
926
|
+
if (this.#n !== "category") {
|
|
908
927
|
s.renderer.keepLast(e, i);
|
|
909
928
|
return;
|
|
910
929
|
}
|
|
911
|
-
this.#
|
|
930
|
+
this.#bt({
|
|
912
931
|
entry: s,
|
|
913
932
|
layerIndex: i,
|
|
914
933
|
mutate: (r) => e < 0 ? [...r] : r.slice(Math.max(0, r.length - e))
|
|
@@ -920,21 +939,21 @@ class _e extends Et {
|
|
|
920
939
|
* (time series) moves it onto a named Y scale, `undefined` back to the default.
|
|
921
940
|
*/
|
|
922
941
|
updateSeriesOptions(t, e) {
|
|
923
|
-
const i = this.#t.find((
|
|
942
|
+
const i = this.#t.find((y) => y.id === t);
|
|
924
943
|
if (!i) return;
|
|
925
944
|
const { scale: s, ...r } = e, n = "scale" in e, a = n ? s : i.scale;
|
|
926
945
|
if (("stacking" in e || n) && a === void 0) {
|
|
927
|
-
const
|
|
928
|
-
|
|
946
|
+
const y = "stacking" in e ? e.stacking : ot(i.renderer);
|
|
947
|
+
I({ seriesId: t, stacking: y, isPlottable: this.#xt(a) });
|
|
929
948
|
}
|
|
930
949
|
const o = i.labels, h = i.renderer.getLayerColors().slice(), l = this.#g.overrides(i.renderer.kind);
|
|
931
950
|
i.renderer.updateOptions({ ...r, ...l }), "label" in e && typeof e.label == "string" && (i.labels = [e.label]), this.#i.markDirty();
|
|
932
|
-
const
|
|
951
|
+
const c = this.#I(i);
|
|
933
952
|
i.scale = a;
|
|
934
|
-
const f = this.#
|
|
935
|
-
f && this.#
|
|
936
|
-
const
|
|
937
|
-
(
|
|
953
|
+
const f = this.#I(i) !== c;
|
|
954
|
+
f && this.#Me();
|
|
955
|
+
const g = i.renderer.getLayerColors(), u = h.length !== g.length || h.some((y, p) => y !== g[p]), m = !at(o, i.labels);
|
|
956
|
+
(u || m || f) && this.#m();
|
|
938
957
|
}
|
|
939
958
|
/**
|
|
940
959
|
* Batch multiple updates: suppress recomputes until `fn` returns. Exceptions
|
|
@@ -946,14 +965,14 @@ class _e extends Et {
|
|
|
946
965
|
t();
|
|
947
966
|
} finally {
|
|
948
967
|
if (--this.#R <= 0) {
|
|
949
|
-
if (this.#R = 0, this.#
|
|
950
|
-
this.#
|
|
951
|
-
else if (this.#
|
|
952
|
-
this.#
|
|
968
|
+
if (this.#R = 0, this.#dt)
|
|
969
|
+
this.#dt = !1, this.#B = !1, this.onDataChanged();
|
|
970
|
+
else if (this.#B) {
|
|
971
|
+
this.#B = !1, this.#u = !0;
|
|
953
972
|
const e = performance.now();
|
|
954
973
|
this.#e.onSeriesVisibilityChanged(e), this.#x(e), this.#i.markDirty();
|
|
955
974
|
}
|
|
956
|
-
this.#
|
|
975
|
+
this.#ut && (this.#ut = !1, this.emit("overlayChange"));
|
|
957
976
|
}
|
|
958
977
|
}
|
|
959
978
|
}
|
|
@@ -967,13 +986,13 @@ class _e extends Et {
|
|
|
967
986
|
setSeriesVisible(t, e) {
|
|
968
987
|
const i = this.#t.find((n) => n.id === t);
|
|
969
988
|
if (!i || i.visible === e) return;
|
|
970
|
-
i.visible = e, this.#
|
|
989
|
+
i.visible = e, this.#m(), this.#rt();
|
|
971
990
|
const s = this.#g.toggleMs;
|
|
972
991
|
if (i.renderer.setAlpha?.(e ? 1 : 0, s), this.#i.markDirty(), this.#R > 0) {
|
|
973
|
-
this.#
|
|
992
|
+
this.#B = !0;
|
|
974
993
|
return;
|
|
975
994
|
}
|
|
976
|
-
this.#
|
|
995
|
+
this.#u = !0;
|
|
977
996
|
const r = performance.now();
|
|
978
997
|
this.#e.onSeriesVisibilityChanged(r), this.#x(r);
|
|
979
998
|
}
|
|
@@ -1003,28 +1022,28 @@ class _e extends Et {
|
|
|
1003
1022
|
setLayerVisible(t, e, i) {
|
|
1004
1023
|
const s = this.#t.find((a) => a.id === t);
|
|
1005
1024
|
if (!s || s.renderer.getLayerCount() <= 1 || s.renderer.isLayerVisible(e) === i) return;
|
|
1006
|
-
s.renderer.setLayerVisible(e, i), this.#
|
|
1025
|
+
s.renderer.setLayerVisible(e, i), this.#m();
|
|
1007
1026
|
const r = this.#g.toggleMs;
|
|
1008
1027
|
if (s.renderer.setLayerAlpha?.(e, i ? 1 : 0, r), this.#i.markDirty(), this.#R > 0) {
|
|
1009
|
-
this.#
|
|
1028
|
+
this.#B = !0;
|
|
1010
1029
|
return;
|
|
1011
1030
|
}
|
|
1012
|
-
this.#
|
|
1031
|
+
this.#u = !0;
|
|
1013
1032
|
const n = performance.now();
|
|
1014
1033
|
this.#e.onSeriesVisibilityChanged(n), this.#x(n);
|
|
1015
1034
|
}
|
|
1016
1035
|
isLayerVisible(t, e) {
|
|
1017
1036
|
return this.#t.find((i) => i.id === t)?.renderer.isLayerVisible(e) ?? !0;
|
|
1018
1037
|
}
|
|
1019
|
-
/** Auto-fit the viewport to show all data across every series. */
|
|
1038
|
+
/** Auto-fit the viewport to show all data across every series, however many bars that is. */
|
|
1020
1039
|
fitContent() {
|
|
1021
1040
|
const { first: t, last: e } = this.getDataBounds();
|
|
1022
1041
|
if (t === void 0 || e === void 0) return;
|
|
1023
|
-
const i = this.#
|
|
1024
|
-
this.#
|
|
1042
|
+
const i = this.#c.size.media.width - this.#k();
|
|
1043
|
+
this.#et(), this.#At({ firstTime: t, lastTime: e, chartWidth: i }), this.#te({ xEase: !0 });
|
|
1025
1044
|
}
|
|
1026
1045
|
getVisibleRange() {
|
|
1027
|
-
return this.#
|
|
1046
|
+
return this.#a.from === 0 && this.#a.to === 0 ? this.#e.getAnimationState().xRange : this.#a;
|
|
1028
1047
|
}
|
|
1029
1048
|
/**
|
|
1030
1049
|
* Return the full span of registered data, or `null` before any data has
|
|
@@ -1032,7 +1051,7 @@ class _e extends Et {
|
|
|
1032
1051
|
* tracking and is cheaper than recomputing from series stores.
|
|
1033
1052
|
*/
|
|
1034
1053
|
getDataRange() {
|
|
1035
|
-
return this.#
|
|
1054
|
+
return this.#T === null || this.#s === null ? null : { from: this.#T, to: this.#s };
|
|
1036
1055
|
}
|
|
1037
1056
|
/**
|
|
1038
1057
|
* Imperatively set the visible time range. Three forms:
|
|
@@ -1059,31 +1078,44 @@ class _e extends Et {
|
|
|
1059
1078
|
* lockstep rather than lagging behind on the long sticky contract.
|
|
1060
1079
|
*/
|
|
1061
1080
|
setVisibleRange(t, e) {
|
|
1081
|
+
const i = this.#_t(t);
|
|
1082
|
+
if (i !== null) {
|
|
1083
|
+
if (this.#et(), e?.gesture && me(t)) {
|
|
1084
|
+
i && this.#He();
|
|
1085
|
+
return;
|
|
1086
|
+
}
|
|
1087
|
+
this.#te();
|
|
1088
|
+
}
|
|
1089
|
+
}
|
|
1090
|
+
/**
|
|
1091
|
+
* Write `spec` into the logical X range, the autoscroll flag and the warm-up
|
|
1092
|
+
* hold, without touching the engine. Returns whether the range changed, or
|
|
1093
|
+
* `null` when the spec is invalid or a bar count has no data to count back from.
|
|
1094
|
+
*/
|
|
1095
|
+
#_t(t) {
|
|
1062
1096
|
if (typeof t == "number") {
|
|
1063
|
-
if (!
|
|
1064
|
-
const { first:
|
|
1065
|
-
if (
|
|
1066
|
-
const
|
|
1067
|
-
this.#
|
|
1068
|
-
return;
|
|
1097
|
+
if (!M(t)) return null;
|
|
1098
|
+
const { first: s, last: r } = this.getDataBounds();
|
|
1099
|
+
if (s === void 0 || r === void 0) return null;
|
|
1100
|
+
const n = Math.max(s, r - (t - 1) * this.#r), a = this.#c.size.media.width - this.#k();
|
|
1101
|
+
return this.#At({ firstTime: n, lastTime: r, chartWidth: a });
|
|
1069
1102
|
}
|
|
1070
1103
|
if ("bars" in t) {
|
|
1071
|
-
if (!
|
|
1072
|
-
const
|
|
1073
|
-
this.#p = this.#s !== null && this.#s >=
|
|
1074
|
-
|
|
1104
|
+
if (!M(t.bars)) return null;
|
|
1105
|
+
const s = k(t.from), r = s + t.bars * this.#r;
|
|
1106
|
+
this.#p = this.#s !== null && this.#s >= s && this.#s <= r;
|
|
1107
|
+
const n = this.#D({ from: s, to: r }, { emitChange: !0 });
|
|
1108
|
+
return this.#L = !0, n;
|
|
1075
1109
|
}
|
|
1076
|
-
const
|
|
1077
|
-
this.#p = this.#s !== null && this.#s >=
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
}
|
|
1083
|
-
this.#st();
|
|
1110
|
+
const e = k(t.from), i = k(t.to);
|
|
1111
|
+
return this.#p = this.#s !== null && this.#s >= e && this.#s <= i, this.#L = !1, this.#D({ from: e, to: i }, { emitChange: !0 });
|
|
1112
|
+
}
|
|
1113
|
+
/** The user or the app took over the view: drop `initialRange` and stop growing the chart's own fit. */
|
|
1114
|
+
#et() {
|
|
1115
|
+
this.#H = void 0, this.#G = !1;
|
|
1084
1116
|
}
|
|
1085
1117
|
getYRange() {
|
|
1086
|
-
return this.#
|
|
1118
|
+
return this.#w.range;
|
|
1087
1119
|
}
|
|
1088
1120
|
getCrosshairPosition() {
|
|
1089
1121
|
return this.#f;
|
|
@@ -1124,7 +1156,7 @@ class _e extends Et {
|
|
|
1124
1156
|
setCrosshair(t) {
|
|
1125
1157
|
if (t === null) {
|
|
1126
1158
|
if (this.#f === null) return;
|
|
1127
|
-
this.#f = null, this.#
|
|
1159
|
+
this.#f = null, this.#d.markDirty(), this.emit("crosshairMove", null);
|
|
1128
1160
|
return;
|
|
1129
1161
|
}
|
|
1130
1162
|
const { time: e } = t;
|
|
@@ -1133,19 +1165,19 @@ class _e extends Et {
|
|
|
1133
1165
|
let s;
|
|
1134
1166
|
if (t.y !== void 0 ? s = t.y : i !== null ? s = i.y : s = this.yScale.yToValue(this.yScale.getMediaHeight() / 2), !Number.isFinite(s) || i !== null && i.time === e && i.y === s) return;
|
|
1135
1167
|
const r = this.plotLeft + this.timeScale.timeToX(e), n = this.yScale.valueToY(s);
|
|
1136
|
-
this.#
|
|
1168
|
+
this.#lt = "time", this.#f = { mediaX: r, mediaY: n, time: e, x: this.timeScale.domainValue(e), y: s }, this.#d.markDirty(), this.emit("crosshairMove", this.#f);
|
|
1137
1169
|
}
|
|
1138
1170
|
/** Get the last visible value and whether the absolute last point is on screen. */
|
|
1139
1171
|
getLastValue(t) {
|
|
1140
|
-
return
|
|
1172
|
+
return bt(t, this.#t, this.#e.getAnimationState().xRange);
|
|
1141
1173
|
}
|
|
1142
1174
|
/** Get the second-to-last value, useful for computing change. */
|
|
1143
1175
|
getPreviousClose(t) {
|
|
1144
|
-
return
|
|
1176
|
+
return kt(t, this.#t);
|
|
1145
1177
|
}
|
|
1146
1178
|
getLastData(t) {
|
|
1147
1179
|
const e = this.#t.find((i) => i.id === t);
|
|
1148
|
-
return !e || !
|
|
1180
|
+
return !e || !S(e.renderer) ? null : e.renderer.getLastDataPoint();
|
|
1149
1181
|
}
|
|
1150
1182
|
/** Find the data point closest to the given timestamp within one data interval. */
|
|
1151
1183
|
getDataAtTime(t, e) {
|
|
@@ -1169,10 +1201,10 @@ class _e extends Et {
|
|
|
1169
1201
|
* past a wide gap is still the nearest.
|
|
1170
1202
|
*/
|
|
1171
1203
|
#X() {
|
|
1172
|
-
return this.#
|
|
1204
|
+
return this.#n === "category" ? 0.5 : this.#n === "time" || this.#T === null || this.#s === null ? this.#r : Math.max(this.#r, this.#s - this.#T);
|
|
1173
1205
|
}
|
|
1174
1206
|
getSeriesIds() {
|
|
1175
|
-
return this.#
|
|
1207
|
+
return this.#F || (this.#F = this.#t.map((t) => t.id)), this.#F.slice();
|
|
1176
1208
|
}
|
|
1177
1209
|
/**
|
|
1178
1210
|
* True if any visible series has a time axis (line / bar / candlestick).
|
|
@@ -1180,9 +1212,9 @@ class _e extends Et {
|
|
|
1180
1212
|
* has no meaningful x/y coordinate system, so the dashed hairlines would
|
|
1181
1213
|
* just be visual noise.
|
|
1182
1214
|
*/
|
|
1183
|
-
#
|
|
1215
|
+
#Gt() {
|
|
1184
1216
|
for (const t of this.#t)
|
|
1185
|
-
if (t.visible &&
|
|
1217
|
+
if (t.visible && S(t.renderer))
|
|
1186
1218
|
return !0;
|
|
1187
1219
|
return !1;
|
|
1188
1220
|
}
|
|
@@ -1192,8 +1224,8 @@ class _e extends Et {
|
|
|
1192
1224
|
* to reserve and nothing slides under an axis column. Reads registration,
|
|
1193
1225
|
* not visibility — a legend toggle must not shift the layout.
|
|
1194
1226
|
*/
|
|
1195
|
-
#
|
|
1196
|
-
return this.#t.length === 0 ? !1 : this.#t.every((t) => !
|
|
1227
|
+
#it() {
|
|
1228
|
+
return this.#t.length === 0 ? !1 : this.#t.every((t) => !S(t.renderer));
|
|
1197
1229
|
}
|
|
1198
1230
|
#Z() {
|
|
1199
1231
|
return {
|
|
@@ -1206,8 +1238,8 @@ class _e extends Et {
|
|
|
1206
1238
|
}
|
|
1207
1239
|
/** Reassign the Y-axis columns, then resync the scales if the gutters moved
|
|
1208
1240
|
* and let DOM axis / label components re-read the layout, as they do after a resize. */
|
|
1209
|
-
#
|
|
1210
|
-
this.#
|
|
1241
|
+
#st(t) {
|
|
1242
|
+
this.#Tt();
|
|
1211
1243
|
const e = this.#Z();
|
|
1212
1244
|
(e.yAxisWidth !== t.yAxisWidth || e.xAxisHeight !== t.xAxisHeight || e.yAxisPosition !== t.yAxisPosition || e.leftWidth !== t.leftWidth || e.rightWidth !== t.rightWidth) && (this.syncScales(), this.emit("viewportChange"), this.#i.markDirty());
|
|
1213
1245
|
}
|
|
@@ -1218,7 +1250,7 @@ class _e extends Et {
|
|
|
1218
1250
|
* capturing wheel and touch events, so the page scrolls normally under the cursor.
|
|
1219
1251
|
*/
|
|
1220
1252
|
canPanZoom() {
|
|
1221
|
-
return (this.#v.x?.panZoom ?? this.#
|
|
1253
|
+
return (this.#v.x?.panZoom ?? this.#n !== "category") && this.#Gt();
|
|
1222
1254
|
}
|
|
1223
1255
|
/**
|
|
1224
1256
|
* Whether a time-only feature (Navigator, EdgeLoader, TimeRegion) can run
|
|
@@ -1228,7 +1260,7 @@ class _e extends Et {
|
|
|
1228
1260
|
* @internal
|
|
1229
1261
|
*/
|
|
1230
1262
|
checkTimeOnlyFeature(t) {
|
|
1231
|
-
return this.#
|
|
1263
|
+
return this.#n === "time" ? !0 : (this.#V(`time-only:${t}`, () => Wt({ feature: t, axisType: this.#n })), !1);
|
|
1232
1264
|
}
|
|
1233
1265
|
/**
|
|
1234
1266
|
* Push the current pan/zoom capability into the interaction layer (canvas
|
|
@@ -1237,8 +1269,8 @@ class _e extends Et {
|
|
|
1237
1269
|
* every mutation that can flip {@link canPanZoom}: series add/remove and
|
|
1238
1270
|
* series visibility.
|
|
1239
1271
|
*/
|
|
1240
|
-
#
|
|
1241
|
-
this.#
|
|
1272
|
+
#rt() {
|
|
1273
|
+
this.#N?.syncPanZoomMode();
|
|
1242
1274
|
}
|
|
1243
1275
|
/**
|
|
1244
1276
|
* Filter `getSeriesIds()` by renderer type. A concrete kind (`'pie'`,
|
|
@@ -1254,7 +1286,7 @@ class _e extends Et {
|
|
|
1254
1286
|
getSeriesIdsByType(t, e) {
|
|
1255
1287
|
const i = e?.visibleOnly === !0, s = e?.singleLayerOnly === !0, r = [];
|
|
1256
1288
|
for (const n of this.#t) {
|
|
1257
|
-
if (!(t === "time" ?
|
|
1289
|
+
if (!(t === "time" ? S(n.renderer) : n.renderer.kind === t)) continue;
|
|
1258
1290
|
const a = n.renderer.getLayerCount();
|
|
1259
1291
|
if (!(s && a > 1)) {
|
|
1260
1292
|
if (i) {
|
|
@@ -1281,7 +1313,7 @@ class _e extends Et {
|
|
|
1281
1313
|
* Returns `null` for unknown ids or empty series.
|
|
1282
1314
|
*/
|
|
1283
1315
|
getStackedLastValue(t) {
|
|
1284
|
-
return
|
|
1316
|
+
return Tt(t, this.#t, this.#e.getAnimationState().xRange);
|
|
1285
1317
|
}
|
|
1286
1318
|
/**
|
|
1287
1319
|
* Stacked value at an arbitrary `time` — the cumulative stack top at that
|
|
@@ -1296,7 +1328,7 @@ class _e extends Et {
|
|
|
1296
1328
|
const s = i.renderer.getStackedValueAtTime?.(e, this.#X());
|
|
1297
1329
|
if (s != null) return s;
|
|
1298
1330
|
const r = i.renderer.getDataAtTime?.(e, this.#X());
|
|
1299
|
-
return !r ||
|
|
1331
|
+
return !r || ie(r) ? null : Q(r);
|
|
1300
1332
|
}
|
|
1301
1333
|
/**
|
|
1302
1334
|
* Per-layer last snapshots with each layer's own `time`. Returns `null`
|
|
@@ -1320,7 +1352,7 @@ class _e extends Et {
|
|
|
1320
1352
|
/** Get the primary display color for a series. */
|
|
1321
1353
|
getSeriesColor(t) {
|
|
1322
1354
|
const e = this.#t.find((i) => i.id === t);
|
|
1323
|
-
return e ? e.renderer.getLayerColors()[0] ?? this.#
|
|
1355
|
+
return e ? e.renderer.getLayerColors()[0] ?? this.#h.line.color : null;
|
|
1324
1356
|
}
|
|
1325
1357
|
/** The series' primary name (first layer). Used for single-layer overlays. */
|
|
1326
1358
|
getSeriesLabel(t) {
|
|
@@ -1338,7 +1370,7 @@ class _e extends Et {
|
|
|
1338
1370
|
*/
|
|
1339
1371
|
setSeriesLabels(t, e) {
|
|
1340
1372
|
const i = this.#t.find((s) => s.id === t);
|
|
1341
|
-
!i ||
|
|
1373
|
+
!i || at(i.labels, e) || (i.labels = e, this.#m());
|
|
1342
1374
|
}
|
|
1343
1375
|
/**
|
|
1344
1376
|
* Set the per-layer color overrides carried in `data` (sparse — `undefined`
|
|
@@ -1349,7 +1381,7 @@ class _e extends Et {
|
|
|
1349
1381
|
*/
|
|
1350
1382
|
setLayerColors(t, e) {
|
|
1351
1383
|
const i = this.#t.find((s) => s.id === t);
|
|
1352
|
-
!i ||
|
|
1384
|
+
!i || xe(i.colorOverrides, e) || (i.colorOverrides = e, i.renderer.setColorOverrides?.(e), this.#i.markDirty(), this.#m());
|
|
1353
1385
|
}
|
|
1354
1386
|
/** Get per-layer colors for a series. Returns null for single-layer non-bar/line series. */
|
|
1355
1387
|
getSeriesLayers(t) {
|
|
@@ -1362,50 +1394,50 @@ class _e extends Et {
|
|
|
1362
1394
|
}
|
|
1363
1395
|
/** Get all slices with computed colors and percentages. Returns null for series without slice data (e.g. candlestick, line, bar). */
|
|
1364
1396
|
getSliceInfo(t) {
|
|
1365
|
-
return this.#t.find((e) => e.id === t)?.renderer.getSliceInfo?.(this.#
|
|
1397
|
+
return this.#t.find((e) => e.id === t)?.renderer.getSliceInfo?.(this.#h) ?? null;
|
|
1366
1398
|
}
|
|
1367
1399
|
/** Get hover info (label/value/percent/color) for the currently hovered element, or null. */
|
|
1368
1400
|
getHoverInfo(t) {
|
|
1369
|
-
return this.#t.find((e) => e.id === t)?.renderer.getHoverInfo?.(this.#
|
|
1401
|
+
return this.#t.find((e) => e.id === t)?.renderer.getHoverInfo?.(this.#h) ?? null;
|
|
1370
1402
|
}
|
|
1371
1403
|
/** Apply a new theme and update series colors where appropriate. */
|
|
1372
1404
|
setTheme(t) {
|
|
1373
|
-
const e = this.#
|
|
1374
|
-
this.#
|
|
1405
|
+
const e = this.#h;
|
|
1406
|
+
this.#h = t;
|
|
1375
1407
|
for (const i of this.#t)
|
|
1376
1408
|
i.renderer.applyTheme(t, e);
|
|
1377
|
-
this.#i.markDirty(), this.#
|
|
1409
|
+
this.#i.markDirty(), this.#m();
|
|
1378
1410
|
}
|
|
1379
1411
|
getTheme() {
|
|
1380
|
-
return this.#
|
|
1412
|
+
return this.#h;
|
|
1381
1413
|
}
|
|
1382
1414
|
/** BCP 47 locale applied to the built-in time-axis / tooltip / crosshair formatting. */
|
|
1383
1415
|
setLocale(t) {
|
|
1384
|
-
this.timeScale.setLocale(t), this.#
|
|
1416
|
+
this.timeScale.setLocale(t), this.#m();
|
|
1385
1417
|
}
|
|
1386
1418
|
getLocale() {
|
|
1387
1419
|
return this.timeScale.getLocale();
|
|
1388
1420
|
}
|
|
1389
1421
|
/** IANA timezone applied to the same built-in date-time formatting. */
|
|
1390
1422
|
setTimeZone(t) {
|
|
1391
|
-
this.timeScale.setTimeZone(t), this.#
|
|
1423
|
+
this.timeScale.setTimeZone(t), this.#m();
|
|
1392
1424
|
}
|
|
1393
1425
|
getTimeZone() {
|
|
1394
1426
|
return this.timeScale.getTimeZone();
|
|
1395
1427
|
}
|
|
1396
1428
|
/** Update axis configuration and re-render. */
|
|
1397
1429
|
setAxis(t) {
|
|
1398
|
-
const e = t.y?.scale ?? null, i = (
|
|
1399
|
-
for (const
|
|
1400
|
-
!
|
|
1430
|
+
const e = t.y?.scale ?? null, i = (c) => q(e, c);
|
|
1431
|
+
for (const c of this.#t)
|
|
1432
|
+
!S(c.renderer) || c.scale !== void 0 || I({ seriesId: c.id, stacking: c.renderer.stacking, isPlottable: i });
|
|
1401
1433
|
const s = this.#Z(), r = e !== this.yScale.getTransform(), n = t.x?.type ?? "time";
|
|
1402
|
-
n !== this.#
|
|
1434
|
+
n !== this.#n && this.#V("x-type", () => Ot({ from: this.#n, to: n }));
|
|
1403
1435
|
const a = this.timeScale.getBandPadding();
|
|
1404
1436
|
this.timeScale.setBandPadding(t.x?.padding);
|
|
1405
1437
|
const o = this.timeScale.getBandPadding(), h = a.inner !== o.inner || a.outer !== o.outer;
|
|
1406
|
-
this.#v = t, this.#
|
|
1438
|
+
this.#v = t, this.#w.bounds = { min: t.y?.min, max: t.y?.max }, L({ y: t.y, isPlottable: i });
|
|
1407
1439
|
const l = performance.now();
|
|
1408
|
-
r && (this.yScale.setTransform(e), this.yScale.tickTracker.reset(), this.#
|
|
1440
|
+
r && (this.yScale.setTransform(e), this.yScale.tickTracker.reset(), this.#U() === null && this.#e.snap({ y: { min: 0, max: 0 } }, l)), this.#u = !0, this.#e.onAxisReconfig(l), this.#x(l), this.#st(s), this.#rt(), h && this.#n === "category" && this.fitContent(), this.#i.markDirty();
|
|
1409
1441
|
}
|
|
1410
1442
|
/**
|
|
1411
1443
|
* Replace the named Y scales (see {@link ChartOptions.scales}). Added,
|
|
@@ -1414,69 +1446,69 @@ class _e extends Et {
|
|
|
1414
1446
|
*/
|
|
1415
1447
|
setScales(t) {
|
|
1416
1448
|
const e = t ?? {};
|
|
1417
|
-
if (
|
|
1418
|
-
const i = this.#Z(), s = this.#
|
|
1419
|
-
this.#
|
|
1449
|
+
if (Qt(e, this.#Lt)) return;
|
|
1450
|
+
const i = this.#Z(), s = this.#Ut(e);
|
|
1451
|
+
this.#Tt();
|
|
1420
1452
|
const r = performance.now(), n = {};
|
|
1421
1453
|
for (const a of s)
|
|
1422
|
-
this.#
|
|
1423
|
-
this.#e.snap({ scales: n }, r), this.#
|
|
1454
|
+
this.#U(void 0, a) === null && (n[a] = { min: 0, max: 0 });
|
|
1455
|
+
this.#e.snap({ scales: n }, r), this.#u = !0, this.#e.onAxisReconfig(r), this.#x(r), this.#st(i), this.emit("viewportChange"), this.#m(), this.#i.markDirty();
|
|
1424
1456
|
}
|
|
1425
1457
|
/**
|
|
1426
1458
|
* Create, update and drop named-scale slots to match `next`, in its key
|
|
1427
1459
|
* order. Returns the ids of existing scales whose transform changed.
|
|
1428
1460
|
*/
|
|
1429
|
-
#
|
|
1461
|
+
#Ut(t) {
|
|
1430
1462
|
const e = /* @__PURE__ */ new Map(), i = [];
|
|
1431
1463
|
for (const [s, r] of Object.entries(t)) {
|
|
1432
1464
|
const n = r.scale ?? null;
|
|
1433
|
-
let a = this.#
|
|
1465
|
+
let a = this.#o.get(s);
|
|
1434
1466
|
if (a === void 0) {
|
|
1435
|
-
const o = new
|
|
1436
|
-
o.setTransform(n), o.tickTracker.setFadeMs(this.#g.axis.ticksMs), a = { ...
|
|
1467
|
+
const o = new K();
|
|
1468
|
+
o.setTransform(n), o.tickTracker.setFadeMs(this.#g.axis.ticksMs), a = { ...it(o, r), config: r, column: null };
|
|
1437
1469
|
} else n !== a.yScale.getTransform() && (a.yScale.setTransform(n), a.yScale.tickTracker.reset(), i.push(s));
|
|
1438
|
-
a.config = { ...r }, a.bounds = { min: r.min, max: r.max },
|
|
1470
|
+
a.config = { ...r }, a.bounds = { min: r.min, max: r.max }, L({
|
|
1439
1471
|
y: r,
|
|
1440
|
-
isPlottable: (o) =>
|
|
1472
|
+
isPlottable: (o) => q(n, o),
|
|
1441
1473
|
path: `scales.${s}`
|
|
1442
1474
|
}), e.set(s, a);
|
|
1443
1475
|
}
|
|
1444
|
-
return this.#
|
|
1476
|
+
return this.#o = e, this.#Lt = Object.fromEntries([...e].map(([s, r]) => [s, r.config])), this.#e.setYScales([...e.keys()]), i;
|
|
1445
1477
|
}
|
|
1446
1478
|
/**
|
|
1447
1479
|
* Hand out the Y-axis columns: the default axis keeps its side, and each
|
|
1448
1480
|
* visible named scale takes its side unless an earlier one holds it —
|
|
1449
1481
|
* that one becomes an overlay scale (dev warning).
|
|
1450
1482
|
*/
|
|
1451
|
-
#
|
|
1483
|
+
#Tt() {
|
|
1452
1484
|
const t = /* @__PURE__ */ new Set();
|
|
1453
1485
|
this.yAxisWidth > 0 && t.add(this.yAxisPosition);
|
|
1454
|
-
const e =
|
|
1455
|
-
for (const [i, s] of this.#
|
|
1456
|
-
if (s.column = null, this.#
|
|
1486
|
+
const e = rt(this.yAxisPosition);
|
|
1487
|
+
for (const [i, s] of this.#o) {
|
|
1488
|
+
if (s.column = null, this.#q(s.config) <= 0) continue;
|
|
1457
1489
|
const r = s.config.position ?? e;
|
|
1458
1490
|
if (t.has(r)) {
|
|
1459
|
-
this.#
|
|
1491
|
+
this.#V(`side:${i}`, () => Ct({ scaleId: i, side: r }));
|
|
1460
1492
|
continue;
|
|
1461
1493
|
}
|
|
1462
1494
|
t.add(r), s.column = r;
|
|
1463
1495
|
}
|
|
1464
1496
|
}
|
|
1465
1497
|
/** Dev warnings for a series' `scale`: an id `scales` doesn't define, a percent stack on a scale without 0. */
|
|
1466
|
-
#
|
|
1498
|
+
#be(t) {
|
|
1467
1499
|
const e = t.scale;
|
|
1468
|
-
e !== void 0 && (this.#
|
|
1500
|
+
e !== void 0 && (this.#o.has(e) || this.#V(`unknown:${e}`, () => Lt({ seriesId: t.id, scaleId: e })), ot(t.renderer) === "percent" && !this.getYScale(this.#I(t)).isPlottable(0) && this.#V(`percent:${t.id}`, () => It({ seriesId: t.id })));
|
|
1469
1501
|
}
|
|
1470
|
-
#
|
|
1471
|
-
this.#
|
|
1502
|
+
#V(t, e) {
|
|
1503
|
+
this.#It.has(t) || (this.#It.add(t), e());
|
|
1472
1504
|
}
|
|
1473
1505
|
/** Ids of the named Y scales, in declaration order. */
|
|
1474
1506
|
getYScaleIds() {
|
|
1475
|
-
return [...this.#
|
|
1507
|
+
return [...this.#o.keys()];
|
|
1476
1508
|
}
|
|
1477
1509
|
/** The Y scale named `scaleId`; the default scale for `undefined` or an id `scales` doesn't define. */
|
|
1478
1510
|
getYScale(t) {
|
|
1479
|
-
return t === void 0 ? this.yScale : this.#
|
|
1511
|
+
return t === void 0 ? this.yScale : this.#o.get(t)?.yScale ?? this.yScale;
|
|
1480
1512
|
}
|
|
1481
1513
|
/**
|
|
1482
1514
|
* The column a scale's axis sits in — always the default axis's for
|
|
@@ -1484,31 +1516,31 @@ class _e extends Et {
|
|
|
1484
1516
|
*/
|
|
1485
1517
|
getYScaleColumn(t) {
|
|
1486
1518
|
if (t === void 0) return { position: this.yAxisPosition, width: this.yAxisWidth };
|
|
1487
|
-
const e = this.#
|
|
1488
|
-
return e === void 0 || e.column === null ? null : { position: e.column, width: this.#
|
|
1519
|
+
const e = this.#o.get(t);
|
|
1520
|
+
return e === void 0 || e.column === null ? null : { position: e.column, width: this.#q(e.config) };
|
|
1489
1521
|
}
|
|
1490
1522
|
/** The named scale a series maps through, `undefined` for the default scale. */
|
|
1491
1523
|
getSeriesScale(t) {
|
|
1492
1524
|
const e = this.#t.find((i) => i.id === t);
|
|
1493
|
-
return e === void 0 ? void 0 : this.#
|
|
1525
|
+
return e === void 0 ? void 0 : this.#I(e);
|
|
1494
1526
|
}
|
|
1495
1527
|
/** `scale` if `options.scales` defines it, else `undefined` (the default scale). */
|
|
1496
|
-
#
|
|
1497
|
-
return t !== void 0 && this.#
|
|
1528
|
+
#ke(t) {
|
|
1529
|
+
return t !== void 0 && this.#o.has(t) ? t : void 0;
|
|
1498
1530
|
}
|
|
1499
|
-
#
|
|
1500
|
-
return this.#
|
|
1531
|
+
#I(t) {
|
|
1532
|
+
return this.#ke(t.scale);
|
|
1501
1533
|
}
|
|
1502
|
-
#
|
|
1503
|
-
return t === void 0 ? this.#
|
|
1534
|
+
#Te(t) {
|
|
1535
|
+
return t === void 0 ? this.#w : this.#o.get(t) ?? this.#w;
|
|
1504
1536
|
}
|
|
1505
1537
|
/** The series a scale autoscales from. */
|
|
1506
|
-
#
|
|
1507
|
-
return this.#
|
|
1538
|
+
#we(t) {
|
|
1539
|
+
return this.#o.size === 0 ? this.#t : this.#t.filter((e) => this.#I(e) === t);
|
|
1508
1540
|
}
|
|
1509
1541
|
/** Snap every scale to a fresh fit — what each one holds just changed. */
|
|
1510
|
-
#
|
|
1511
|
-
this.#
|
|
1542
|
+
#Me() {
|
|
1543
|
+
this.#u = !0;
|
|
1512
1544
|
const t = performance.now();
|
|
1513
1545
|
this.#e.onAxisReconfig(t), this.#x(t), this.emit("viewportChange"), this.#i.markDirty();
|
|
1514
1546
|
}
|
|
@@ -1518,7 +1550,7 @@ class _e extends Et {
|
|
|
1518
1550
|
* picks a named scale; an id `scales` doesn't define is a no-op.
|
|
1519
1551
|
*/
|
|
1520
1552
|
setYAxisFormat(t) {
|
|
1521
|
-
t.scale !== void 0 && !this.#
|
|
1553
|
+
t.scale !== void 0 && !this.#o.has(t.scale) || (this.getYScale(t.scale).setFormat(t.format), this.#m());
|
|
1522
1554
|
}
|
|
1523
1555
|
/**
|
|
1524
1556
|
* Apply label-density knobs driven by `<YAxis labelCount=… minLabelSpacing=…>`
|
|
@@ -1528,7 +1560,7 @@ class _e extends Et {
|
|
|
1528
1560
|
* charts react without waiting for pan/zoom.
|
|
1529
1561
|
*/
|
|
1530
1562
|
setYAxisLabelDensity(t) {
|
|
1531
|
-
if (t.scale !== void 0 && !this.#
|
|
1563
|
+
if (t.scale !== void 0 && !this.#o.has(t.scale)) return;
|
|
1532
1564
|
const e = this.getYScale(t.scale);
|
|
1533
1565
|
let i = !1;
|
|
1534
1566
|
"labelCount" in t && (e.setLabelCount(t.labelCount ?? null), i = !0), "minLabelSpacing" in t && (e.setMinSpacing(t.minLabelSpacing ?? null), i = !0), i && (this.syncScales(), this.emit("viewportChange"), this.#i.markDirty());
|
|
@@ -1539,7 +1571,7 @@ class _e extends Et {
|
|
|
1539
1571
|
* info-bar headers read it.
|
|
1540
1572
|
*/
|
|
1541
1573
|
setXAxisFormat(t) {
|
|
1542
|
-
this.timeScale.setFormat(t), this.#
|
|
1574
|
+
this.timeScale.setFormat(t), this.#m();
|
|
1543
1575
|
}
|
|
1544
1576
|
/** Label-density knobs for the X axis — mirror of {@link setYAxisLabelDensity}. */
|
|
1545
1577
|
setTimeAxisLabelDensity(t) {
|
|
@@ -1547,11 +1579,11 @@ class _e extends Et {
|
|
|
1547
1579
|
"labelCount" in t && (this.timeScale.setLabelCount(t.labelCount ?? null), e = !0), "minLabelSpacing" in t && (this.timeScale.setMinSpacing(t.minLabelSpacing ?? null), e = !0), e && (this.syncScales(), this.emit("viewportChange"), this.#i.markDirty());
|
|
1548
1580
|
}
|
|
1549
1581
|
getMediaSize() {
|
|
1550
|
-
return this.#
|
|
1582
|
+
return this.#c.size.media;
|
|
1551
1583
|
}
|
|
1552
1584
|
/** Returns layout metrics for the chart area, Y axis, and time axis. */
|
|
1553
1585
|
getLayout() {
|
|
1554
|
-
const t = this.#
|
|
1586
|
+
const t = this.#c.size.media, e = this.yAxisWidth, i = this.xAxisHeight, s = t.width - this.#k();
|
|
1555
1587
|
return {
|
|
1556
1588
|
chartArea: { x: this.plotLeft, y: 0, width: s, height: t.height - i },
|
|
1557
1589
|
yAxisWidth: e,
|
|
@@ -1560,7 +1592,7 @@ class _e extends Et {
|
|
|
1560
1592
|
};
|
|
1561
1593
|
}
|
|
1562
1594
|
getDataInterval() {
|
|
1563
|
-
return this.#
|
|
1595
|
+
return this.#r;
|
|
1564
1596
|
}
|
|
1565
1597
|
/**
|
|
1566
1598
|
* Update viewport padding at runtime. Refits the visible time range to
|
|
@@ -1571,18 +1603,15 @@ class _e extends Et {
|
|
|
1571
1603
|
* InfoBar ResizeObserver).
|
|
1572
1604
|
*/
|
|
1573
1605
|
setPadding(t) {
|
|
1574
|
-
const e = this.#
|
|
1575
|
-
this.#
|
|
1576
|
-
const i = this.#
|
|
1606
|
+
const e = this.#l;
|
|
1607
|
+
this.#l = Z(t);
|
|
1608
|
+
const i = this.#l, s = !_(e.left, i.left) || !_(e.right, i.right), r = e.top !== i.top || e.bottom !== i.bottom;
|
|
1577
1609
|
if (s) {
|
|
1578
|
-
const
|
|
1579
|
-
|
|
1580
|
-
const o = this.#l.size.media.width - this.#w();
|
|
1581
|
-
this.#O(n, a, o);
|
|
1582
|
-
}
|
|
1610
|
+
const n = this.#c.size.media.width - this.#k();
|
|
1611
|
+
this.#Mt(n);
|
|
1583
1612
|
}
|
|
1584
1613
|
if (s || r) {
|
|
1585
|
-
this.#
|
|
1614
|
+
this.#u = !0;
|
|
1586
1615
|
const n = performance.now();
|
|
1587
1616
|
this.#e.onAxisReconfig(n), this.#x(n);
|
|
1588
1617
|
}
|
|
@@ -1590,7 +1619,7 @@ class _e extends Et {
|
|
|
1590
1619
|
}
|
|
1591
1620
|
/** Show or hide the background grid. Takes effect on the next render frame. */
|
|
1592
1621
|
setGrid(t) {
|
|
1593
|
-
this.#
|
|
1622
|
+
this.#j = t.visible, this.#i.markDirty();
|
|
1594
1623
|
}
|
|
1595
1624
|
/**
|
|
1596
1625
|
* Set or clear the edge fade masks (see {@link ChartOptions.fade}).
|
|
@@ -1600,14 +1629,14 @@ class _e extends Et {
|
|
|
1600
1629
|
* the next render frame.
|
|
1601
1630
|
*/
|
|
1602
1631
|
setFade(t) {
|
|
1603
|
-
const e =
|
|
1632
|
+
const e = X(t), i = this.#C;
|
|
1604
1633
|
e.top === i.top && e.right === i.right && e.left === i.left || (this.#C = e, this.#i.markDirty());
|
|
1605
1634
|
}
|
|
1606
1635
|
/** Report the floating header's height (see {@link headerHeight}). The
|
|
1607
1636
|
* framework wrappers keep it in sync with the measured Title / InfoBar. */
|
|
1608
1637
|
setHeaderHeight(t) {
|
|
1609
1638
|
const e = Number.isFinite(t) && t > 0 ? t : 0;
|
|
1610
|
-
e !== this.#
|
|
1639
|
+
e !== this.#ht && (this.#ht = e, this.#m());
|
|
1611
1640
|
}
|
|
1612
1641
|
/**
|
|
1613
1642
|
* Set the visual state for one side of the chart. Typically called in
|
|
@@ -1620,8 +1649,8 @@ class _e extends Et {
|
|
|
1620
1649
|
*/
|
|
1621
1650
|
setEdgeState(t, e) {
|
|
1622
1651
|
if (this.#A[t] === e || !this.checkTimeOnlyFeature("EdgeLoader")) return;
|
|
1623
|
-
const i = this.#A[t] === "loading", s = this.#
|
|
1624
|
-
this.#
|
|
1652
|
+
const i = this.#A[t] === "loading", s = this.#E[t];
|
|
1653
|
+
this.#E[t] = !1, this.#K[t] = i && !s && (e === "idle" || e === "has-more") ? performance.now() : null, this.#A[t] = e, this.#d.markDirty();
|
|
1625
1654
|
}
|
|
1626
1655
|
/** Read the current host-declared state for a given edge. */
|
|
1627
1656
|
getEdgeState(t) {
|
|
@@ -1631,11 +1660,11 @@ class _e extends Et {
|
|
|
1631
1660
|
* Alpha for a side's `loading` exit fade, or `null` when none is in
|
|
1632
1661
|
* flight. Self-cleaning: an elapsed fade clears its start stamp.
|
|
1633
1662
|
*/
|
|
1634
|
-
#
|
|
1663
|
+
#jt(t) {
|
|
1635
1664
|
const e = this.#K[t];
|
|
1636
1665
|
if (e === null) return null;
|
|
1637
|
-
const i = (performance.now() - e) /
|
|
1638
|
-
return i >= 1 ? (this.#K[t] = null, null) : 1 -
|
|
1666
|
+
const i = (performance.now() - e) / se;
|
|
1667
|
+
return i >= 1 ? (this.#K[t] = null, null) : 1 - E(Math.max(0, i));
|
|
1639
1668
|
}
|
|
1640
1669
|
/**
|
|
1641
1670
|
* Swap the painter used for a side's `loading` spinner — the same
|
|
@@ -1644,7 +1673,7 @@ class _e extends Et {
|
|
|
1644
1673
|
* immediately if that side is currently in the `loading` state.
|
|
1645
1674
|
*/
|
|
1646
1675
|
setEdgeIndicator(t, e) {
|
|
1647
|
-
e !== null && !this.checkTimeOnlyFeature("EdgeLoader") || (this.#
|
|
1676
|
+
e !== null && !this.checkTimeOnlyFeature("EdgeLoader") || (this.#Ft[t] = e, this.#A[t] === "loading" && this.#d.markDirty());
|
|
1648
1677
|
}
|
|
1649
1678
|
/**
|
|
1650
1679
|
* Resolve the boundary point's Y position and series kind on the primary
|
|
@@ -1654,14 +1683,14 @@ class _e extends Et {
|
|
|
1654
1683
|
* `open` (the value immediately preceding the boundary); `right` from the
|
|
1655
1684
|
* last visible candle's `close`.
|
|
1656
1685
|
*/
|
|
1657
|
-
#
|
|
1686
|
+
#Ae(t, e) {
|
|
1658
1687
|
const i = this.getSeriesIdsByType("time", { visibleOnly: !0, singleLayerOnly: !0 })[0] ?? this.getSeriesIdsByType("time", { visibleOnly: !0 })[0];
|
|
1659
1688
|
if (!i) return null;
|
|
1660
1689
|
const s = this.getDataAtTime(i, e);
|
|
1661
1690
|
if (!s) return null;
|
|
1662
1691
|
const r = this.#t.find((n) => n.id === i);
|
|
1663
1692
|
return r ? {
|
|
1664
|
-
valueY: this.getYScale(this.#
|
|
1693
|
+
valueY: this.getYScale(this.#I(r)).valueToY(xt(t, s)),
|
|
1665
1694
|
seriesKind: r.renderer.kind
|
|
1666
1695
|
} : null;
|
|
1667
1696
|
}
|
|
@@ -1671,8 +1700,8 @@ class _e extends Et {
|
|
|
1671
1700
|
* placeholder shapes to match the real bars that will render once data
|
|
1672
1701
|
* lands. `null` when the viewport has no meaningful span yet.
|
|
1673
1702
|
*/
|
|
1674
|
-
#
|
|
1675
|
-
const t = this.timeScale.barWidthMedia(this.#
|
|
1703
|
+
#Pe() {
|
|
1704
|
+
const t = this.timeScale.barWidthMedia(this.#r);
|
|
1676
1705
|
return Number.isFinite(t) && t > 0 ? t : null;
|
|
1677
1706
|
}
|
|
1678
1707
|
/**
|
|
@@ -1690,8 +1719,8 @@ class _e extends Et {
|
|
|
1690
1719
|
* probed, not kind-gated: a kind check here silently kills hover for the
|
|
1691
1720
|
* next spatial renderer.
|
|
1692
1721
|
*/
|
|
1693
|
-
#
|
|
1694
|
-
const e = this.#
|
|
1722
|
+
#wt(t) {
|
|
1723
|
+
const e = this.#c.size, i = this.#l, s = {
|
|
1695
1724
|
top: i.top * e.verticalPixelRatio,
|
|
1696
1725
|
bottom: i.bottom * e.verticalPixelRatio
|
|
1697
1726
|
};
|
|
@@ -1703,7 +1732,7 @@ class _e extends Et {
|
|
|
1703
1732
|
const h = (t.mediaX - this.plotLeft) * e.horizontalPixelRatio, l = t.mediaY * e.verticalPixelRatio;
|
|
1704
1733
|
o = a.renderer.hitTest(h, l, e.bitmap.width, e.bitmap.height, s);
|
|
1705
1734
|
}
|
|
1706
|
-
a.renderer.setHoverIndex(o) && (r = !0), o >= 0 && !n && (n = { seriesId: a.id, index: o, info: a.renderer.getHoverInfo?.(this.#
|
|
1735
|
+
a.renderer.setHoverIndex(o) && (r = !0), o >= 0 && !n && (n = { seriesId: a.id, index: o, info: a.renderer.getHoverInfo?.(this.#h) ?? null });
|
|
1707
1736
|
}
|
|
1708
1737
|
r && (this.#i.markDirty(), this.emit("seriesHover", n));
|
|
1709
1738
|
}
|
|
@@ -1714,8 +1743,8 @@ class _e extends Et {
|
|
|
1714
1743
|
* Returns the first spatial series (pie, heatmap, or a custom spatial kind)
|
|
1715
1744
|
* whose `hitTest` claims the position, or `null` if none does.
|
|
1716
1745
|
*/
|
|
1717
|
-
#
|
|
1718
|
-
const e = this.#
|
|
1746
|
+
#Kt(t) {
|
|
1747
|
+
const e = this.#c.size, i = this.#l, s = {
|
|
1719
1748
|
top: i.top * e.verticalPixelRatio,
|
|
1720
1749
|
bottom: i.bottom * e.verticalPixelRatio
|
|
1721
1750
|
}, r = (t.mediaX - this.plotLeft) * e.horizontalPixelRatio, n = t.mediaY * e.verticalPixelRatio;
|
|
@@ -1746,42 +1775,42 @@ class _e extends Et {
|
|
|
1746
1775
|
* viewport didn't move, the re-derived values are bit-identical and the
|
|
1747
1776
|
* method exits without emitting.
|
|
1748
1777
|
*/
|
|
1749
|
-
#
|
|
1750
|
-
const t = this.#
|
|
1751
|
-
this.#
|
|
1778
|
+
#Ce() {
|
|
1779
|
+
const t = this.#ot;
|
|
1780
|
+
this.#ot = !1;
|
|
1752
1781
|
const e = this.#f;
|
|
1753
1782
|
if (e === null) return;
|
|
1754
1783
|
const { from: i, to: s } = this.timeScale.getRange(), r = this.yScale.getRange(), n = Math.abs(s - i) * 1e-9, a = Math.abs(r.max - r.min) * 1e-9, o = 1e-6;
|
|
1755
1784
|
let h;
|
|
1756
|
-
if (this.#
|
|
1757
|
-
const l = this.timeScale.snapToBand(this.timeScale.xToTime(e.mediaX - this.plotLeft)),
|
|
1758
|
-
if (!Number.isFinite(l) || !Number.isFinite(
|
|
1759
|
-
h = { mediaX: e.mediaX, mediaY: e.mediaY, time: l, x: this.timeScale.domainValue(l), y:
|
|
1785
|
+
if (this.#lt === "pointer") {
|
|
1786
|
+
const l = this.timeScale.snapToBand(this.timeScale.xToTime(e.mediaX - this.plotLeft)), c = this.yScale.yToValue(e.mediaY);
|
|
1787
|
+
if (!Number.isFinite(l) || !Number.isFinite(c) || Math.abs(l - e.time) <= n && Math.abs(c - e.y) <= a && !t && e.x === this.timeScale.domainValue(e.time)) return;
|
|
1788
|
+
h = { mediaX: e.mediaX, mediaY: e.mediaY, time: l, x: this.timeScale.domainValue(l), y: c };
|
|
1760
1789
|
} else {
|
|
1761
1790
|
if (e.time < i || e.time > s) {
|
|
1762
|
-
this.#f = null, this.#
|
|
1791
|
+
this.#f = null, this.#d.markDirty(), this.emit("crosshairMove", null), this.#wt(null);
|
|
1763
1792
|
return;
|
|
1764
1793
|
}
|
|
1765
|
-
const l = this.plotLeft + this.timeScale.timeToX(e.time),
|
|
1766
|
-
if (!Number.isFinite(l) || !Number.isFinite(
|
|
1767
|
-
h = { mediaX: l, mediaY:
|
|
1794
|
+
const l = this.plotLeft + this.timeScale.timeToX(e.time), c = this.yScale.valueToY(e.y);
|
|
1795
|
+
if (!Number.isFinite(l) || !Number.isFinite(c) || Math.abs(l - e.mediaX) <= o && Math.abs(c - e.mediaY) <= o && !t && e.x === this.timeScale.domainValue(e.time)) return;
|
|
1796
|
+
h = { mediaX: l, mediaY: c, time: e.time, x: this.timeScale.domainValue(e.time), y: e.y };
|
|
1768
1797
|
}
|
|
1769
|
-
this.#f = h, this.#
|
|
1798
|
+
this.#f = h, this.#d.markDirty(), this.emit("crosshairMove", h), this.#wt(h);
|
|
1770
1799
|
}
|
|
1771
1800
|
/** Tear down the chart: cancel animations, remove listeners, and detach the canvas. */
|
|
1772
1801
|
destroy() {
|
|
1773
1802
|
for (const t of this.#t) t.renderer.dispose();
|
|
1774
|
-
this.#t = [], this.#y = [], this.#
|
|
1803
|
+
this.#t = [], this.#y = [], this.#M = [], this.#S = [], this.#F = null, this.#i.destroy(), this.#d.destroy(), this.#N?.destroy(), this.#c.destroy(), this.#gt?.destroy(), this.#gt = null, this.#ft && this.#P?.destroy(), this.#P = null, this.#ft = !1, this.removeAllListeners();
|
|
1775
1804
|
}
|
|
1776
1805
|
/** The attached performance monitor, or `null` when instrumentation is disabled. */
|
|
1777
1806
|
getPerfMonitor() {
|
|
1778
|
-
return this.#
|
|
1807
|
+
return this.#P;
|
|
1779
1808
|
}
|
|
1780
1809
|
/** Compute the earliest and latest timestamps across all series. */
|
|
1781
1810
|
getDataBounds() {
|
|
1782
1811
|
let t, e;
|
|
1783
1812
|
for (const i of this.#t) {
|
|
1784
|
-
if (!i.visible || !
|
|
1813
|
+
if (!i.visible || !S(i.renderer)) continue;
|
|
1785
1814
|
const s = i.renderer.getTimeBounds();
|
|
1786
1815
|
s !== null && ((t === void 0 || s.first < t) && (t = s.first), (e === void 0 || s.last > e) && (e = s.last));
|
|
1787
1816
|
}
|
|
@@ -1790,62 +1819,72 @@ class _e extends Et {
|
|
|
1790
1819
|
/** Set by `setSeriesData`/bulk-replace paths so the next `onDataChanged`
|
|
1791
1820
|
* snaps the Y range (instead of easing) and `yScale.getRange()` reflects
|
|
1792
1821
|
* the new domain synchronously. Cleared by `onDataChanged` after each run. */
|
|
1793
|
-
#
|
|
1822
|
+
#nt = !1;
|
|
1794
1823
|
onDataChanged() {
|
|
1795
1824
|
if (this.#R > 0) {
|
|
1796
|
-
this.#
|
|
1825
|
+
this.#dt = !0;
|
|
1797
1826
|
return;
|
|
1798
1827
|
}
|
|
1799
|
-
this.updateDataInterval();
|
|
1828
|
+
this.updateDataInterval({ full: this.#nt || !this.#u });
|
|
1800
1829
|
const { first: t, last: e } = this.getDataBounds();
|
|
1801
|
-
t !== void 0 && (this.#
|
|
1802
|
-
const i = this.#
|
|
1803
|
-
this.#
|
|
1804
|
-
const s = !this.#
|
|
1830
|
+
t !== void 0 && (this.#T = t), e !== void 0 && (this.#Q = this.#s, this.#s = e);
|
|
1831
|
+
const i = this.#nt;
|
|
1832
|
+
this.#nt = !1;
|
|
1833
|
+
const s = !this.#u && t !== void 0;
|
|
1805
1834
|
if (i) {
|
|
1806
1835
|
this.yScale.tickTracker.reset(), this.timeScale.tickTracker.reset();
|
|
1807
|
-
for (const n of this.#
|
|
1836
|
+
for (const n of this.#o.values())
|
|
1808
1837
|
n.yScale.tickTracker.reset();
|
|
1809
1838
|
}
|
|
1810
|
-
this.#
|
|
1839
|
+
this.#Ot = i;
|
|
1811
1840
|
const r = performance.now();
|
|
1812
|
-
i || s ? (this.#
|
|
1841
|
+
i || s ? (this.#W.seed(r), this.#e.onDataReplaced(r)) : this.#e.onPointAppended(r), this.#e.lastXTarget !== null && (this.#_ = !0), t !== void 0 && (this.#u = !0), this.#x(r), this.syncScales(), s ? this.#Pt() : this.#i.markDirty(), this.emit("dataUpdate"), this.#m();
|
|
1813
1842
|
}
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1843
|
+
/** `full`: the data was replaced, so a long series is read whole instead of from its tail. */
|
|
1844
|
+
updateDataInterval(t) {
|
|
1845
|
+
if (this.#n === "category") {
|
|
1846
|
+
this.#r = 1;
|
|
1817
1847
|
return;
|
|
1818
1848
|
}
|
|
1819
|
-
for (const
|
|
1820
|
-
if (!
|
|
1821
|
-
const
|
|
1822
|
-
if (
|
|
1823
|
-
this.#
|
|
1824
|
-
|
|
1849
|
+
for (const e of this.#t) {
|
|
1850
|
+
if (!S(e.renderer)) continue;
|
|
1851
|
+
const i = e.renderer.sampleTimes(tt + 1);
|
|
1852
|
+
if (!(i.length < 2)) {
|
|
1853
|
+
this.#r = this.#Le({ renderer: e.renderer, head: i, full: t.full });
|
|
1854
|
+
return;
|
|
1825
1855
|
}
|
|
1826
1856
|
}
|
|
1827
1857
|
}
|
|
1858
|
+
/** The step of one series. Past {@link FULL_INTERVAL_SCAN_POINTS}, an append can only refine it from the tail. */
|
|
1859
|
+
#Le(t) {
|
|
1860
|
+
const { renderer: e, head: i, full: s } = t;
|
|
1861
|
+
if (i.length <= tt) return D(i);
|
|
1862
|
+
if (s) return D(e.sampleTimes(Number.POSITIVE_INFINITY));
|
|
1863
|
+
const r = e.sampleTimes(et, "end");
|
|
1864
|
+
return r.length < et ? this.#r : Math.min(this.#r, D(r));
|
|
1865
|
+
}
|
|
1828
1866
|
/** Whether the Y range has been initialized (first snap vs smooth lerp).
|
|
1829
1867
|
* Pre-init Y emits are forced to `instant` so the first paint snaps to
|
|
1830
1868
|
* data regardless of the caller's requested kind. Also reset by paths
|
|
1831
1869
|
* that intentionally invalidate the current Y baseline (axis bound
|
|
1832
1870
|
* change, empty viewport). */
|
|
1833
|
-
#
|
|
1871
|
+
#u = !1;
|
|
1834
1872
|
/** Whether the engine's X slot has received its first emit. Pre-init X
|
|
1835
1873
|
* emits are forced to `instant` so first paint snaps to the fitted
|
|
1836
1874
|
* range — without this guard the engine would ease from `{0,0}` into
|
|
1837
1875
|
* the new target and the very first frame would render with a
|
|
1838
1876
|
* zero-width X domain. */
|
|
1839
|
-
#
|
|
1877
|
+
#_ = !1;
|
|
1840
1878
|
/**
|
|
1841
|
-
*
|
|
1842
|
-
*
|
|
1843
|
-
*
|
|
1844
|
-
* back to the initial window.
|
|
1879
|
+
* {@link ChartOptions.viewport.initialRange}: the chart's own window until the
|
|
1880
|
+
* user or the app moves the view, so more series or a re-seed keep it. A
|
|
1881
|
+
* `{ from, to }` or `{ from, bars }` window also ends once streaming moves it.
|
|
1845
1882
|
*/
|
|
1846
|
-
#
|
|
1883
|
+
#H;
|
|
1884
|
+
/** The chart's own fit holds fewer bars than it asks for, so appends widen it until it is full. */
|
|
1885
|
+
#G = !1;
|
|
1847
1886
|
/** Dev warning for values the Y scale can't place — fires once per chart. */
|
|
1848
|
-
#
|
|
1887
|
+
#qt = !1;
|
|
1849
1888
|
/**
|
|
1850
1889
|
* Sample the visible data window and return the resolved Y bounds of one
|
|
1851
1890
|
* scale (`undefined` = default) in its scale space (see {@link resolveYTarget}),
|
|
@@ -1855,23 +1894,23 @@ class _e extends Et {
|
|
|
1855
1894
|
* converge together. Clears {@link #yInited} on empty so the next emit
|
|
1856
1895
|
* with valid data lands as an instant snap.
|
|
1857
1896
|
*/
|
|
1858
|
-
#
|
|
1859
|
-
const i = t ?? this.#
|
|
1860
|
-
h && this.#
|
|
1861
|
-
const l =
|
|
1862
|
-
return l === null ? (e === void 0 && (this.#
|
|
1897
|
+
#U(t, e) {
|
|
1898
|
+
const i = t ?? this.#a, { yScale: s, bounds: r } = this.#Te(e), n = r.min !== void 0 && r.min !== "auto" && typeof r.min != "number" || r.max !== void 0 && r.max !== "auto" && typeof r.max != "number" ? [] : null, a = this.#we(e), o = s.getTransform(), h = o === null ? void 0 : (c) => s.isPlottable(c);
|
|
1899
|
+
h && this.#Ie({ window: i, series: a, yScale: s });
|
|
1900
|
+
const l = Yt({ targetVisible: i, series: a, allValues: n, plottable: h });
|
|
1901
|
+
return l === null ? (e === void 0 && (this.#u = !1), null) : (e !== void 0 && (this.#u = !0), $t({ raw: l, bounds: r, allValues: n ?? [], transform: o }));
|
|
1863
1902
|
}
|
|
1864
1903
|
/** Dev-only sweep behind {@link warnUnplottableValues}; stops once it has warned. */
|
|
1865
|
-
#
|
|
1866
|
-
if (this.#
|
|
1904
|
+
#Ie(t) {
|
|
1905
|
+
if (this.#qt || process.env.NODE_ENV === "production") return;
|
|
1867
1906
|
const { window: e, series: i, yScale: s } = t;
|
|
1868
1907
|
for (const r of i) {
|
|
1869
|
-
if (!r.visible || !
|
|
1908
|
+
if (!r.visible || !S(r.renderer)) continue;
|
|
1870
1909
|
const n = r.renderer.getValueRange(e.from, e.to);
|
|
1871
1910
|
if (n === null) continue;
|
|
1872
1911
|
const a = (r.renderer.stacking === "normal" || r.renderer.stacking === "percent" ? n.min < 0 && !s.isPlottable(n.min) : !s.isPlottable(n.min)) ? n.min : s.isPlottable(n.max) ? null : n.max;
|
|
1873
1912
|
if (a !== null) {
|
|
1874
|
-
this.#
|
|
1913
|
+
this.#qt = !0, Dt({ seriesId: r.id, value: a });
|
|
1875
1914
|
return;
|
|
1876
1915
|
}
|
|
1877
1916
|
}
|
|
@@ -1894,53 +1933,112 @@ class _e extends Et {
|
|
|
1894
1933
|
* - **autoscroll off** → `null` (no X retarget; user has panned away
|
|
1895
1934
|
* from the tail).
|
|
1896
1935
|
*/
|
|
1897
|
-
#
|
|
1898
|
-
if (this.#
|
|
1899
|
-
const { from: t, to: e } = this.#
|
|
1900
|
-
if (this.#
|
|
1901
|
-
return this.#
|
|
1902
|
-
if (i)
|
|
1903
|
-
|
|
1904
|
-
const { to: n } = this.#h;
|
|
1905
|
-
this.#s >= n && this.#s - n <= this.#o * 1.5 && (this.#p = !0);
|
|
1906
|
-
}
|
|
1907
|
-
return this.#h;
|
|
1908
|
-
}
|
|
1936
|
+
#De() {
|
|
1937
|
+
if (this.#T === null || this.#s === null) return null;
|
|
1938
|
+
const { from: t, to: e } = this.#a, i = t === 0 && e === 0, s = this.#c.size.media.width - this.#k();
|
|
1939
|
+
if (this.#n === "category")
|
|
1940
|
+
return this.#At({ firstTime: this.#T, lastTime: this.#s, chartWidth: s }), this.#a;
|
|
1941
|
+
if (i)
|
|
1942
|
+
return this.#Mt(s), this.#a;
|
|
1909
1943
|
if (!this.#p) return null;
|
|
1910
|
-
if (this.#
|
|
1911
|
-
return this.#
|
|
1912
|
-
|
|
1913
|
-
|
|
1944
|
+
if (this.#Ot)
|
|
1945
|
+
return this.#Mt(s), this.#a;
|
|
1946
|
+
if (this.#G) {
|
|
1947
|
+
const n = this.#Jt(s);
|
|
1948
|
+
if (n !== null) return this.#Re(n);
|
|
1949
|
+
}
|
|
1950
|
+
const r = Vt({
|
|
1951
|
+
currentLogical: this.#a,
|
|
1914
1952
|
lastTime: this.#s,
|
|
1915
|
-
prevDataEnd: this.#
|
|
1916
|
-
dataInterval: this.#
|
|
1917
|
-
paddingRight: this.#
|
|
1953
|
+
prevDataEnd: this.#Q,
|
|
1954
|
+
dataInterval: this.#r,
|
|
1955
|
+
paddingRight: this.#l.right,
|
|
1918
1956
|
chartWidth: s,
|
|
1919
1957
|
holdUntilFilled: this.#L
|
|
1920
1958
|
});
|
|
1921
|
-
return r.releaseHold && (this.#L = !1), r.reengageAutoScroll && (this.#p = !0), r.newLogical === null ? null : (this.#
|
|
1959
|
+
return r.releaseHold && (this.#L = !1), r.reengageAutoScroll && (this.#p = !0), r.newLogical === null ? null : (typeof this.#H == "object" && (this.#H = void 0), this.#Qt(r.newLogical));
|
|
1960
|
+
}
|
|
1961
|
+
/** Commit an X target that follows the data tail; the engine eases there. */
|
|
1962
|
+
#Qt(t) {
|
|
1963
|
+
return this.#W.observe(performance.now()), this.#e.setXSettleMs(this.#W.pickSettleMs(this.#g.axis.x.settleMs)), this.#D(t, { emitChange: !1, skipValidation: !0 }), this.#Q = this.#s, t;
|
|
1922
1964
|
}
|
|
1923
1965
|
/**
|
|
1924
|
-
* Fit the
|
|
1925
|
-
*
|
|
1926
|
-
*
|
|
1927
|
-
* commits the new range via `viewport.setRange` (which emits `change`).
|
|
1966
|
+
* Fit X to the window the chart picks for itself: `initialRange` while it
|
|
1967
|
+
* holds, else every bar up to `maxVisibleBars`. Runs on the first data, on a
|
|
1968
|
+
* bulk replace and on a horizontal padding change.
|
|
1928
1969
|
*/
|
|
1929
|
-
#
|
|
1930
|
-
const
|
|
1931
|
-
if (
|
|
1932
|
-
this.#
|
|
1933
|
-
|
|
1970
|
+
#Mt(t) {
|
|
1971
|
+
const e = this.#H;
|
|
1972
|
+
if (typeof e == "object") {
|
|
1973
|
+
if (this.#G = !1, this.#_t(e), this.#a.from !== 0 || this.#a.to !== 0) {
|
|
1974
|
+
this.#Ve();
|
|
1975
|
+
return;
|
|
1976
|
+
}
|
|
1977
|
+
this.#H = void 0;
|
|
1934
1978
|
}
|
|
1935
|
-
const
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1979
|
+
const i = this.#Jt(t);
|
|
1980
|
+
i !== null && (this.#L = !1, this.#p = !0, this.#G = i.filling, this.#D(i.range, { emitChange: !0 }));
|
|
1981
|
+
}
|
|
1982
|
+
/**
|
|
1983
|
+
* The chart's own window over the current data: the last `initialRange`
|
|
1984
|
+
* bars, else every bar up to `maxVisibleBars`. `filling` while the data holds
|
|
1985
|
+
* fewer bars than that. `null` before data, or for a `{ from, … }` window.
|
|
1986
|
+
*/
|
|
1987
|
+
#Jt(t) {
|
|
1988
|
+
const e = this.#H, i = this.#T, s = this.#s;
|
|
1989
|
+
if (i === null || s === null || typeof e == "object") return null;
|
|
1990
|
+
const r = e ?? this.#mt, n = Math.max(i, s - (r - 1) * this.#r);
|
|
1991
|
+
return { range: B({
|
|
1992
|
+
firstTime: e === void 0 ? i : n,
|
|
1993
|
+
lastTime: s,
|
|
1994
|
+
dataInterval: this.#r,
|
|
1995
|
+
// An explicit bar count is shown whole; only the default fit is capped.
|
|
1996
|
+
maxVisibleBars: e === void 0 ? this.#mt : Number.POSITIVE_INFINITY,
|
|
1997
|
+
chartWidth: t,
|
|
1998
|
+
padding: { left: this.#l.left, right: this.#l.right }
|
|
1999
|
+
}), filling: n === i };
|
|
2000
|
+
}
|
|
2001
|
+
/** Widen the chart's own fit to the data tail. A trimmed head never narrows it (`keepLast`). */
|
|
2002
|
+
#Re(t) {
|
|
2003
|
+
this.#G = t.filling;
|
|
2004
|
+
const e = this.#a, i = e.to - e.from, s = t.range.to - t.range.from;
|
|
2005
|
+
if (t.range.to === e.to && s <= i) return null;
|
|
2006
|
+
const r = Math.max(s, i);
|
|
2007
|
+
return this.#Qt({ from: t.range.to - r, to: t.range.to });
|
|
2008
|
+
}
|
|
2009
|
+
/**
|
|
2010
|
+
* `setVisibleRange` reads a window that ends before the data tail as
|
|
2011
|
+
* "panned into history" and drops tail-follow. That is wrong for a streaming
|
|
2012
|
+
* lead-in that parks the seed just past the right edge so the first tick
|
|
2013
|
+
* scrolls it into view (the Sparkline `flow.align: 'offscreen'` drive-in) —
|
|
2014
|
+
* without follow-live the stream accumulates off-canvas forever. Re-arm when
|
|
2015
|
+
* the tail sits within ~one interval past the window.
|
|
2016
|
+
*/
|
|
2017
|
+
#Ve() {
|
|
2018
|
+
if (this.#p || this.#s === null) return;
|
|
2019
|
+
const { to: t } = this.#a;
|
|
2020
|
+
this.#s >= t && this.#s - t <= this.#r * 1.5 && (this.#p = !0);
|
|
2021
|
+
}
|
|
2022
|
+
/**
|
|
2023
|
+
* Fit the viewport's logical X range around a data span, padding included.
|
|
2024
|
+
* Clears the warm-up hold, forces autoscroll on (the data tail is in the new
|
|
2025
|
+
* window by construction) and emits `viewportChange`. Returns whether the range changed.
|
|
2026
|
+
*/
|
|
2027
|
+
#At(t) {
|
|
2028
|
+
const { firstTime: e, lastTime: i, chartWidth: s } = t;
|
|
2029
|
+
this.#L = !1, this.#p = !0;
|
|
2030
|
+
const r = this.timeScale.bandRange();
|
|
2031
|
+
if (this.#n === "category" && r !== null)
|
|
2032
|
+
return this.#D(r, { emitChange: !0, skipValidation: !0 });
|
|
2033
|
+
const n = B({
|
|
2034
|
+
firstTime: e,
|
|
2035
|
+
lastTime: i,
|
|
2036
|
+
dataInterval: this.#r,
|
|
2037
|
+
maxVisibleBars: Number.POSITIVE_INFINITY,
|
|
2038
|
+
chartWidth: s,
|
|
2039
|
+
padding: { left: this.#l.left, right: this.#l.right }
|
|
1942
2040
|
});
|
|
1943
|
-
|
|
2041
|
+
return this.#D(n, { emitChange: !0 });
|
|
1944
2042
|
}
|
|
1945
2043
|
/**
|
|
1946
2044
|
* Commit a programmatic zoom — `fitContent` or `setVisibleRange`. Reads
|
|
@@ -1956,12 +2054,12 @@ class _e extends Et {
|
|
|
1956
2054
|
* passes `xEase: true` so X eases instead — viewport and axis converge
|
|
1957
2055
|
* on the same frame.
|
|
1958
2056
|
*/
|
|
1959
|
-
#
|
|
1960
|
-
const e = this.#
|
|
2057
|
+
#te(t) {
|
|
2058
|
+
const e = this.#a;
|
|
1961
2059
|
if (e.to <= e.from) return;
|
|
1962
2060
|
const i = performance.now();
|
|
1963
|
-
if (!this.#
|
|
1964
|
-
this.#
|
|
2061
|
+
if (!this.#_ || !this.#u) {
|
|
2062
|
+
this.#ee(i);
|
|
1965
2063
|
return;
|
|
1966
2064
|
}
|
|
1967
2065
|
this.#e.onProgrammaticZoom({ xTarget: e, xEase: t?.xEase }, i), this.#x(i);
|
|
@@ -1978,12 +2076,12 @@ class _e extends Et {
|
|
|
1978
2076
|
* instead of lagging on the long sticky contract. First paint still snaps
|
|
1979
2077
|
* (same as the programmatic path) so synchronous readers see final values.
|
|
1980
2078
|
*/
|
|
1981
|
-
#
|
|
1982
|
-
const t = this.#
|
|
2079
|
+
#He() {
|
|
2080
|
+
const t = this.#a;
|
|
1983
2081
|
if (t.to <= t.from) return;
|
|
1984
2082
|
const e = performance.now();
|
|
1985
|
-
if (!this.#
|
|
1986
|
-
this.#
|
|
2083
|
+
if (!this.#_ || !this.#u) {
|
|
2084
|
+
this.#ee(e);
|
|
1987
2085
|
return;
|
|
1988
2086
|
}
|
|
1989
2087
|
this.#e.onPanZoom({ xTarget: t, yAuto: !0 }, e), this.#x(e);
|
|
@@ -1995,13 +2093,13 @@ class _e extends Et {
|
|
|
1995
2093
|
* commits — both must snap before the chart has painted once so a
|
|
1996
2094
|
* synchronous `getYRange()` / `getVisibleRange()` read sees final values.
|
|
1997
2095
|
*/
|
|
1998
|
-
#
|
|
1999
|
-
const e = this.#
|
|
2000
|
-
for (const r of this.#
|
|
2001
|
-
const n = this.#
|
|
2096
|
+
#ee(t) {
|
|
2097
|
+
const e = this.#a, i = this.#U(e), s = {};
|
|
2098
|
+
for (const r of this.#o.keys()) {
|
|
2099
|
+
const n = this.#U(e, r);
|
|
2002
2100
|
n !== null && (s[r] = n);
|
|
2003
2101
|
}
|
|
2004
|
-
this.#
|
|
2102
|
+
this.#_ = !0, i !== null && (this.#u = !0), this.#e.snap({ x: e, y: i ?? void 0, scales: s }, t), this.#x(t);
|
|
2005
2103
|
}
|
|
2006
2104
|
/**
|
|
2007
2105
|
* Validate and commit a new logical X range. Mirrors the old
|
|
@@ -2021,9 +2119,9 @@ class _e extends Et {
|
|
|
2021
2119
|
* see `setVisibleRange`'s gesture path, where a per-frame echo would
|
|
2022
2120
|
* otherwise re-arm and stall the in-flight Y ease.
|
|
2023
2121
|
*/
|
|
2024
|
-
#
|
|
2122
|
+
#D(t, e) {
|
|
2025
2123
|
const { from: i, to: s } = t;
|
|
2026
|
-
return !Number.isFinite(i) || !Number.isFinite(s) || s <= i || !e.skipValidation && (s - i) / this.#
|
|
2124
|
+
return !Number.isFinite(i) || !Number.isFinite(s) || s <= i || !e.skipValidation && (s - i) / this.#r < 2 || this.#a.from === i && this.#a.to === s ? !1 : (this.#a = { from: i, to: s }, e.emitChange && (this.syncScales(), this.#i?.markDirty(), this.emit("viewportChange")), !0);
|
|
2027
2125
|
}
|
|
2028
2126
|
/**
|
|
2029
2127
|
* Apply pixel-padding to the engine's Y (scale space) and return it as
|
|
@@ -2032,23 +2130,23 @@ class _e extends Et {
|
|
|
2032
2130
|
* that has an explicit (fixed) axis bound. Padding in scale space keeps
|
|
2033
2131
|
* the pixel gutters even on a log axis.
|
|
2034
2132
|
*/
|
|
2035
|
-
#
|
|
2036
|
-
const { slot: e, min: i, max: s, chartHeight: r } = t, { yScale: n } = e, { min: a, max: o } = this.#
|
|
2037
|
-
min: a ? i : i -
|
|
2133
|
+
#Ne(t) {
|
|
2134
|
+
const { slot: e, min: i, max: s, chartHeight: r } = t, { yScale: n } = e, { min: a, max: o } = this.#Fe(e), h = s - i, l = r > 0 ? this.#l.top / r * h : 0, c = r > 0 ? this.#l.bottom / r * h : 0, f = {
|
|
2135
|
+
min: a ? i : i - c,
|
|
2038
2136
|
max: o ? s : s + l
|
|
2039
|
-
},
|
|
2040
|
-
if (
|
|
2041
|
-
const
|
|
2137
|
+
}, g = n.getTransform();
|
|
2138
|
+
if (g === null) return f;
|
|
2139
|
+
const u = g.inverse(f.min), m = g.inverse(f.max), y = n.isPlottable(u) && u <= g.inverse(i), p = n.isPlottable(m) && m >= g.inverse(s);
|
|
2042
2140
|
return {
|
|
2043
|
-
min:
|
|
2044
|
-
max:
|
|
2141
|
+
min: y ? u : g.inverse(i),
|
|
2142
|
+
max: p ? m : g.inverse(s)
|
|
2045
2143
|
};
|
|
2046
2144
|
}
|
|
2047
2145
|
/** Which Y edges of a scale the user pinned — a pinned edge takes no padding. */
|
|
2048
|
-
#
|
|
2146
|
+
#Fe(t) {
|
|
2049
2147
|
return {
|
|
2050
|
-
min:
|
|
2051
|
-
max:
|
|
2148
|
+
min: nt(t.bounds.min, t.yScale),
|
|
2149
|
+
max: nt(t.bounds.max, t.yScale)
|
|
2052
2150
|
};
|
|
2053
2151
|
}
|
|
2054
2152
|
/**
|
|
@@ -2062,17 +2160,17 @@ class _e extends Et {
|
|
|
2062
2160
|
* programmatically.
|
|
2063
2161
|
*/
|
|
2064
2162
|
pan(t, e = this.#J) {
|
|
2065
|
-
e > 0 && (this.#J = e), this.#L = !1;
|
|
2066
|
-
const i =
|
|
2067
|
-
currentLogical: this.#
|
|
2163
|
+
e > 0 && (this.#J = e), this.#L = !1, this.#et();
|
|
2164
|
+
const i = At({
|
|
2165
|
+
currentLogical: this.#a,
|
|
2068
2166
|
timeDelta: t,
|
|
2069
2167
|
chartWidth: e,
|
|
2070
|
-
dataInterval: this.#
|
|
2071
|
-
padding: { left: this.#
|
|
2072
|
-
dataStart: this.#
|
|
2168
|
+
dataInterval: this.#r,
|
|
2169
|
+
padding: { left: this.#l.left, right: this.#l.right },
|
|
2170
|
+
dataStart: this.#T,
|
|
2073
2171
|
dataEnd: this.#s
|
|
2074
2172
|
});
|
|
2075
|
-
i.newLogical !== null && (this.#p = !i.autoScrollOff, this.#
|
|
2173
|
+
i.newLogical !== null && (this.#p = !i.autoScrollOff, this.#D(i.newLogical, { emitChange: !0 }), i.edgeReached !== null && (this.#Ht[i.edgeReached.side] = i.edgeReached.boundaryTime, this.#Nt?.(i.edgeReached)), this.#W.pause(), this.#ie());
|
|
2076
2174
|
}
|
|
2077
2175
|
/**
|
|
2078
2176
|
* Zoom around a time anchor. `factor < 1` zooms in, `> 1` zooms out.
|
|
@@ -2090,34 +2188,34 @@ class _e extends Et {
|
|
|
2090
2188
|
* sacrificed in follow-live mode — pan first to inspect history.
|
|
2091
2189
|
*/
|
|
2092
2190
|
zoomAt(t, e, i = this.#J) {
|
|
2093
|
-
i > 0 && (this.#J = i), this.#L = !1;
|
|
2094
|
-
const s =
|
|
2095
|
-
currentLogical: this.#
|
|
2191
|
+
i > 0 && (this.#J = i), this.#L = !1, this.#et();
|
|
2192
|
+
const s = Pt({
|
|
2193
|
+
currentLogical: this.#a,
|
|
2096
2194
|
centerTime: t,
|
|
2097
2195
|
factor: e,
|
|
2098
2196
|
chartWidth: i,
|
|
2099
|
-
dataInterval: this.#
|
|
2100
|
-
padding: { left: this.#
|
|
2101
|
-
dataStart: this.#
|
|
2197
|
+
dataInterval: this.#r,
|
|
2198
|
+
padding: { left: this.#l.left, right: this.#l.right },
|
|
2199
|
+
dataStart: this.#T,
|
|
2102
2200
|
dataEnd: this.#s
|
|
2103
2201
|
});
|
|
2104
2202
|
if (s.newLogical === null) return;
|
|
2105
2203
|
let r = s.newLogical;
|
|
2106
2204
|
if (this.#p && this.#s !== null) {
|
|
2107
|
-
const n = r.to - r.from, a =
|
|
2108
|
-
r = { from: o - n, to: o }, this.#
|
|
2205
|
+
const n = r.to - r.from, a = G(this.#l.right, n, this.#r, i), o = this.#s + a;
|
|
2206
|
+
r = { from: o - n, to: o }, this.#Q = this.#s;
|
|
2109
2207
|
}
|
|
2110
|
-
this.#
|
|
2208
|
+
this.#D(r, { emitChange: !0 }), this.#W.pause(), this.#ie();
|
|
2111
2209
|
}
|
|
2112
2210
|
/**
|
|
2113
2211
|
* Common tail for `pan` / `zoomAt`: routes the just-committed `#logical`
|
|
2114
2212
|
* to the engine as a gesture so the X spring retargets and the Y spring
|
|
2115
2213
|
* eases over `animations.axis.y.gesture`.
|
|
2116
2214
|
*/
|
|
2117
|
-
#
|
|
2118
|
-
const t = this.#
|
|
2215
|
+
#ie() {
|
|
2216
|
+
const t = this.#a;
|
|
2119
2217
|
if (t.to <= t.from) return;
|
|
2120
|
-
this.#
|
|
2218
|
+
this.#_ = !0, this.#u = !0;
|
|
2121
2219
|
const e = performance.now();
|
|
2122
2220
|
this.#e.onPanZoom({ xTarget: t, yAuto: !0 }, e), this.#x(e);
|
|
2123
2221
|
}
|
|
@@ -2135,26 +2233,34 @@ class _e extends Et {
|
|
|
2135
2233
|
* events long enough for the slot processor to snap them.
|
|
2136
2234
|
*/
|
|
2137
2235
|
#x(t) {
|
|
2138
|
-
const e = this.#e.tick(t), i = this.#
|
|
2236
|
+
const e = this.#e.tick(t), i = this.#c.size;
|
|
2139
2237
|
if (i.media.width === 0 || i.media.height === 0) return;
|
|
2140
2238
|
const s = i.media.height - this.xAxisHeight;
|
|
2141
|
-
for (const { slot: r, range: n } of this.#
|
|
2142
|
-
this.#
|
|
2239
|
+
for (const { slot: r, range: n } of this.#se(e))
|
|
2240
|
+
this.#re({ slot: r, range: n, chartHeight: s });
|
|
2143
2241
|
this.syncScales();
|
|
2144
2242
|
}
|
|
2243
|
+
/** Record the X and Y ranges this paint draws; `true` when any moved since the last paint. */
|
|
2244
|
+
#We(t) {
|
|
2245
|
+
let e = t.from !== this.#tt.from || t.to !== this.#tt.to;
|
|
2246
|
+
this.#tt.from = t.from, this.#tt.to = t.to, st(this.#w) && (e = !0);
|
|
2247
|
+
for (const i of this.#o.values())
|
|
2248
|
+
st(i) && (e = !0);
|
|
2249
|
+
return e;
|
|
2250
|
+
}
|
|
2145
2251
|
/** Each scale's slot with the engine's current Y (scale space) for it. */
|
|
2146
|
-
#
|
|
2147
|
-
const e = [{ slot: this.#
|
|
2148
|
-
for (const [i, s] of this.#
|
|
2252
|
+
#se(t) {
|
|
2253
|
+
const e = [{ slot: this.#w, range: t.yRange }];
|
|
2254
|
+
for (const [i, s] of this.#o) {
|
|
2149
2255
|
const r = this.#e.getScaleYRange(i);
|
|
2150
2256
|
r !== null && e.push({ slot: s, range: r });
|
|
2151
2257
|
}
|
|
2152
2258
|
return e;
|
|
2153
2259
|
}
|
|
2154
2260
|
/** Pad an engine Y (scale space) into the slot's value range and remember it. */
|
|
2155
|
-
#
|
|
2261
|
+
#re(t) {
|
|
2156
2262
|
const { slot: e, range: i, chartHeight: s } = t, r = e.range;
|
|
2157
|
-
e.range = this.#
|
|
2263
|
+
e.range = this.#Ne({ slot: e, min: i.min, max: i.max, chartHeight: s }), e.prevMin = i.min, e.prevMax = i.max, (r.min !== e.range.min || r.max !== e.range.max) && e !== this.#w && (this.#ot = !0);
|
|
2158
2264
|
}
|
|
2159
2265
|
/**
|
|
2160
2266
|
* Lightweight scale sync: updates timeScale/yScale from current viewport state
|
|
@@ -2162,99 +2268,100 @@ class _e extends Et {
|
|
|
2162
2268
|
* handler, so DOM axis components always read fresh coordinates on re-render.
|
|
2163
2269
|
*/
|
|
2164
2270
|
syncScales() {
|
|
2165
|
-
const t = this.#
|
|
2271
|
+
const t = this.#c.size;
|
|
2166
2272
|
if (t.media.width === 0 || t.media.height === 0) return;
|
|
2167
|
-
const e = t.media.width - this.#
|
|
2273
|
+
const e = t.media.width - this.#k(), i = t.media.height - this.xAxisHeight;
|
|
2168
2274
|
this.timeScale.update(
|
|
2169
2275
|
this.#e.getAnimationState().xRange,
|
|
2170
2276
|
e,
|
|
2171
2277
|
t.horizontalPixelRatio,
|
|
2172
|
-
this.#
|
|
2173
|
-
), this.yScale.update(this.#
|
|
2174
|
-
for (const s of this.#
|
|
2278
|
+
this.#r
|
|
2279
|
+
), this.yScale.update(this.#w.range, i, t.verticalPixelRatio);
|
|
2280
|
+
for (const s of this.#o.values())
|
|
2175
2281
|
s.yScale.update(s.range, i, t.verticalPixelRatio);
|
|
2176
2282
|
}
|
|
2177
2283
|
/** Expensive: background, grid, all series. Only on data/viewport/resize change. */
|
|
2178
2284
|
renderMain(t) {
|
|
2179
|
-
const e = this.#
|
|
2285
|
+
const e = this.#c.size;
|
|
2180
2286
|
if (e.media.width === 0 || e.media.height === 0) return;
|
|
2181
2287
|
const i = typeof t == "number" ? t : performance.now(), s = this.#e.tick(i);
|
|
2182
2288
|
s.animating && this.#i.markDirty();
|
|
2183
2289
|
const r = e.media.height - this.xAxisHeight;
|
|
2184
2290
|
let n = !1;
|
|
2185
|
-
for (const { slot:
|
|
2186
|
-
m.min ===
|
|
2187
|
-
if (this.syncScales(), this.#
|
|
2188
|
-
const
|
|
2291
|
+
for (const { slot: u, range: m } of this.#se(s))
|
|
2292
|
+
m.min === u.prevMin && m.max === u.prevMax || (this.#re({ slot: u, range: m, chartHeight: r }), n = !0);
|
|
2293
|
+
if (this.syncScales(), this.#Ce(), this.#s !== null && !this.#p) {
|
|
2294
|
+
const u = this.#e.lastXTarget ?? this.#a, m = u.to - u.from;
|
|
2189
2295
|
if (m > 0) {
|
|
2190
|
-
const y = this.#
|
|
2191
|
-
Math.abs(
|
|
2296
|
+
const y = this.#c.size.media.width - this.#k(), p = G(this.#l.right, m, this.#r, y), v = this.#r * 0.5;
|
|
2297
|
+
Math.abs(u.to - (this.#s + p)) < v && (this.#p = !0);
|
|
2192
2298
|
}
|
|
2193
2299
|
}
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
m
|
|
2199
|
-
|
|
2300
|
+
const a = this.#We(s.xRange);
|
|
2301
|
+
(n || a && !s.animating) && this.emit("viewportChange");
|
|
2302
|
+
let o = !1, h = !1, l = !1, c = !1;
|
|
2303
|
+
this.#c.useMainLayer((u) => {
|
|
2304
|
+
const { context: m, bitmapSize: y } = u, p = (e.media.width - this.#k()) * e.horizontalPixelRatio, v = (e.media.height - this.xAxisHeight) * e.verticalPixelRatio, V = this.#z(u);
|
|
2305
|
+
m.clearRect(0, 0, y.width, y.height), m.save(), m.translate(V, 0), m.beginPath(), m.rect(0, 0, this.#de(u, p), v), m.clip(), this.yScale.tickTracker.setCurrentTicks(this.yScale.niceTickValues()), this.timeScale.tickTracker.setCurrentTicks(this.timeScale.niceTickValues(this.#r).ticks), this.yScale.tickTracker.tick(i), this.timeScale.tickTracker.tick(i);
|
|
2306
|
+
for (const x of this.#o.values()) {
|
|
2200
2307
|
const b = x.yScale.tickTracker;
|
|
2201
|
-
b.setCurrentTicks(x.yScale.niceTickValues()), b.tick(i) && (
|
|
2308
|
+
b.setCurrentTicks(x.yScale.niceTickValues()), b.tick(i) && (l = !0);
|
|
2202
2309
|
}
|
|
2203
|
-
const
|
|
2204
|
-
|
|
2205
|
-
const A = this.#
|
|
2206
|
-
if ((A === 0 ||
|
|
2207
|
-
const x =
|
|
2208
|
-
this
|
|
2310
|
+
const T = this.yScale.tickTracker.snapshot(), w = this.timeScale.tickTracker.snapshot();
|
|
2311
|
+
o = T.isAnimating, h = w.isAnimating, (T.isAnimating || w.isAnimating || l || s.animating) && this.emit("tickFrame");
|
|
2312
|
+
const A = this.#j ? 1 : 0;
|
|
2313
|
+
if ((A === 0 || T.entries.length > 0 || w.entries.length > 0) && A !== this.#$.target) {
|
|
2314
|
+
const x = gt() ? 0 : this.#g.axis.gridMs;
|
|
2315
|
+
this.#$.setTarget(A, { now: i, duration: x });
|
|
2209
2316
|
}
|
|
2210
|
-
|
|
2211
|
-
const
|
|
2212
|
-
scope:
|
|
2317
|
+
c = this.#$.tick(i);
|
|
2318
|
+
const H = this.#$.current, N = this.#n === "category" ? oe : w, F = {
|
|
2319
|
+
scope: u,
|
|
2213
2320
|
timeScale: this.timeScale,
|
|
2214
2321
|
yScale: this.yScale,
|
|
2215
|
-
theme: this.#
|
|
2216
|
-
yTicks:
|
|
2217
|
-
timeTicks:
|
|
2218
|
-
alpha:
|
|
2219
|
-
},
|
|
2220
|
-
|
|
2221
|
-
const
|
|
2322
|
+
theme: this.#h,
|
|
2323
|
+
yTicks: T,
|
|
2324
|
+
timeTicks: N,
|
|
2325
|
+
alpha: H
|
|
2326
|
+
}, P = this.#le(u, p);
|
|
2327
|
+
P === 0 && U(F), this.#ye(u, p, v);
|
|
2328
|
+
const W = this.#l, ht = { top: W.top, bottom: W.bottom }, lt = this.#yt(s), O = this.#P;
|
|
2222
2329
|
for (const x of this.#t) {
|
|
2223
|
-
this.#
|
|
2330
|
+
this.#be(x);
|
|
2224
2331
|
const b = x.renderer.getAlpha?.() ?? (x.visible ? 1 : 0);
|
|
2225
2332
|
if (b <= 0) continue;
|
|
2226
|
-
const
|
|
2227
|
-
scope:
|
|
2333
|
+
const C = this.#I(x), ct = this.getYScale(C), Y = {
|
|
2334
|
+
scope: u,
|
|
2228
2335
|
timeScale: this.timeScale,
|
|
2229
|
-
yScale:
|
|
2230
|
-
theme: this.#
|
|
2231
|
-
dataInterval: this.#
|
|
2232
|
-
padding:
|
|
2233
|
-
state:
|
|
2336
|
+
yScale: ct,
|
|
2337
|
+
theme: this.#h,
|
|
2338
|
+
dataInterval: this.#r,
|
|
2339
|
+
padding: ht,
|
|
2340
|
+
state: C === void 0 ? lt : this.#Et(s, C),
|
|
2234
2341
|
seriesId: x.id
|
|
2235
2342
|
}, $ = m.globalAlpha;
|
|
2236
|
-
if (b < 1 && (m.globalAlpha = $ * b),
|
|
2237
|
-
const
|
|
2238
|
-
x.renderer.render(
|
|
2343
|
+
if (b < 1 && (m.globalAlpha = $ * b), O) {
|
|
2344
|
+
const dt = performance.now();
|
|
2345
|
+
x.renderer.render(Y), O.recordSeries(x.id, performance.now() - dt, i);
|
|
2239
2346
|
} else
|
|
2240
|
-
x.renderer.render(
|
|
2347
|
+
x.renderer.render(Y);
|
|
2241
2348
|
b < 1 && (m.globalAlpha = $);
|
|
2242
2349
|
}
|
|
2243
2350
|
m.restore();
|
|
2244
|
-
const
|
|
2245
|
-
|
|
2246
|
-
}), this.#
|
|
2247
|
-
let
|
|
2248
|
-
for (const
|
|
2249
|
-
if (
|
|
2250
|
-
|
|
2351
|
+
const z = { left: V, width: p, height: v };
|
|
2352
|
+
P === 0 ? (this.#ae({ scope: u, pane: z, timeTicks: N, alpha: H }), this.#O(u, p, "left"), this.#O(u, p, "right")) : (this.#O(u, p, "left"), this.#Ye({ grid: F, pane: z, overhang: P }), this.#O(u, p, "right")), this.#he(u, p), this.#ne(u, v);
|
|
2353
|
+
}), this.#vt();
|
|
2354
|
+
let f = !1;
|
|
2355
|
+
for (const u of this.#t)
|
|
2356
|
+
if (u.renderer.needsAnimation) {
|
|
2357
|
+
f = !0, this.#i.markDirty();
|
|
2251
2358
|
break;
|
|
2252
2359
|
}
|
|
2253
|
-
const
|
|
2254
|
-
if ((
|
|
2360
|
+
const g = o || h || l;
|
|
2361
|
+
if ((g || c) && this.#i.markDirty(), !s.animating && !f && !g) {
|
|
2255
2362
|
this.yScale.tickTracker.markArmed(), this.timeScale.tickTracker.markArmed();
|
|
2256
|
-
for (const
|
|
2257
|
-
|
|
2363
|
+
for (const u of this.#o.values())
|
|
2364
|
+
u.yScale.tickTracker.markArmed();
|
|
2258
2365
|
}
|
|
2259
2366
|
}
|
|
2260
2367
|
/**
|
|
@@ -2264,12 +2371,12 @@ class _e extends Et {
|
|
|
2264
2371
|
* a paint-over — so the container background behind the canvas (solid or
|
|
2265
2372
|
* CSS gradient) shows through untouched.
|
|
2266
2373
|
*/
|
|
2267
|
-
#
|
|
2374
|
+
#ne(t, e) {
|
|
2268
2375
|
if (this.#C.top <= 0) return;
|
|
2269
2376
|
const i = Math.min(Math.round(this.#C.top * t.verticalPixelRatio), Math.round(e));
|
|
2270
2377
|
if (i < 1) return;
|
|
2271
2378
|
const { context: s } = t;
|
|
2272
|
-
s.save(), s.globalCompositeOperation = "destination-out", s.fillStyle = this.#
|
|
2379
|
+
s.save(), s.globalCompositeOperation = "destination-out", s.fillStyle = this.#Ee(s, i), s.fillRect(0, 0, t.bitmapSize.width, i), s.restore();
|
|
2273
2380
|
}
|
|
2274
2381
|
/**
|
|
2275
2382
|
* Run the vertical gridlines a short stub past the pane floor, dissolving
|
|
@@ -2279,23 +2386,23 @@ class _e extends Et {
|
|
|
2279
2386
|
* nothing else paints) and faded with the same destination-out ramp the
|
|
2280
2387
|
* edge masks use, so the taper stays correct over any background.
|
|
2281
2388
|
*/
|
|
2282
|
-
#
|
|
2389
|
+
#ae(t) {
|
|
2283
2390
|
const { scope: e, pane: i, timeTicks: s, alpha: r } = t;
|
|
2284
|
-
if (!this.#
|
|
2285
|
-
const { context: n, horizontalPixelRatio: a, verticalPixelRatio: o } = e, h = Math.round(i.height), l = Math.round(
|
|
2391
|
+
if (!this.#j && r <= 0.01 || this.xAxisHeight === 0) return;
|
|
2392
|
+
const { context: n, horizontalPixelRatio: a, verticalPixelRatio: o } = e, h = Math.round(i.height), l = Math.round(R * o);
|
|
2286
2393
|
if (l < 1) return;
|
|
2287
|
-
const
|
|
2288
|
-
n.save(), n.strokeStyle =
|
|
2289
|
-
const f =
|
|
2290
|
-
for (const { value:
|
|
2291
|
-
const
|
|
2292
|
-
if (
|
|
2293
|
-
const
|
|
2294
|
-
if (
|
|
2295
|
-
const
|
|
2296
|
-
n.globalAlpha =
|
|
2394
|
+
const c = this.#h.grid;
|
|
2395
|
+
n.save(), n.strokeStyle = c.color, c.style === "dashed" ? n.setLineDash([4 * a, 4 * a]) : c.style === "dotted" && n.setLineDash([1 * a, 3 * a]), n.lineDashOffset = h, n.lineWidth = te(a);
|
|
2396
|
+
const f = ee(a), g = Math.round(i.width);
|
|
2397
|
+
for (const { value: u, opacity: m } of s.entries) {
|
|
2398
|
+
const y = m * r;
|
|
2399
|
+
if (y <= 0.01) continue;
|
|
2400
|
+
const p = Math.round(this.timeScale.timeToBitmapX(u)) + f;
|
|
2401
|
+
if (p < 0 || p > g) continue;
|
|
2402
|
+
const v = i.left + p;
|
|
2403
|
+
n.globalAlpha = y, n.beginPath(), n.moveTo(v, h), n.lineTo(v, h + l), n.stroke();
|
|
2297
2404
|
}
|
|
2298
|
-
n.restore(), this.#
|
|
2405
|
+
n.restore(), this.#oe(e, i.height);
|
|
2299
2406
|
}
|
|
2300
2407
|
/**
|
|
2301
2408
|
* Erase ramp over the below-pane overrun strip — the gridline tail stubs
|
|
@@ -2303,12 +2410,12 @@ class _e extends Et {
|
|
|
2303
2410
|
* erased at the pane floor, total at the strip's bottom edge, so whatever
|
|
2304
2411
|
* crosses the floor tapers out short of the time-axis labels.
|
|
2305
2412
|
*/
|
|
2306
|
-
#
|
|
2413
|
+
#oe(t, e) {
|
|
2307
2414
|
if (this.xAxisHeight === 0) return;
|
|
2308
|
-
const i = Math.round(e), s = Math.round(
|
|
2415
|
+
const i = Math.round(e), s = Math.round(R * t.verticalPixelRatio);
|
|
2309
2416
|
if (s < 1) return;
|
|
2310
2417
|
const { context: r } = t;
|
|
2311
|
-
r.save(), r.globalCompositeOperation = "destination-out", r.fillStyle = this.#
|
|
2418
|
+
r.save(), r.globalCompositeOperation = "destination-out", r.fillStyle = this.#Xe({ context: r, start: i, height: s }), r.fillRect(0, i, t.bitmapSize.width, s), r.restore();
|
|
2312
2419
|
}
|
|
2313
2420
|
/**
|
|
2314
2421
|
* Crosshair hairlines with the same edge melt the main layer runs: the
|
|
@@ -2320,18 +2427,18 @@ class _e extends Et {
|
|
|
2320
2427
|
* edge. Erases alpha (destination-out), so it must run while the
|
|
2321
2428
|
* crosshair is the only content on the layer.
|
|
2322
2429
|
*/
|
|
2323
|
-
#
|
|
2430
|
+
#Oe(t) {
|
|
2324
2431
|
const e = this.#f;
|
|
2325
2432
|
if (e === null) return;
|
|
2326
|
-
const { scope: i, chartBitmapWidth: s, chartBitmapHeight: r } = t, { context: n } = i, a = this.#
|
|
2327
|
-
n.save(), n.translate(a, 0), n.beginPath(), n.rect(-h, 0, o + h, r + l), n.clip(),
|
|
2433
|
+
const { scope: i, chartBitmapWidth: s, chartBitmapHeight: r } = t, { context: n } = i, a = this.#z(i), o = this.#de(i, s), h = this.#le(i, s), l = this.xAxisHeight > 0 ? Math.round(R * i.verticalPixelRatio) : 0;
|
|
2434
|
+
n.save(), n.translate(a, 0), n.beginPath(), n.rect(-h, 0, o + h, r + l), n.clip(), Et({
|
|
2328
2435
|
scope: i,
|
|
2329
2436
|
bitmapX: e.mediaX * i.horizontalPixelRatio - a,
|
|
2330
2437
|
bitmapY: e.mediaY * i.verticalPixelRatio,
|
|
2331
|
-
theme: this.#
|
|
2438
|
+
theme: this.#h,
|
|
2332
2439
|
pane: { width: s, height: r },
|
|
2333
2440
|
leftOverhang: h
|
|
2334
|
-
}), n.restore(), this.#
|
|
2441
|
+
}), n.restore(), this.#oe(i, r), h === 0 ? this.#O(i, s, "left") : this.#ce(i, h), this.#O(i, s, "right"), this.#he(i, s), this.#ne(i, r);
|
|
2335
2442
|
}
|
|
2336
2443
|
/**
|
|
2337
2444
|
* Horizontal companion to {@link #applyTopFade}: dissolve content that
|
|
@@ -2340,58 +2447,58 @@ class _e extends Et {
|
|
|
2340
2447
|
* Runs the full bitmap height so the below-pane gridline tail stubs melt
|
|
2341
2448
|
* at the edges in step with their lines above.
|
|
2342
2449
|
*/
|
|
2343
|
-
|
|
2344
|
-
const s = this.#
|
|
2450
|
+
#O(t, e, i) {
|
|
2451
|
+
const s = this.#at(t, e, i);
|
|
2345
2452
|
if (s === null) return;
|
|
2346
2453
|
const { context: r } = t, n = Math.min(s.inner, s.outer), a = Math.abs(s.outer - s.inner);
|
|
2347
|
-
r.save(), r.globalCompositeOperation = "destination-out", r.fillStyle = this.#
|
|
2454
|
+
r.save(), r.globalCompositeOperation = "destination-out", r.fillStyle = this.#Be({ context: r, side: i, zone: s }), r.fillRect(n, 0, a, t.bitmapSize.height), r.restore();
|
|
2348
2455
|
}
|
|
2349
2456
|
/** Dissolve content leaving through a plain canvas edge — the side opposite
|
|
2350
2457
|
* the Y axis, or either side on a spatial-only chart — when configured. */
|
|
2351
|
-
#
|
|
2458
|
+
#he(t, e) {
|
|
2352
2459
|
const { context: i } = t;
|
|
2353
|
-
for (const s of this.#
|
|
2354
|
-
const r = this
|
|
2460
|
+
for (const s of this.#ze()) {
|
|
2461
|
+
const r = this.#$e({ scope: t, paneBitmapWidth: e, side: s });
|
|
2355
2462
|
if (r === null) continue;
|
|
2356
2463
|
const n = Math.min(r.edge, r.inner), a = Math.abs(r.inner - r.edge);
|
|
2357
|
-
i.save(), i.globalCompositeOperation = "destination-out", i.fillStyle = this.#
|
|
2464
|
+
i.save(), i.globalCompositeOperation = "destination-out", i.fillStyle = this.#_e({ context: i, side: s, zone: r }), i.fillRect(n, 0, a, t.bitmapSize.height), i.restore();
|
|
2358
2465
|
}
|
|
2359
2466
|
}
|
|
2360
2467
|
/** Sides whose fade is a plain edge zone rather than the axis-column ramp —
|
|
2361
2468
|
* neither the default axis's side nor one a named scale's column holds. */
|
|
2362
|
-
#
|
|
2363
|
-
if (this.#
|
|
2364
|
-
const t =
|
|
2365
|
-
return this.getAxisColumnWidth(t) > 0 ?
|
|
2469
|
+
#ze() {
|
|
2470
|
+
if (this.#it()) return ae;
|
|
2471
|
+
const t = rt(this.yAxisPosition);
|
|
2472
|
+
return this.getAxisColumnWidth(t) > 0 ? he : t === "left" ? le : ce;
|
|
2366
2473
|
}
|
|
2367
2474
|
/** Bitmap px the gridlines and crosshair run under a left Y-axis column, where
|
|
2368
2475
|
* data can't follow (see {@link #axisFadeZone}). `0` without one or with its fade off. */
|
|
2369
|
-
#
|
|
2370
|
-
return this.#
|
|
2476
|
+
#le(t, e) {
|
|
2477
|
+
return this.#at(t, e, "left") === null ? 0 : Math.min(Math.round(J * t.horizontalPixelRatio), this.#z(t));
|
|
2371
2478
|
}
|
|
2372
2479
|
/** Left-axis grid pass, run after the axis fade: `destination-over` keeps the
|
|
2373
2480
|
* gridlines out of the data ramp, then they taper out under the column. */
|
|
2374
|
-
#
|
|
2481
|
+
#Ye(t) {
|
|
2375
2482
|
const { grid: e, pane: i, overhang: s } = t, { scope: r } = e, { context: n } = r;
|
|
2376
2483
|
n.save(), n.globalCompositeOperation = "destination-over";
|
|
2377
|
-
const a = this.#
|
|
2378
|
-
n.save(), n.translate(i.left, 0), n.beginPath(), n.rect(-s, 0, i.width + s + a, i.height), n.clip(),
|
|
2484
|
+
const a = this.#at(r, i.width, "right")?.intrusion ?? 0;
|
|
2485
|
+
n.save(), n.translate(i.left, 0), n.beginPath(), n.rect(-s, 0, i.width + s + a, i.height), n.clip(), U({ ...e, leftOverhang: s }), n.restore(), this.#ae({ scope: r, pane: i, timeTicks: e.timeTicks, alpha: e.alpha ?? 1 }), n.restore(), this.#ce(r, s);
|
|
2379
2486
|
}
|
|
2380
2487
|
/** Erase the {@link #gridOverhang} strip: none at the pane edge, total at its outer end. */
|
|
2381
|
-
#
|
|
2382
|
-
const i = this.#
|
|
2383
|
-
r.save(), r.globalCompositeOperation = "destination-out", r.fillStyle = this.#
|
|
2488
|
+
#ce(t, e) {
|
|
2489
|
+
const i = this.#z(t), s = i - e, { context: r } = t;
|
|
2490
|
+
r.save(), r.globalCompositeOperation = "destination-out", r.fillStyle = this.#Ze({ context: r, start: s, end: i }), r.fillRect(s, 0, e, t.bitmapSize.height), r.restore();
|
|
2384
2491
|
}
|
|
2385
2492
|
/** Canvas bitmap x of the pane's left edge — whole device pixels, so the
|
|
2386
2493
|
* translated pane keeps crisp strokes. */
|
|
2387
|
-
#
|
|
2494
|
+
#z(t) {
|
|
2388
2495
|
return Math.round(this.plotLeft * t.horizontalPixelRatio);
|
|
2389
2496
|
}
|
|
2390
2497
|
/** Pane-local width of the pane clip: the pane plus the right fade
|
|
2391
2498
|
* intrusion, so content can slide under a right Y-axis column before the
|
|
2392
2499
|
* mask dissolves it. */
|
|
2393
|
-
#
|
|
2394
|
-
const i = this.#
|
|
2500
|
+
#de(t, e) {
|
|
2501
|
+
const i = this.#at(t, e, "right")?.intrusion ?? 0;
|
|
2395
2502
|
return e + i;
|
|
2396
2503
|
}
|
|
2397
2504
|
/**
|
|
@@ -2405,22 +2512,22 @@ class _e extends Et {
|
|
|
2405
2512
|
* total-erased anyway). `null` when no column sits on `side`, its fade
|
|
2406
2513
|
* is `0`, or the chart is spatial-only.
|
|
2407
2514
|
*/
|
|
2408
|
-
#
|
|
2409
|
-
if (this.#
|
|
2410
|
-
const s = i === "left", r = t.bitmapSize.width, n = this.#
|
|
2515
|
+
#at(t, e, i) {
|
|
2516
|
+
if (this.#it()) return null;
|
|
2517
|
+
const s = i === "left", r = t.bitmapSize.width, n = this.#z(t), a = s ? n : Math.max(0, Math.round(r - n - e));
|
|
2411
2518
|
if (a === 0) return null;
|
|
2412
|
-
const o = t.horizontalPixelRatio, h = Math.round(
|
|
2413
|
-
if (
|
|
2519
|
+
const o = t.horizontalPixelRatio, h = Math.round(J * o), l = Math.round(ne * o), c = s ? 0 : Math.min(h, a), f = s ? h + l : c + l, g = s ? this.#C.left : this.#C.right, u = g === null ? f : Math.round(g * o);
|
|
2520
|
+
if (u < 1) return null;
|
|
2414
2521
|
if (s) {
|
|
2415
|
-
const
|
|
2416
|
-
return { inner:
|
|
2522
|
+
const p = a, v = Math.min(u, r - p);
|
|
2523
|
+
return { inner: p + v, outer: p, intrusion: c };
|
|
2417
2524
|
}
|
|
2418
|
-
const
|
|
2419
|
-
return { inner:
|
|
2525
|
+
const m = n + e + c, y = Math.min(u, m);
|
|
2526
|
+
return { inner: m - y, outer: m, intrusion: c };
|
|
2420
2527
|
}
|
|
2421
2528
|
/** Bitmap geometry of a plain fade at the `side` canvas edge — total erase
|
|
2422
2529
|
* at `edge`, none at `inner`. Off unless that side's fade is configured. */
|
|
2423
|
-
|
|
2530
|
+
#$e(t) {
|
|
2424
2531
|
const { scope: e, paneBitmapWidth: i, side: s } = t, r = this.#C[s];
|
|
2425
2532
|
if (r === null) return null;
|
|
2426
2533
|
const n = Math.min(Math.round(r * e.horizontalPixelRatio), Math.round(i));
|
|
@@ -2435,15 +2542,15 @@ class _e extends Et {
|
|
|
2435
2542
|
* changes (resize, DPR change, `setFade`). Ease-out ramp (`1 - t²`):
|
|
2436
2543
|
* near-total erasure across the upper half keeps a floating header
|
|
2437
2544
|
* legible, then a soft tail into full opacity at the zone's bottom. */
|
|
2438
|
-
#
|
|
2439
|
-
const i = this.#
|
|
2545
|
+
#Ee(t, e) {
|
|
2546
|
+
const i = this.#b.top;
|
|
2440
2547
|
if (i !== null && i.height === e) return i.gradient;
|
|
2441
2548
|
const s = t.createLinearGradient(0, 0, 0, e);
|
|
2442
2549
|
for (let r = 0; r <= 4; r++) {
|
|
2443
2550
|
const n = r / 4;
|
|
2444
2551
|
s.addColorStop(n, `rgba(0, 0, 0, ${1 - n * n})`);
|
|
2445
2552
|
}
|
|
2446
|
-
return this.#
|
|
2553
|
+
return this.#b.top = { height: e, gradient: s }, s;
|
|
2447
2554
|
}
|
|
2448
2555
|
/** Axis-column mask — erase grows from 0 at the ramp's inner start to
|
|
2449
2556
|
* total at its outer end on an ease-in (`s³`): zero slope *and* zero
|
|
@@ -2451,51 +2558,51 @@ class _e extends Et {
|
|
|
2451
2558
|
* candles at rest and the aggressive erasing all happens deep under the
|
|
2452
2559
|
* axis column. Nine stops keep the piecewise interpolation smooth across
|
|
2453
2560
|
* the zone. */
|
|
2454
|
-
#
|
|
2455
|
-
const { context: e, side: i, zone: s } = t, r = this.#
|
|
2561
|
+
#Be(t) {
|
|
2562
|
+
const { context: e, side: i, zone: s } = t, r = this.#b.axis[i];
|
|
2456
2563
|
if (r !== null && r.inner === s.inner && r.outer === s.outer) return r.gradient;
|
|
2457
2564
|
const n = e.createLinearGradient(s.inner, 0, s.outer, 0);
|
|
2458
2565
|
for (let a = 0; a <= 8; a++) {
|
|
2459
2566
|
const o = a / 8;
|
|
2460
2567
|
n.addColorStop(o, `rgba(0, 0, 0, ${o * o * o})`);
|
|
2461
2568
|
}
|
|
2462
|
-
return this.#
|
|
2569
|
+
return this.#b.axis[i] = { inner: s.inner, outer: s.outer, gradient: n }, n;
|
|
2463
2570
|
}
|
|
2464
2571
|
/** Erase ramp for the gridline tail stubs — nothing erased at the pane
|
|
2465
2572
|
* floor, total at the stub tip, ease-in (`t²`) so a stub holds strength
|
|
2466
2573
|
* briefly before melting away short of the label glyphs. */
|
|
2467
|
-
#
|
|
2468
|
-
const e = this.#
|
|
2574
|
+
#Xe(t) {
|
|
2575
|
+
const e = this.#b.tail;
|
|
2469
2576
|
if (e !== null && e.start === t.start && e.height === t.height) return e.gradient;
|
|
2470
2577
|
const i = t.context.createLinearGradient(0, t.start, 0, t.start + t.height);
|
|
2471
2578
|
for (let s = 0; s <= 4; s++) {
|
|
2472
2579
|
const r = s / 4;
|
|
2473
2580
|
i.addColorStop(r, `rgba(0, 0, 0, ${r * r})`);
|
|
2474
2581
|
}
|
|
2475
|
-
return this.#
|
|
2582
|
+
return this.#b.tail = { start: t.start, height: t.height, gradient: i }, i;
|
|
2476
2583
|
}
|
|
2477
2584
|
/** Gridline overhang ramp — ease-in (`t²`) like the tail stubs. */
|
|
2478
|
-
#
|
|
2479
|
-
const e = this.#
|
|
2585
|
+
#Ze(t) {
|
|
2586
|
+
const e = this.#b.overhang;
|
|
2480
2587
|
if (e !== null && e.start === t.start && e.end === t.end) return e.gradient;
|
|
2481
2588
|
const i = t.context.createLinearGradient(t.end, 0, t.start, 0);
|
|
2482
2589
|
for (let s = 0; s <= 4; s++) {
|
|
2483
2590
|
const r = s / 4;
|
|
2484
2591
|
i.addColorStop(r, `rgba(0, 0, 0, ${r * r})`);
|
|
2485
2592
|
}
|
|
2486
|
-
return this.#
|
|
2593
|
+
return this.#b.overhang = { start: t.start, end: t.end, gradient: i }, i;
|
|
2487
2594
|
}
|
|
2488
2595
|
/** Opposite-edge mask — mirror of the top ramp: total erase at the
|
|
2489
2596
|
* canvas edge, fully opaque at the zone's inner boundary. */
|
|
2490
|
-
#
|
|
2491
|
-
const { context: e, side: i, zone: s } = t, r = this.#
|
|
2597
|
+
#_e(t) {
|
|
2598
|
+
const { context: e, side: i, zone: s } = t, r = this.#b.edge[i];
|
|
2492
2599
|
if (r !== null && r.edge === s.edge && r.inner === s.inner) return r.gradient;
|
|
2493
2600
|
const n = e.createLinearGradient(s.edge, 0, s.inner, 0);
|
|
2494
2601
|
for (let a = 0; a <= 4; a++) {
|
|
2495
2602
|
const o = a / 4;
|
|
2496
2603
|
n.addColorStop(o, `rgba(0, 0, 0, ${1 - o * o})`);
|
|
2497
2604
|
}
|
|
2498
|
-
return this.#
|
|
2605
|
+
return this.#b.edge[i] = { edge: s.edge, inner: s.inner, gradient: n }, n;
|
|
2499
2606
|
}
|
|
2500
2607
|
/**
|
|
2501
2608
|
* Paint a full frame: the main layer, then the overlay synchronously on
|
|
@@ -2506,13 +2613,13 @@ class _e extends Et {
|
|
|
2506
2613
|
* `markDirty` calls made *during* `renderOverlay` (pulse, edge spinner)
|
|
2507
2614
|
* land after the consume and re-arm cleanly for the next frame.
|
|
2508
2615
|
*/
|
|
2509
|
-
#
|
|
2510
|
-
this.#
|
|
2616
|
+
#Pt(t) {
|
|
2617
|
+
this.#Ct("main", t, () => this.renderMain(t)), this.#d.consume(), this.#Ct("overlay", t, () => this.renderOverlay(t));
|
|
2511
2618
|
}
|
|
2512
2619
|
/** Run a layer's paint, booking duration + draw calls to the perf monitor
|
|
2513
2620
|
* when one is attached — keeps overlay time out of the `main` samples. */
|
|
2514
|
-
#
|
|
2515
|
-
const s = this.#
|
|
2621
|
+
#Ct(t, e, i) {
|
|
2622
|
+
const s = this.#P;
|
|
2516
2623
|
if (!s) {
|
|
2517
2624
|
i();
|
|
2518
2625
|
return;
|
|
@@ -2523,7 +2630,7 @@ class _e extends Et {
|
|
|
2523
2630
|
}
|
|
2524
2631
|
/** Cheap overlay: crosshair, nearest-point dots, pulse animation, edge indicator. */
|
|
2525
2632
|
renderOverlay(t) {
|
|
2526
|
-
const e = this.#
|
|
2633
|
+
const e = this.#c.size;
|
|
2527
2634
|
if (e.media.width === 0 || e.media.height === 0) return;
|
|
2528
2635
|
let i = !1;
|
|
2529
2636
|
for (const l of this.#t)
|
|
@@ -2533,71 +2640,71 @@ class _e extends Et {
|
|
|
2533
2640
|
}
|
|
2534
2641
|
this.#y.some((l) => l.pulse) && (i = !0);
|
|
2535
2642
|
const s = {
|
|
2536
|
-
left: this.#
|
|
2537
|
-
right: this.#
|
|
2643
|
+
left: this.#E.left && this.#A.left === "loading" ? "idle" : this.#A.left,
|
|
2644
|
+
right: this.#E.right && this.#A.right === "loading" ? "idle" : this.#A.right
|
|
2538
2645
|
}, r = {
|
|
2539
|
-
left: this.#
|
|
2540
|
-
right: this.#
|
|
2541
|
-
}, n = r.left !== null || r.right !== null, a = s.left === "loading" || s.right === "loading" || n, o = s.left !== "idle" || s.right !== "idle" || n, h = !!this.#f || i || o || this.#y.length > 0 || this.#
|
|
2542
|
-
if (!(!h && !this.#
|
|
2543
|
-
if (this.#
|
|
2646
|
+
left: this.#jt("left"),
|
|
2647
|
+
right: this.#jt("right")
|
|
2648
|
+
}, n = r.left !== null || r.right !== null, a = s.left === "loading" || s.right === "loading" || n, o = s.left !== "idle" || s.right !== "idle" || n, h = !!this.#f || i || o || this.#y.length > 0 || this.#S.length > 0;
|
|
2649
|
+
if (!(!h && !this.#Vt)) {
|
|
2650
|
+
if (this.#Vt = h, this.#c.useOverlayLayer((l) => {
|
|
2544
2651
|
if (!h) return;
|
|
2545
|
-
const
|
|
2546
|
-
this.#f && this.#
|
|
2547
|
-
const
|
|
2548
|
-
for (const
|
|
2549
|
-
if (!
|
|
2550
|
-
const
|
|
2551
|
-
|
|
2652
|
+
const c = (e.media.width - this.#k()) * e.horizontalPixelRatio, f = (e.media.height - this.xAxisHeight) * e.verticalPixelRatio;
|
|
2653
|
+
this.#f && this.#Gt() && this.#Oe({ scope: l, chartBitmapWidth: c, chartBitmapHeight: f }), l.context.save(), l.context.translate(this.#z(l), 0), l.context.beginPath(), l.context.rect(0, 0, c, f), l.context.clip();
|
|
2654
|
+
const g = this.#l, u = { top: g.top, bottom: g.bottom }, m = this.getAnimationState();
|
|
2655
|
+
for (const y of this.#t) {
|
|
2656
|
+
if (!y.visible) continue;
|
|
2657
|
+
const p = this.#I(y);
|
|
2658
|
+
y.renderer.drawOverlay?.({
|
|
2552
2659
|
scope: l,
|
|
2553
2660
|
timeScale: this.timeScale,
|
|
2554
|
-
yScale: this.getYScale(
|
|
2555
|
-
theme: this.#
|
|
2661
|
+
yScale: this.getYScale(p),
|
|
2662
|
+
theme: this.#h,
|
|
2556
2663
|
// Overlays only snap the crosshair dots with it.
|
|
2557
2664
|
dataInterval: this.#X(),
|
|
2558
|
-
padding:
|
|
2665
|
+
padding: u,
|
|
2559
2666
|
crosshair: this.#f,
|
|
2560
|
-
state:
|
|
2561
|
-
seriesId:
|
|
2667
|
+
state: p === void 0 ? m : this.#Et(m, p),
|
|
2668
|
+
seriesId: y.id
|
|
2562
2669
|
});
|
|
2563
2670
|
}
|
|
2564
|
-
this.#
|
|
2671
|
+
this.#xe(l, c, f), this.#pe(l, c, f), o && vt({
|
|
2565
2672
|
scope: l,
|
|
2566
|
-
chartMediaWidth: e.media.width - this.#
|
|
2673
|
+
chartMediaWidth: e.media.width - this.#k(),
|
|
2567
2674
|
chartMediaHeight: e.media.height - this.xAxisHeight,
|
|
2568
2675
|
timeScale: this.timeScale,
|
|
2569
|
-
theme: this.#
|
|
2676
|
+
theme: this.#h,
|
|
2570
2677
|
edgeStates: s,
|
|
2571
2678
|
edgeExitFades: r,
|
|
2572
|
-
edgeIndicatorFns: this.#
|
|
2573
|
-
resolveBoundary: (
|
|
2574
|
-
resolveEdgeAnchor: (
|
|
2575
|
-
resolveEdgeBarSpacing: () => this.#
|
|
2576
|
-
reportPlaceholders: (
|
|
2577
|
-
this.#
|
|
2679
|
+
edgeIndicatorFns: this.#Ft,
|
|
2680
|
+
resolveBoundary: (y) => St(y, this.#Ht[y], this.getDataBounds()),
|
|
2681
|
+
resolveEdgeAnchor: (y, p) => this.#Ae(y, p),
|
|
2682
|
+
resolveEdgeBarSpacing: () => this.#Pe(),
|
|
2683
|
+
reportPlaceholders: (y, p) => {
|
|
2684
|
+
this.#ct[y] = { bars: p, at: performance.now() };
|
|
2578
2685
|
}
|
|
2579
2686
|
}), l.context.restore();
|
|
2580
2687
|
}), i) {
|
|
2581
|
-
const { from: l, to:
|
|
2688
|
+
const { from: l, to: c } = this.timeScale.getRange();
|
|
2582
2689
|
let f = !1;
|
|
2583
|
-
for (const
|
|
2584
|
-
if (!(!
|
|
2690
|
+
for (const g of this.#t)
|
|
2691
|
+
if (!(!g.visible || !g.renderer.overlayNeedsAnimation) && (g.renderer.hasOverlayContentInRange?.(l, c) ?? !0)) {
|
|
2585
2692
|
f = !0;
|
|
2586
2693
|
break;
|
|
2587
2694
|
}
|
|
2588
2695
|
if (!f) {
|
|
2589
|
-
for (const
|
|
2590
|
-
if (
|
|
2696
|
+
for (const g of this.#y)
|
|
2697
|
+
if (g.pulse && g.time >= l && g.time <= c) {
|
|
2591
2698
|
f = !0;
|
|
2592
2699
|
break;
|
|
2593
2700
|
}
|
|
2594
2701
|
}
|
|
2595
|
-
f && this.#
|
|
2702
|
+
f && this.#d.markDirty();
|
|
2596
2703
|
}
|
|
2597
|
-
a && this.#
|
|
2704
|
+
a && this.#d.markDirty();
|
|
2598
2705
|
}
|
|
2599
2706
|
}
|
|
2600
2707
|
}
|
|
2601
2708
|
export {
|
|
2602
|
-
|
|
2709
|
+
ti as ChartInstance
|
|
2603
2710
|
};
|