react-native-vroom-chart 0.14.0 → 0.16.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.
Files changed (47) hide show
  1. package/cpp/VroomChartHostObject.cpp +289 -2
  2. package/cpp/_core_include/vroom/vroom_chart.h +221 -4
  3. package/cpp/_core_src/atr.cpp +67 -0
  4. package/cpp/_core_src/atr.h +44 -0
  5. package/cpp/_core_src/atr_pane.cpp +162 -0
  6. package/cpp/_core_src/atr_pane.h +48 -0
  7. package/cpp/_core_src/chart.cpp +477 -172
  8. package/cpp/_core_src/chart.h +173 -1
  9. package/cpp/_core_src/chart_facade.cpp +317 -23
  10. package/cpp/_core_src/fair_value_gaps.cpp +76 -0
  11. package/cpp/_core_src/fair_value_gaps.h +54 -0
  12. package/cpp/_core_src/footprints.cpp +226 -0
  13. package/cpp/_core_src/footprints.h +45 -0
  14. package/cpp/_core_src/footprints_layout.cpp +140 -0
  15. package/cpp/_core_src/footprints_layout.h +94 -0
  16. package/cpp/_core_src/fvg_overlay.cpp +262 -0
  17. package/cpp/_core_src/fvg_overlay.h +43 -0
  18. package/cpp/_core_src/ichimoku.cpp +65 -0
  19. package/cpp/_core_src/ichimoku.h +45 -0
  20. package/cpp/_core_src/labels.cpp +3 -0
  21. package/cpp/_core_src/line_morph.h +159 -0
  22. package/cpp/_core_src/ma_overlay.cpp +259 -36
  23. package/cpp/_core_src/ma_overlay.h +57 -2
  24. package/cpp/_core_src/macd.cpp +24 -1
  25. package/cpp/_core_src/macd.h +16 -0
  26. package/cpp/_core_src/macd_pane.cpp +71 -62
  27. package/cpp/_core_src/macd_pane.h +13 -1
  28. package/cpp/_core_src/pane_series.h +169 -0
  29. package/cpp/_core_src/rsi.cpp +4 -0
  30. package/cpp/_core_src/rsi.h +7 -0
  31. package/cpp/_core_src/rsi_pane.cpp +85 -29
  32. package/cpp/_core_src/rsi_pane.h +11 -1
  33. package/cpp/_core_src/tip_pulse.h +4 -4
  34. package/cpp/_core_src/viewport.h +35 -0
  35. package/lib/index.d.mts +385 -3
  36. package/lib/index.d.ts +385 -3
  37. package/lib/index.js +305 -7
  38. package/lib/index.js.map +1 -1
  39. package/lib/index.mjs +305 -7
  40. package/lib/index.mjs.map +1 -1
  41. package/package.json +1 -1
  42. package/src/VroomChart.tsx +108 -7
  43. package/src/dataTransitions.ts +47 -0
  44. package/src/index.ts +10 -0
  45. package/src/jsi.d.ts +136 -1
  46. package/src/types.ts +10 -0
  47. package/src/useChartCore.ts +330 -5
