react-native-vroom-chart 0.6.0 → 0.8.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 (49) hide show
  1. package/cpp/VroomChartHostObject.cpp +281 -33
  2. package/cpp/_core_include/vroom/vroom_chart.h +231 -36
  3. package/cpp/_core_src/bollinger.h +1 -1
  4. package/cpp/_core_src/candles.cpp +138 -41
  5. package/cpp/_core_src/candles.h +11 -1
  6. package/cpp/_core_src/chart.cpp +91 -40
  7. package/cpp/_core_src/chart.h +69 -29
  8. package/cpp/_core_src/chart_facade.cpp +247 -69
  9. package/cpp/_core_src/drawings.cpp +147 -4
  10. package/cpp/_core_src/drawings.h +10 -5
  11. package/cpp/_core_src/gradient.cpp +46 -0
  12. package/cpp/_core_src/gradient.h +31 -0
  13. package/cpp/_core_src/labels.cpp +49 -16
  14. package/cpp/_core_src/labels.h +33 -4
  15. package/cpp/_core_src/liquidity.cpp +3 -37
  16. package/cpp/_core_src/ma_overlay.cpp +174 -12
  17. package/cpp/_core_src/ma_overlay.h +55 -3
  18. package/cpp/_core_src/macd.cpp +13 -42
  19. package/cpp/_core_src/macd.h +11 -8
  20. package/cpp/_core_src/macd_pane.cpp +57 -27
  21. package/cpp/_core_src/price_line_layout.h +1 -1
  22. package/cpp/_core_src/rsi.cpp +4 -18
  23. package/cpp/_core_src/rsi.h +6 -6
  24. package/cpp/_core_src/rsi_pane.cpp +34 -19
  25. package/cpp/_core_src/series_ma.cpp +64 -0
  26. package/cpp/_core_src/series_ma.h +30 -0
  27. package/cpp/_core_src/style_inherit.h +35 -0
  28. package/cpp/_core_src/theme.cpp +2 -1
  29. package/cpp/_core_src/viewport.cpp +36 -12
  30. package/cpp/_core_src/viewport.h +50 -0
  31. package/cpp/_core_src/volume.cpp +33 -8
  32. package/cpp/_core_src/volume.h +12 -1
  33. package/cpp/_core_src/volume_anim.cpp +32 -0
  34. package/cpp/_core_src/volume_anim.h +41 -0
  35. package/lib/index.d.mts +206 -31
  36. package/lib/index.d.ts +206 -31
  37. package/lib/index.js +324 -44
  38. package/lib/index.js.map +1 -1
  39. package/lib/index.mjs +329 -52
  40. package/lib/index.mjs.map +1 -1
  41. package/package.json +1 -1
  42. package/src/VroomChart.tsx +100 -17
  43. package/src/dataTransitions.ts +148 -0
  44. package/src/easing.ts +40 -0
  45. package/src/index.ts +9 -0
  46. package/src/jsi.d.ts +126 -19
  47. package/src/theme.ts +1 -0
  48. package/src/types.ts +3 -0
  49. package/src/useChartCore.ts +273 -30
