@wick-charts/vue 0.8.1 → 0.8.2
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/dist/BandSeries.vue.js +25 -24
- package/dist/BarSeries.vue.js +27 -26
- package/dist/CandlestickSeries.vue.js +25 -24
- package/dist/HeatmapSeries.vue.js +21 -20
- package/dist/LineSeries.vue.js +24 -23
- package/dist/PieSeries.vue.js +25 -24
- package/dist/composables.js +63 -36
- package/dist/core/dist/axis/dom-labels.js +64 -53
- package/dist/core/dist/chart/options.js +1 -1
- package/dist/core/dist/chart/y-target.js +38 -32
- package/dist/core/dist/chart.js +475 -439
- package/dist/core/dist/data/decimation.js +52 -51
- package/dist/core/dist/data/store.js +38 -20
- package/dist/core/dist/data/sync.js +80 -69
- package/dist/core/dist/perf/perf-hud.js +3 -3
- package/dist/core/dist/scales/tick-tracker.js +2 -1
- package/dist/core/dist/series/band.js +1 -1
- package/dist/core/dist/series/bar.js +240 -211
- package/dist/core/dist/series/base-multi-layer.js +267 -249
- package/dist/core/dist/series/candlestick.js +116 -116
- package/dist/core/dist/series/line.js +540 -455
- package/dist/core/dist/snapshots.js +96 -77
- package/dist/index.d.ts +22 -4
- package/dist/ui/InfoBar.vue.js +68 -68
- package/dist/ui/NumberFlow.vue.js +36 -27
- package/dist/ui/Tooltip.vue.js +127 -130
- package/package.json +2 -2
- package/src/BandSeries.vue +5 -3
- package/src/BarSeries.vue +5 -3
- package/src/CandlestickSeries.vue +5 -4
- package/src/ChartContainer.vue +1 -1
- package/src/HeatmapSeries.vue +5 -4
- package/src/LineSeries.vue +5 -3
- package/src/PieSeries.vue +6 -5
- package/src/composables.ts +64 -1
- package/src/ui/InfoBar.vue +11 -3
- package/src/ui/NumberFlow.vue +17 -3
- package/src/ui/Tooltip.vue +23 -12
package/src/ui/InfoBar.vue
CHANGED
|
@@ -4,13 +4,13 @@ import {
|
|
|
4
4
|
type OHLCData,
|
|
5
5
|
type SeriesSnapshot,
|
|
6
6
|
type SnapshotSort,
|
|
7
|
-
type TimePoint,
|
|
8
7
|
type TooltipFormatter,
|
|
9
8
|
buildHoverSnapshots,
|
|
10
9
|
buildLastSnapshots,
|
|
11
10
|
formatCompact,
|
|
12
11
|
formatHeaderX,
|
|
13
12
|
formatPriceAdaptive,
|
|
13
|
+
formatRowValue,
|
|
14
14
|
resolveCandlestickBodyColor,
|
|
15
15
|
} from '@wick-charts/core';
|
|
16
16
|
import { computed, inject, onMounted, onUnmounted, ref, useSlots } from 'vue';
|
|
@@ -56,12 +56,15 @@ const onOverlayChange = () => {
|
|
|
56
56
|
};
|
|
57
57
|
onMounted(() => {
|
|
58
58
|
chart.on('overlayChange', onOverlayChange);
|
|
59
|
+
// Rows read animated values (smoothing, fades, percent shares).
|
|
60
|
+
chart.on('seriesFrame', onOverlayChange);
|
|
59
61
|
// Catch-up: a sibling series' mount effect may have registered data in the
|
|
60
62
|
// same synchronous flush, so poke the computed now.
|
|
61
63
|
if (chart.getSeriesIds().length > 0) bump.value++;
|
|
62
64
|
});
|
|
63
65
|
onUnmounted(() => {
|
|
64
66
|
chart.off('overlayChange', onOverlayChange);
|
|
67
|
+
chart.off('seriesFrame', onOverlayChange);
|
|
65
68
|
});
|
|
66
69
|
|
|
67
70
|
// Hover-over-the-y-axis gap: the overlay canvas includes the y-axis strip,
|
|
@@ -89,7 +92,12 @@ const snapshots = computed<readonly SeriesSnapshot[]>(() =>
|
|
|
89
92
|
isHover.value ? (hoverSnapshots.value as readonly SeriesSnapshot[]) : lastSnapshots.value,
|
|
90
93
|
);
|
|
91
94
|
|
|
92
|
-
|
|
95
|
+
// `chart` is not reactive: `bump` re-reads the interval once data lands after mount.
|
|
96
|
+
const dataInterval = computed(() => {
|
|
97
|
+
void bump.value;
|
|
98
|
+
|
|
99
|
+
return chart.getDataInterval();
|
|
100
|
+
});
|
|
93
101
|
const displayTime = computed(() => {
|
|
94
102
|
if (snapshots.value.length === 0) return 0;
|
|
95
103
|
if (isHover.value && crosshair.value) return crosshair.value.time;
|
|
@@ -205,7 +213,7 @@ function isBand(data: SeriesSnapshot['data']): data is BandPoint {
|
|
|
205
213
|
}"
|
|
206
214
|
/>
|
|
207
215
|
<span :style="{ color: s.color, fontWeight: 500 }">
|
|
208
|
-
{{
|
|
216
|
+
{{ formatRowValue(s, (v) => effectiveFormat(v, 'value')) }}
|
|
209
217
|
</span>
|
|
210
218
|
</span>
|
|
211
219
|
</template>
|
package/src/ui/NumberFlow.vue
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { computed, onMounted, ref } from 'vue';
|
|
2
|
+
import { computed, onMounted, ref, watch } from 'vue';
|
|
3
3
|
|
|
4
4
|
const props = withDefaults(
|
|
5
5
|
defineProps<{
|
|
@@ -11,6 +11,7 @@ const props = withDefaults(
|
|
|
11
11
|
*/
|
|
12
12
|
format?: ((value: number) => string) | Intl.NumberFormatOptions;
|
|
13
13
|
locale?: string;
|
|
14
|
+
/** Per-digit spin duration in ms. A value that arrives sooner than this after the previous one snaps instead. */
|
|
14
15
|
spinDuration?: number;
|
|
15
16
|
}>(),
|
|
16
17
|
{
|
|
@@ -50,6 +51,19 @@ const parts = computed<CharPart[]>(() => {
|
|
|
50
51
|
return result;
|
|
51
52
|
});
|
|
52
53
|
|
|
54
|
+
// A spin retargeted mid-turn shows two half digits, so values faster than a spin snap.
|
|
55
|
+
const duration = ref(props.spinDuration);
|
|
56
|
+
let changedAt = Number.NEGATIVE_INFINITY;
|
|
57
|
+
watch(
|
|
58
|
+
() => effectiveFormat.value(props.value),
|
|
59
|
+
() => {
|
|
60
|
+
const now = performance.now();
|
|
61
|
+
const tooFast = now - changedAt < props.spinDuration;
|
|
62
|
+
changedAt = now;
|
|
63
|
+
duration.value = tooFast ? 0 : props.spinDuration;
|
|
64
|
+
},
|
|
65
|
+
);
|
|
66
|
+
|
|
53
67
|
const digits = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
|
|
54
68
|
</script>
|
|
55
69
|
|
|
@@ -77,8 +91,8 @@ const digits = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
|
|
|
77
91
|
display: 'flex',
|
|
78
92
|
flexDirection: 'column',
|
|
79
93
|
transform: 'translateY(' + (-parseInt(part.value) * 1.2) + 'em)',
|
|
80
|
-
transition: mounted
|
|
81
|
-
? 'transform ' +
|
|
94
|
+
transition: mounted && duration > 0
|
|
95
|
+
? 'transform ' + duration + 'ms cubic-bezier(0.16, 1, 0.3, 1)'
|
|
82
96
|
: 'none',
|
|
83
97
|
}"
|
|
84
98
|
>
|
package/src/ui/Tooltip.vue
CHANGED
|
@@ -4,14 +4,13 @@ import {
|
|
|
4
4
|
type OHLCData,
|
|
5
5
|
type SeriesSnapshot,
|
|
6
6
|
type SnapshotSort,
|
|
7
|
-
type TimePoint,
|
|
8
7
|
type TooltipFormatter,
|
|
9
8
|
buildHoverSnapshots,
|
|
10
9
|
computeTooltipPosition,
|
|
11
10
|
formatCompact,
|
|
12
|
-
formatDate,
|
|
13
|
-
formatHeaderX,
|
|
14
11
|
formatPriceAdaptive,
|
|
12
|
+
formatRowValue,
|
|
13
|
+
formatTooltipHeader,
|
|
15
14
|
resolveCandlestickBodyColor,
|
|
16
15
|
} from '@wick-charts/core';
|
|
17
16
|
import { computed, onMounted, onUnmounted, ref, useSlots, watchEffect } from 'vue';
|
|
@@ -47,14 +46,26 @@ const onOverlayChange = () => {
|
|
|
47
46
|
};
|
|
48
47
|
onMounted(() => {
|
|
49
48
|
chart.on('overlayChange', onOverlayChange);
|
|
49
|
+
// Rows read animated values (smoothing, fades, percent shares).
|
|
50
|
+
chart.on('seriesFrame', onOverlayChange);
|
|
50
51
|
if (chart.getSeriesIds().length > 0) bump.value++;
|
|
51
52
|
});
|
|
52
53
|
onUnmounted(() => {
|
|
53
54
|
chart.off('overlayChange', onOverlayChange);
|
|
55
|
+
chart.off('seriesFrame', onOverlayChange);
|
|
54
56
|
});
|
|
55
57
|
|
|
56
|
-
const theme = computed(() =>
|
|
57
|
-
|
|
58
|
+
const theme = computed(() => {
|
|
59
|
+
void bump.value;
|
|
60
|
+
|
|
61
|
+
return chart.getTheme();
|
|
62
|
+
});
|
|
63
|
+
// `chart` is not reactive: `bump` re-reads the interval once data lands after mount.
|
|
64
|
+
const dataInterval = computed(() => {
|
|
65
|
+
void bump.value;
|
|
66
|
+
|
|
67
|
+
return chart.getDataInterval();
|
|
68
|
+
});
|
|
58
69
|
|
|
59
70
|
const snapshots = computed<readonly SeriesSnapshot[]>(() => {
|
|
60
71
|
void bump.value;
|
|
@@ -127,9 +138,12 @@ const floatingPos = computed<{ left: number; top: number } | null>(() => {
|
|
|
127
138
|
|
|
128
139
|
const hasOHLC = snapshots.value.some((s) => 'open' in s.data);
|
|
129
140
|
const lineCount = snapshots.value.filter((s) => !('open' in s.data)).length;
|
|
130
|
-
// A band row carries two numbers,
|
|
141
|
+
// A band row carries two numbers, and a percent-stack row a share and a value, so both need a wider box.
|
|
131
142
|
const hasBand = snapshots.value.some((s) => 'high' in s.data && !('open' in s.data));
|
|
132
|
-
const
|
|
143
|
+
const hasShare = snapshots.value.some((s) => s.share !== undefined);
|
|
144
|
+
let tooltipWidth = 160;
|
|
145
|
+
if (hasBand) tooltipWidth = 220;
|
|
146
|
+
if (hasShare) tooltipWidth = 240;
|
|
133
147
|
const tooltipHeight = hasOHLC ? 140 : 40 + lineCount * 22;
|
|
134
148
|
|
|
135
149
|
return computeTooltipPosition({
|
|
@@ -188,10 +202,7 @@ function isBand(data: SeriesSnapshot['data']): data is BandPoint {
|
|
|
188
202
|
letterSpacing: '0.02em',
|
|
189
203
|
}"
|
|
190
204
|
>
|
|
191
|
-
|
|
192
|
-
{{ formatDate(displayTime, { locale: chart.timeScale.getLocale(), timeZone: chart.timeScale.getTimeZone() }) }}
|
|
193
|
-
</template>
|
|
194
|
-
{{ formatHeaderX(chart, { time: displayTime, snapshots, interval: dataInterval }) }}
|
|
205
|
+
{{ formatTooltipHeader(chart, { time: displayTime, snapshots, interval: dataInterval }) }}
|
|
195
206
|
</div>
|
|
196
207
|
|
|
197
208
|
<template v-for="s in snapshots" :key="s.id">
|
|
@@ -264,7 +275,7 @@ function isBand(data: SeriesSnapshot['data']): data is BandPoint {
|
|
|
264
275
|
/>
|
|
265
276
|
<span :style="{ opacity: 0.6, flex: '1' }">{{ s.label ?? 'Value' }}</span>
|
|
266
277
|
<span :style="{ fontWeight: 600, color: s.color }">
|
|
267
|
-
{{
|
|
278
|
+
{{ formatRowValue(s, (v) => effectiveFormat(v, 'value')) }}
|
|
268
279
|
</span>
|
|
269
280
|
</div>
|
|
270
281
|
</template>
|