@@ -108,6 +108,41 @@ inline std::size_t morph_from_count(const CandleSnapshot* from,
108
108
  // anything else = fade the outgoing snapshot out then the new scene in.
109
109
  inline bool interval_morph_is_fade(int32_t mode) { return mode != 0; }
110
110
 
111
+ // Rewrites a fresh capture so it starts from the shape currently on screen
112
+ // rather than from the data underneath it. Live ticks arrive faster than a
113
+ // morph lands, so every restart interrupts one; without this the bar would jump
114
+ // back to its un-morphed position on each tick, which is the snap the animation
115
+ // exists to remove.
116
+ //
117
+ // `interrupted` is the capture being replaced and `morph_t` the progress it had
118
+ // reached, so `dst` becomes exactly the frame that was being painted: the draw
119
+ // path interpolates in this same fraction space (see candles::draw), which is
120
+ // what makes a plain lerp here land pixel-exact.
121
+ //
122
+ // Slot 0 is the newest in both, so a differing visible count only drops the
123
+ // oldest slots — those keep the fresh capture, which is where they already are.
124
+ inline void blend_candle_snapshots(CandleSnapshot* dst, std::size_t dst_n,
125
+ const CandleSnapshot* interrupted,
126
+ std::size_t interrupted_n, float morph_t) {
127
+ if (!dst || !interrupted) return;
128
+ const std::size_t n = dst_n < interrupted_n ? dst_n : interrupted_n;
129
+ for (std::size_t k = 0; k < n; ++k) {
130
+ const CandleSnapshot& from = interrupted[k];
131
+ CandleSnapshot& to = dst[k];
132
+ const auto mix = [morph_t](float a, float b) {
133
+ return a + (b - a) * morph_t;
134
+ };
135
+ to.open = mix(from.open, to.open);
136
+ to.high = mix(from.high, to.high);
137
+ to.low = mix(from.low, to.low);
138
+ to.close = mix(from.close, to.close);
139
+ to.x = mix(from.x, to.x);
140
+ // `bull` stays the fresh one: the draw path colors a paired slot from
141
+ // the live candle and only reads the capture's flag for a slot the next
142
+ // update drops, where the newer direction is the better answer.
143
+ }
144
+ }
145
+
111
146
  // Returns the indices of candles whose time_ms falls in [start_ms, end_ms].
112
147
  // When both are 0, returns the full range (Phase 1 default-everything behavior).
113
148
  // Candles must be sorted ascending by time_ms (invariant of the public API).
package/lib/index.d.mts CHANGED
@@ -194,6 +194,14 @@ type TransitionEasing = 'linear' | 'ease-in' | 'ease-out' | 'ease-in-out';
194
194
  * (e.g. a fixed lookback).
195
195
  */
196
196
  type IntervalTransition = 'transform' | 'fade';
197
+ /**
198
+ * How a live update to the series being displayed animates. `'none'` (default)
199
+ * applies it on the next frame with no animation and leaves the viewport where
200
+ * it is. `'transform'` eases the in-progress bar into its new values and, when
201
+ * the view is already pinned to the newest bar, slides the series left as each
202
+ * new bar arrives.
203
+ */
204
+ type StreamTransition = 'none' | 'transform';
197
205
  /** Active drawing tool while in `draw` mode. `null` draws nothing. */
198
206
  type DrawTool = null | 'line' | 'box' | 'pencil' | 'path';
199
207
  /** A drawing anchor in data space, so it stays glued to the candles on pan/zoom. */
@@ -436,6 +444,16 @@ type RSIConfig = {
436
444
  bandColor?: string | number;
437
445
  /** Draw the overbought/oversold rules. Default true. */
438
446
  bandsVisible?: boolean;
447
+ /**
448
+ * Shade the stretches where the RSI line sits past a band, fading out at the
449
+ * rule and deepening toward the end of the scale, so how far a reading went
450
+ * past the threshold reads at a glance. Default true.
451
+ *
452
+ * Colored from the theme's `accentBull` (overbought) and `accentBear`
453
+ * (oversold), the same pair the volume bars and MACD histogram use. Never
454
+ * reaches full opacity — the line and its rule stay legible through it.
455
+ */
456
+ extremeFill?: boolean;
439
457
  };
440
458
  /**
441
459
  * A moving-average overlay line drawn on the price pane. Provide an array of
@@ -505,6 +523,180 @@ type BollingerBandsConfig = {
505
523
  /** Fill opacity 0..1, applied to the upper band color. Default 0.1. */
506
524
  fillOpacity?: number;
507
525
  };