package/lib/index.d.mts CHANGED
@@ -82,7 +82,12 @@ type VroomTheme = {
82
82
  candleRadius?: number;
83
83
  /** Round the wick end caps. Defaults to false. */
84
84
  wickRoundCap?: boolean;
85
- /** Corner radius (px) of the *top* of volume bars. Defaults to 0 (square). */
85
+ /**
86
+ * Corner radius (px) of the *top* of volume bars. Defaults to 0 (square).
87
+ *
88
+ * @deprecated Use `volume.radius`, which sits with the rest of the volume
89
+ * styling. This still applies when `volume.radius` is omitted.
90
+ */
86
91
  volumeRadius?: number;
87
92
  /** Gridlines. */
88
93
  grid?: VroomColor;
@@ -92,10 +97,16 @@ type VroomTheme = {
92
97
  crosshair?: VroomColor;
93
98
  /** Crosshair target — the hollow ring/dot at the intersection. */
94
99
  crosshairTarget?: VroomColor;
95
- /** Line-chart-mode close polyline color. Defaults to a neutral foreground. */
100
+ /** Line-chart-mode close polyline color. Defaults to violet, matching the RSI line. */
96
101
  lineColor?: VroomColor;
97
102
  /** Line-chart-mode polyline stroke width in px. Defaults to 1.5. */
98
103
  lineWidth?: number;
104
+ /**
105
+ * Opacity of the gradient filled beneath the line-chart polyline, at its
106
+ * strongest point. The fill uses `lineColor` and ramps to fully transparent at
107
+ * the bottom of the price pane. Defaults to 0.28; set to 0 to disable the fill.
108
+ */
109
+ lineGradientOpacity?: number;
99
110
  };
100
111
  /** A time window over the candle data, as Unix epoch milliseconds. */
101
112
  type VisibleRange = {
@@ -117,8 +128,13 @@ type ChartMode = 'pan' | 'draw';
117
128
  * overlays, crosshair, and drawings still render.
118
129
  */
119
130
  type ChartType = 'candles' | 'line';
131
+ /**
132
+ * Easing curve for animated transitions (candle↔line and interval switches).
133
+ * Defaults to `'ease-in-out'`.
134
+ */
135
+ type TransitionEasing = 'linear' | 'ease-in' | 'ease-out' | 'ease-in-out';
120
136
  /** Active drawing tool while in `draw` mode. `null` draws nothing. */
121
- type DrawTool = null | 'line' | 'box' | 'pencil';
137
+ type DrawTool = null | 'line' | 'box' | 'pencil' | 'path';
122
138
  /** A drawing anchor in data space, so it stays glued to the candles on pan/zoom. */
123
139
  type DrawPoint = {
124
140
  /** Anchor time as Unix epoch milliseconds (not snapped to a candle slot). */
@@ -160,16 +176,27 @@ type PencilDrawing = DrawingBase & {
160
176
  /** The path's points in draw order (at least 2), in data space. */
161
177
  points: DrawPoint[];
162
178
  };
179
+ /**
180
+ * A multi-segment path: straight segments through `points`, in order, ending in
181
+ * an arrowhead on the last vertex. Like a pencil stroke it holds a variable
182
+ * number of points, but every one was placed deliberately (one click each), so
183
+ * each is an individually draggable handle once the path is committed.
184
+ */
185
+ type PathDrawing = DrawingBase & {
186
+ type: 'path';
187
+ /** The path's vertices in draw order (at least 2), in data space. */
188
+ points: DrawPoint[];
189
+ };
163
190
  /**
164
191
  * A committed drawing. Pass an array of these via the `drawings` prop to render
165
192
  * persisted annotations; the chart appends a new one (via `onDrawingComplete`)
166
193
  * each time the user finishes drawing.
167
194
  *
168
195
  * This is a discriminated union on `type` — narrow on it before reading
169
- * `points[1]`, since a `'pencil'` stroke has a variable-length array while
196
+ * `points[1]`, since `'pencil'` and `'path'` have variable-length arrays while
170
197
  * `'line'` and `'box'` are always exactly two points.
171
198
  */
172
- type Drawing = LineDrawing | BoxDrawing | PencilDrawing;
199
+ type Drawing = LineDrawing | BoxDrawing | PencilDrawing | PathDrawing;
173
200
  /**
174
201
  * Storage adapter for **managed** drawing persistence. Provide it via the
175
202
  * `drawingStore` prop and the chart owns the drawings array itself — loading and
@@ -226,8 +253,21 @@ type UndoRedoControls = {
226
253
  */
227
254
  clearHistory: () => void;
228
255
  };
229
- /** RSI indicator config. Rendered in a pane below the candles when enabled. */
256
+ /** Price source for a moving average. */
257
+ type MASource = 'close' | 'open' | 'high' | 'low' | 'hl2' | 'hlc3' | 'ohlc4';
258
+ /** Averaging used by a moving average: simple or exponential. */
259
+ type MAKind = 'sma' | 'ema';
260
+ /**
261
+ * RSI indicator config. Rendered in a pane below the candles when enabled: the
262
+ * RSI line, an optional moving-average trendline over it, and two dashed rules
263
+ * at the overbought and oversold levels.
264
+ *
265
+ * RSI reads closes only — Wilder's definition is built on close-to-close
266
+ * change — so unlike the moving-average, Bollinger, and MACD configs it takes
267
+ * no {@link MASource}.
268
+ */
230
269
  type RSIConfig = {
270
+ /** Draw the pane. Default false. */
231
271
  enabled?: boolean;
232
272
  /** Lookback period in candle counts. Default 14, clamped to >= 2. */
233
273
  period?: number;
@@ -235,23 +275,37 @@ type RSIConfig = {
235
275
  upperBand?: number;
236
276
  /** Oversold band level (0..100). Default 30. */
237
277
  lowerBand?: number;
238
- /** Show the RSI-based moving-average trendline. Default true. */
239
- maEnabled?: boolean;
240
278
  /** Trendline (MA of RSI) length. Default 14, clamped to >= 1. */
241
279
  maPeriod?: number;
280
+ /** Averaging used for the trendline ({@link MAKind}). Default 'sma'. */
281
+ maType?: MAKind;
282
+ /** Draw the moving-average trendline. Default true. */
283
+ maVisible?: boolean;
284
+ /** RSI line color (hex string or packed ARGB number). Default violet. */
285
+ lineColor?: string | number;
286
+ /** RSI line stroke width in px. Default 1.5. */
287
+ lineWidth?: number;
288
+ /** Draw the RSI line. Default true. */
289
+ lineVisible?: boolean;
290
+ /** Trendline color. Default amber. */
291
+ maColor?: string | number;
292
+ /** Trendline stroke width in px. Default 1.5. */
293
+ maWidth?: number;
294
+ /** Color of both dashed band rules. Default gray. */
295
+ bandColor?: string | number;
296
+ /** Draw the overbought/oversold rules. Default true. */
297
+ bandsVisible?: boolean;
242
298
  };
243
- /** Price source for a moving average. */
244
- type MASource = 'close' | 'open' | 'high' | 'low' | 'hl2' | 'hlc3' | 'ohlc4';
245
299
  /**
246
300
  * A moving-average overlay line drawn on the price pane. Provide an array of
247
301
  * these via `movingAverages` to render a ribbon of SMA/EMA lines.
248
302
  */
249
303
  type MovingAverageOverlay = {
250
- /** 'sma' (simple) or 'ema' (exponential). */
251
- kind: 'sma' | 'ema';
304
+ /** Averaging for this line ({@link MAKind}). */
305
+ maType: MAKind;
252
306
  /** Lookback in candles. */
253
- length: number;
254
- /** Price source. Default 'close'. */
307
+ period: number;
308
+ /** Price source ({@link MASource}). Default 'close'. */
255
309
  source?: MASource;
256
310
  /** Line color (hex string or packed ARGB number). */
257
311
  color?: string | number;
@@ -263,6 +317,7 @@ type MovingAverageOverlay = {
263
317
  * pane, resetting each session.
264
318
  */
265
319
  type VWAPConfig = {
320
+ /** Draw the line. Default false. */
266
321
  enabled?: boolean;
267
322
  /** Session reset offset from UTC midnight, in minutes (default 0). */
268
323
  resetMinutes?: number;
@@ -278,18 +333,20 @@ type VWAPConfig = {
278
333
  * fill between the bands. No pane is reserved.
279
334
  */
280
335
  type BollingerBandsConfig = {
336
+ /** Draw the bands. Default false. */
281
337
  enabled?: boolean;
282
338
  /** Lookback in candles. Default 20, clamped to >= 1. */
283
339
  period?: number;
284
340
  /** Standard-deviation multiplier. Default 2. */
285
341
  stdDev?: number;
286
- /** Price source. Default 'close'. */
342
+ /** Price source ({@link MASource}). Default 'close'. */
287
343
  source?: MASource;
288
344
  /**
289
- * Basis (middle) line type. Default 'sma'. The stdev always uses the
290
- * window's arithmetic mean, even with an EMA basis (TradingView semantics).
345
+ * Averaging for the basis (middle) line ({@link MAKind}). Default 'sma'. The
346
+ * stdev always uses the window's arithmetic mean, even with an EMA basis
347
+ * (the standard semantics).
291
348
  */
292
- basis?: 'sma' | 'ema';
349
+ maType?: MAKind;
293
350
  /** Upper band color (hex string or packed ARGB number). Default blue. */
294
351
  upperColor?: string | number;
295
352
  /** Upper band stroke width in px. Default 1. */
@@ -302,11 +359,40 @@ type BollingerBandsConfig = {
302
359
  lowerColor?: string | number;
303
360
  /** Lower band stroke width in px. Default 1. */
304
361
  lowerWidth?: number;
305
- /** Translucent fill between the bands. Default true. */
306
- fill?: boolean;
362
+ /** Draw the translucent fill between the bands. Default true. */
363
+ fillVisible?: boolean;
307
364
  /** Fill opacity 0..1, applied to the upper band color. Default 0.1. */
308
365
  fillOpacity?: number;
309
366
  };
367
+ /**
368
+ * Volume bar config. One bottom-anchored bar per candle on the price pane,
369
+ * drawn under the candles and sharing their x position and body width.
370
+ *
371
+ * Unlike the other indicator configs the bars are on by default, so omitting
372
+ * this prop leaves the chart looking as it always has.
373
+ */
374
+ type VolumeConfig = {
375
+ /** Draw the bars. Default true. */
376
+ enabled?: boolean;
377
+ /** Bar opacity 0..1 (1 = opaque). Default 0.5, so bars read quieter than the candles. */
378
+ opacity?: number;
379
+ /**
380
+ * Height of the tallest bar as a fraction of the price pane, 0..1.
381
+ * Default 0.2.
382
+ *
383
+ * This is a ceiling rather than a reserved strip: raising it lets the bars
384
+ * reach further up over the candles rather than compressing them, matching
385
+ * the conventional volume overlay. Heights always auto-fit the loudest volume
386
+ * in view, so the tallest bar sits exactly at the ceiling.
387
+ */
388
+ height?: number;
389
+ /** Corner radius (px) of the *top* of each bar. Defaults to `theme.volumeRadius`, else 0 (square). */
390
+ radius?: number;
391
+ /** Up-bar color (hex string or packed ARGB number). Defaults to `theme.accentBull`. */
392
+ upColor?: string | number;
393
+ /** Down-bar color (hex string or packed ARGB number). Defaults to `theme.accentBear`. */
394
+ downColor?: string | number;
395
+ };
310
396
  /**
311
397
  * A single resting-liquidity band: a price interval carrying a total order size
312
398
  * on one side of the book. Consolidate raw L2 levels into these buckets before
@@ -360,9 +446,9 @@ type LiquidityConfig = {
360
446
  * plus an optional solid-filled `quantity` pill and an optional close button),
361
447
  * with a price badge in the y-axis strip.
362
448
  *
363
- * Interaction is opt-in and callback-gated, mirroring TradingView: the line is
364
- * only draggable when `draggable` is set, and the close button only renders when
365
- * you pass `onPriceLineClose`. Dragging is a *preview* — the chart never mutates
449
+ * Interaction is opt-in and callback-gated: the line is only draggable when
450
+ * `draggable` is set, and the close button only renders when you pass
451
+ * `onPriceLineClose`. Dragging is a *preview* — the chart never mutates
366
452
  * the price you gave it, so a move your backend rejects reverts on its own
367
453
  * simply by leaving your `priceLines` state unchanged.
368
454
  */
@@ -424,15 +510,65 @@ type PriceLinesStyle = {
424
510
  */
425
511
  hoverBoost?: number;
426
512
  };
427
- /** MACD indicator config. Rendered in its own pane below the candles. */
513
+ /**
514
+ * MACD indicator config. Rendered in its own pane below the candles: the gap
515
+ * between a fast and a slow moving average, a signal line smoothing that gap,
516
+ * and a histogram of the distance between the two.
517
+ *
518
+ * Every style field is optional and falls back to the stock look, so an
519
+ * untouched config renders exactly as it always has.
520
+ */
428
521
  type MACDConfig = {
522
+ /** Draw the pane. Default false. */
429
523
  enabled?: boolean;
430
- /** Fast EMA length. Default 12. */
524
+ /** Fast moving-average length. Default 12. */
431
525
  fast?: number;
432
- /** Slow EMA length (forced > fast). Default 26. */
526
+ /** Slow moving-average length (forced > fast). Default 26. */
433
527
  slow?: number;
434
- /** Signal-line EMA length. Default 9. */
528
+ /** Signal-line length. Default 9. */
435
529
  signal?: number;
530
+ /** Price source for the fast/slow legs ({@link MASource}). Default 'close'. */
531
+ source?: MASource;
532
+ /** Averaging used for the fast and slow legs ({@link MAKind}). Default 'ema'. */
533
+ maType?: MAKind;
534
+ /** Averaging applied to the MACD series for the signal line. Default 'ema'. */
535
+ signalMaType?: MAKind;
536
+ /** MACD line color (hex string or packed ARGB number). Default blue. */
537
+ lineColor?: string | number;
538
+ /** MACD line stroke width in px. Default 1.5. */
539
+ lineWidth?: number;
540
+ /** Draw the MACD line. Default true. */
541
+ lineVisible?: boolean;
542
+ /** Signal line color. Default orange. */
543
+ signalColor?: string | number;
544
+ /** Signal line stroke width in px. Default 1.5. */
545
+ signalWidth?: number;
546
+ /** Draw the signal line. Default true. */
547
+ signalVisible?: boolean;
548
+ /** Draw the histogram bars. Default true. */
549
+ histogramVisible?: boolean;
550
+ /**
551
+ * Bars above zero that are still growing away from it. Defaults to
552
+ * `theme.accentBull`. Set all four histogram colors alike for a flat,
553
+ * single-color histogram.
554
+ */
555
+ histogramUpColor?: string | number;
556
+ /**
557
+ * Bars above zero that are falling back toward it, i.e. momentum easing.
558
+ * Defaults to `histogramUpColor` at half opacity.
559
+ */
560
+ histogramUpFadingColor?: string | number;
561
+ /** Bars below zero still growing away from it. Defaults to `theme.accentBear`. */
562
+ histogramDownColor?: string | number;
563
+ /**
564
+ * Bars below zero rising back toward it. Defaults to `histogramDownColor` at
565
+ * half opacity.
566
+ */
567
+ histogramDownFadingColor?: string | number;
568
+ /** Zero-reference line color. Default gray. */
569
+ zeroLineColor?: string | number;
570
+ /** Draw the zero-reference line. Default true. */
571
+ zeroLineVisible?: boolean;
436
572
  };
437
573
  /**
438
574
  * Platform-agnostic props shared by every vroom chart component. Each platform
@@ -474,11 +610,17 @@ type VroomChartCoreProps = {
474
610
  */
475
611
  chartType?: ChartType;
476
612
  /**
477
- * Duration (ms) of the animated candle↔line transition when `chartType`
478
- * changes. Default ~300. `0` snaps instantly. Ignored (snaps) when the OS
479
- * requests reduced motion, which instead uses a plain cross-fade.
613
+ * Duration (ms) of the animated transitions: the candle↔line switch when
614
+ * `chartType` changes, and the candle reshape when the `candles` array is
615
+ * swapped for a different interval of the same asset. Default ~300. `0` snaps
616
+ * instantly. Ignored (snaps) when the OS requests reduced motion, which
617
+ * instead uses a plain cross-fade.
480
618
  */
481
619
  transitionMs?: number;
620
+ /**
621
+ * Easing curve applied to those transitions. Default `'ease-in-out'`.
622
+ */
623
+ transitionEasing?: TransitionEasing;
482
624
  theme?: VroomTheme;
483
625
  /** RSI indicator (pane below the candles). Omit/disable to hide it. */
484
626
  rsi?: RSIConfig;
@@ -490,6 +632,8 @@ type VroomChartCoreProps = {
490
632
  vwap?: VWAPConfig;
491
633
  /** Bollinger Bands overlay (three lines + fill on the price pane). */
492
634
  bollingerBands?: BollingerBandsConfig;
635
+ /** Volume bars under the candles. On by default; disable or restyle them here. */
636
+ volume?: VolumeConfig;
493
637
  /** Resting-order / order-book liquidity bands drawn behind the candles. */
494
638
  liquidity?: LiquidityConfig;
495
639
  /**
@@ -650,4 +794,35 @@ declare global {
650
794
  */
651
795
  declare function VroomChart(props: VroomChartProps): React.JSX.Element;
652
796
 
653
- export { type BollingerBandsConfig, type Candle, type ChartType, type CrosshairEvent, type MACDConfig, type MASource, type MovingAverageOverlay, type PriceLine, type PriceLinesStyle, type RSIConfig, type VWAPConfig, type VisibleRange, VroomChart, type VroomChartProps, type VroomColor, type VroomTheme };
797
+ /**
798
+ * How a new `candles` array relates to the one the chart already holds:
799
+ * `'initial'` is the first data, `'stream'` a live update to the same series,
800
+ * `'timeframe'` the same asset re-bucketed into a different interval, and
801
+ * `'reset'` a different series entirely.
802
+ */
803
+ type DataTransition = 'initial' | 'stream' | 'timeframe' | 'reset';
804
+ /**
805
+ * The candle period in ms, inferred as the median of the first few intervals
806
+ * (robust to a single gap). Null when there are fewer than two candles.
807
+ */
808
+ declare function inferStepMs(candles: Candle[]): number | null;
809
+ /**
810
+ * Classify a candles-prop change. `prev` is the previously rendered array
811
+ * (null on first render); `seriesKeyChanged` forces `reset` regardless of the
812
+ * data (the explicit escape hatch).
813
+ *
814
+ * Constraint: detection compares two immutable snapshots. An array mutated in
815
+ * place (same reference) never reaches this code — React props must change
816
+ * identity to re-render.
817
+ */
818
+ declare function classifyTransition(prev: Candle[] | null, next: Candle[], seriesKeyChanged: boolean): DataTransition;
819
+ /**
820
+ * The visible window to apply after a timeframe switch so each candle keeps
821
+ * the exact pixel width it had before: the visible slot count is preserved and
822
+ * the right edge re-anchors on the newest candle (any future-gap overshoot is
823
+ * carried over in slots, clamped to the core's 3/4-window cap). The new start
824
+ * may precede the first candle — that gap is intentional, width wins.
825
+ */
826
+ declare function timeframeWindow(oldWindow: VisibleRange, oldStepMs: number, oldLastMs: number, newStepMs: number, newLastMs: number): VisibleRange;
827
+
828
+ export { type BollingerBandsConfig, type Candle, type ChartType, type CrosshairEvent, type DataTransition, 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 };