react-native-vroom-chart 0.13.0 → 0.13.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/android/CMakeLists.txt +8 -0
- package/android/README.md +11 -10
- package/cpp/VroomChartHostObject.cpp +140 -47
- package/cpp/VroomChartHostObject.h +1 -1
- package/cpp/VroomJsiInstaller.cpp +1 -1
- package/lib/index.js +62 -32
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +71 -34
- package/lib/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/VroomChart.tsx +92 -43
- package/src/jsi.d.ts +12 -9
- package/src/useChartCore.ts +4 -5
package/lib/index.mjs
CHANGED
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
// src/VroomChart.tsx
|
|
2
2
|
import React, { useEffect as useEffect2, useRef as useRef2, useCallback as useCallback2, useState as useState2, useMemo } from "react";
|
|
3
|
-
import { View } from "react-native";
|
|
4
|
-
import {
|
|
3
|
+
import { PixelRatio, View } from "react-native";
|
|
4
|
+
import {
|
|
5
|
+
AlphaType,
|
|
6
|
+
Canvas,
|
|
7
|
+
ColorType,
|
|
8
|
+
Image,
|
|
9
|
+
Picture,
|
|
10
|
+
Skia
|
|
11
|
+
} from "@shopify/react-native-skia";
|
|
5
12
|
import {
|
|
6
13
|
Gesture,
|
|
7
14
|
GestureDetector,
|
|
@@ -479,6 +486,9 @@ function useChartCore(candles, size, visibleRange, defaultCandleWidth, chartType
|
|
|
479
486
|
}
|
|
480
487
|
|
|
481
488
|
// src/VroomChart.tsx
|
|
489
|
+
function isSkImage(frame) {
|
|
490
|
+
return typeof frame.getImageInfo === "function";
|
|
491
|
+
}
|
|
482
492
|
function VroomChart(props) {
|
|
483
493
|
const {
|
|
484
494
|
candles,
|
|
@@ -530,17 +540,38 @@ function VroomChart(props) {
|
|
|
530
540
|
rec.beginRecording(Skia.XYWHRect(0, 0, 1, 1));
|
|
531
541
|
return rec.finishRecordingAsPicture();
|
|
532
542
|
}, []);
|
|
543
|
+
const emptyImage = useMemo(() => {
|
|
544
|
+
const data = Skia.Data.fromBytes(new Uint8Array(4));
|
|
545
|
+
return Skia.Image.MakeImage(
|
|
546
|
+
{
|
|
547
|
+
width: 1,
|
|
548
|
+
height: 1,
|
|
549
|
+
colorType: ColorType.RGBA_8888,
|
|
550
|
+
alphaType: AlphaType.Premul
|
|
551
|
+
},
|
|
552
|
+
data,
|
|
553
|
+
4
|
|
554
|
+
);
|
|
555
|
+
}, []);
|
|
533
556
|
const pictureSV = useSharedValue(emptyPicture);
|
|
557
|
+
const imageSV = useSharedValue(emptyImage);
|
|
558
|
+
const applyFrame = useCallback2(
|
|
559
|
+
(frame) => {
|
|
560
|
+
if (isSkImage(frame)) imageSV.value = frame;
|
|
561
|
+
else pictureSV.value = frame;
|
|
562
|
+
},
|
|
563
|
+
[imageSV, pictureSV]
|
|
564
|
+
);
|
|
534
565
|
const reduceMotion = useReducedMotion();
|
|
535
566
|
const onFrame = useCallback2(
|
|
536
567
|
(p) => {
|
|
537
|
-
|
|
568
|
+
applyFrame(p);
|
|
538
569
|
},
|
|
539
|
-
[
|
|
570
|
+
[applyFrame]
|
|
540
571
|
);
|
|
541
572
|
const { handle, picture, volumeCollapseRef } = useChartCore(
|
|
542
573
|
candles,
|
|
543
|
-
{ width, height },
|
|
574
|
+
{ width, height, pxRatio: PixelRatio.get() },
|
|
544
575
|
visibleRange,
|
|
545
576
|
defaultCandleWidth,
|
|
546
577
|
chartType,
|
|
@@ -569,11 +600,11 @@ function VroomChart(props) {
|
|
|
569
600
|
animRaf.current = null;
|
|
570
601
|
if (!handle) return;
|
|
571
602
|
const next = handle.render();
|
|
572
|
-
if (next)
|
|
603
|
+
if (next) applyFrame(next);
|
|
573
604
|
if (handle.isAnimating()) {
|
|
574
605
|
animRaf.current = requestAnimationFrame(animTick);
|
|
575
606
|
}
|
|
576
|
-
}, [handle,
|
|
607
|
+
}, [handle, applyFrame]);
|
|
577
608
|
const maybeStartAnim = useCallback2(() => {
|
|
578
609
|
if (animRaf.current != null) return;
|
|
579
610
|
if (!handle?.isAnimating()) return;
|
|
@@ -588,9 +619,9 @@ function VroomChart(props) {
|
|
|
588
619
|
};
|
|
589
620
|
}, []);
|
|
590
621
|
useEffect2(() => {
|
|
591
|
-
if (picture)
|
|
622
|
+
if (picture) applyFrame(picture);
|
|
592
623
|
maybeStartAnim();
|
|
593
|
-
}, [picture,
|
|
624
|
+
}, [picture, applyFrame, maybeStartAnim]);
|
|
594
625
|
const morphRaf = useRef2(null);
|
|
595
626
|
const morphFade = useRef2(null);
|
|
596
627
|
const morphHandle = useRef2(null);
|
|
@@ -604,7 +635,7 @@ function VroomChart(props) {
|
|
|
604
635
|
morphFade.current = target;
|
|
605
636
|
handle.setChartType(target);
|
|
606
637
|
const p = handle.render();
|
|
607
|
-
if (p)
|
|
638
|
+
if (p) applyFrame(p);
|
|
608
639
|
maybeStartAnim();
|
|
609
640
|
return void 0;
|
|
610
641
|
}
|
|
@@ -621,7 +652,7 @@ function VroomChart(props) {
|
|
|
621
652
|
morphFade.current = target;
|
|
622
653
|
handle.setChartType(target);
|
|
623
654
|
const p = handle.render();
|
|
624
|
-
if (p)
|
|
655
|
+
if (p) applyFrame(p);
|
|
625
656
|
maybeStartAnim();
|
|
626
657
|
return void 0;
|
|
627
658
|
}
|
|
@@ -634,7 +665,7 @@ function VroomChart(props) {
|
|
|
634
665
|
morphFade.current = fade;
|
|
635
666
|
handle.setMorph(reduceMotion ? 0 : fade, fade);
|
|
636
667
|
const p = handle.render();
|
|
637
|
-
if (p)
|
|
668
|
+
if (p) applyFrame(p);
|
|
638
669
|
if (prog < 1) {
|
|
639
670
|
morphRaf.current = requestAnimationFrame(step);
|
|
640
671
|
} else {
|
|
@@ -642,7 +673,7 @@ function VroomChart(props) {
|
|
|
642
673
|
morphFade.current = target;
|
|
643
674
|
handle.setChartType(target);
|
|
644
675
|
const q = handle.render();
|
|
645
|
-
if (q)
|
|
676
|
+
if (q) applyFrame(q);
|
|
646
677
|
maybeStartAnim();
|
|
647
678
|
}
|
|
648
679
|
};
|
|
@@ -653,7 +684,7 @@ function VroomChart(props) {
|
|
|
653
684
|
morphRaf.current = null;
|
|
654
685
|
}
|
|
655
686
|
};
|
|
656
|
-
}, [handle, chartType, transitionMs, reduceMotion,
|
|
687
|
+
}, [handle, chartType, transitionMs, reduceMotion, applyFrame, maybeStartAnim]);
|
|
657
688
|
const volumeRaf = useRef2(null);
|
|
658
689
|
const volumeHandle = useRef2(null);
|
|
659
690
|
useEffect2(() => {
|
|
@@ -679,7 +710,7 @@ function VroomChart(props) {
|
|
|
679
710
|
volumeCollapseRef.current = { t: target, easing };
|
|
680
711
|
handle.setVolumeCollapse(target, easing);
|
|
681
712
|
const p = handle.render();
|
|
682
|
-
if (p)
|
|
713
|
+
if (p) applyFrame(p);
|
|
683
714
|
maybeStartAnim();
|
|
684
715
|
return void 0;
|
|
685
716
|
}
|
|
@@ -693,7 +724,7 @@ function VroomChart(props) {
|
|
|
693
724
|
volumeCollapseRef.current = { t, easing: kind };
|
|
694
725
|
handle.setVolumeCollapse(t, kind);
|
|
695
726
|
const p = handle.render();
|
|
696
|
-
if (p)
|
|
727
|
+
if (p) applyFrame(p);
|
|
697
728
|
if (prog < 1) {
|
|
698
729
|
volumeRaf.current = requestAnimationFrame(step);
|
|
699
730
|
} else {
|
|
@@ -713,7 +744,7 @@ function VroomChart(props) {
|
|
|
713
744
|
volume?.enabled,
|
|
714
745
|
transitionMs,
|
|
715
746
|
reduceMotion,
|
|
716
|
-
|
|
747
|
+
applyFrame,
|
|
717
748
|
volumeCollapseRef,
|
|
718
749
|
maybeStartAnim
|
|
719
750
|
]);
|
|
@@ -731,7 +762,7 @@ function VroomChart(props) {
|
|
|
731
762
|
axisCollapse.current = { y: targetY, x: targetX };
|
|
732
763
|
handle.setAxisCollapse(targetY, targetX);
|
|
733
764
|
const p = handle.render();
|
|
734
|
-
if (p)
|
|
765
|
+
if (p) applyFrame(p);
|
|
735
766
|
maybeStartAnim();
|
|
736
767
|
return void 0;
|
|
737
768
|
}
|
|
@@ -750,7 +781,7 @@ function VroomChart(props) {
|
|
|
750
781
|
axisCollapse.current = { y: targetY, x: targetX };
|
|
751
782
|
handle.setAxisCollapse(targetY, targetX);
|
|
752
783
|
const p = handle.render();
|
|
753
|
-
if (p)
|
|
784
|
+
if (p) applyFrame(p);
|
|
754
785
|
maybeStartAnim();
|
|
755
786
|
return void 0;
|
|
756
787
|
}
|
|
@@ -764,7 +795,7 @@ function VroomChart(props) {
|
|
|
764
795
|
axisCollapse.current = { y, x };
|
|
765
796
|
handle.setAxisCollapse(y, x);
|
|
766
797
|
const p = handle.render();
|
|
767
|
-
if (p)
|
|
798
|
+
if (p) applyFrame(p);
|
|
768
799
|
if (prog < 1) {
|
|
769
800
|
axisRaf.current = requestAnimationFrame(step);
|
|
770
801
|
} else {
|
|
@@ -785,7 +816,7 @@ function VroomChart(props) {
|
|
|
785
816
|
showXAxis,
|
|
786
817
|
transitionMs,
|
|
787
818
|
reduceMotion,
|
|
788
|
-
|
|
819
|
+
applyFrame,
|
|
789
820
|
maybeStartAnim
|
|
790
821
|
]);
|
|
791
822
|
const hitAxis = useCallback2(
|
|
@@ -825,7 +856,7 @@ function VroomChart(props) {
|
|
|
825
856
|
priceDrag.current = { index: pl.index, id: pl.line.id, price: pl.line.price };
|
|
826
857
|
handle.setPriceLineDrag(pl.index, pl.line.price);
|
|
827
858
|
const p = handle.render();
|
|
828
|
-
if (p)
|
|
859
|
+
if (p) applyFrame(p);
|
|
829
860
|
}
|
|
830
861
|
}
|
|
831
862
|
}).onChange((e) => {
|
|
@@ -848,7 +879,7 @@ function VroomChart(props) {
|
|
|
848
879
|
next = handle.render();
|
|
849
880
|
} else if (crosshairActive.current) {
|
|
850
881
|
const ch = handle.setCrosshair(e.x, e.y - crosshairOffset);
|
|
851
|
-
if (ch)
|
|
882
|
+
if (ch) applyFrame(ch);
|
|
852
883
|
const info = handle.getCrosshairInfo();
|
|
853
884
|
const t = info?.timeMs ?? null;
|
|
854
885
|
if (t !== lastCrosshairTime.current) {
|
|
@@ -859,7 +890,7 @@ function VroomChart(props) {
|
|
|
859
890
|
} else {
|
|
860
891
|
next = handle.translate(e.changeX, e.changeY);
|
|
861
892
|
}
|
|
862
|
-
if (next)
|
|
893
|
+
if (next) applyFrame(next);
|
|
863
894
|
maybeStartAnim();
|
|
864
895
|
}).onEnd((e) => {
|
|
865
896
|
if (!handle) return;
|
|
@@ -868,7 +899,7 @@ function VroomChart(props) {
|
|
|
868
899
|
priceDrag.current = null;
|
|
869
900
|
handle.setPriceLineDrag(-1, 0);
|
|
870
901
|
const p = handle.render();
|
|
871
|
-
if (p)
|
|
902
|
+
if (p) applyFrame(p);
|
|
872
903
|
if (g) onPriceLineDragEnd?.(g.id, g.price);
|
|
873
904
|
return;
|
|
874
905
|
}
|
|
@@ -888,7 +919,7 @@ function VroomChart(props) {
|
|
|
888
919
|
velocity *= Math.pow(0.5, dt / HALF_LIFE_S);
|
|
889
920
|
const dx = velocity * dt;
|
|
890
921
|
const next = handle.pan(dx, 0);
|
|
891
|
-
if (next)
|
|
922
|
+
if (next) applyFrame(next);
|
|
892
923
|
maybeStartAnim();
|
|
893
924
|
if (Math.abs(velocity) > MIN_STOP) {
|
|
894
925
|
decayRaf.current = requestAnimationFrame(tick);
|
|
@@ -942,7 +973,7 @@ function VroomChart(props) {
|
|
|
942
973
|
}
|
|
943
974
|
if (frameX === 1 && frameY === 1) return;
|
|
944
975
|
const next = handle.zoom(frameX, frameY, focalX, focalY);
|
|
945
|
-
if (next)
|
|
976
|
+
if (next) applyFrame(next);
|
|
946
977
|
maybeStartAnim();
|
|
947
978
|
});
|
|
948
979
|
const longPress = Gesture.LongPress().runOnJS(true).onStart((e) => {
|
|
@@ -952,7 +983,7 @@ function VroomChart(props) {
|
|
|
952
983
|
cancelDecay();
|
|
953
984
|
crosshairActive.current = true;
|
|
954
985
|
const ch = handle.setCrosshair(e.x, e.y - crosshairOffset);
|
|
955
|
-
if (ch)
|
|
986
|
+
if (ch) applyFrame(ch);
|
|
956
987
|
const info = handle.getCrosshairInfo();
|
|
957
988
|
lastCrosshairTime.current = info?.timeMs ?? null;
|
|
958
989
|
onCrosshair?.({
|
|
@@ -975,7 +1006,7 @@ function VroomChart(props) {
|
|
|
975
1006
|
if (hitAxis(e.x, e.y) !== "chart") return;
|
|
976
1007
|
crosshairActive.current = false;
|
|
977
1008
|
const ch = handle.clearCrosshair();
|
|
978
|
-
if (ch)
|
|
1009
|
+
if (ch) applyFrame(ch);
|
|
979
1010
|
lastCrosshairTime.current = null;
|
|
980
1011
|
onCrosshair?.({ active: false, candle: null, timeMs: null, price: null, reason: "hide" });
|
|
981
1012
|
});
|
|
@@ -990,11 +1021,17 @@ function VroomChart(props) {
|
|
|
990
1021
|
style
|
|
991
1022
|
]
|
|
992
1023
|
},
|
|
993
|
-
/* @__PURE__ */ React.createElement(GestureDetector, { gesture }, /* @__PURE__ */ React.createElement(View, { style: { flex: 1 } }, /* @__PURE__ */ React.createElement(Canvas, { style: { flex: 1 } }, width > 0 && height > 0 ? (
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
1024
|
+
/* @__PURE__ */ React.createElement(GestureDetector, { gesture }, /* @__PURE__ */ React.createElement(View, { style: { flex: 1 } }, /* @__PURE__ */ React.createElement(Canvas, { style: { flex: 1 } }, width > 0 && height > 0 ? /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Picture, { picture: pictureSV }), /* @__PURE__ */ React.createElement(
|
|
1025
|
+
Image,
|
|
1026
|
+
{
|
|
1027
|
+
image: imageSV,
|
|
1028
|
+
x: 0,
|
|
1029
|
+
y: 0,
|
|
1030
|
+
width,
|
|
1031
|
+
height,
|
|
1032
|
+
fit: "fill"
|
|
1033
|
+
}
|
|
1034
|
+
)) : null)))
|
|
998
1035
|
);
|
|
999
1036
|
}
|
|
1000
1037
|
export {
|