526
+ /**
527
+ * Ichimoku Kinko Hyo overlay config. Five lines on the price pane plus the
528
+ * cloud (kumo) shaded between the two leading spans. No pane is reserved.
529
+ *
530
+ * Unlike the other overlays, three of the lines are drawn away from the bar
531
+ * they were computed on:
532
+ *
533
+ * - Senkou A and B lead by `displacement` bars, so the cloud extends past the
534
+ * newest candle into empty time. The chart reserves that space when it frames
535
+ * itself, so the forward cloud is on screen without panning.
536
+ * - Chikou lags by `displacement` bars.
537
+ *
538
+ * Ichimoku is built on highs and lows rather than a single price series, so it
539
+ * takes no {@link MASource} or {@link MAKind}.
540
+ *
541
+ * Like the other price-pane overlays, its values don't feed the automatic
542
+ * y-axis fit — the cloud can run off the top or bottom of the pane on a chart
543
+ * scaled to the candles alone.
544
+ */
545
+ type IchimokuConfig = {
546
+ /** Draw the indicator. Default false. */
547
+ enabled?: boolean;
548
+ /** Tenkan-sen (conversion) lookback. Default 9, clamped to >= 1. */
549
+ tenkanPeriod?: number;
550
+ /** Kijun-sen (base) lookback. Default 26, clamped to >= 1. */
551
+ kijunPeriod?: number;
552
+ /** Senkou Span B lookback. Default 52, clamped to >= 1. */
553
+ senkouBPeriod?: number;
554
+ /**
555
+ * Bars the cloud leads by and Chikou lags by. Default 26, clamped to >= 0.
556
+ * Changing it only moves what's already drawn — the lines themselves don't
557
+ * recompute.
558
+ */
559
+ displacement?: number;
560
+ /** Tenkan-sen color (hex string or packed ARGB number). Default blue. */
561
+ tenkanColor?: string | number;
562
+ /** Tenkan-sen stroke width in px. Default 1. */
563
+ tenkanWidth?: number;
564
+ /** Draw the Tenkan-sen. Default true. */
565
+ tenkanVisible?: boolean;
566
+ /** Kijun-sen color. Default red. */
567
+ kijunColor?: string | number;
568
+ /** Kijun-sen stroke width in px. Default 1. */
569
+ kijunWidth?: number;
570
+ /** Draw the Kijun-sen. Default true. */
571
+ kijunVisible?: boolean;
572
+ /** Senkou Span A color. Default green. */
573
+ senkouAColor?: string | number;
574
+ /** Senkou Span A stroke width in px. Default 1. */
575
+ senkouAWidth?: number;
576
+ /** Draw the Senkou Span A edge. Default true. */
577
+ senkouAVisible?: boolean;
578
+ /** Senkou Span B color. Default orange. */
579
+ senkouBColor?: string | number;
580
+ /** Senkou Span B stroke width in px. Default 1. */
581
+ senkouBWidth?: number;
582
+ /** Draw the Senkou Span B edge. Default true. */
583
+ senkouBVisible?: boolean;
584
+ /** Chikou span color. Default teal. */
585
+ chikouColor?: string | number;
586
+ /** Chikou span stroke width in px. Default 1. */
587
+ chikouWidth?: number;
588
+ /** Draw the Chikou span. Default true. */
589
+ chikouVisible?: boolean;
590
+ /** Draw the cloud between the two leading spans. Default true. */
591
+ cloudVisible?: boolean;
592
+ /** Cloud fill where Senkou A is above Senkou B. Default green. */
593
+ bullishCloudColor?: string | number;
594
+ /** Cloud fill where Senkou A is below Senkou B. Default red. */
595
+ bearishCloudColor?: string | number;
596
+ /** Cloud opacity 0..1, applied to whichever cloud color is in play. Default 0.15. */
597
+ cloudOpacity?: number;
598
+ };
599
+ /**
600
+ * Fair Value Gap overlay config. Shaded boxes on the price pane marking
601
+ * three-candle imbalances — a run so fast the first and third candles' wicks
602
+ * never overlap, leaving a band of price that was skipped.
603
+ *
604
+ * A gap is bullish when `candles[i - 1].high < candles[i + 1].low` and bearish
605
+ * when `candles[i - 1].low > candles[i + 1].high`, and spans the untouched
606
+ * range between those two wicks. Each box is anchored to the middle bar's open
607
+ * and runs `boxLength` bars to the right, or to the pane's edge under
608
+ * `extendBoxes`.
609
+ *
610
+ * Gaps are tracked until price trades back through them — see `fillType` for
611
+ * which price settles that, and `deleteAfterFill` for what happens once it
612
+ * does. With `showInverse`, a filled gap carries on as a zone of the opposite
613
+ * polarity. Unlike the line overlays, the boxes are pure geometry: they don't
614
+ * feed the automatic y-axis fit.
615
+ */
616
+ type FairValueGapsConfig = {
617
+ /** Draw the indicator. Default false. */
618
+ enabled?: boolean;
619
+ /** How many bars back to scan for gaps. Default 300, clamped to >= 0. */
620
+ maxBarsBack?: number;
621
+ /**
622
+ * Withhold a gap until its third candle closes. Default false, so a gap
623
+ * formed by the still-forming bar appears immediately and disappears again
624
+ * if that bar fills back in.
625
+ */
626
+ waitForClose?: boolean;
627
+ /**
628
+ * Which price counts as trading back through the gap. `'close'` (default)
629
+ * needs a candle to close past the far edge; `'wick'` settles it the moment
630
+ * a high or low reaches through.
631
+ */
632
+ fillType?: 'close' | 'wick';
633
+ /**
634
+ * Hide a gap once it's been filled. Default true. When false the box stays
635
+ * but stops at the bar that filled it, leaving a record of the rebalance.
636
+ */
637
+ deleteAfterFill?: boolean;
638
+ /**
639
+ * Run every box to the right edge of the pane instead of ending it after
640
+ * `boxLength` bars. Default false. A filled box still stops at its fill bar.
641
+ */
642
+ extendBoxes?: boolean;
643
+ /** Box width in bars when `extendBoxes` is off. Default 20, clamped to >= 1. */
644
+ boxLength?: number;
645
+ /** Fill color for bullish gaps (hex string or packed ARGB). Default green. */
646
+ bullishColor?: VroomColor;
647
+ /** Fill color for bearish gaps. Default red. */
648
+ bearishColor?: VroomColor;
649
+ /** Fill opacity 0..1, applied to whichever fill color is in play. Default 0.15. */
650
+ opacity?: number;
651
+ /** Draw the box outline. Default true. */
652
+ borderVisible?: boolean;
653
+ /** Outline style. Default `'solid'`. */
654
+ borderStyle?: 'solid' | 'dotted' | 'dashed';
655
+ /** Outline stroke width in px. Default 1. */
656
+ borderWidth?: number;
657
+ /** Outline color for bullish gaps. Defaults to `bullishColor` at full alpha. */
658
+ bullishBorderColor?: VroomColor;
659
+ /** Outline color for bearish gaps. Defaults to `bearishColor` at full alpha. */
660
+ bearishBorderColor?: VroomColor;
661
+ /** Draw a text label on each box. Default true. */
662
+ showLabels?: boolean;
663
+ /** Label text. Default `'FVG'`. */
664
+ label?: string;
665
+ /**
666
+ * Bars of clearance between the box and its label, used only under
667
+ * `extendBoxes` — a fixed-length box places the label inside its right end.
668
+ * Default 10, clamped to >= 0.
669
+ */
670
+ labelDistance?: number;
671
+ /** Label color. Defaults to the box's border color. */
672
+ labelColor?: VroomColor;
673
+ /** Label font size in px. Defaults to the axis font size. */
674
+ labelFontSize?: number;
675
+ /**
676
+ * Keep drawing a gap after it's been filled, with its polarity flipped — the
677
+ * band price rejected on the way through becomes a zone of the opposite
678
+ * kind. Default false.
679
+ *
680
+ * The inverse box starts where the original one stops, at the close of the
681
+ * bar that filled the gap, and lasts until price reclaims the band the other
682
+ * way (by the same rule `fillType` sets). This pairs with the default
683
+ * `deleteAfterFill: true`: the original box vanishes at the fill and the
684
+ * inverse takes over from there.
685
+ */
686
+ showInverse?: boolean;
687
+ /**
688
+ * Fill color for inverted zones that are bullish — that is, for *bearish*
689
+ * gaps price has broken above. Defaults to `bullishColor`.
690
+ */
691
+ inverseBullishColor?: VroomColor;
692
+ /**
693
+ * Fill color for inverted zones that are bearish — that is, for *bullish*
694
+ * gaps price has broken below. Defaults to `bearishColor`.
695
+ */
696
+ inverseBearishColor?: VroomColor;
697
+ /** Label text on inverted boxes. Default `'iFVG'`. */
698
+ inverseLabel?: string;
699
+ };
508
700
  /**
509
701
  * Volume bar config. One bottom-anchored bar per candle on the price pane,
510
702
  * drawn under the candles and sharing their x position and body width.
@@ -651,6 +843,123 @@ type PriceLinesStyle = {
651
843
  */
