react-native-livechart 4.24.1 → 4.25.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/dist/components/DegenParticlesOverlay.d.ts +2 -2
- package/dist/components/DegenParticlesOverlay.d.ts.map +1 -1
- package/dist/components/LiveChart.d.ts.map +1 -1
- package/dist/components/LiveChartSeries.d.ts.map +1 -1
- package/dist/components/LoadingOverlay.d.ts +5 -1
- package/dist/components/LoadingOverlay.d.ts.map +1 -1
- package/dist/components/YAxisOverlay.d.ts +3 -1
- package/dist/components/YAxisOverlay.d.ts.map +1 -1
- package/dist/constants.d.ts +3 -3
- package/dist/core/historyRangeCache.d.ts +25 -0
- package/dist/core/historyRangeCache.d.ts.map +1 -0
- package/dist/core/liveChartEngineTick.d.ts +4 -1
- package/dist/core/liveChartEngineTick.d.ts.map +1 -1
- package/dist/core/resolveConfig.d.ts +1 -1
- package/dist/core/useHistoryRevision.d.ts +5 -0
- package/dist/core/useHistoryRevision.d.ts.map +1 -0
- package/dist/core/useLiveChartEngine.d.ts +17 -1
- package/dist/core/useLiveChartEngine.d.ts.map +1 -1
- package/dist/core/useLiveChartSeriesEngine.d.ts +2 -0
- package/dist/core/useLiveChartSeriesEngine.d.ts.map +1 -1
- package/dist/draw/candleBodyPath.d.ts +10 -0
- package/dist/draw/candleBodyPath.d.ts.map +1 -0
- package/dist/draw/lineFillPaths.d.ts +10 -0
- package/dist/draw/lineFillPaths.d.ts.map +1 -0
- package/dist/draw/volume.d.ts +4 -1
- package/dist/draw/volume.d.ts.map +1 -1
- package/dist/draw/volumeRange.d.ts +12 -0
- package/dist/draw/volumeRange.d.ts.map +1 -0
- package/dist/hooks/useCandlePaths.d.ts +1 -1
- package/dist/hooks/useCandlePaths.d.ts.map +1 -1
- package/dist/hooks/useChartPaths.d.ts +1 -1
- package/dist/hooks/useChartPaths.d.ts.map +1 -1
- package/dist/hooks/useDegen.d.ts +1 -0
- package/dist/hooks/useDegen.d.ts.map +1 -1
- package/dist/hooks/useDemandFrameLoop.d.ts +11 -0
- package/dist/hooks/useDemandFrameLoop.d.ts.map +1 -0
- package/dist/hooks/useLoadingLook.d.ts +12 -0
- package/dist/hooks/useLoadingLook.d.ts.map +1 -0
- package/dist/hooks/useMarkers.d.ts +3 -1
- package/dist/hooks/useMarkers.d.ts.map +1 -1
- package/dist/hooks/useMultiSeriesDegen.d.ts +1 -0
- package/dist/hooks/useMultiSeriesDegen.d.ts.map +1 -1
- package/dist/hooks/usePanScroll.d.ts +2 -0
- package/dist/hooks/usePanScroll.d.ts.map +1 -1
- package/dist/hooks/usePinchZoom.d.ts +2 -0
- package/dist/hooks/usePinchZoom.d.ts.map +1 -1
- package/dist/hooks/useVolumeRange.d.ts +14 -0
- package/dist/hooks/useVolumeRange.d.ts.map +1 -0
- package/dist/hooks/useXAxis.d.ts +7 -0
- package/dist/hooks/useXAxis.d.ts.map +1 -1
- package/dist/hooks/useYAxis.d.ts.map +1 -1
- package/dist/math/spline.d.ts +3 -1
- package/dist/math/spline.d.ts.map +1 -1
- package/dist/math/squiggly.d.ts +8 -0
- package/dist/math/squiggly.d.ts.map +1 -1
- package/dist/types.d.ts +11 -2
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/DegenParticlesOverlay.tsx +5 -5
- package/src/components/LiveChart.tsx +34 -4
- package/src/components/LiveChartSeries.tsx +14 -6
- package/src/components/LoadingOverlay.tsx +53 -12
- package/src/components/YAxisOverlay.tsx +38 -2
- package/src/constants.ts +3 -3
- package/src/core/historyRangeCache.ts +109 -0
- package/src/core/liveChartEngineTick.ts +24 -57
- package/src/core/resolveConfig.ts +1 -1
- package/src/core/useHistoryRevision.ts +36 -0
- package/src/core/useLiveChartEngine.ts +151 -64
- package/src/core/useLiveChartSeriesEngine.ts +16 -1
- package/src/draw/candleBodyPath.ts +38 -0
- package/src/draw/lineFillPaths.ts +63 -0
- package/src/draw/volume.ts +21 -23
- package/src/draw/volumeRange.ts +51 -0
- package/src/hooks/useCandlePaths.ts +68 -94
- package/src/hooks/useChartPaths.ts +87 -111
- package/src/hooks/useDegen.ts +10 -6
- package/src/hooks/useDemandFrameLoop.ts +82 -0
- package/src/hooks/useLoadingLook.ts +30 -0
- package/src/hooks/useMarkers.ts +18 -4
- package/src/hooks/useMultiSeriesDegen.ts +7 -3
- package/src/hooks/usePanScroll.ts +5 -0
- package/src/hooks/usePinchZoom.ts +5 -0
- package/src/hooks/useVolumeRange.ts +40 -0
- package/src/hooks/useXAxis.ts +27 -3
- package/src/hooks/useYAxis.ts +18 -2
- package/src/math/spline.ts +16 -8
- package/src/math/squiggly.ts +12 -0
- package/src/types.ts +11 -2
package/src/hooks/useMarkers.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { useEffect, useRef } from "react";
|
|
2
2
|
import { Gesture } from "react-native-gesture-handler";
|
|
3
3
|
import {
|
|
4
|
+
useAnimatedReaction,
|
|
4
5
|
useFrameCallback,
|
|
5
6
|
useSharedValue,
|
|
6
7
|
type SharedValue,
|
|
@@ -57,6 +58,8 @@ export function useMarkers(
|
|
|
57
58
|
cluster: ResolvedMarkerCluster = ANCHORED_CLUSTER,
|
|
58
59
|
/** Runtime gate shared with the chart engine. */
|
|
59
60
|
isFrameLoopActive?: SharedValue<boolean>,
|
|
61
|
+
/** Experimental input-driven projection instead of continuous frames; defaults to false. */
|
|
62
|
+
autoSleep = false,
|
|
60
63
|
): {
|
|
61
64
|
projected: SharedValue<ProjectedMarker[]>;
|
|
62
65
|
tapGesture: ReturnType<typeof Gesture.Tap>;
|
|
@@ -79,7 +82,7 @@ export function useMarkers(
|
|
|
79
82
|
onMarkerPress?.(event);
|
|
80
83
|
};
|
|
81
84
|
|
|
82
|
-
const
|
|
85
|
+
const project =
|
|
83
86
|
/* istanbul ignore next -- worklet runs on UI thread, not in Jest */ () => {
|
|
84
87
|
"worklet";
|
|
85
88
|
if (isFrameLoopActive?.get() === false) return;
|
|
@@ -111,13 +114,24 @@ export function useMarkers(
|
|
|
111
114
|
maxY: engine.canvasHeight.get(),
|
|
112
115
|
});
|
|
113
116
|
projected.set(buf);
|
|
117
|
+
};
|
|
118
|
+
const legacyActive = autostart && !autoSleep;
|
|
119
|
+
const markerFrameCallback = useFrameCallback(project, legacyActive);
|
|
120
|
+
useAnimatedReaction(
|
|
121
|
+
() => {
|
|
122
|
+
if (!autoSleep || !autostart) return null;
|
|
123
|
+
return [active, markers.get(), engine.canvasWidth.get(), engine.canvasHeight.get(),
|
|
124
|
+
engine.timestamp.get(), engine.displayWindow.get(), engine.displayMin.get(),
|
|
125
|
+
engine.displayMax.get(), seriesSV?.get(), lineData?.get(), isFrameLoopActive?.get()];
|
|
126
|
+
},
|
|
127
|
+
(inputs) => {
|
|
128
|
+
if (inputs !== null) project();
|
|
114
129
|
},
|
|
115
|
-
autostart,
|
|
116
130
|
);
|
|
117
131
|
useEffect(() => {
|
|
118
132
|
// Reanimated does not reactively apply later `autostart` values.
|
|
119
|
-
markerFrameCallback.setActive(
|
|
120
|
-
}, [
|
|
133
|
+
markerFrameCallback.setActive(legacyActive);
|
|
134
|
+
}, [legacyActive, markerFrameCallback]);
|
|
121
135
|
|
|
122
136
|
const tapGesture = Gesture.Tap().onEnd(
|
|
123
137
|
/* istanbul ignore next -- gesture worklet runs on UI thread, not in Jest */ (
|
|
@@ -30,6 +30,7 @@ export function useMultiSeriesDegen(
|
|
|
30
30
|
): {
|
|
31
31
|
pack: SharedValue<Float64Array<ArrayBuffer>>;
|
|
32
32
|
packRevision: SharedValue<number>;
|
|
33
|
+
particleTimestamp: SharedValue<number>;
|
|
33
34
|
shakeTransform: DerivedValue<
|
|
34
35
|
[{ translateX: number }, { translateY: number }]
|
|
35
36
|
>;
|
|
@@ -37,6 +38,7 @@ export function useMultiSeriesDegen(
|
|
|
37
38
|
const MAX_SLOTS = 80;
|
|
38
39
|
const pack = useSharedValue(new Float64Array(MAX_SLOTS * DEGEN_STRIDE));
|
|
39
40
|
const packRevision = useSharedValue(0);
|
|
41
|
+
const particleTimestamp = useSharedValue(0);
|
|
40
42
|
// Per-series previous momentum (0 = flat, 1 = up, 2 = down), index-aligned to series.
|
|
41
43
|
const prevMoms = useSharedValue<number[]>([]);
|
|
42
44
|
const writeRot = useSharedValue(0);
|
|
@@ -131,9 +133,10 @@ export function useMultiSeriesDegen(
|
|
|
131
133
|
]);
|
|
132
134
|
|
|
133
135
|
useFrameCallback(
|
|
134
|
-
/* istanbul ignore next -- worklet runs on UI thread, not in Jest */ () => {
|
|
136
|
+
/* istanbul ignore next -- worklet runs on UI thread, not in Jest */ (frame) => {
|
|
135
137
|
"worklet";
|
|
136
|
-
|
|
138
|
+
// Effect timing is independent of the quantized/pinned viewport clock.
|
|
139
|
+
const now = frame.timestamp / 1000;
|
|
137
140
|
const buf = pack.get();
|
|
138
141
|
const slots = slotCountSV.get();
|
|
139
142
|
|
|
@@ -242,6 +245,7 @@ export function useMultiSeriesDegen(
|
|
|
242
245
|
);
|
|
243
246
|
|
|
244
247
|
if (activeCount > 0 || prevActiveCount.get() > 0) {
|
|
248
|
+
particleTimestamp.set(now);
|
|
245
249
|
packRevision.set(packRevision.get() + 1);
|
|
246
250
|
}
|
|
247
251
|
prevActiveCount.set(activeCount);
|
|
@@ -256,5 +260,5 @@ export function useMultiSeriesDegen(
|
|
|
256
260
|
];
|
|
257
261
|
});
|
|
258
262
|
|
|
259
|
-
return { pack, packRevision, shakeTransform };
|
|
263
|
+
return { pack, packRevision, particleTimestamp, shakeTransform };
|
|
260
264
|
}
|
|
@@ -22,6 +22,8 @@ export type PanScrollGestureMode = "holdToScrub" | "axisDrag";
|
|
|
22
22
|
|
|
23
23
|
/** Engine SharedValues the pan-scroll gesture reads/writes (subset of the engine state). */
|
|
24
24
|
export interface PanScrollEngineRefs {
|
|
25
|
+
/** Wake a demand-driven engine before reading the gesture bounds. */
|
|
26
|
+
wake?: () => void;
|
|
25
27
|
/** Absolute right-edge time to freeze at, or `null` to follow the live edge. */
|
|
26
28
|
viewEnd: SharedValue<number | null>;
|
|
27
29
|
/** Right-edge time the engine would use if following live (advances each frame). */
|
|
@@ -263,10 +265,13 @@ export function usePanScroll({
|
|
|
263
265
|
},
|
|
264
266
|
);
|
|
265
267
|
|
|
268
|
+
const wakeEngine = engine.wake;
|
|
269
|
+
|
|
266
270
|
const onStart =
|
|
267
271
|
/* istanbul ignore next -- gesture worklet runs on the UI thread, not in Jest */
|
|
268
272
|
() => {
|
|
269
273
|
"worklet";
|
|
274
|
+
wakeEngine?.();
|
|
270
275
|
// Stop an in-flight fling FIRST. `withDecay` keeps writing `viewEnd` after
|
|
271
276
|
// the finger lifts, and `Gesture.Race` declares no relation between the two
|
|
272
277
|
// pans, so this can run while a scrub is already engaged. Bailing out below
|
|
@@ -10,6 +10,8 @@ import { FOLLOW_SNAP, panLowerBound, panUpperBound } from "./usePanScroll";
|
|
|
10
10
|
|
|
11
11
|
/** Engine SharedValues the pinch-zoom gesture reads/writes. */
|
|
12
12
|
export interface PinchZoomEngineRefs {
|
|
13
|
+
/** Wake a demand-driven engine before reading the gesture bounds. */
|
|
14
|
+
wake?: () => void;
|
|
13
15
|
/** Visible-window width override in seconds, or `null` to follow `timeWindow`. */
|
|
14
16
|
viewWindow: SharedValue<number | null>;
|
|
15
17
|
/** Absolute right-edge time, or `null` to follow the live edge (shared with pan). */
|
|
@@ -170,10 +172,13 @@ export function usePinchZoom({
|
|
|
170
172
|
const startWindow = useSharedValue(timeWindow);
|
|
171
173
|
const startViewEnd = useSharedValue(0);
|
|
172
174
|
|
|
175
|
+
const wakeEngine = engine.wake;
|
|
176
|
+
|
|
173
177
|
const onStart =
|
|
174
178
|
/* istanbul ignore next -- gesture worklet runs on the UI thread, not in Jest */
|
|
175
179
|
() => {
|
|
176
180
|
"worklet";
|
|
181
|
+
wakeEngine?.();
|
|
177
182
|
cancelAnimation(viewEnd);
|
|
178
183
|
cancelAnimation(viewWindow);
|
|
179
184
|
const edge = liveEdge.get();
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { useDerivedValue, type SharedValue } from "react-native-reanimated";
|
|
2
|
+
import type { CandlePoint } from "../types";
|
|
3
|
+
import {
|
|
4
|
+
visibleMaxVolume,
|
|
5
|
+
volumeEndIndex,
|
|
6
|
+
volumeStartIndex,
|
|
7
|
+
} from "../draw/volumeRange";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Primitive index outputs suppress downstream scans while the window glides
|
|
11
|
+
* within the same buckets. The maximum also depends directly on candles, so
|
|
12
|
+
* every notified data revision (including same-length replacement or modify)
|
|
13
|
+
* invalidates it. Array length and object identity are never cache keys.
|
|
14
|
+
*/
|
|
15
|
+
export function useVolumeRange(
|
|
16
|
+
candles: SharedValue<CandlePoint[]> | undefined,
|
|
17
|
+
timestamp: SharedValue<number>,
|
|
18
|
+
window: SharedValue<number>,
|
|
19
|
+
width: SharedValue<number>,
|
|
20
|
+
active: boolean,
|
|
21
|
+
) {
|
|
22
|
+
const start = useDerivedValue(() =>
|
|
23
|
+
!active || !candles
|
|
24
|
+
? 0
|
|
25
|
+
: volumeStartIndex(
|
|
26
|
+
candles.get(),
|
|
27
|
+
timestamp.get() - window.get(),
|
|
28
|
+
width.get(),
|
|
29
|
+
),
|
|
30
|
+
);
|
|
31
|
+
const end = useDerivedValue(() =>
|
|
32
|
+
!active || !candles ? 0 : volumeEndIndex(candles.get(), timestamp.get()),
|
|
33
|
+
);
|
|
34
|
+
const max = useDerivedValue(() =>
|
|
35
|
+
!active || !candles
|
|
36
|
+
? 0
|
|
37
|
+
: visibleMaxVolume(candles.get(), start.get(), end.get()),
|
|
38
|
+
);
|
|
39
|
+
return { start, end, max };
|
|
40
|
+
}
|
package/src/hooks/useXAxis.ts
CHANGED
|
@@ -167,11 +167,16 @@ export function useXAxis(
|
|
|
167
167
|
const edgeAlpha =
|
|
168
168
|
fromEdge >= fadeZone ? 1 : fromEdge <= 0 ? 0 : fromEdge / fadeZone;
|
|
169
169
|
|
|
170
|
-
const
|
|
170
|
+
const isTarget = xAxisKeyIsTarget(key, targetKeys);
|
|
171
|
+
const target = isTarget ? edgeAlpha : 0;
|
|
171
172
|
let next = lerp(label.alpha, target, FADE, MS_PER_FRAME_60FPS);
|
|
172
173
|
if (Math.abs(next - target) < 0.02) next = target;
|
|
173
174
|
|
|
174
|
-
|
|
175
|
+
// Only a key that left the target set is deleted once it has faded out. A
|
|
176
|
+
// target key can sit at alpha 0 (the set spans one interval past each edge,
|
|
177
|
+
// outside the plot); deleting it would re-create it on the next run and
|
|
178
|
+
// write `labelAlphas`, this mapper's own input, every frame.
|
|
179
|
+
if (next < 0.01 && !isTarget) {
|
|
175
180
|
delete alphas[key];
|
|
176
181
|
cacheChanged = true;
|
|
177
182
|
} else {
|
|
@@ -182,7 +187,12 @@ export function useXAxis(
|
|
|
182
187
|
}
|
|
183
188
|
}
|
|
184
189
|
|
|
185
|
-
|
|
190
|
+
// Publish only a changed final cache so this derived value cannot keep
|
|
191
|
+
// waking itself after the engine sleeps. Off-screen target keys are retained
|
|
192
|
+
// above; this equality check also guards against other no-op cache updates.
|
|
193
|
+
if (cacheChanged && !sameXAxisLabels(previousAlphas, alphas)) {
|
|
194
|
+
labelAlphas.set(alphas);
|
|
195
|
+
}
|
|
186
196
|
|
|
187
197
|
// Collect visible labels
|
|
188
198
|
const raw: XAxisEntry[] = [];
|
|
@@ -226,3 +236,17 @@ export function useXAxis(
|
|
|
226
236
|
|
|
227
237
|
return { xAxisEntries, font };
|
|
228
238
|
}
|
|
239
|
+
|
|
240
|
+
export function sameXAxisLabels(
|
|
241
|
+
previous: Record<number, { alpha: number; text: string }>,
|
|
242
|
+
next: Record<number, { alpha: number; text: string }>,
|
|
243
|
+
): boolean {
|
|
244
|
+
"worklet";
|
|
245
|
+
const keys = Object.keys(next);
|
|
246
|
+
if (keys.length !== Object.keys(previous).length) return false;
|
|
247
|
+
for (let i = 0; i < keys.length; i++) {
|
|
248
|
+
const key = Number(keys[i]);
|
|
249
|
+
if (!previous[key] || previous[key].alpha !== next[key].alpha || previous[key].text !== next[key].text) return false;
|
|
250
|
+
}
|
|
251
|
+
return true;
|
|
252
|
+
}
|
package/src/hooks/useYAxis.ts
CHANGED
|
@@ -28,7 +28,15 @@ export function useYAxis(
|
|
|
28
28
|
const yAxisEntries = useDerivedValue(() => {
|
|
29
29
|
const dt = MS_PER_FRAME_60FPS;
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
// SharedValue payloads may be frozen after crossing the JS/UI boundary.
|
|
32
|
+
// Copy before computeGridEntries adds, updates, or removes label keys.
|
|
33
|
+
const previousAlphas = labelAlphas.get();
|
|
34
|
+
const alphas: Record<number, number> = {};
|
|
35
|
+
const previousKeys = Object.keys(previousAlphas);
|
|
36
|
+
for (let i = 0; i < previousKeys.length; i++) {
|
|
37
|
+
const key = Number(previousKeys[i]);
|
|
38
|
+
alphas[key] = previousAlphas[key];
|
|
39
|
+
}
|
|
32
40
|
const result = computeGridEntries(
|
|
33
41
|
engine.displayMin.get(),
|
|
34
42
|
engine.displayMax.get(),
|
|
@@ -46,7 +54,15 @@ export function useYAxis(
|
|
|
46
54
|
);
|
|
47
55
|
|
|
48
56
|
prevInterval.set(result.interval);
|
|
49
|
-
|
|
57
|
+
// This derived value also reads the cache. Only publish actual changes so
|
|
58
|
+
// a settled axis doesn't keep scheduling itself with fresh object identities.
|
|
59
|
+
const nextKeys = Object.keys(alphas);
|
|
60
|
+
let cacheChanged = nextKeys.length !== previousKeys.length;
|
|
61
|
+
for (let i = 0; i < nextKeys.length && !cacheChanged; i++) {
|
|
62
|
+
const key = Number(nextKeys[i]);
|
|
63
|
+
if (alphas[key] !== previousAlphas[key]) cacheChanged = true;
|
|
64
|
+
}
|
|
65
|
+
if (cacheChanged) labelAlphas.set(alphas);
|
|
50
66
|
|
|
51
67
|
return result.entries;
|
|
52
68
|
});
|
package/src/math/spline.ts
CHANGED
|
@@ -60,6 +60,9 @@ export function drawSpline(
|
|
|
60
60
|
startPoint = 0,
|
|
61
61
|
/** Last point index to draw (exclusive). Defaults to the full array. */
|
|
62
62
|
endPoint = pts.length >> 1,
|
|
63
|
+
/** Optional paired sinks receive identical verbs from the same curve math. */
|
|
64
|
+
second?: SplinePathSink,
|
|
65
|
+
third?: SplinePathSink,
|
|
63
66
|
) {
|
|
64
67
|
"worklet";
|
|
65
68
|
const start = Math.max(0, startPoint);
|
|
@@ -70,12 +73,16 @@ export function drawSpline(
|
|
|
70
73
|
for (let i = 1; i < n; i++) {
|
|
71
74
|
const point = (start + i) * 2;
|
|
72
75
|
path.lineTo(pts[point], pts[point + 1]);
|
|
76
|
+
second?.lineTo(pts[point], pts[point + 1]);
|
|
77
|
+
third?.lineTo(pts[point], pts[point + 1]);
|
|
73
78
|
}
|
|
74
79
|
return;
|
|
75
80
|
}
|
|
76
81
|
if (n === 2) {
|
|
77
82
|
const point = (start + 1) * 2;
|
|
78
83
|
path.lineTo(pts[point], pts[point + 1]);
|
|
84
|
+
second?.lineTo(pts[point], pts[point + 1]);
|
|
85
|
+
third?.lineTo(pts[point], pts[point + 1]);
|
|
79
86
|
return;
|
|
80
87
|
}
|
|
81
88
|
|
|
@@ -123,14 +130,15 @@ export function drawSpline(
|
|
|
123
130
|
const i2 = (start + i) * 2;
|
|
124
131
|
const j2 = i2 + 2;
|
|
125
132
|
const hi = h[i];
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
pts[j2]
|
|
132
|
-
|
|
133
|
-
);
|
|
133
|
+
const x1 = pts[i2] + hi / 3;
|
|
134
|
+
const y1 = pts[i2 + 1] + (m[i] * hi) / 3;
|
|
135
|
+
const x2 = pts[j2] - hi / 3;
|
|
136
|
+
const y2 = pts[j2 + 1] - (m[i + 1] * hi) / 3;
|
|
137
|
+
const x = pts[j2],
|
|
138
|
+
y = pts[j2 + 1];
|
|
139
|
+
path.cubicTo(x1, y1, x2, y2, x, y);
|
|
140
|
+
second?.cubicTo(x1, y1, x2, y2, x, y);
|
|
141
|
+
third?.cubicTo(x1, y1, x2, y2, x, y);
|
|
134
142
|
}
|
|
135
143
|
}
|
|
136
144
|
|
package/src/math/squiggly.ts
CHANGED
|
@@ -27,6 +27,18 @@ export function squigglyYAt(
|
|
|
27
27
|
);
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
+
/**
|
|
31
|
+
* The squiggle's clock, in seconds: wall time. The loading shell
|
|
32
|
+
* (`LoadingOverlay`) and the reveal's morph (`useChartPaths`) both phase their
|
|
33
|
+
* wave on it rather than on `engine.timestamp`, which a `nowOverride` freezes
|
|
34
|
+
* between data updates (freezing the loading line with it). Sharing one clock
|
|
35
|
+
* keeps the wave continuous where the shell hands over to the morph.
|
|
36
|
+
*/
|
|
37
|
+
export function squiggleClockSeconds(): number {
|
|
38
|
+
"worklet";
|
|
39
|
+
return Date.now() / 1000;
|
|
40
|
+
}
|
|
41
|
+
|
|
30
42
|
/**
|
|
31
43
|
* Build a flat [x0,y0,x1,y1,...] point array for a standalone squiggly line
|
|
32
44
|
* spanning the full chart area (used in loading / empty state).
|
package/src/types.ts
CHANGED
|
@@ -757,8 +757,8 @@ export interface YAxisConfig {
|
|
|
757
757
|
* numbers; they track the live range each frame.
|
|
758
758
|
*
|
|
759
759
|
* `minGap` still acts as a floor: if `count` labels won't fit at least
|
|
760
|
-
* `minGap` px apart, the count is reduced to what fits. Clamped to at most 15
|
|
761
|
-
*
|
|
760
|
+
* `minGap` px apart, the count is reduced to what fits. Clamped to at most 15.
|
|
761
|
+
* Omit (or `0`) for the default dynamic grid.
|
|
762
762
|
*/
|
|
763
763
|
count?: number;
|
|
764
764
|
/**
|
|
@@ -2704,6 +2704,15 @@ export interface LiveChartProps extends LiveChartCoreProps {
|
|
|
2704
2704
|
* @experimental
|
|
2705
2705
|
*/
|
|
2706
2706
|
isFrameLoopActive?: SharedValue<boolean>;
|
|
2707
|
+
/**
|
|
2708
|
+
* Experimental single-series demand scheduling. Stop engine frames after a
|
|
2709
|
+
* paused, parked, or fixed-time chart settles; shared input changes and
|
|
2710
|
+
* gestures wake it on the UI thread. Default false. Live scrolling, pulse,
|
|
2711
|
+
* loading/reveal, and enabled degen/trade effects keep the engine awake.
|
|
2712
|
+
* Does not cache a bitmap or disable gestures. `static` takes precedence.
|
|
2713
|
+
* @experimental
|
|
2714
|
+
*/
|
|
2715
|
+
autoSleep?: boolean;
|
|
2707
2716
|
/**
|
|
2708
2717
|
* Optional development counter for engine frames that did or did not change
|
|
2709
2718
|
* tracked engine values. It is not a count of Skia redraws. Supplying it adds
|