react-native-vroom-chart 0.16.0 → 0.17.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/lib/index.mjs CHANGED
@@ -158,8 +158,10 @@ var COLOR_KEYS = {
158
158
  // VROOM_COLOR_ACCENT_BULL
159
159
  accentBear: 15,
160
160
  // VROOM_COLOR_ACCENT_BEAR
161
- lineColor: 16
161
+ lineColor: 16,
162
162
  // VROOM_COLOR_LINE
163
+ skeleton: 17
164
+ // VROOM_COLOR_SKELETON
163
165
  };
164
166
  var FLOAT_KEYS = {
165
167
  wickWidth: 1,
@@ -459,7 +461,7 @@ function ensureInstalled() {
459
461
  }
460
462
  installed = true;
461
463
  }
462
- function useChartCore(candles, size, visibleRange, defaultCandleWidth, chartType, theme, rsi, macd, atr, movingAverages, vwap, bollingerBands, ichimoku, fairValueGaps, volume, priceLines, footprints, transition) {
464
+ function useChartCore(candles, size, visibleRange, defaultCandleWidth, chartType, theme, rsi, macd, atr, movingAverages, vwap, bollingerBands, ichimoku, fairValueGaps, volume, priceLines, footprints, transition, loading) {
463
465
  const handleRef = useRef(null);
464
466
  const defaultWidthAppliedRef = useRef(false);
465
467
  const volumeCollapseRef = useRef(null);
@@ -494,18 +496,26 @@ function useChartCore(candles, size, visibleRange, defaultCandleWidth, chartType
494
496
  const onFrameRef = useRef(transition?.onFrame);
495
497
  onFrameRef.current = transition?.onFrame;
496
498
  const seriesKey = transition?.seriesKey;
499
+ const loadingHandoffRef = useRef(false);
497
500
  const endIntervalMorph = useCallback(() => {
498
501
  if (intervalMorphRaf.current != null) {
499
502
  cancelAnimationFrame(intervalMorphRaf.current);
500
503
  intervalMorphRaf.current = null;
501
504
  }
502
- handleRef.current?.setIntervalMorph(1);
505
+ const h = handleRef.current;
506
+ if (loadingHandoffRef.current) {
507
+ loadingHandoffRef.current = false;
508
+ h?.setLoadingMorph(1);
509
+ h?.beginLoadingReveal();
510
+ }
511
+ h?.setIntervalMorph(1);
503
512
  }, []);
504
- const startIntervalMorph = useCallback((h) => {
513
+ const startIntervalMorph = useCallback((h, durationMs) => {
505
514
  const { ms, easing } = animRef.current;
515
+ const dur = durationMs ?? ms;
506
516
  const start = performance.now();
507
517
  const step = (now) => {
508
- const p = Math.min(1, (now - start) / ms);
518
+ const p = Math.min(1, (now - start) / dur);
509
519
  h.setIntervalMorph(p < 1 ? ease(easing, p) : 1);
510
520
  const pic = h.render();
511
521
  if (pic) onFrameRef.current?.(pic);
@@ -513,6 +523,31 @@ function useChartCore(candles, size, visibleRange, defaultCandleWidth, chartType
513
523
  };
514
524
  intervalMorphRaf.current = requestAnimationFrame(step);
515
525
  }, []);
526
+ const startLoadingHandoff = useCallback(
527
+ (h) => {
528
+ const { ms, easing } = animRef.current;
529
+ const half = ms / 2;
530
+ loadingHandoffRef.current = true;
531
+ h.beginLoadingMorph();
532
+ const start = performance.now();
533
+ const step = (now) => {
534
+ const p = Math.min(1, (now - start) / half);
535
+ h.setLoadingMorph(p < 1 ? ease(easing, p) : 1);
536
+ const pic = h.render();
537
+ if (pic) onFrameRef.current?.(pic);
538
+ if (p < 1) {
539
+ intervalMorphRaf.current = requestAnimationFrame(step);
540
+ return;
541
+ }
542
+ intervalMorphRaf.current = null;
543
+ loadingHandoffRef.current = false;
544
+ h.beginLoadingReveal();
545
+ startIntervalMorph(h, half);
546
+ };
547
+ intervalMorphRaf.current = requestAnimationFrame(step);
548
+ },
549
+ [startIntervalMorph]
550
+ );
516
551
  const settleStream = useCallback((keepMorph = false) => {
517
552
  if (streamRaf.current != null) {
518
553
  cancelAnimationFrame(streamRaf.current);
@@ -582,6 +617,8 @@ function useChartCore(candles, size, visibleRange, defaultCandleWidth, chartType
582
617
  const explicit = visibleRange != null;
583
618
  const startMs = visibleRange?.startMs ?? 0;
584
619
  const endMs = visibleRange?.endMs ?? 0;
620
+ const showLoadingLine = loading === true && candles.length === 0;
621
+ const lineUpRef = useRef(false);
585
622
  const themeKey = theme ? JSON.stringify(theme) : "";
586
623
  const rsiKey = rsi ? JSON.stringify(rsi) : "";
587
624
  const macdKey = macd ? JSON.stringify(macd) : "";
@@ -604,6 +641,19 @@ function useChartCore(candles, size, visibleRange, defaultCandleWidth, chartType
604
641
  defaultWidthAppliedRef.current = true;
605
642
  }
606
643
  let morphing = false;
644
+ if (showLoadingLine) {
645
+ if (!lineUpRef.current) {
646
+ endIntervalMorph();
647
+ settleStream();
648
+ h.setCandles(packCandles([]));
649
+ prevDataRef.current = null;
650
+ }
651
+ h.setLoading(true, !animRef.current.reduceMotion);
652
+ lineUpRef.current = true;
653
+ } else if (lineUpRef.current && candles.length === 0) {
654
+ h.setLoading(false, true);
655
+ lineUpRef.current = false;
656
+ }
607
657
  if (candles.length > 0) {
608
658
  const prev = prevDataRef.current;
609
659
  const freshHandle = prev == null || prev.handle !== h;
@@ -611,6 +661,7 @@ function useChartCore(candles, size, visibleRange, defaultCandleWidth, chartType
611
661
  const transitionKind = freshHandle ? "initial" : explicit ? "stream" : classifyTransition(prev.candles, candles, seriesKey !== prev.seriesKey);
612
662
  let tfArgs = null;
613
663
  let prevEnvelope = null;
664
+ let handOff = false;
614
665
  let stream = null;
615
666
  if (transitionKind === "stream" && prev != null && !explicit) {
616
667
  const { stream: mode, streamMs, reduceMotion } = animRef.current;
@@ -660,6 +711,11 @@ function useChartCore(candles, size, visibleRange, defaultCandleWidth, chartType
660
711
  } else if (transitionKind === "initial" || transitionKind === "reset") {
661
712
  endIntervalMorph();
662
713
  }
714
+ if (lineUpRef.current) {
715
+ lineUpRef.current = false;
716
+ handOff = animRef.current.ms > 0 && !animRef.current.reduceMotion && onFrameRef.current != null;
717
+ if (!handOff) h.setLoading(false, true);
718
+ }
663
719
  h.setCandles(packCandles(candles));
664
720
  if (transitionKind === "timeframe") {
665
721
  const newStepMs = inferStepMs(candles);
@@ -681,6 +737,7 @@ function useChartCore(candles, size, visibleRange, defaultCandleWidth, chartType
681
737
  } else if (transitionKind === "reset") {
682
738
  h.resetView();
683
739
  }
740
+ if (handOff) startLoadingHandoff(h);
684
741
  prevDataRef.current = { handle: h, candles, seriesKey };
685
742
  }
686
743
  }
@@ -710,7 +767,7 @@ function useChartCore(candles, size, visibleRange, defaultCandleWidth, chartType
710
767
  footprints?.prints.length ? footprintsToSpec(footprints) : EMPTY_FOOTPRINTS
711
768
  );
712
769
  if (!morphing) setPicture(h.render());
713
- }, [candles, seriesKey, size.width, size.height, size.pxRatio, explicit, startMs, endMs, defaultCandleWidth, themeKey, rsiKey, macdKey, atrKey, maKey, vwapKey, bollingerKey, ichimokuKey, fvgKey, volumeKey, priceLinesKey, footprintsKey, startIntervalMorph, endIntervalMorph, startStreamAnim, settleStream]);
770
+ }, [candles, showLoadingLine, seriesKey, size.width, size.height, size.pxRatio, explicit, startMs, endMs, defaultCandleWidth, themeKey, rsiKey, macdKey, atrKey, maKey, vwapKey, bollingerKey, ichimokuKey, fvgKey, volumeKey, priceLinesKey, footprintsKey, startIntervalMorph, startLoadingHandoff, endIntervalMorph, startStreamAnim, settleStream]);
714
771
  return { handle: handleRef.current, picture, volumeCollapseRef };
715
772
  }
716
773
 
@@ -722,6 +779,7 @@ function isSkImage(frame) {
722
779
  function VroomChart(props) {
723
780
  const {
724
781
  candles,
782
+ loading,
725
783
  seriesKey,
726
784
  width: widthProp,
727
785
  height: heightProp,
@@ -839,8 +897,10 @@ function VroomChart(props) {
839
897
  streamTransitionMs,
840
898
  reduceMotion,
841
899
  onFrame
842
- }
900
+ },
901
+ loading
843
902
  );
903
+ const showLoadingLine = loading === true && candles.length === 0;
844
904
  const crosshairActive = useRef2(false);
845
905
  const footprintActive = useRef2(false);
846
906
  const lastCrosshairTime = useRef2(null);
@@ -1120,7 +1180,7 @@ function VroomChart(props) {
1120
1180
  pane: null
1121
1181
  });
1122
1182
  };
1123
- const pan = Gesture.Pan().runOnJS(true).maxPointers(1).onStart((e) => {
1183
+ const pan = Gesture.Pan().enabled(!showLoadingLine).runOnJS(true).maxPointers(1).onStart((e) => {
1124
1184
  cancelDecay();
1125
1185
  panMode.current = hitAxis(e.x, e.y);
1126
1186
  priceDrag.current = null;
@@ -1215,7 +1275,7 @@ function VroomChart(props) {
1215
1275
  enableX: false,
1216
1276
  enableY: false
1217
1277
  });
1218
- const pinch = Gesture.Pinch().runOnJS(true).onTouchesDown((e) => {
1278
+ const pinch = Gesture.Pinch().enabled(!showLoadingLine).runOnJS(true).onTouchesDown((e) => {
1219
1279
  if (e.numberOfTouches < 2) return;
1220
1280
  dismissFootprint();
1221
1281
  const [a, b] = e.allTouches;
@@ -1253,7 +1313,7 @@ function VroomChart(props) {
1253
1313
  if (next) applyFrame(next);
1254
1314
  maybeStartAnim();
1255
1315
  });
1256
- const longPress = Gesture.LongPress().runOnJS(true).onStart((e) => {
1316
+ const longPress = Gesture.LongPress().enabled(!showLoadingLine).runOnJS(true).onStart((e) => {
1257
1317
  if (!handle) return;
1258
1318
  if (hitAxis(e.x, e.y) !== "chart") return;
1259
1319
  if (hitPriceLine(e.x, e.y)) return;
@@ -1273,7 +1333,7 @@ function VroomChart(props) {
1273
1333
  reason: "show"
1274
1334
  });
1275
1335
  });
1276
- const tap = Gesture.Tap().runOnJS(true).onStart((e) => {
1336
+ const tap = Gesture.Tap().enabled(!showLoadingLine).runOnJS(true).onStart((e) => {
1277
1337
  if (!handle) return;
1278
1338
  const prints = footprints ?? [];
1279
1339
  const fp = prints.length ? handle.hitTestFootprint(e.x, e.y) : null;