652
844
  hoverBoost?: number;
653
845
  };
846
+ /** Which side of a position a footprint marks. */
847
+ type FootprintSide = 'buy' | 'sell';
848
+ /**
849
+ * A single filled trade, drawn as a circular badge above the candle it fell in —
850
+ * the "footprint" a trader leaves on the chart: `buy` marks an entry (a `+`
851
+ * badge in the bull color), `sell` marks an exit (a `−` badge in the bear color).
852
+ *
853
+ * `timeMs` is the raw execution time, *not* a bar-open time. The chart buckets
854
+ * each footprint into whichever candle's window contains it, so the same array
855
+ * renders correctly at every interval — switch from 1m to 1h and the badges
856
+ * re-group onto the wider bars on their own.
857
+ *
858
+ * At most two badges render per candle: one for that bar's buys and one for its
859
+ * sells, however many trades went into each. Hovering (or tapping) a badge hands
860
+ * every footprint on that candle back through `onFootprint`, so a bar holding
861
+ * twenty fills still shows one badge and still reports all twenty.
862
+ */
863
+ type Footprint = {
864
+ /** Stable unique id, echoed back in `onFootprint`. */
865
+ id: string;
866
+ /** Execution time as Unix epoch milliseconds, unsnapped. */
867
+ timeMs: number;
868
+ /** Entry (`'buy'`) or exit (`'sell'`) — picks the badge color and glyph. */
869
+ side: FootprintSide;
870
+ /**
871
+ * Execution price. Ignored by the renderer (badges sit above the bar, not at
872
+ * the fill), and carried through to `onFootprint` for your own UI.
873
+ */
874
+ price?: number;
875
+ };
876
+ /** Shared layout/style for every footprint badge, passed via `footprintsStyle`. */
877
+ type FootprintsStyle = {
878
+ /** Badge radius in px. Default 9. */
879
+ radius?: number;
880
+ /**
881
+ * Vertical gap between the two stacked badges on a candle that has both a buy
882
+ * and a sell. Default 4 — wide enough that each stays independently hoverable.
883
+ */
884
+ gap?: number;
885
+ /** Gap between the candle's high and the first badge, in px. Default 8. */
886
+ margin?: number;
887
+ /**
888
+ * How much the hovered badge brightens, as a channel multiplier. 1 disables
889
+ * the highlight (the halo ring still draws). Default 1.25.
890
+ */
891
+ hoverBoost?: number;
892
+ };
893
+ /**
894
+ * The chart's plot area in logical px relative to the chart element's top-left:
895
+ * the candles and everything drawn over them, with the price and time axis
896
+ * strips excluded.
897
+ *
898
+ * This is the rect to test a floating UI against, and it is deliberately *not*
899
+ * the element's own box — the element includes the axis strips, so measuring it
900
+ * overstates the room beside anything near an edge.
901
+ */
902
+ type PlotRect = {
903
+ left: number;
904
+ top: number;
905
+ right: number;
906
+ bottom: number;
907
+ };
908
+ /**
909
+ * Fired when the pointer enters, moves between, or leaves footprint badges (on
910
+ * touch platforms, when one is tapped or dismissed).
911
+ *
912
+ * The chart draws no tooltip of its own — this event is the hook for yours.
913
+ * Position your UI off `badge` and `pane`, both in the same coordinate space as
914
+ * the chart element, and fill it from `footprints`.
915
+ *
916
+ * Panning or zooming fires a `'hide'`, since the bar the badge belongs to has
917
+ * moved: you don't need your own gesture listener to take the tooltip down.
918
+ */
919
+ type FootprintEvent = {
920
+ /** True while a badge is hovered/tapped; false when it's dismissed. */
921
+ active: boolean;
922
+ /**
923
+ * Why this event fired:
924
+ * 'show' — a badge became hovered/tapped from nothing
925
+ * 'move' — the pointer moved to a *different* badge without leaving in between
926
+ * 'hide' — the badge was dismissed: the pointer left (or a tap missed), the
927
+ * chart was panned or zoomed out from under it, or the crosshair
928
+ * took the pane over
929
+ */
930
+ reason: 'show' | 'move' | 'hide';
931
+ /** Which badge — its buys or its sells. Null when inactive. */
932
+ side: FootprintSide | null;
933
+ /** Bar-open time (epoch ms) of the candle the badge sits on. Null when inactive. */
934
+ timeMs: number | null;
935
+ /**
936
+ * Every footprint bucketed into that candle, *both* sides, ascending by
937
+ * `timeMs`. Empty when inactive. Filter on `side` to show only the hovered
938
+ * badge's trades, or render the whole bar's activity at once.
939
+ */
940
+ footprints: Footprint[];
941
+ /**
942
+ * The badge's center and radius in logical px relative to the chart element's
943
+ * top-left — anchor your tooltip to it. Null when inactive.
944
+ */
945
+ badge: {
946
+ x: number;
947
+ y: number;
948
+ radius: number;
949
+ } | null;
950
+ /**
951
+ * The plot area the badge sits in, for choosing which side of it your tooltip
952
+ * fits on. Null when inactive (there is nothing to place).
953
+ *
954
+ * Only you know how big your tooltip is, so the chart reports the rect rather
955
+ * than picking a side:
956
+ *
957
+ * ```ts
958
+ * const fitsRight = badge.x + badge.radius + 8 + width <= pane.right;
959
+ * ```
960
+ */
961
+ pane: PlotRect | null;
962
+ };
654
963
  /**
655
964
  * MACD indicator config. Rendered in its own pane below the candles: the gap
656
965
  * between a fast and a slow moving average, a signal line smoothing that gap,
@@ -711,6 +1020,37 @@ type MACDConfig = {
711
1020
  /** Draw the zero-reference line. Default true. */
