@wick-charts/vue 0.6.4 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/dist/BandSeries.vue.js +20 -18
- package/dist/BarSeries.vue.js +15 -13
- package/dist/CandlestickSeries.vue.js +31 -29
- package/dist/ChartContainer.vue.js +77 -70
- package/dist/LineSeries.vue.js +19 -17
- package/dist/composables.js +46 -36
- package/dist/core/dist/animation/viewport-engine.js +155 -96
- package/dist/core/dist/axis/dom-labels.js +56 -51
- package/dist/core/dist/chart/scale-guards.js +23 -5
- package/dist/core/dist/chart/x-guards.js +37 -0
- package/dist/core/dist/chart.js +1286 -843
- package/dist/core/dist/data/sync.js +37 -31
- package/dist/core/dist/navigator/controller.js +37 -37
- package/dist/core/dist/perf/perf-hud.js +3 -3
- package/dist/core/dist/scales/tick-tracker.js +2 -2
- package/dist/core/dist/scales/x-scale.js +167 -53
- package/dist/core/dist/scales/y-scale.js +36 -34
- package/dist/core/dist/series/band.js +266 -213
- package/dist/core/dist/series/bar.js +297 -291
- package/dist/core/dist/series/base-multi-layer.js +283 -237
- package/dist/core/dist/series/candlestick.js +1 -0
- package/dist/core/dist/series/line.js +21 -20
- package/dist/core/dist/snapshots.js +55 -43
- package/dist/index.d.ts +323 -58
- package/dist/index.js +9 -9
- package/dist/ui/Crosshair.vue.js +51 -27
- package/dist/ui/InfoBar.vue.js +37 -37
- package/dist/ui/Marker.vue.js +14 -11
- package/dist/ui/Navigator.vue.js +23 -23
- package/dist/ui/ReferenceLine.vue.js +19 -16
- package/dist/ui/Tooltip.vue.js +91 -86
- package/dist/ui/XAxis.vue.js +48 -0
- package/dist/ui/XAxis.vue2.js +4 -0
- package/dist/ui/YAxis.vue.js +44 -28
- package/dist/ui/YLabel.vue.js +78 -74
- package/package.json +2 -2
- package/src/BandSeries.vue +11 -6
- package/src/BarSeries.vue +13 -6
- package/src/CandlestickSeries.vue +9 -5
- package/src/ChartContainer.vue +20 -0
- package/src/LineSeries.vue +13 -6
- package/src/composables.ts +23 -4
- package/src/index.ts +8 -1
- package/src/ui/Crosshair.vue +41 -1
- package/src/ui/InfoBar.vue +2 -1
- package/src/ui/Marker.vue +5 -1
- package/src/ui/Navigator.vue +2 -1
- package/src/ui/ReferenceLine.vue +5 -1
- package/src/ui/Tooltip.vue +7 -4
- package/src/ui/{TimeAxis.vue → XAxis.vue} +18 -5
- package/src/ui/YAxis.vue +66 -12
- package/src/ui/YLabel.vue +35 -5
- package/dist/ui/TimeAxis.vue.js +0 -44
- package/dist/ui/TimeAxis.vue2.js +0 -4
|
@@ -1,14 +1,20 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
import { clamp as d } from "../utils/math.js";
|
|
2
|
+
import { crispCenterOffset as v } from "../utils/pixel-grid.js";
|
|
3
|
+
import { formatTime as g, niceTimeIntervals as p } from "../utils/time.js";
|
|
4
|
+
import { AxisTickTracker as I } from "./tick-tracker.js";
|
|
5
|
+
import { pickNiceCeiling as b, pickNiceFloor as k } from "./y-scale.js";
|
|
6
|
+
const o = 50, y = 80, h = 0.3, u = 0.2;
|
|
7
|
+
class W {
|
|
6
8
|
/**
|
|
7
9
|
* Shared fade state for time ticks. Grid lines (canvas) and DOM tick labels
|
|
8
10
|
* read opacity from the same tracker, so a tick fading in/out looks
|
|
9
11
|
* identical on both surfaces.
|
|
10
12
|
*/
|
|
11
|
-
tickTracker = new
|
|
13
|
+
tickTracker = new I();
|
|
14
|
+
type = "time";
|
|
15
|
+
/** Category names in band order — category `i` is centred on coordinate `i`. */
|
|
16
|
+
categories = [];
|
|
17
|
+
bandPadding = { inner: h, outer: u };
|
|
12
18
|
from = 0;
|
|
13
19
|
to = 0;
|
|
14
20
|
width = 1;
|
|
@@ -17,7 +23,7 @@ class b {
|
|
|
17
23
|
// Label density knobs — written by <TimeAxis labelCount=… minLabelSpacing=…>.
|
|
18
24
|
labelCountHintValue = null;
|
|
19
25
|
minSpacingValue = null;
|
|
20
|
-
/** Custom formatter
|
|
26
|
+
/** Custom formatter, installed by `<XAxis format=…>`. */
|
|
21
27
|
customFormat = null;
|
|
22
28
|
/** Custom tick generator — bypasses tier resolution in `niceTickValues` when set. */
|
|
23
29
|
customTickGenerator = null;
|
|
@@ -38,22 +44,21 @@ class b {
|
|
|
38
44
|
return this.labelCountHintValue;
|
|
39
45
|
}
|
|
40
46
|
get minLabelSpacing() {
|
|
41
|
-
return this.minSpacingValue ??
|
|
47
|
+
return this.minSpacingValue ?? y;
|
|
42
48
|
}
|
|
43
|
-
update(t,
|
|
44
|
-
if (this.from = t.from, this.to = t.to, this.width =
|
|
45
|
-
const
|
|
46
|
-
this.lastBucketKey !== null && this.lastBucketKey !==
|
|
49
|
+
update(t, i, s, e) {
|
|
50
|
+
if (this.from = t.from, this.to = t.to, this.width = i, this.pixelRatio = s, this.type === "time" && e !== void 0 && e > 0) {
|
|
51
|
+
const r = c(e);
|
|
52
|
+
this.lastBucketKey !== null && this.lastBucketKey !== r && this.resetHysteresis(), this.lastBucketKey = r, this.dataInterval = e;
|
|
47
53
|
}
|
|
48
54
|
this.resolveInterval();
|
|
49
55
|
}
|
|
50
56
|
setLabelCount(t) {
|
|
51
|
-
this.labelCountHintValue =
|
|
57
|
+
this.labelCountHintValue = M(t), this.resetHysteresis(), this.resolveInterval();
|
|
52
58
|
}
|
|
53
59
|
setMinSpacing(t) {
|
|
54
|
-
this.minSpacingValue =
|
|
60
|
+
this.minSpacingValue = x(t), this.resetHysteresis(), this.resolveInterval();
|
|
55
61
|
}
|
|
56
|
-
/** Install (or clear) a custom tick-label formatter. */
|
|
57
62
|
setFormat(t) {
|
|
58
63
|
this.customFormat = t;
|
|
59
64
|
}
|
|
@@ -61,6 +66,60 @@ class b {
|
|
|
61
66
|
getFormat() {
|
|
62
67
|
return this.customFormat;
|
|
63
68
|
}
|
|
69
|
+
/** What the axis maps. Set once by the chart at construction. */
|
|
70
|
+
setType(t) {
|
|
71
|
+
this.type = t, this.resetHysteresis(), this.resolveInterval();
|
|
72
|
+
}
|
|
73
|
+
getType() {
|
|
74
|
+
return this.type;
|
|
75
|
+
}
|
|
76
|
+
/** Category names in band order (category axis). */
|
|
77
|
+
setCategories(t) {
|
|
78
|
+
this.categories = t;
|
|
79
|
+
}
|
|
80
|
+
getCategories() {
|
|
81
|
+
return this.categories;
|
|
82
|
+
}
|
|
83
|
+
/** Band spacing on a category axis; an omitted or invalid side takes its default. */
|
|
84
|
+
setBandPadding(t) {
|
|
85
|
+
this.bandPadding = {
|
|
86
|
+
inner: m({ value: t?.inner, fallback: h, max: 1 }),
|
|
87
|
+
outer: m({ value: t?.outer, fallback: u, max: 1 / 0 })
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
getBandPadding() {
|
|
91
|
+
return this.bandPadding;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* The coordinate range that fits every band with its outer padding, or
|
|
95
|
+
* `null` without categories. Band `i` spans `i ± (1 - inner) / 2`.
|
|
96
|
+
*/
|
|
97
|
+
bandRange() {
|
|
98
|
+
const t = this.categories.length;
|
|
99
|
+
if (t === 0) return null;
|
|
100
|
+
const i = (1 - this.bandPadding.inner) / 2, s = this.bandPadding.outer;
|
|
101
|
+
return { from: -i - s, to: t - 1 + i + s };
|
|
102
|
+
}
|
|
103
|
+
/** Width of one category band in physical pixels — what a bar on a category axis fills. */
|
|
104
|
+
bandWidthBitmap() {
|
|
105
|
+
return Math.max(1, Math.round(this.barWidthMedia(1 - this.bandPadding.inner) * this.pixelRatio));
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* The internal coordinate the pointer resolves to: the nearest band's index
|
|
109
|
+
* on a category axis, `coord` itself elsewhere.
|
|
110
|
+
*/
|
|
111
|
+
snapToBand(t) {
|
|
112
|
+
const i = this.categories.length;
|
|
113
|
+
return this.type !== "category" || i === 0 ? t : d(Math.round(t), 0, i - 1);
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* An internal coordinate in the axis domain: the category name at that
|
|
117
|
+
* band on a category axis (`''` without categories), the number itself on
|
|
118
|
+
* time and numeric axes.
|
|
119
|
+
*/
|
|
120
|
+
domainValue(t) {
|
|
121
|
+
return this.type !== "category" ? t : this.categories[this.snapToBand(t)] ?? "";
|
|
122
|
+
}
|
|
64
123
|
/**
|
|
65
124
|
* Install (or clear) a custom tick-value generator. When set, it replaces
|
|
66
125
|
* `niceTimeIntervals` tier resolution entirely — `niceTickValues` calls it
|
|
@@ -84,12 +143,23 @@ class b {
|
|
|
84
143
|
return this.timeZoneValue;
|
|
85
144
|
}
|
|
86
145
|
/**
|
|
87
|
-
* Format
|
|
88
|
-
* {@link setFormat})
|
|
89
|
-
*
|
|
146
|
+
* Format an internal X coordinate for display — a tick, the crosshair, a
|
|
147
|
+
* tooltip header. A custom formatter (via {@link setFormat}) gets the
|
|
148
|
+
* domain value; otherwise a time axis formats the timestamp with the
|
|
149
|
+
* installed locale/timezone, a numeric axis prints a locale number, and a
|
|
150
|
+
* category axis prints the name.
|
|
90
151
|
*/
|
|
91
|
-
formatX(t,
|
|
92
|
-
|
|
152
|
+
formatX(t, i) {
|
|
153
|
+
const s = this.domainValue(t);
|
|
154
|
+
return this.customFormat ? this.customFormat(s, i) : this.type === "category" ? String(s) : this.type === "numeric" ? T({ value: t, step: i, locale: this.localeValue }) : g(t, i, { locale: this.localeValue, timeZone: this.timeZoneValue });
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Format a data point's X for a tooltip or info-bar header. Like
|
|
158
|
+
* {@link formatX}, except a numeric axis prints the value with its own
|
|
159
|
+
* decimals — `1.25` stays `1.25` where the step would round it.
|
|
160
|
+
*/
|
|
161
|
+
formatPointX(t, i) {
|
|
162
|
+
return this.type !== "numeric" || this.customFormat ? this.formatX(t, i) : t.toLocaleString(this.localeValue ?? "en-US", { maximumFractionDigits: 20 });
|
|
93
163
|
}
|
|
94
164
|
resetHysteresis() {
|
|
95
165
|
this.lastInterval = null, this.lastWant = null;
|
|
@@ -112,7 +182,7 @@ class b {
|
|
|
112
182
|
* so text and gridline share one pixel grid.
|
|
113
183
|
*/
|
|
114
184
|
timeToSnappedX(t) {
|
|
115
|
-
return (this.timeToBitmapX(t) +
|
|
185
|
+
return (this.timeToBitmapX(t) + v(this.pixelRatio)) / this.pixelRatio;
|
|
116
186
|
}
|
|
117
187
|
xToTime(t) {
|
|
118
188
|
return this.to <= this.from ? this.from : this.from + t / this.width * (this.to - this.from);
|
|
@@ -134,17 +204,25 @@ class b {
|
|
|
134
204
|
niceTickValues(t) {
|
|
135
205
|
if (this.to <= this.from) return { ticks: [], tickInterval: 0 };
|
|
136
206
|
if (this.customTickGenerator) {
|
|
137
|
-
const
|
|
138
|
-
return { ticks:
|
|
207
|
+
const a = this.customTickGenerator({ from: this.from, to: this.to }, t).slice(0, o), l = a.length >= 2 ? a[1] - a[0] : t;
|
|
208
|
+
return { ticks: a, tickInterval: l };
|
|
139
209
|
}
|
|
140
|
-
if (this.
|
|
141
|
-
|
|
142
|
-
|
|
210
|
+
if (this.type === "category") return this.bandTicks();
|
|
211
|
+
if (this.type === "time" && this.dataInterval !== t) {
|
|
212
|
+
const a = c(t);
|
|
213
|
+
this.lastBucketKey !== null && this.lastBucketKey !== a && this.resetHysteresis(), this.lastBucketKey = a, this.dataInterval = t, this.resolveInterval();
|
|
143
214
|
}
|
|
144
215
|
if (this.resolvedInterval == null) return { ticks: [], tickInterval: 0 };
|
|
145
|
-
const
|
|
146
|
-
for (let
|
|
147
|
-
return { ticks:
|
|
216
|
+
const i = this.resolvedInterval, s = Math.ceil(this.from / i) * i, e = Math.max(0, Math.min(o, Math.floor((this.to - s) / i) + 1)), r = [];
|
|
217
|
+
for (let a = 0; a < e; a++) r.push(s + a * i);
|
|
218
|
+
return { ticks: r, tickInterval: i };
|
|
219
|
+
}
|
|
220
|
+
/** One tick per category whose band centre is in view. */
|
|
221
|
+
bandTicks() {
|
|
222
|
+
const t = Math.max(0, Math.ceil(this.from)), i = Math.min(this.categories.length - 1, Math.floor(this.to)), s = [];
|
|
223
|
+
for (let e = t; e <= i; e++)
|
|
224
|
+
s.push(e);
|
|
225
|
+
return { ticks: s, tickInterval: 1 };
|
|
148
226
|
}
|
|
149
227
|
getRange() {
|
|
150
228
|
return { from: this.from, to: this.to };
|
|
@@ -158,51 +236,87 @@ class b {
|
|
|
158
236
|
* tier inside a ratio band so micro pan/zoom doesn't flip label density.
|
|
159
237
|
*/
|
|
160
238
|
resolveInterval() {
|
|
239
|
+
if (this.type === "numeric") {
|
|
240
|
+
this.resolveNumericInterval();
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
161
243
|
if (this.to <= this.from || this.width <= 0 || this.dataInterval == null || this.dataInterval <= 0) {
|
|
162
244
|
this.resolvedInterval = null;
|
|
163
245
|
return;
|
|
164
246
|
}
|
|
165
|
-
const t =
|
|
166
|
-
let
|
|
247
|
+
const t = p(this.dataInterval), i = this.to - this.from, s = i / this.width * this.minLabelSpacing;
|
|
248
|
+
let e;
|
|
167
249
|
if (this.labelCountHint != null) {
|
|
168
|
-
const
|
|
169
|
-
|
|
250
|
+
const l = Math.max(1, this.labelCountHint);
|
|
251
|
+
e = Math.max(i / l, s);
|
|
170
252
|
} else
|
|
171
|
-
|
|
253
|
+
e = s;
|
|
172
254
|
if (this.lastInterval != null && this.lastWant != null && t.includes(this.lastInterval)) {
|
|
173
|
-
const
|
|
174
|
-
if (
|
|
255
|
+
const l = e >= this.lastWant * 0.8 && e <= this.lastWant * 1.25, f = this.lastInterval >= s;
|
|
256
|
+
if (l && f) {
|
|
175
257
|
this.resolvedInterval = this.lastInterval;
|
|
176
258
|
return;
|
|
177
259
|
}
|
|
178
260
|
}
|
|
179
|
-
let
|
|
180
|
-
for (let
|
|
181
|
-
if (t[
|
|
182
|
-
|
|
261
|
+
let r = t[t.length - 1], a = t.length - 1;
|
|
262
|
+
for (let l = 0; l < t.length; l++)
|
|
263
|
+
if (t[l] >= e) {
|
|
264
|
+
r = t[l], a = l;
|
|
183
265
|
break;
|
|
184
266
|
}
|
|
185
|
-
if (this.labelCountHint != null &&
|
|
186
|
-
const
|
|
187
|
-
|
|
267
|
+
if (this.labelCountHint != null && a > 0 && this.countTicks(r) < this.labelCountHint) {
|
|
268
|
+
const l = t[a - 1];
|
|
269
|
+
l >= s && (r = l);
|
|
188
270
|
}
|
|
189
|
-
this.resolvedInterval =
|
|
271
|
+
this.resolvedInterval = r, this.lastInterval = r, this.lastWant = e;
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Numeric counterpart of the time-tier walk: the {1,2,5}×10^k step that
|
|
275
|
+
* clears `minLabelSpacing` and targets `labelCount`, with the same hysteresis band.
|
|
276
|
+
*/
|
|
277
|
+
resolveNumericInterval() {
|
|
278
|
+
if (this.to <= this.from || this.width <= 0) {
|
|
279
|
+
this.resolvedInterval = null;
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
const t = this.to - this.from, i = t / this.width * this.minLabelSpacing, s = this.labelCountHint != null ? t / Math.max(1, this.labelCountHint) : 0, e = Math.max(s, i);
|
|
283
|
+
if (this.lastInterval != null && this.lastWant != null) {
|
|
284
|
+
const a = e >= this.lastWant * 0.8 && e <= this.lastWant * 1.25, l = this.lastInterval >= i;
|
|
285
|
+
if (a && l) {
|
|
286
|
+
this.resolvedInterval = this.lastInterval;
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
let r = b(e);
|
|
291
|
+
if (this.labelCountHint != null && this.countTicks(r) < this.labelCountHint) {
|
|
292
|
+
const a = k(e);
|
|
293
|
+
a >= i && (r = a);
|
|
294
|
+
}
|
|
295
|
+
this.resolvedInterval = r, this.lastInterval = r, this.lastWant = e;
|
|
190
296
|
}
|
|
191
297
|
countTicks(t) {
|
|
192
298
|
if (!(t > 0)) return 0;
|
|
193
|
-
const
|
|
194
|
-
return Math.max(0, Math.floor((this.to -
|
|
299
|
+
const i = Math.ceil(this.from / t) * t;
|
|
300
|
+
return Math.max(0, Math.floor((this.to - i) / t) + 1);
|
|
195
301
|
}
|
|
196
302
|
}
|
|
197
|
-
function
|
|
198
|
-
return
|
|
303
|
+
function c(n) {
|
|
304
|
+
return n < 6e4 ? 0 : n < 36e5 ? 1 : n < 864e5 ? 2 : 3;
|
|
305
|
+
}
|
|
306
|
+
function T(n) {
|
|
307
|
+
const { value: t, step: i, locale: s } = n, e = Number.isFinite(i) && i > 0 ? -Math.floor(Math.log10(i)) : 2, r = d(e, 0, 20);
|
|
308
|
+
return t.toLocaleString(s ?? "en-US", { maximumFractionDigits: r });
|
|
309
|
+
}
|
|
310
|
+
function m(n) {
|
|
311
|
+
const { value: t, fallback: i, max: s } = n;
|
|
312
|
+
return t === void 0 || !Number.isFinite(t) || t < 0 ? i : Math.min(t, s);
|
|
199
313
|
}
|
|
200
|
-
function
|
|
201
|
-
return typeof
|
|
314
|
+
function M(n) {
|
|
315
|
+
return typeof n == "number" && Number.isFinite(n) && n >= 2 ? Math.floor(n) : null;
|
|
202
316
|
}
|
|
203
|
-
function
|
|
204
|
-
return typeof
|
|
317
|
+
function x(n) {
|
|
318
|
+
return typeof n == "number" && Number.isFinite(n) && n > 0 ? n : null;
|
|
205
319
|
}
|
|
206
320
|
export {
|
|
207
|
-
|
|
321
|
+
W as XScale
|
|
208
322
|
};
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import { formatCompact as o } from "../utils/format.js";
|
|
2
2
|
import { crispCenterOffset as u } from "../utils/pixel-grid.js";
|
|
3
3
|
import { AxisTickTracker as m } from "./tick-tracker.js";
|
|
4
|
-
function c(
|
|
5
|
-
if (!Number.isFinite(
|
|
6
|
-
const t = 10 ** Math.floor(Math.log10(
|
|
4
|
+
function c(n) {
|
|
5
|
+
if (!Number.isFinite(n) || n <= 0) return 1;
|
|
6
|
+
const t = 10 ** Math.floor(Math.log10(n)), i = n / t;
|
|
7
7
|
return (i <= 1 ? 1 : i <= 2 ? 2 : i <= 5 ? 5 : 10) * t;
|
|
8
8
|
}
|
|
9
|
-
function f(
|
|
10
|
-
if (!Number.isFinite(
|
|
11
|
-
const t = 10 ** Math.floor(Math.log10(
|
|
9
|
+
function f(n) {
|
|
10
|
+
if (!Number.isFinite(n) || n <= 0) return 1;
|
|
11
|
+
const t = 10 ** Math.floor(Math.log10(n)), i = n / t;
|
|
12
12
|
return (i >= 5 ? 5 : i >= 2 ? 2 : 1) * t;
|
|
13
13
|
}
|
|
14
14
|
const a = 50, v = 50;
|
|
15
|
-
function
|
|
16
|
-
return Number.isFinite(t) ?
|
|
15
|
+
function p(n, t) {
|
|
16
|
+
return Number.isFinite(t) ? n?.isPlottable?.(t) ?? !0 : !1;
|
|
17
17
|
}
|
|
18
18
|
class d {
|
|
19
19
|
/** Shared fade state for Y ticks; see {@link TimeScale.tickTracker}. */
|
|
@@ -72,11 +72,11 @@ class d {
|
|
|
72
72
|
* downstream sees NaN.
|
|
73
73
|
*/
|
|
74
74
|
isPlottable(t) {
|
|
75
|
-
return
|
|
75
|
+
return p(this.transform, t);
|
|
76
76
|
}
|
|
77
77
|
/** Desired label count. Invalid values (NaN, <2, Infinity) clear the hint. */
|
|
78
78
|
setLabelCount(t) {
|
|
79
|
-
this.labelCountHintValue =
|
|
79
|
+
this.labelCountHintValue = g(t), this.resetHysteresis(), this.resolveTicks();
|
|
80
80
|
}
|
|
81
81
|
/** Minimum pixel gap between adjacent labels. */
|
|
82
82
|
setMinSpacing(t) {
|
|
@@ -159,11 +159,11 @@ class d {
|
|
|
159
159
|
* axis. An endpoint the transform can't place returns `to`, so a gap stays a gap.
|
|
160
160
|
*/
|
|
161
161
|
lerpValue(t, i, s) {
|
|
162
|
-
const
|
|
163
|
-
if (
|
|
162
|
+
const e = this.transform;
|
|
163
|
+
if (e === null) return t + (i - t) * s;
|
|
164
164
|
if (!this.isPlottable(t) || !this.isPlottable(i)) return i;
|
|
165
|
-
const r =
|
|
166
|
-
return
|
|
165
|
+
const r = e.forward(t);
|
|
166
|
+
return e.inverse(r + (e.forward(i) - r) * s);
|
|
167
167
|
}
|
|
168
168
|
/**
|
|
169
169
|
* Generate evenly spaced "nice" tick values for the current range and
|
|
@@ -175,9 +175,9 @@ class d {
|
|
|
175
175
|
/** {1,2,5}×10^k ticks at the resolved interval, limited to what the transform can place. */
|
|
176
176
|
linearTickValues() {
|
|
177
177
|
if (this.resolvedInterval == null) return [];
|
|
178
|
-
const t = this.resolvedInterval, i = Math.ceil(this.min / t) * t, s = Math.max(0, Math.min(a, Math.floor((this.max - i) / t) + 1)),
|
|
179
|
-
for (let r = 0; r < s; r++)
|
|
180
|
-
return this.transform === null ?
|
|
178
|
+
const t = this.resolvedInterval, i = Math.ceil(this.min / t) * t, s = Math.max(0, Math.min(a, Math.floor((this.max - i) / t) + 1)), e = [];
|
|
179
|
+
for (let r = 0; r < s; r++) e.push(i + r * t);
|
|
180
|
+
return this.transform === null ? e : e.filter((r) => this.isPlottable(r));
|
|
181
181
|
}
|
|
182
182
|
getRange() {
|
|
183
183
|
return { min: this.min, max: this.max };
|
|
@@ -197,8 +197,8 @@ class d {
|
|
|
197
197
|
const i = this.ownTicks !== null ? this.transform?.format : void 0;
|
|
198
198
|
if (i) return i(t);
|
|
199
199
|
if (this.max - this.min >= 1e6) return o(t);
|
|
200
|
-
const s = this.resolvedInterval,
|
|
201
|
-
return t.toFixed(
|
|
200
|
+
const s = this.resolvedInterval, e = s != null && s > 0 ? Math.max(0, -Math.floor(Math.log10(s))) : 1;
|
|
201
|
+
return t.toFixed(e);
|
|
202
202
|
}
|
|
203
203
|
resolveTicks() {
|
|
204
204
|
this.ownTicks = null;
|
|
@@ -213,7 +213,7 @@ class d {
|
|
|
213
213
|
return;
|
|
214
214
|
}
|
|
215
215
|
if (this.resolveInterval(this.transformedGapFloor(t, i)), !t.ticks) return;
|
|
216
|
-
const s = this.linearTickValues(),
|
|
216
|
+
const s = this.linearTickValues(), e = t.ticks({
|
|
217
217
|
min: this.min,
|
|
218
218
|
max: this.max,
|
|
219
219
|
height: this.height,
|
|
@@ -221,7 +221,7 @@ class d {
|
|
|
221
221
|
labelCount: this.labelCountHint,
|
|
222
222
|
linear: s
|
|
223
223
|
});
|
|
224
|
-
this.ownTicks =
|
|
224
|
+
this.ownTicks = e === s ? null : e;
|
|
225
225
|
}
|
|
226
226
|
/**
|
|
227
227
|
* Smallest linear interval whose ticks stay `minLabelSpacing` apart on the
|
|
@@ -230,8 +230,8 @@ class d {
|
|
|
230
230
|
* checking both ends covers it.
|
|
231
231
|
*/
|
|
232
232
|
transformedGapFloor(t, i) {
|
|
233
|
-
const s = this.minLabelSpacing / this.height * i,
|
|
234
|
-
return Math.max(
|
|
233
|
+
const s = this.minLabelSpacing / this.height * i, e = this.max - t.inverse(Math.max(this.lo, this.hi - s)), r = t.inverse(Math.min(this.hi, this.lo + s)) - this.min;
|
|
234
|
+
return Math.max(e, r);
|
|
235
235
|
}
|
|
236
236
|
/**
|
|
237
237
|
* Resolve the interval to a {1,2,5}×10^k tick size that satisfies the pixel
|
|
@@ -251,20 +251,20 @@ class d {
|
|
|
251
251
|
return;
|
|
252
252
|
}
|
|
253
253
|
const i = this.max - this.min, s = this.labelCountHint != null ? Math.max(1, this.labelCountHint) : Math.max(1, Math.floor(this.height / this.minLabelSpacing));
|
|
254
|
-
let
|
|
255
|
-
if (
|
|
256
|
-
const l =
|
|
254
|
+
let e = i / s;
|
|
255
|
+
if (e < t && (e = t), this.lastInterval != null && this.lastRawInterval != null) {
|
|
256
|
+
const l = e >= this.lastRawInterval * 0.8 && e <= this.lastRawInterval * 1.25, h = this.lastInterval >= t;
|
|
257
257
|
if (l && h) {
|
|
258
258
|
this.resolvedInterval = this.lastInterval;
|
|
259
259
|
return;
|
|
260
260
|
}
|
|
261
261
|
}
|
|
262
|
-
let r = c(
|
|
262
|
+
let r = c(e);
|
|
263
263
|
if (this.labelCountHint != null && this.countTicks(r) < this.labelCountHint) {
|
|
264
|
-
const l = f(
|
|
264
|
+
const l = f(e);
|
|
265
265
|
l >= t && l > 0 && (r = l);
|
|
266
266
|
}
|
|
267
|
-
this.resolvedInterval = r, this.lastInterval = r, this.lastRawInterval =
|
|
267
|
+
this.resolvedInterval = r, this.lastInterval = r, this.lastRawInterval = e;
|
|
268
268
|
}
|
|
269
269
|
countTicks(t) {
|
|
270
270
|
if (!(t > 0)) return 0;
|
|
@@ -272,13 +272,15 @@ class d {
|
|
|
272
272
|
return Math.max(0, Math.floor((this.max - i) / t) + 1);
|
|
273
273
|
}
|
|
274
274
|
}
|
|
275
|
-
function
|
|
276
|
-
return typeof
|
|
275
|
+
function g(n) {
|
|
276
|
+
return typeof n == "number" && Number.isFinite(n) && n >= 2 ? Math.floor(n) : null;
|
|
277
277
|
}
|
|
278
|
-
function x(
|
|
279
|
-
return typeof
|
|
278
|
+
function x(n) {
|
|
279
|
+
return typeof n == "number" && Number.isFinite(n) && n > 0 ? n : null;
|
|
280
280
|
}
|
|
281
281
|
export {
|
|
282
282
|
d as YScale,
|
|
283
|
-
|
|
283
|
+
p as isPlottableOn,
|
|
284
|
+
c as pickNiceCeiling,
|
|
285
|
+
f as pickNiceFloor
|
|
284
286
|
};
|