@wick-charts/vue 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -3
- package/dist/BarSeries.vue.js +26 -20
- package/dist/CandlestickSeries.vue.js +30 -24
- package/dist/ChartContainer.vue.js +88 -65
- package/dist/HeatmapSeries.vue.js +40 -0
- package/dist/HeatmapSeries.vue2.js +4 -0
- package/dist/LineSeries.vue.js +26 -20
- package/dist/PieSeries.vue.js +24 -18
- package/dist/core/dist/animation/animator.js +21 -21
- package/dist/core/dist/animation/config.js +114 -87
- package/dist/core/dist/animation/easing.js +3 -1
- package/dist/core/dist/animation/intro-wave.js +68 -0
- package/dist/core/dist/axis/dom-labels.js +13 -14
- package/dist/core/dist/chart/badge-animator.js +56 -0
- package/dist/core/dist/chart/edge-indicators.js +28 -13
- package/dist/core/dist/chart/last-value.js +18 -17
- package/dist/core/dist/chart/y-target.js +13 -12
- package/dist/core/dist/chart.js +908 -626
- package/dist/core/dist/components/annotation-chip.js +28 -0
- package/dist/core/dist/components/edge-indicator.js +58 -26
- package/dist/core/dist/components/loading-indicator.js +46 -0
- package/dist/core/dist/components/marker.js +49 -31
- package/dist/core/dist/components/reference-line.js +27 -36
- package/dist/core/dist/components/time-region.js +30 -28
- package/dist/core/dist/data/store.js +38 -19
- package/dist/core/dist/data/sync.js +60 -38
- package/dist/core/dist/heatmap-tooltip.js +16 -0
- package/dist/core/dist/interactions/handler.js +67 -43
- package/dist/core/dist/perf/perf-hud.js +2 -2
- package/dist/core/dist/scales/x-scale.js +85 -37
- package/dist/core/dist/scales/y-scale.js +38 -27
- package/dist/core/dist/series/bar-intro.js +18 -0
- package/dist/core/dist/series/bar.js +337 -205
- package/dist/core/dist/series/base-multi-layer.js +224 -96
- package/dist/core/dist/series/candlestick-intro.js +57 -0
- package/dist/core/dist/series/candlestick.js +454 -276
- package/dist/core/dist/series/heatmap.js +387 -0
- package/dist/core/dist/series/line-intro.js +85 -0
- package/dist/core/dist/series/line.js +590 -282
- package/dist/core/dist/series/painters/builtins.js +2 -2
- package/dist/core/dist/series/pie.js +396 -259
- package/dist/core/dist/series/register-builtins.js +8 -7
- package/dist/core/dist/series/types.js +6 -0
- package/dist/core/dist/series/wave-intro.js +26 -0
- package/dist/core/dist/theme/create.js +69 -63
- package/dist/core/dist/theme/themes/mint-breeze.js +2 -2
- package/dist/core/dist/theme/themes/sand-dune.js +2 -2
- package/dist/core/dist/utils/color.js +109 -34
- package/dist/core/dist/utils/deep-equal.js +18 -0
- package/dist/core/dist/utils/time.js +25 -19
- package/dist/index.d.ts +1411 -122
- package/dist/index.js +177 -130
- package/dist/ui/Crosshair.vue.js +20 -21
- package/dist/ui/HeatmapTooltip.vue.js +96 -0
- package/dist/ui/HeatmapTooltip.vue2.js +4 -0
- package/dist/ui/InfoBar.vue.js +46 -47
- package/dist/ui/Legend.vue.js +80 -79
- package/dist/ui/PieLegend.vue.js +5 -5
- package/dist/ui/PieTooltip.vue.js +77 -67
- package/dist/ui/Tooltip.vue.js +60 -60
- package/dist/ui/YAxis.vue.js +2 -2
- package/dist/ui/YLabel.vue.js +94 -61
- package/package.json +2 -2
- package/src/BarSeries.vue +23 -7
- package/src/CandlestickSeries.vue +23 -7
- package/src/ChartContainer.vue +134 -12
- package/src/HeatmapSeries.vue +69 -0
- package/src/LineSeries.vue +23 -7
- package/src/PieSeries.vue +22 -6
- package/src/index.ts +84 -3
- package/src/ui/Crosshair.vue +1 -2
- package/src/ui/HeatmapTooltip.vue +144 -0
- package/src/ui/InfoBar.vue +1 -2
- package/src/ui/Legend.vue +13 -0
- package/src/ui/Marker.vue +1 -1
- package/src/ui/PieTooltip.vue +10 -0
- package/src/ui/ReferenceLine.vue +2 -2
- package/src/ui/TimeRegion.vue +2 -2
- package/src/ui/Tooltip.vue +2 -2
- package/src/ui/YLabel.vue +123 -8
|
@@ -1,47 +1,69 @@
|
|
|
1
|
-
import { normalizeTime as
|
|
2
|
-
const
|
|
3
|
-
function
|
|
4
|
-
|
|
1
|
+
import { normalizeTime as s } from "../utils/time.js";
|
|
2
|
+
const g = { len: 0, firstTime: null, lastTime: null, data: null }, d = 20;
|
|
3
|
+
function c(t, a) {
|
|
4
|
+
if (s(t.time) !== s(a.time)) return !1;
|
|
5
|
+
const r = Object.keys(t), e = Object.keys(a);
|
|
6
|
+
return r.length !== e.length ? !1 : r.every((n) => n === "time" || t[n] === a[n]);
|
|
5
7
|
}
|
|
6
|
-
function
|
|
7
|
-
if (!
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
function y(t, a) {
|
|
9
|
+
if (!t || t.length !== a.length || t === a) return !1;
|
|
10
|
+
for (let r = 0; r < a.length - 1; r++)
|
|
11
|
+
if (t[r] !== a[r] && !c(t[r], a[r]))
|
|
12
|
+
return !1;
|
|
13
|
+
return !0;
|
|
11
14
|
}
|
|
12
|
-
function
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
function p(t, a, r) {
|
|
16
|
+
if (!t || t.length === 0 || r <= 0 || t.length !== a.length - r) return !1;
|
|
17
|
+
for (let e = 1; e < r; e++)
|
|
18
|
+
if (s(a[e - 1].time) >= s(a[e].time)) return !1;
|
|
19
|
+
if (s(a[r - 1].time) >= s(t[0].time)) return !1;
|
|
20
|
+
for (let e = 0; e < t.length; e++)
|
|
21
|
+
if (!c(t[e], a[r + e])) return !1;
|
|
22
|
+
return !0;
|
|
23
|
+
}
|
|
24
|
+
function T(t) {
|
|
25
|
+
return typeof t == "object" && t !== null && !Array.isArray(t) && Array.isArray(t.data);
|
|
26
|
+
}
|
|
27
|
+
function A(t) {
|
|
28
|
+
if (!Array.isArray(t)) return [t];
|
|
29
|
+
if (t.length === 0) return [{ data: [] }];
|
|
30
|
+
const a = t[0];
|
|
31
|
+
return Array.isArray(a) || T(a) ? t.map((r) => Array.isArray(r) ? { data: r } : r) : [{ data: t }];
|
|
32
|
+
}
|
|
33
|
+
function D(t) {
|
|
34
|
+
const { chart: a, id: r } = t, e = A(t.data), n = e.length > 1 ? e.map((l, f) => l.label ?? `Series ${f + 1}`) : [e[0].label];
|
|
35
|
+
a.setSeriesLabels(r, n), a.setLayerColors(
|
|
36
|
+
r,
|
|
37
|
+
e.map((l) => l.color)
|
|
17
38
|
);
|
|
18
|
-
const
|
|
19
|
-
return
|
|
20
|
-
for (let
|
|
21
|
-
|
|
22
|
-
chart:
|
|
23
|
-
id:
|
|
24
|
-
data: e[
|
|
25
|
-
prev:
|
|
26
|
-
layerIndex:
|
|
39
|
+
const i = [];
|
|
40
|
+
return a.batch(() => {
|
|
41
|
+
for (let l = 0; l < e.length; l++)
|
|
42
|
+
i[l] = b({
|
|
43
|
+
chart: a,
|
|
44
|
+
id: r,
|
|
45
|
+
data: e[l].data,
|
|
46
|
+
prev: t.prev[l] ?? g,
|
|
47
|
+
layerIndex: l
|
|
27
48
|
});
|
|
28
|
-
}),
|
|
49
|
+
}), i;
|
|
29
50
|
}
|
|
30
|
-
function
|
|
31
|
-
const { chart:
|
|
51
|
+
function b(t) {
|
|
52
|
+
const { chart: a, id: r, data: e, prev: n, layerIndex: i } = t;
|
|
32
53
|
if (e.length === 0)
|
|
33
|
-
return
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
54
|
+
return a.setSeriesData(r, [], i), { len: 0, firstTime: null, lastTime: null, data: [] };
|
|
55
|
+
if (n.data === e && n.len === e.length) return n;
|
|
56
|
+
const l = s(e[0].time), f = s(e[e.length - 1].time), h = n.firstTime !== null && n.firstTime !== l, u = e.length - n.len, m = n.lastTime !== null && n.lastTime !== f;
|
|
57
|
+
return h && u === 0 && m ? a.batch(() => {
|
|
58
|
+
a.appendData(r, e[e.length - 1], i), a.keepLast(r, e.length, i);
|
|
59
|
+
}) : p(n.data, e, u) ? a.prependData(r, e.slice(0, u), i) : n.len === 0 || e.length < n.len || u > d || h ? a.setSeriesData(r, e, i) : e.length === n.len ? y(n.data, e) ? a.updateData(r, e[e.length - 1], i) : a.setSeriesData(r, e, i) : a.batch(() => {
|
|
60
|
+
for (let o = n.len; o < e.length; o++)
|
|
61
|
+
a.appendData(r, e[o], i);
|
|
62
|
+
}), { len: e.length, firstTime: l, lastTime: f, data: e };
|
|
41
63
|
}
|
|
42
64
|
export {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
65
|
+
g as EMPTY_SYNC_STATE,
|
|
66
|
+
D as syncLayers,
|
|
67
|
+
b as syncSeriesLayer,
|
|
68
|
+
A as toLayers
|
|
47
69
|
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { formatCompact as a } from "./utils/format.js";
|
|
2
|
+
const s = 170, o = 78;
|
|
3
|
+
function i(e) {
|
|
4
|
+
return Number.isInteger(e) ? e.toString() : a(e);
|
|
5
|
+
}
|
|
6
|
+
function m(e, t) {
|
|
7
|
+
if (t !== void 0) return t;
|
|
8
|
+
const r = e.getSeriesIdsByType("heatmap", { visibleOnly: !0 });
|
|
9
|
+
return r.length > 0 ? r[0] : null;
|
|
10
|
+
}
|
|
11
|
+
export {
|
|
12
|
+
o as HEATMAP_TOOLTIP_HEIGHT,
|
|
13
|
+
s as HEATMAP_TOOLTIP_WIDTH,
|
|
14
|
+
i as defaultHeatmapFormat,
|
|
15
|
+
m as resolveHeatmapSeriesId
|
|
16
|
+
};
|
|
@@ -1,29 +1,30 @@
|
|
|
1
|
-
import { EventEmitter as
|
|
2
|
-
import { clamp as
|
|
3
|
-
import { PanHandler as
|
|
1
|
+
import { EventEmitter as a } from "../events.js";
|
|
2
|
+
import { clamp as l } from "../utils/math.js";
|
|
3
|
+
import { PanHandler as u } from "./pan.js";
|
|
4
4
|
import { ZoomHandler as r } from "./zoom.js";
|
|
5
|
-
function i(
|
|
6
|
-
const
|
|
7
|
-
return Math.hypot(
|
|
5
|
+
function i(o, e) {
|
|
6
|
+
const t = o.clientX - e.clientX, s = o.clientY - e.clientY;
|
|
7
|
+
return Math.hypot(t, s);
|
|
8
8
|
}
|
|
9
|
-
|
|
9
|
+
const d = 5, v = 500;
|
|
10
|
+
class M extends a {
|
|
10
11
|
zoom;
|
|
11
12
|
pan;
|
|
12
13
|
canvas;
|
|
13
14
|
timeScale;
|
|
14
15
|
yScale;
|
|
15
16
|
target;
|
|
16
|
-
constructor(
|
|
17
|
-
super(), this.canvas =
|
|
17
|
+
constructor(e, t, s, n) {
|
|
18
|
+
super(), this.canvas = e, this.target = t, this.timeScale = s, this.yScale = n, this.zoom = new r(t, s), this.pan = new u(t, s, e), e.style.cursor = "crosshair", e.style.touchAction = "none", e.addEventListener("wheel", this.onWheel, { passive: !1 }), e.addEventListener("mousedown", this.onMouseDown), e.addEventListener("mousemove", this.onMouseMove), e.addEventListener("mouseup", this.onMouseUp), e.addEventListener("mouseleave", this.onMouseLeave), e.addEventListener("click", this.onClick), e.addEventListener("dblclick", this.onDblClick), e.addEventListener("touchstart", this.onTouchStart, { passive: !1 }), e.addEventListener("touchmove", this.onTouchMove, { passive: !1 }), e.addEventListener("touchend", this.onTouchEnd), e.addEventListener("touchcancel", this.onTouchCancel);
|
|
18
19
|
}
|
|
19
|
-
onWheel = (
|
|
20
|
-
this.zoom.handleWheel(
|
|
20
|
+
onWheel = (e) => {
|
|
21
|
+
this.zoom.handleWheel(e);
|
|
21
22
|
};
|
|
22
|
-
onMouseDown = (
|
|
23
|
-
this.zoom.cancelPendingRebound(), this.pan.handleMouseDown(
|
|
23
|
+
onMouseDown = (e) => {
|
|
24
|
+
this.zoom.cancelPendingRebound(), this.pan.handleMouseDown(e), this.downClient = { x: e.clientX, y: e.clientY };
|
|
24
25
|
};
|
|
25
|
-
onMouseMove = (
|
|
26
|
-
this.pan.isDragging() && this.pan.handleMouseMove(
|
|
26
|
+
onMouseMove = (e) => {
|
|
27
|
+
this.pan.isDragging() && this.pan.handleMouseMove(e), this.emitCrosshair(e.offsetX, e.offsetY);
|
|
27
28
|
};
|
|
28
29
|
onMouseUp = () => {
|
|
29
30
|
this.pan.handleMouseUp();
|
|
@@ -31,52 +32,75 @@ class M extends c {
|
|
|
31
32
|
onMouseLeave = () => {
|
|
32
33
|
this.pan.handleMouseUp(), this.emit("crosshairMove", null);
|
|
33
34
|
};
|
|
34
|
-
|
|
35
|
+
// Pointer-down origin (mouse or the single touch that started a tap),
|
|
36
|
+
// used to tell a click/tap from a drag that happened to end over the canvas.
|
|
37
|
+
downClient = null;
|
|
38
|
+
onClick = (e) => {
|
|
39
|
+
this.movedBeyondClickTolerance(e.clientX, e.clientY) || e.detail > 1 || this.emit("click", this.posFromOffset(e.offsetX, e.offsetY));
|
|
35
40
|
};
|
|
41
|
+
onDblClick = (e) => {
|
|
42
|
+
this.emit("dblclick", this.posFromOffset(e.offsetX, e.offsetY));
|
|
43
|
+
};
|
|
44
|
+
movedBeyondClickTolerance(e, t) {
|
|
45
|
+
return this.downClient ? Math.hypot(e - this.downClient.x, t - this.downClient.y) > d : !1;
|
|
46
|
+
}
|
|
36
47
|
// Touch handling
|
|
37
48
|
lastTouchDist = 0;
|
|
38
49
|
touchCount = 0;
|
|
39
|
-
|
|
40
|
-
|
|
50
|
+
touchDownTime = 0;
|
|
51
|
+
// True once a gesture has ever held two fingers (a pinch). A pinch is never a
|
|
52
|
+
// tap, even after it decays to one finger, so this gates tap synthesis in
|
|
53
|
+
// onTouchEnd — otherwise lifting both fingers in quick succession would
|
|
54
|
+
// synthesize a phantom 'click'.
|
|
55
|
+
gestureHadTwoFingers = !1;
|
|
56
|
+
onTouchStart = (e) => {
|
|
57
|
+
e.preventDefault(), this.zoom.cancelPendingRebound(), this.touchCount = e.touches.length, e.touches.length === 1 ? (this.pan.handleMouseDown({
|
|
41
58
|
button: 0,
|
|
42
|
-
clientX:
|
|
43
|
-
}) :
|
|
59
|
+
clientX: e.touches[0].clientX
|
|
60
|
+
}), this.downClient = { x: e.touches[0].clientX, y: e.touches[0].clientY }, this.touchDownTime = Date.now(), this.gestureHadTwoFingers = !1) : e.touches.length === 2 && (this.lastTouchDist = i(e.touches[0], e.touches[1]), this.gestureHadTwoFingers = !0);
|
|
44
61
|
};
|
|
45
|
-
onTouchMove = (
|
|
46
|
-
if (
|
|
62
|
+
onTouchMove = (e) => {
|
|
63
|
+
if (e.preventDefault(), e.touches.length === 1 && this.touchCount === 1)
|
|
47
64
|
this.pan.handleMouseMove({
|
|
48
|
-
clientX:
|
|
65
|
+
clientX: e.touches[0].clientX
|
|
49
66
|
});
|
|
50
|
-
else if (
|
|
51
|
-
const
|
|
52
|
-
if (
|
|
53
|
-
const h =
|
|
54
|
-
this.target.zoomAt(
|
|
67
|
+
else if (e.touches.length === 2) {
|
|
68
|
+
const t = i(e.touches[0], e.touches[1]), s = (e.touches[0].clientX + e.touches[1].clientX) / 2, n = this.canvas.getBoundingClientRect();
|
|
69
|
+
if (t > 0 && this.lastTouchDist > 0) {
|
|
70
|
+
const h = l(this.lastTouchDist / t, 0.1, 10), c = this.timeScale.xToTime(s - n.left);
|
|
71
|
+
this.target.zoomAt(c, h, this.timeScale.getMediaWidth());
|
|
55
72
|
}
|
|
56
|
-
this.lastTouchDist =
|
|
73
|
+
this.lastTouchDist = t;
|
|
57
74
|
}
|
|
58
75
|
};
|
|
59
|
-
onTouchEnd = (
|
|
60
|
-
if (
|
|
61
|
-
|
|
76
|
+
onTouchEnd = (e) => {
|
|
77
|
+
if (e.touches.length === 0) {
|
|
78
|
+
const t = e.changedTouches[0];
|
|
79
|
+
if (this.touchCount === 1 && !this.gestureHadTwoFingers && t && !this.movedBeyondClickTolerance(t.clientX, t.clientY) && Date.now() - this.touchDownTime <= v) {
|
|
80
|
+
const s = this.canvas.getBoundingClientRect();
|
|
81
|
+
this.emit("click", this.posFromOffset(t.clientX - s.left, t.clientY - s.top));
|
|
82
|
+
}
|
|
83
|
+
this.pan.handleMouseUp(), this.touchCount = 0, this.lastTouchDist = 0, this.downClient = null, this.gestureHadTwoFingers = !1, this.emit("crosshairMove", null);
|
|
62
84
|
return;
|
|
63
85
|
}
|
|
64
|
-
|
|
86
|
+
e.touches.length === 1 && (this.touchCount = 1, this.lastTouchDist = 0, this.pan.handleMouseDown({ button: 0, clientX: e.touches[0].clientX }), this.downClient = { x: e.touches[0].clientX, y: e.touches[0].clientY }, this.touchDownTime = Date.now());
|
|
65
87
|
};
|
|
66
88
|
onTouchCancel = () => {
|
|
67
|
-
this.pan.handleMouseUp(), this.touchCount = 0, this.lastTouchDist = 0, this.emit("crosshairMove", null);
|
|
89
|
+
this.pan.handleMouseUp(), this.touchCount = 0, this.lastTouchDist = 0, this.downClient = null, this.gestureHadTwoFingers = !1, this.emit("crosshairMove", null);
|
|
68
90
|
};
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
91
|
+
posFromOffset(e, t) {
|
|
92
|
+
return {
|
|
93
|
+
mediaX: e,
|
|
94
|
+
mediaY: t,
|
|
95
|
+
time: this.timeScale.xToTime(e),
|
|
96
|
+
y: this.yScale.yToValue(t)
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
emitCrosshair(e, t) {
|
|
100
|
+
this.emit("crosshairMove", this.posFromOffset(e, t));
|
|
77
101
|
}
|
|
78
102
|
destroy() {
|
|
79
|
-
this.zoom.cancelPendingRebound(), this.canvas.removeEventListener("wheel", this.onWheel), this.canvas.removeEventListener("mousedown", this.onMouseDown), this.canvas.removeEventListener("mousemove", this.onMouseMove), this.canvas.removeEventListener("mouseup", this.onMouseUp), this.canvas.removeEventListener("mouseleave", this.onMouseLeave), this.canvas.removeEventListener("dblclick", this.onDblClick), this.canvas.removeEventListener("touchstart", this.onTouchStart), this.canvas.removeEventListener("touchmove", this.onTouchMove), this.canvas.removeEventListener("touchend", this.onTouchEnd), this.canvas.removeEventListener("touchcancel", this.onTouchCancel), this.removeAllListeners();
|
|
103
|
+
this.zoom.cancelPendingRebound(), this.canvas.removeEventListener("wheel", this.onWheel), this.canvas.removeEventListener("mousedown", this.onMouseDown), this.canvas.removeEventListener("mousemove", this.onMouseMove), this.canvas.removeEventListener("mouseup", this.onMouseUp), this.canvas.removeEventListener("mouseleave", this.onMouseLeave), this.canvas.removeEventListener("click", this.onClick), this.canvas.removeEventListener("dblclick", this.onDblClick), this.canvas.removeEventListener("touchstart", this.onTouchStart), this.canvas.removeEventListener("touchmove", this.onTouchMove), this.canvas.removeEventListener("touchend", this.onTouchEnd), this.canvas.removeEventListener("touchcancel", this.onTouchCancel), this.removeAllListeners();
|
|
80
104
|
}
|
|
81
105
|
}
|
|
82
106
|
export {
|
|
@@ -2,7 +2,7 @@ import { ChartInstance as R } from "../chart.js";
|
|
|
2
2
|
import { LineSeriesDef as E } from "../series/line.js";
|
|
3
3
|
import { PerfMonitor as g } from "./perf-monitor.js";
|
|
4
4
|
import { createTheme as T } from "../theme/create.js";
|
|
5
|
-
function
|
|
5
|
+
function N(i) {
|
|
6
6
|
const e = i instanceof g;
|
|
7
7
|
return {
|
|
8
8
|
monitor: e ? i : new g(i),
|
|
@@ -449,5 +449,5 @@ class D {
|
|
|
449
449
|
}
|
|
450
450
|
export {
|
|
451
451
|
D as PerfHud,
|
|
452
|
-
|
|
452
|
+
N as perfHud
|
|
453
453
|
};
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { niceTimeIntervals as
|
|
2
|
-
import { AxisTickTracker as
|
|
3
|
-
const
|
|
1
|
+
import { formatTime as m, niceTimeIntervals as c } from "../utils/time.js";
|
|
2
|
+
import { AxisTickTracker as f } from "./tick-tracker.js";
|
|
3
|
+
const o = 50, v = 80;
|
|
4
4
|
class p {
|
|
5
5
|
/**
|
|
6
6
|
* Shared fade state for time ticks. Grid lines (canvas) and DOM tick labels
|
|
7
7
|
* read opacity from the same tracker, so a tick fading in/out looks
|
|
8
8
|
* identical on both surfaces.
|
|
9
9
|
*/
|
|
10
|
-
tickTracker = new
|
|
10
|
+
tickTracker = new f();
|
|
11
11
|
from = 0;
|
|
12
12
|
to = 0;
|
|
13
13
|
width = 1;
|
|
@@ -16,6 +16,12 @@ class p {
|
|
|
16
16
|
// Label density knobs — written by <TimeAxis labelCount=… minLabelSpacing=…>.
|
|
17
17
|
labelCountHintValue = null;
|
|
18
18
|
minSpacingValue = null;
|
|
19
|
+
/** Custom formatter (driven by `setFormat` / a future `<TimeAxis format=…>`). */
|
|
20
|
+
customFormat = null;
|
|
21
|
+
/** Custom tick generator — bypasses tier resolution in `niceTickValues` when set. */
|
|
22
|
+
customTickGenerator = null;
|
|
23
|
+
localeValue;
|
|
24
|
+
timeZoneValue;
|
|
19
25
|
resolvedInterval = null;
|
|
20
26
|
lastInterval = null;
|
|
21
27
|
/**
|
|
@@ -31,20 +37,58 @@ class p {
|
|
|
31
37
|
return this.labelCountHintValue;
|
|
32
38
|
}
|
|
33
39
|
get minLabelSpacing() {
|
|
34
|
-
return this.minSpacingValue ??
|
|
40
|
+
return this.minSpacingValue ?? v;
|
|
35
41
|
}
|
|
36
|
-
update(t,
|
|
37
|
-
if (this.from = t.from, this.to = t.to, this.width =
|
|
38
|
-
const
|
|
39
|
-
this.lastBucketKey !== null && this.lastBucketKey !==
|
|
42
|
+
update(t, e, n, r) {
|
|
43
|
+
if (this.from = t.from, this.to = t.to, this.width = e, this.pixelRatio = n, r !== void 0 && r > 0) {
|
|
44
|
+
const a = h(r);
|
|
45
|
+
this.lastBucketKey !== null && this.lastBucketKey !== a && this.resetHysteresis(), this.lastBucketKey = a, this.dataInterval = r;
|
|
40
46
|
}
|
|
41
47
|
this.resolveInterval();
|
|
42
48
|
}
|
|
43
49
|
setLabelCount(t) {
|
|
44
|
-
this.labelCountHintValue =
|
|
50
|
+
this.labelCountHintValue = d(t), this.resetHysteresis(), this.resolveInterval();
|
|
45
51
|
}
|
|
46
52
|
setMinSpacing(t) {
|
|
47
|
-
this.minSpacingValue =
|
|
53
|
+
this.minSpacingValue = I(t), this.resetHysteresis(), this.resolveInterval();
|
|
54
|
+
}
|
|
55
|
+
/** Install (or clear) a custom tick-label formatter. */
|
|
56
|
+
setFormat(t) {
|
|
57
|
+
this.customFormat = t;
|
|
58
|
+
}
|
|
59
|
+
/** Read back the currently installed formatter — null when the built-in is active. */
|
|
60
|
+
getFormat() {
|
|
61
|
+
return this.customFormat;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Install (or clear) a custom tick-value generator. When set, it replaces
|
|
65
|
+
* `niceTimeIntervals` tier resolution entirely — `niceTickValues` calls it
|
|
66
|
+
* directly with the current range and reports its own tick spacing.
|
|
67
|
+
*/
|
|
68
|
+
setTickGenerator(t) {
|
|
69
|
+
this.customTickGenerator = t, this.resetHysteresis();
|
|
70
|
+
}
|
|
71
|
+
/** BCP 47 locale applied to the built-in formatter. Ignored while a custom `setFormat` is installed. */
|
|
72
|
+
setLocale(t) {
|
|
73
|
+
this.localeValue = t;
|
|
74
|
+
}
|
|
75
|
+
getLocale() {
|
|
76
|
+
return this.localeValue;
|
|
77
|
+
}
|
|
78
|
+
/** IANA timezone applied to the built-in formatter. Ignored while a custom `setFormat` is installed. */
|
|
79
|
+
setTimeZone(t) {
|
|
80
|
+
this.timeZoneValue = t;
|
|
81
|
+
}
|
|
82
|
+
getTimeZone() {
|
|
83
|
+
return this.timeZoneValue;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Format a tick timestamp for display. A custom formatter (via
|
|
87
|
+
* {@link setFormat}) wins; otherwise falls back to the built-in
|
|
88
|
+
* `formatTime`, applying the installed locale/timezone.
|
|
89
|
+
*/
|
|
90
|
+
formatX(t, e) {
|
|
91
|
+
return this.customFormat ? this.customFormat(t, e) : m(t, e, { locale: this.localeValue, timeZone: this.timeZoneValue });
|
|
48
92
|
}
|
|
49
93
|
resetHysteresis() {
|
|
50
94
|
this.lastInterval = null, this.lastWant = null;
|
|
@@ -74,14 +118,18 @@ class p {
|
|
|
74
118
|
*/
|
|
75
119
|
niceTickValues(t) {
|
|
76
120
|
if (this.to <= this.from) return { ticks: [], tickInterval: 0 };
|
|
121
|
+
if (this.customTickGenerator) {
|
|
122
|
+
const i = this.customTickGenerator({ from: this.from, to: this.to }, t).slice(0, o), l = i.length >= 2 ? i[1] - i[0] : t;
|
|
123
|
+
return { ticks: i, tickInterval: l };
|
|
124
|
+
}
|
|
77
125
|
if (this.dataInterval !== t) {
|
|
78
|
-
const
|
|
79
|
-
this.lastBucketKey !== null && this.lastBucketKey !==
|
|
126
|
+
const i = h(t);
|
|
127
|
+
this.lastBucketKey !== null && this.lastBucketKey !== i && this.resetHysteresis(), this.lastBucketKey = i, this.dataInterval = t, this.resolveInterval();
|
|
80
128
|
}
|
|
81
129
|
if (this.resolvedInterval == null) return { ticks: [], tickInterval: 0 };
|
|
82
|
-
const
|
|
83
|
-
for (let
|
|
84
|
-
return { ticks:
|
|
130
|
+
const e = this.resolvedInterval, n = Math.ceil(this.from / e) * e, r = Math.max(0, Math.min(o, Math.floor((this.to - n) / e) + 1)), a = [];
|
|
131
|
+
for (let i = 0; i < r; i++) a.push(n + i * e);
|
|
132
|
+
return { ticks: a, tickInterval: e };
|
|
85
133
|
}
|
|
86
134
|
getRange() {
|
|
87
135
|
return { from: this.from, to: this.to };
|
|
@@ -99,46 +147,46 @@ class p {
|
|
|
99
147
|
this.resolvedInterval = null;
|
|
100
148
|
return;
|
|
101
149
|
}
|
|
102
|
-
const t =
|
|
103
|
-
let
|
|
150
|
+
const t = c(this.dataInterval), e = this.to - this.from, n = e / this.width * this.minLabelSpacing;
|
|
151
|
+
let r;
|
|
104
152
|
if (this.labelCountHint != null) {
|
|
105
153
|
const l = Math.max(1, this.labelCountHint);
|
|
106
|
-
|
|
154
|
+
r = Math.max(e / l, n);
|
|
107
155
|
} else
|
|
108
|
-
|
|
156
|
+
r = n;
|
|
109
157
|
if (this.lastInterval != null && this.lastWant != null && t.includes(this.lastInterval)) {
|
|
110
|
-
const l =
|
|
111
|
-
if (l &&
|
|
158
|
+
const l = r >= this.lastWant * 0.8 && r <= this.lastWant * 1.25, u = this.lastInterval >= n;
|
|
159
|
+
if (l && u) {
|
|
112
160
|
this.resolvedInterval = this.lastInterval;
|
|
113
161
|
return;
|
|
114
162
|
}
|
|
115
163
|
}
|
|
116
|
-
let
|
|
164
|
+
let a = t[t.length - 1], i = t.length - 1;
|
|
117
165
|
for (let l = 0; l < t.length; l++)
|
|
118
|
-
if (t[l] >=
|
|
119
|
-
|
|
166
|
+
if (t[l] >= r) {
|
|
167
|
+
a = t[l], i = l;
|
|
120
168
|
break;
|
|
121
169
|
}
|
|
122
|
-
if (this.labelCountHint != null &&
|
|
123
|
-
const l = t[
|
|
124
|
-
l >=
|
|
170
|
+
if (this.labelCountHint != null && i > 0 && this.countTicks(a) < this.labelCountHint) {
|
|
171
|
+
const l = t[i - 1];
|
|
172
|
+
l >= n && (a = l);
|
|
125
173
|
}
|
|
126
|
-
this.resolvedInterval =
|
|
174
|
+
this.resolvedInterval = a, this.lastInterval = a, this.lastWant = r;
|
|
127
175
|
}
|
|
128
176
|
countTicks(t) {
|
|
129
177
|
if (!(t > 0)) return 0;
|
|
130
|
-
const
|
|
131
|
-
return Math.max(0, Math.floor((this.to -
|
|
178
|
+
const e = Math.ceil(this.from / t) * t;
|
|
179
|
+
return Math.max(0, Math.floor((this.to - e) / t) + 1);
|
|
132
180
|
}
|
|
133
181
|
}
|
|
134
|
-
function h(
|
|
135
|
-
return
|
|
182
|
+
function h(s) {
|
|
183
|
+
return s < 6e4 ? 0 : s < 36e5 ? 1 : s < 864e5 ? 2 : 3;
|
|
136
184
|
}
|
|
137
|
-
function
|
|
138
|
-
return typeof
|
|
185
|
+
function d(s) {
|
|
186
|
+
return typeof s == "number" && Number.isFinite(s) && s >= 2 ? Math.floor(s) : null;
|
|
139
187
|
}
|
|
140
|
-
function
|
|
141
|
-
return typeof
|
|
188
|
+
function I(s) {
|
|
189
|
+
return typeof s == "number" && Number.isFinite(s) && s > 0 ? s : null;
|
|
142
190
|
}
|
|
143
191
|
export {
|
|
144
192
|
p as XScale
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
import { formatCompact as
|
|
2
|
-
import { AxisTickTracker as
|
|
3
|
-
function
|
|
4
|
-
if (!Number.isFinite(
|
|
5
|
-
const t = 10 ** Math.floor(Math.log10(
|
|
1
|
+
import { formatCompact as o } from "../utils/format.js";
|
|
2
|
+
import { AxisTickTracker as u } from "./tick-tracker.js";
|
|
3
|
+
function m(e) {
|
|
4
|
+
if (!Number.isFinite(e) || e <= 0) return 1;
|
|
5
|
+
const t = 10 ** Math.floor(Math.log10(e)), i = e / t;
|
|
6
6
|
return (i <= 1 ? 1 : i <= 2 ? 2 : i <= 5 ? 5 : 10) * t;
|
|
7
7
|
}
|
|
8
|
-
function
|
|
9
|
-
if (!Number.isFinite(
|
|
10
|
-
const t = 10 ** Math.floor(Math.log10(
|
|
8
|
+
function c(e) {
|
|
9
|
+
if (!Number.isFinite(e) || e <= 0) return 1;
|
|
10
|
+
const t = 10 ** Math.floor(Math.log10(e)), i = e / t;
|
|
11
11
|
return (i >= 5 ? 5 : i >= 2 ? 2 : 1) * t;
|
|
12
12
|
}
|
|
13
|
-
const
|
|
13
|
+
const r = 50, v = 50;
|
|
14
14
|
class M {
|
|
15
15
|
/** Shared fade state for Y ticks; see {@link TimeScale.tickTracker}. */
|
|
16
|
-
tickTracker = new
|
|
16
|
+
tickTracker = new u();
|
|
17
17
|
min = 0;
|
|
18
18
|
max = 0;
|
|
19
19
|
height = 1;
|
|
@@ -35,6 +35,8 @@ class M {
|
|
|
35
35
|
lastRawInterval = null;
|
|
36
36
|
/** Custom formatter (driven by `<YAxis format=…>`). */
|
|
37
37
|
customFormat = null;
|
|
38
|
+
/** Custom tick generator — bypasses {1,2,5}×10^k resolution in `niceTickValues` when set. */
|
|
39
|
+
customTickGenerator = null;
|
|
38
40
|
get labelCountHint() {
|
|
39
41
|
return this.labelCountHintValue;
|
|
40
42
|
}
|
|
@@ -64,6 +66,14 @@ class M {
|
|
|
64
66
|
getFormat() {
|
|
65
67
|
return this.customFormat;
|
|
66
68
|
}
|
|
69
|
+
/**
|
|
70
|
+
* Install (or clear) a custom tick-value generator. When set, it replaces
|
|
71
|
+
* {1,2,5}×10^k resolution entirely — `niceTickValues` calls it directly
|
|
72
|
+
* with the current range.
|
|
73
|
+
*/
|
|
74
|
+
setTickGenerator(t) {
|
|
75
|
+
this.customTickGenerator = t, this.resetHysteresis();
|
|
76
|
+
}
|
|
67
77
|
/** Convert a value to a Y position in CSS (media) pixels. */
|
|
68
78
|
valueToY(t) {
|
|
69
79
|
const i = this.max - this.min;
|
|
@@ -83,10 +93,11 @@ class M {
|
|
|
83
93
|
* chart height. Pure read — resolution happens in `update()`.
|
|
84
94
|
*/
|
|
85
95
|
niceTickValues() {
|
|
96
|
+
if (this.customTickGenerator) return this.customTickGenerator({ min: this.min, max: this.max }).slice(0, r);
|
|
86
97
|
if (this.resolvedInterval == null) return [];
|
|
87
|
-
const t = this.resolvedInterval, i = Math.ceil(this.min / t) * t, a = Math.max(0, Math.min(
|
|
88
|
-
for (let
|
|
89
|
-
return
|
|
98
|
+
const t = this.resolvedInterval, i = Math.ceil(this.min / t) * t, a = Math.max(0, Math.min(r, Math.floor((this.max - i) / t) + 1)), s = [];
|
|
99
|
+
for (let n = 0; n < a; n++) s.push(i + n * t);
|
|
100
|
+
return s;
|
|
90
101
|
}
|
|
91
102
|
getRange() {
|
|
92
103
|
return { min: this.min, max: this.max };
|
|
@@ -103,7 +114,7 @@ class M {
|
|
|
103
114
|
*/
|
|
104
115
|
formatY(t) {
|
|
105
116
|
if (this.customFormat) return this.customFormat(t);
|
|
106
|
-
if (this.max - this.min >= 1e6) return
|
|
117
|
+
if (this.max - this.min >= 1e6) return o(t);
|
|
107
118
|
const i = this.resolvedInterval, a = i != null && i > 0 ? Math.max(0, -Math.floor(Math.log10(i))) : 1;
|
|
108
119
|
return t.toFixed(a);
|
|
109
120
|
}
|
|
@@ -124,20 +135,20 @@ class M {
|
|
|
124
135
|
return;
|
|
125
136
|
}
|
|
126
137
|
const t = this.max - this.min, i = t * this.minLabelSpacing / this.height, a = this.labelCountHint != null ? Math.max(1, this.labelCountHint) : Math.max(1, Math.floor(this.height / this.minLabelSpacing));
|
|
127
|
-
let
|
|
128
|
-
if (
|
|
129
|
-
const l =
|
|
130
|
-
if (l &&
|
|
138
|
+
let s = t / a;
|
|
139
|
+
if (s < i && (s = i), this.lastInterval != null && this.lastRawInterval != null) {
|
|
140
|
+
const l = s >= this.lastRawInterval * 0.8 && s <= this.lastRawInterval * 1.25, h = this.lastInterval >= i;
|
|
141
|
+
if (l && h) {
|
|
131
142
|
this.resolvedInterval = this.lastInterval;
|
|
132
143
|
return;
|
|
133
144
|
}
|
|
134
145
|
}
|
|
135
|
-
let
|
|
136
|
-
if (this.labelCountHint != null && this.countTicks(
|
|
137
|
-
const l =
|
|
138
|
-
l >= i && l > 0 && (
|
|
146
|
+
let n = m(s);
|
|
147
|
+
if (this.labelCountHint != null && this.countTicks(n) < this.labelCountHint) {
|
|
148
|
+
const l = c(s);
|
|
149
|
+
l >= i && l > 0 && (n = l);
|
|
139
150
|
}
|
|
140
|
-
this.resolvedInterval =
|
|
151
|
+
this.resolvedInterval = n, this.lastInterval = n, this.lastRawInterval = s;
|
|
141
152
|
}
|
|
142
153
|
countTicks(t) {
|
|
143
154
|
if (!(t > 0)) return 0;
|
|
@@ -145,11 +156,11 @@ class M {
|
|
|
145
156
|
return Math.max(0, Math.floor((this.max - i) / t) + 1);
|
|
146
157
|
}
|
|
147
158
|
}
|
|
148
|
-
function f(
|
|
149
|
-
return typeof
|
|
159
|
+
function f(e) {
|
|
160
|
+
return typeof e == "number" && Number.isFinite(e) && e >= 2 ? Math.floor(e) : null;
|
|
150
161
|
}
|
|
151
|
-
function g(
|
|
152
|
-
return typeof
|
|
162
|
+
function g(e) {
|
|
163
|
+
return typeof e == "number" && Number.isFinite(e) && e > 0 ? e : null;
|
|
153
164
|
}
|
|
154
165
|
export {
|
|
155
166
|
M as YScale
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { easeOutBack as a } from "../animation/easing.js";
|
|
2
|
+
function t() {
|
|
3
|
+
return () => ({
|
|
4
|
+
value: ({ value: e, progress: r }) => e * r,
|
|
5
|
+
element: (e) => ({ alpha: e.progress })
|
|
6
|
+
});
|
|
7
|
+
}
|
|
8
|
+
const o = 0.3;
|
|
9
|
+
function n() {
|
|
10
|
+
return () => ({
|
|
11
|
+
value: ({ value: e, progress: r }) => e * a(r),
|
|
12
|
+
element: (e) => ({ alpha: Math.min(1, e.progress / o) })
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
export {
|
|
16
|
+
t as growIntro,
|
|
17
|
+
n as springIntro
|
|
18
|
+
};
|