712
1021
  zeroLineVisible?: boolean;
713
1022
  };
1023
+ /**
1024
+ * How the true-range series is smoothed into ATR. `'rma'` is Wilder's original
1025
+ * (alpha = 1/period) and the conventional default; the other two are the
1026
+ * ordinary moving averages applied to the same series.
1027
+ *
1028
+ * Distinct from {@link MAKind}, which the other indicators use — RMA is
1029
+ * specific to Wilder's indicators and isn't offered elsewhere.
1030
+ */
1031
+ type ATRSmoothing = 'rma' | 'sma' | 'ema';
1032
+ /**
1033
+ * ATR (Average True Range) indicator config. Rendered in its own pane below the
1034
+ * candles: a single line measuring volatility in price units.
1035
+ *
1036
+ * True Range is the widest of the bar's own high-low span and the two gaps from
1037
+ * its extremes to the previous close, so an overnight jump the bar's range
1038
+ * misses still counts. ATR smooths that series over `period` bars. It is
1039
+ * strictly positive and unbounded, so the pane fits 0..peak from its bottom
1040
+ * edge rather than centering on a reference level.
1041
+ */
1042
+ type ATRConfig = {
1043
+ /** Draw the pane. Default false. */
1044
+ enabled?: boolean;
1045
+ /** Lookback in candles. Default 14. */
1046
+ period?: number;
1047
+ /** Smoothing applied to the true-range series. Default `'rma'`. */
1048
+ smoothing?: ATRSmoothing;
1049
+ /** Line color (hex string or packed ARGB number). Default teal. */
1050
+ lineColor?: string | number;
1051
+ /** Line stroke width in px. Default 1.5. */
1052
+ lineWidth?: number;
1053
+ };
714
1054
  /**
715
1055
  * Platform-agnostic props shared by every vroom chart component. Each platform
716
1056
  * extends this with its own `style` typing (and any platform-only props) to
@@ -770,17 +1110,41 @@ type VroomChartCoreProps = {
770
1110
  * motion still snaps.
771
1111
  */
772
1112
  intervalTransition?: IntervalTransition;
1113
+ /**
1114
+ * How a live update to the series already on screen animates — a tick to the
1115
+ * in-progress bar, or a newly closed bar arriving. `'none'` (default) snaps,
1116
+ * matching a chart with no streaming at all.
1117
+ *
1118
+ * `'transform'` eases the last bar (and every indicator reading from it) from
1119
+ * its old shape into its new one. When a new bar arrives *and* the view is
1120
+ * still pinned to the newest bar, the window advances with it so the series
1121
+ * translates left. A view panned back into history is never moved.
1122
+ */
1123
+ streamTransition?: StreamTransition;
1124
+ /**
1125
+ * Duration (ms) of the `streamTransition` animation. Default ~150 — shorter
1126
+ * than `transitionMs`, since ticks can arrive faster than a 300ms curve can
1127
+ * land. `0` snaps. Follows `transitionEasing`. Ignored (snaps) when the OS
1128
+ * requests reduced motion.
1129
+ */
1130
+ streamTransitionMs?: number;
773
1131
  theme?: VroomTheme;
774
1132
  /** RSI indicator (pane below the candles). Omit/disable to hide it. */
775
1133
  rsi?: RSIConfig;
776
1134
  /** MACD indicator (its own pane below the candles). Omit/disable to hide it. */
777
1135
  macd?: MACDConfig;
1136
+ /** ATR indicator (its own pane below the candles). Omit/disable to hide it. */
1137
+ atr?: ATRConfig;
778
1138
  /** Moving-average overlay lines (SMA/EMA) drawn on the price pane. */
779
1139
  movingAverages?: MovingAverageOverlay[];
780
1140
  /** VWAP overlay (session anchor, configurable reset). */
781
1141
  vwap?: VWAPConfig;
782
1142
  /** Bollinger Bands overlay (three lines + fill on the price pane). */
783
1143
  bollingerBands?: BollingerBandsConfig;
1144
+ /** Ichimoku Kinko Hyo overlay (five lines + the cloud on the price pane). */
1145
+ ichimoku?: IchimokuConfig;
1146
+ /** Fair Value Gap overlay (shaded imbalance boxes on the price pane). */
1147
+ fairValueGaps?: FairValueGapsConfig;
784
1148
  /** Volume bars under the candles. On by default; disable or restyle them here. */
785
1149
  volume?: VolumeConfig;
786
1150
  /** Resting-order / order-book liquidity bands drawn behind the candles. */
@@ -797,6 +1161,23 @@ type VroomChartCoreProps = {
797
1161
  priceLines?: PriceLine[];
798
1162
  /** Shared layout/style for every entry in `priceLines`. */
799
1163
  priceLinesStyle?: PriceLinesStyle;
1164
+ /**
1165
+ * Executed trades to mark on the chart as circular badges above the bar they
1166
+ * fell in — where a position was entered and exited.
1167
+ *
1168
+ * Pass raw fills with their real execution times; the chart groups them onto
1169
+ * candles itself and re-groups on interval changes, so one array serves every
1170
+ * timeframe. Order doesn't matter.
1171
+ */
1172
+ footprints?: Footprint[];
1173
+ /** Shared layout/style for every entry in `footprints`. */
1174
+ footprintsStyle?: FootprintsStyle;
1175
+ /**
1176
+ * Fired when a footprint badge is hovered (tapped on touch platforms) or
1177
+ * dismissed. The chart renders no tooltip itself — use this to place your own,
1178
+ * anchored to `e.badge`, kept inside `e.pane`, and filled from `e.footprints`.
1179
+ */
1180
+ onFootprint?: (e: FootprintEvent) => void;
800
1181
  /**
801
1182
  * Fired continuously while a draggable price line is being dragged, with the
802
1183
  * price under the pointer. Use it for a live readout (e.g. an order ticket);
@@ -953,8 +1334,9 @@ declare global {
953
1334
  * Skia-rendered candlestick chart. Pass OHLCV `candles` and size it via `style`
954
1335
  * (it fills its parent by default). Pan to scroll, pinch to zoom, drag the
955
1336
  * price/time axes to rescale, and long-press for the crosshair. Optional
956
- * indicators (`rsi`, `macd`, `movingAverages`, `vwap`), colors (`theme`), and
957
- * events (`onCrosshair`, `onViewportChange`) are configured through props.
1337
+ * indicators (`rsi`, `macd`, `movingAverages`, `vwap`, `bollingerBands`,
1338
+ * `ichimoku`, and more), colors (`theme`), and events (`onCrosshair`,
1339
+ * `onViewportChange`) are configured through props.
958
1340
  *
959
1341
  * @see {@link VroomChartProps} for the full prop reference.
960
1342
  */
@@ -991,4 +1373,4 @@ declare function classifyTransition(prev: Candle[] | null, next: Candle[], serie
991
1373
  */
992
1374
  declare function timeframeWindow(oldWindow: VisibleRange, oldStepMs: number, oldLastMs: number, newStepMs: number, newLastMs: number): VisibleRange;
993
1375
 
994
- export { type BollingerBandsConfig, type Candle, type ChartType, type CrosshairEvent, type DataTransition, type DefaultDrawingStyle, type IntervalTransition, type MACDConfig, type MAKind, type MASource, type MovingAverageOverlay, type PriceLine, type PriceLinesStyle, type RSIConfig, type TransitionEasing, type VWAPConfig, type VisibleRange, type VolumeConfig, VroomChart, type VroomChartProps, type VroomColor, type VroomTheme, classifyTransition, inferStepMs, timeframeWindow };
1376
+ export { type ATRConfig, type ATRSmoothing, type BollingerBandsConfig, type Candle, type ChartType, type CrosshairEvent, type DataTransition, type DefaultDrawingStyle, type FairValueGapsConfig, type Footprint, type FootprintEvent, type FootprintSide, type FootprintsStyle, type IchimokuConfig, type IntervalTransition, type MACDConfig, type MAKind, type MASource, type MovingAverageOverlay, type PlotRect, type PriceLine, type PriceLinesStyle, type RSIConfig, type StreamTransition, type TransitionEasing, type VWAPConfig, type VisibleRange, type VolumeConfig, VroomChart, type VroomChartProps, type VroomColor, type VroomTheme, classifyTransition, inferStepMs, timeframeWindow };