react-native-vroom-chart 0.6.0 → 0.7.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 (46) hide show
  1. package/cpp/VroomChartHostObject.cpp +150 -32
  2. package/cpp/_core_include/vroom/vroom_chart.h +180 -22
  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 +55 -20
  8. package/cpp/_core_src/chart_facade.cpp +206 -66
  9. package/cpp/_core_src/gradient.cpp +46 -0
  10. package/cpp/_core_src/gradient.h +31 -0
  11. package/cpp/_core_src/labels.cpp +49 -16
  12. package/cpp/_core_src/labels.h +33 -4
  13. package/cpp/_core_src/liquidity.cpp +3 -37
  14. package/cpp/_core_src/ma_overlay.cpp +174 -12
  15. package/cpp/_core_src/ma_overlay.h +55 -3
  16. package/cpp/_core_src/macd.cpp +13 -42
  17. package/cpp/_core_src/macd.h +11 -8
  18. package/cpp/_core_src/macd_pane.cpp +57 -27
  19. package/cpp/_core_src/price_line_layout.h +1 -1
  20. package/cpp/_core_src/rsi.cpp +4 -18
  21. package/cpp/_core_src/rsi.h +6 -6
  22. package/cpp/_core_src/rsi_pane.cpp +34 -19
  23. package/cpp/_core_src/series_ma.cpp +64 -0
  24. package/cpp/_core_src/series_ma.h +30 -0
  25. package/cpp/_core_src/style_inherit.h +35 -0
  26. package/cpp/_core_src/theme.cpp +2 -1
  27. package/cpp/_core_src/viewport.cpp +36 -12
  28. package/cpp/_core_src/viewport.h +50 -0
  29. package/cpp/_core_src/volume.cpp +33 -8
  30. package/cpp/_core_src/volume.h +12 -1
  31. package/cpp/_core_src/volume_anim.cpp +32 -0
  32. package/cpp/_core_src/volume_anim.h +41 -0
  33. package/lib/index.d.mts +161 -28
  34. package/lib/index.d.ts +161 -28
  35. package/lib/index.js +156 -31
  36. package/lib/index.js.map +1 -1
  37. package/lib/index.mjs +156 -31
  38. package/lib/index.mjs.map +1 -1
  39. package/package.json +3 -3
  40. package/src/VroomChart.tsx +69 -3
  41. package/src/easing.ts +40 -0
  42. package/src/index.ts +3 -0
  43. package/src/jsi.d.ts +76 -20
  44. package/src/theme.ts +1 -0
  45. package/src/types.ts +3 -0
  46. package/src/useChartCore.ts +103 -27
@@ -12,11 +12,13 @@
12
12
 
13
13
  #include "theme.h"
14
14
  #include "viewport.h"
15
+ #include "volume_anim.h"
15
16
 
16
17
  namespace vroom::volume {
17
18
 
18
19
  namespace {
19
- constexpr float kVolumeFrac = 0.20f; // tallest bar = this fraction of the area
20
+ // Ceiling for the tallest bar when the config inherits it.
21
+ constexpr float kDefaultHeightFrac = 0.20f;
20
22
  } // namespace
21
23
 
22
24
  void draw(SkCanvas* canvas,
@@ -24,6 +26,9 @@ void draw(SkCanvas* canvas,
24
26
  std::size_t n,
25
27
  const Layout& lay,
26
28
  const Theme& theme,
29
+ const ::VroomVolume& cfg,
30
+ float collapse_t,
31
+ int32_t collapse_easing,
27
32
  int64_t window_ms,
28
33
  int64_t visible_start_ms,
29
34
  int64_t candle_duration_ms) {
@@ -34,23 +39,38 @@ void draw(SkCanvas* canvas,
34
39
  for (std::size_t i = 0; i < n; ++i) max_vol = std::max(max_vol, visible[i].volume);
35
40
  if (max_vol <= 0.0) return;
36
41
 
42
+ // Resolve every inherit sentinel up front so the loop reads plain values.
43
+ const float height_frac =
44
+ cfg.height_frac >= 0.f ? cfg.height_frac : kDefaultHeightFrac;
45
+ const float opacity = cfg.opacity >= 0.f
46
+ ? cfg.opacity
47
+ : theme.floats[VROOM_FLOAT_VOLUME_OPACITY];
48
+ const float vol_r = cfg.radius_px >= 0.f
49
+ ? cfg.radius_px
50
+ : theme.floats[VROOM_FLOAT_VOLUME_RADIUS_PX];
51
+ const SkColor up_color = cfg.up_color != 0
52
+ ? static_cast<SkColor>(cfg.up_color)
53
+ : theme.colors[VROOM_COLOR_ACCENT_BULL];
54
+ const SkColor down_color = cfg.down_color != 0
55
+ ? static_cast<SkColor>(cfg.down_color)
56
+ : theme.colors[VROOM_COLOR_ACCENT_BEAR];
57
+
37
58
  const float candle_area_h = vroom::price_pane_bottom(lay);
38
- const float region_h = candle_area_h * kVolumeFrac;
59
+ const float region_h = candle_area_h * height_frac;
60
+ if (region_h <= 0.f) return;
39
61
 
40
62
  const float body_w = vroom::candle_body_width(
41
63
  lay, window_ms, candle_duration_ms);
42
64
  const float half_body = body_w * 0.5f;
43
65
 
44
- const float opacity = theme.floats[VROOM_FLOAT_VOLUME_OPACITY];
45
- const float vol_r = theme.floats[VROOM_FLOAT_VOLUME_RADIUS_PX];
46
66
  SkPaint bull_paint;
47
67
  bull_paint.setAntiAlias(true);
48
- bull_paint.setColor(theme.colors[VROOM_COLOR_ACCENT_BULL]);
68
+ bull_paint.setColor(up_color);
49
69
  bull_paint.setAlphaf(opacity);
50
70
 
51
71
  SkPaint bear_paint;
52
72
  bear_paint.setAntiAlias(true);
53
- bear_paint.setColor(theme.colors[VROOM_COLOR_ACCENT_BEAR]);
73
+ bear_paint.setColor(down_color);
54
74
  bear_paint.setAlphaf(opacity);
55
75
 
56
76
  for (std::size_t i = 0; i < n; ++i) {
@@ -61,8 +81,13 @@ void draw(SkCanvas* canvas,
61
81
  const float cx = vroom::candle_center_x(
62
82
  lay, c.time_ms, candle_duration_ms,
63
83
  visible_start_ms, window_ms);
64
- const float h = std::max(
65
- 1.f, static_cast<float>(c.volume / max_vol) * region_h);
84
+ // The 1px floor applies to the settled height, not the animated one, so
85
+ // a collapsing bar can still reach zero.
86
+ const float frac = static_cast<float>(c.volume / max_vol);
87
+ const float full_h = std::max(1.f, frac * region_h);
88
+ const float h = full_h * (1.f - vroom::volume_anim::bar_collapse(
89
+ frac, collapse_t, collapse_easing));
90
+ if (h < 0.5f) continue; // collapsed past the point of drawing anything
66
91
  const SkRect rect =
67
92
  SkRect::MakeXYWH(cx - half_body, candle_area_h - h, body_w, h);
68
93
  const SkPaint& paint = bull ? bull_paint : bear_paint;
@@ -21,12 +21,23 @@ namespace vroom::volume {
21
21
 
22
22
  // Draws a volume bar for each candle in [visible, visible + n). Bars share the
23
23
  // candles' x/width (via candle_center_x / candle_body_width) so they scroll and
24
- // resize with the candles. Heights auto-fit to the max volume in the slice.
24
+ // resize with the candles. Heights auto-fit to the max volume in the slice, so
25
+ // the loudest bar lands on cfg.height_frac of the pane.
26
+ //
27
+ // `cfg` supplies height/opacity/radius/colors; each of its style fields falls
28
+ // back to `theme` when left on its inherit sentinel.
29
+ //
30
+ // `collapse_t` (0 = full height, 1 = flat) staggers the bars down out of view,
31
+ // tallest first, all landing together — see volume_anim.h. It's also the
32
+ // visibility gate: callers skip this entirely at 1, since nothing would draw.
25
33
  void draw(SkCanvas* canvas,
26
34
  const ::VroomCandle* visible,
27
35
  std::size_t n,
28
36
  const Layout& lay,
29
37
  const Theme& theme,
38
+ const ::VroomVolume& cfg,
39
+ float collapse_t,
40
+ int32_t collapse_easing,
30
41
  int64_t window_ms,
31
42
  int64_t visible_start_ms,
32
43
  int64_t candle_duration_ms);
@@ -0,0 +1,32 @@
1
+ #include "volume_anim.h"
2
+
3
+ #include <algorithm>
4
+
5
+ #include "vroom/vroom_chart.h"
6
+
7
+ namespace vroom::volume_anim {
8
+
9
+ float ease(int32_t kind, float p) {
10
+ const float t = std::clamp(p, 0.f, 1.f);
11
+ switch (kind) {
12
+ case VROOM_EASING_LINEAR:
13
+ return t;
14
+ case VROOM_EASING_IN:
15
+ return t * t;
16
+ case VROOM_EASING_OUT:
17
+ return t * (2.f - t);
18
+ default:
19
+ return t * t * (3.f - 2.f * t); // smoothstep
20
+ }
21
+ }
22
+
23
+ float bar_collapse(float frac, float t, int32_t easing) {
24
+ const float progress = std::clamp(t, 0.f, 1.f);
25
+ const float window = std::clamp(frac, kMinWindow, 1.f);
26
+ // The window occupies the tail of the timeline, so a taller bar (bigger
27
+ // window) opens earlier. Every window ends at 1.
28
+ const float start = 1.f - window;
29
+ return ease(easing, (progress - start) / window);
30
+ }
31
+
32
+ } // namespace vroom::volume_anim
@@ -0,0 +1,41 @@
1
+ // Volume-bar collapse timing — pure functions, no Skia, no state.
2
+ //
3
+ // Split out from volume.cpp so the stagger arithmetic unit-tests without a Skia
4
+ // checkout, and so the one piece of easing the core owns lives somewhere
5
+ // obvious.
6
+ //
7
+ // Unlike the candle↔line and interval morphs, the host can't pre-ease this
8
+ // animation: every bar runs on its own window, so easing has to be applied per
9
+ // bar, after the window split. Feed bar_collapse the raw linear progress.
10
+
11
+ #pragma once
12
+
13
+ #include <cstdint>
14
+
15
+ namespace vroom::volume_anim {
16
+
17
+ // Shortest window any bar gets, as a fraction of the timeline. Without a floor a
18
+ // near-zero bar would collapse inside a single frame and read as a pop rather
19
+ // than a fall. Clamping only moves a start earlier, so every bar still lands
20
+ // together.
21
+ constexpr float kMinWindow = 0.2f;
22
+
23
+ // Linear progress (0..1) mapped through a VroomEasing curve. Mirrors ease() in
24
+ // packages/react/src/easing.ts; unknown kinds fall back to smoothstep, matching
25
+ // it. Progress outside 0..1 is clamped.
26
+ float ease(int32_t kind, float p);
27
+
28
+ // How far a single bar has collapsed at global linear progress `t`, from 0
29
+ // (untouched, full height) to 1 (flat).
30
+ //
31
+ // `frac` is the bar's height as a fraction of the tallest bar in view, and
32
+ // doubles as the length of its window: a bar falls over the last `frac` of the
33
+ // timeline. So the tallest bar starts immediately and takes the whole
34
+ // transition, shorter bars start progressively later, and everything reaches
35
+ // zero at t = 1 — the "tallest first, all land together" cascade.
36
+ //
37
+ // Symmetric in `t`, so driving it backwards (1 -> 0) plays the reveal: the
38
+ // shortest bar rises first and the tallest arrives last.
39
+ float bar_collapse(float frac, float t, int32_t easing);
40
+
41
+ } // namespace vroom::volume_anim
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,6 +128,11 @@ 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
137
  type DrawTool = null | 'line' | 'box' | 'pencil';
122
138
  /** A drawing anchor in data space, so it stays glued to the candles on pan/zoom. */
@@ -226,8 +242,21 @@ type UndoRedoControls = {
226
242
  */
227
243
  clearHistory: () => void;
228
244
  };
229
- /** RSI indicator config. Rendered in a pane below the candles when enabled. */
245
+ /** Price source for a moving average. */
246
+ type MASource = 'close' | 'open' | 'high' | 'low' | 'hl2' | 'hlc3' | 'ohlc4';
247
+ /** Averaging used by a moving average: simple or exponential. */
248
+ type MAKind = 'sma' | 'ema';
249
+ /**
250
+ * RSI indicator config. Rendered in a pane below the candles when enabled: the
251
+ * RSI line, an optional moving-average trendline over it, and two dashed rules
252
+ * at the overbought and oversold levels.
253
+ *
254
+ * RSI reads closes only — Wilder's definition is built on close-to-close
255
+ * change — so unlike the moving-average, Bollinger, and MACD configs it takes
256
+ * no {@link MASource}.
257
+ */
230
258
  type RSIConfig = {
259
+ /** Draw the pane. Default false. */
231
260
  enabled?: boolean;
232
261
  /** Lookback period in candle counts. Default 14, clamped to >= 2. */
233
262
  period?: number;
@@ -235,23 +264,37 @@ type RSIConfig = {
235
264
  upperBand?: number;
236
265
  /** Oversold band level (0..100). Default 30. */
237
266
  lowerBand?: number;
238
- /** Show the RSI-based moving-average trendline. Default true. */
239
- maEnabled?: boolean;
240
267
  /** Trendline (MA of RSI) length. Default 14, clamped to >= 1. */
241
268
  maPeriod?: number;
269
+ /** Averaging used for the trendline ({@link MAKind}). Default 'sma'. */
270
+ maType?: MAKind;
271
+ /** Draw the moving-average trendline. Default true. */
272
+ maVisible?: boolean;
273
+ /** RSI line color (hex string or packed ARGB number). Default violet. */
274
+ lineColor?: string | number;
275
+ /** RSI line stroke width in px. Default 1.5. */
276
+ lineWidth?: number;
277
+ /** Draw the RSI line. Default true. */
278
+ lineVisible?: boolean;
279
+ /** Trendline color. Default amber. */
280
+ maColor?: string | number;
281
+ /** Trendline stroke width in px. Default 1.5. */
282
+ maWidth?: number;
283
+ /** Color of both dashed band rules. Default gray. */
284
+ bandColor?: string | number;
285
+ /** Draw the overbought/oversold rules. Default true. */
286
+ bandsVisible?: boolean;
242
287
  };
243
- /** Price source for a moving average. */
244
- type MASource = 'close' | 'open' | 'high' | 'low' | 'hl2' | 'hlc3' | 'ohlc4';
245
288
  /**
246
289
  * A moving-average overlay line drawn on the price pane. Provide an array of
247
290
  * these via `movingAverages` to render a ribbon of SMA/EMA lines.
248
291
  */
249
292
  type MovingAverageOverlay = {
250
- /** 'sma' (simple) or 'ema' (exponential). */
251
- kind: 'sma' | 'ema';
293
+ /** Averaging for this line ({@link MAKind}). */
294
+ maType: MAKind;
252
295
  /** Lookback in candles. */
253
- length: number;
254
- /** Price source. Default 'close'. */
296
+ period: number;
297
+ /** Price source ({@link MASource}). Default 'close'. */
255
298
  source?: MASource;
256
299
  /** Line color (hex string or packed ARGB number). */
257
300
  color?: string | number;
@@ -263,6 +306,7 @@ type MovingAverageOverlay = {
263
306
  * pane, resetting each session.
264
307
  */
265
308
  type VWAPConfig = {
309
+ /** Draw the line. Default false. */
266
310
  enabled?: boolean;
267
311
  /** Session reset offset from UTC midnight, in minutes (default 0). */
268
312
  resetMinutes?: number;
@@ -278,18 +322,20 @@ type VWAPConfig = {
278
322
  * fill between the bands. No pane is reserved.
279
323
  */
280
324
  type BollingerBandsConfig = {
325
+ /** Draw the bands. Default false. */
281
326
  enabled?: boolean;
282
327
  /** Lookback in candles. Default 20, clamped to >= 1. */
283
328
  period?: number;
284
329
  /** Standard-deviation multiplier. Default 2. */
285
330
  stdDev?: number;
286
- /** Price source. Default 'close'. */
331
+ /** Price source ({@link MASource}). Default 'close'. */
287
332
  source?: MASource;
288
333
  /**
289
- * Basis (middle) line type. Default 'sma'. The stdev always uses the
290
- * window's arithmetic mean, even with an EMA basis (TradingView semantics).
334
+ * Averaging for the basis (middle) line ({@link MAKind}). Default 'sma'. The
335
+ * stdev always uses the window's arithmetic mean, even with an EMA basis
336
+ * (the standard semantics).
291
337
  */
292
- basis?: 'sma' | 'ema';
338
+ maType?: MAKind;
293
339
  /** Upper band color (hex string or packed ARGB number). Default blue. */
294
340
  upperColor?: string | number;
295
341
  /** Upper band stroke width in px. Default 1. */
@@ -302,11 +348,40 @@ type BollingerBandsConfig = {
302
348
  lowerColor?: string | number;
303
349
  /** Lower band stroke width in px. Default 1. */
304
350
  lowerWidth?: number;
305
- /** Translucent fill between the bands. Default true. */
306
- fill?: boolean;
351
+ /** Draw the translucent fill between the bands. Default true. */
352
+ fillVisible?: boolean;
307
353
  /** Fill opacity 0..1, applied to the upper band color. Default 0.1. */
308
354
  fillOpacity?: number;
309
355
  };
356
+ /**
357
+ * Volume bar config. One bottom-anchored bar per candle on the price pane,
358
+ * drawn under the candles and sharing their x position and body width.
359
+ *
360
+ * Unlike the other indicator configs the bars are on by default, so omitting
361
+ * this prop leaves the chart looking as it always has.
362
+ */
363
+ type VolumeConfig = {
364
+ /** Draw the bars. Default true. */
365
+ enabled?: boolean;
366
+ /** Bar opacity 0..1 (1 = opaque). Default 0.5, so bars read quieter than the candles. */
367
+ opacity?: number;
368
+ /**
369
+ * Height of the tallest bar as a fraction of the price pane, 0..1.
370
+ * Default 0.2.
371
+ *
372
+ * This is a ceiling rather than a reserved strip: raising it lets the bars
373
+ * reach further up over the candles rather than compressing them, matching
374
+ * the conventional volume overlay. Heights always auto-fit the loudest volume
375
+ * in view, so the tallest bar sits exactly at the ceiling.
376
+ */
377
+ height?: number;
378
+ /** Corner radius (px) of the *top* of each bar. Defaults to `theme.volumeRadius`, else 0 (square). */
379
+ radius?: number;
380
+ /** Up-bar color (hex string or packed ARGB number). Defaults to `theme.accentBull`. */
381
+ upColor?: string | number;
382
+ /** Down-bar color (hex string or packed ARGB number). Defaults to `theme.accentBear`. */
383
+ downColor?: string | number;
384
+ };
310
385
  /**
311
386
  * A single resting-liquidity band: a price interval carrying a total order size
312
387
  * on one side of the book. Consolidate raw L2 levels into these buckets before
@@ -360,9 +435,9 @@ type LiquidityConfig = {
360
435
  * plus an optional solid-filled `quantity` pill and an optional close button),
361
436
  * with a price badge in the y-axis strip.
362
437
  *
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
438
+ * Interaction is opt-in and callback-gated: the line is only draggable when
439
+ * `draggable` is set, and the close button only renders when you pass
440
+ * `onPriceLineClose`. Dragging is a *preview* — the chart never mutates
366
441
  * the price you gave it, so a move your backend rejects reverts on its own
367
442
  * simply by leaving your `priceLines` state unchanged.
368
443
  */
@@ -424,15 +499,65 @@ type PriceLinesStyle = {
424
499
  */
425
500
  hoverBoost?: number;
426
501
  };
427
- /** MACD indicator config. Rendered in its own pane below the candles. */
502
+ /**
503
+ * MACD indicator config. Rendered in its own pane below the candles: the gap
504
+ * between a fast and a slow moving average, a signal line smoothing that gap,
505
+ * and a histogram of the distance between the two.
506
+ *
507
+ * Every style field is optional and falls back to the stock look, so an
508
+ * untouched config renders exactly as it always has.
509
+ */
428
510
  type MACDConfig = {
511
+ /** Draw the pane. Default false. */
429
512
  enabled?: boolean;
430
- /** Fast EMA length. Default 12. */
513
+ /** Fast moving-average length. Default 12. */
431
514
  fast?: number;
432
- /** Slow EMA length (forced > fast). Default 26. */
515
+ /** Slow moving-average length (forced > fast). Default 26. */
433
516
  slow?: number;
434
- /** Signal-line EMA length. Default 9. */
517
+ /** Signal-line length. Default 9. */
435
518
  signal?: number;
519
+ /** Price source for the fast/slow legs ({@link MASource}). Default 'close'. */
520
+ source?: MASource;
521
+ /** Averaging used for the fast and slow legs ({@link MAKind}). Default 'ema'. */
522
+ maType?: MAKind;
523
+ /** Averaging applied to the MACD series for the signal line. Default 'ema'. */
524
+ signalMaType?: MAKind;
525
+ /** MACD line color (hex string or packed ARGB number). Default blue. */
526
+ lineColor?: string | number;
527
+ /** MACD line stroke width in px. Default 1.5. */
528
+ lineWidth?: number;
529
+ /** Draw the MACD line. Default true. */
530
+ lineVisible?: boolean;
531
+ /** Signal line color. Default orange. */
532
+ signalColor?: string | number;
533
+ /** Signal line stroke width in px. Default 1.5. */
534
+ signalWidth?: number;
535
+ /** Draw the signal line. Default true. */
536
+ signalVisible?: boolean;
537
+ /** Draw the histogram bars. Default true. */
538
+ histogramVisible?: boolean;
539
+ /**
540
+ * Bars above zero that are still growing away from it. Defaults to
541
+ * `theme.accentBull`. Set all four histogram colors alike for a flat,
542
+ * single-color histogram.
543
+ */
544
+ histogramUpColor?: string | number;
545
+ /**
546
+ * Bars above zero that are falling back toward it, i.e. momentum easing.
547
+ * Defaults to `histogramUpColor` at half opacity.
548
+ */
549
+ histogramUpFadingColor?: string | number;
550
+ /** Bars below zero still growing away from it. Defaults to `theme.accentBear`. */
551
+ histogramDownColor?: string | number;
552
+ /**
553
+ * Bars below zero rising back toward it. Defaults to `histogramDownColor` at
554
+ * half opacity.
555
+ */
556
+ histogramDownFadingColor?: string | number;
557
+ /** Zero-reference line color. Default gray. */
558
+ zeroLineColor?: string | number;
559
+ /** Draw the zero-reference line. Default true. */
560
+ zeroLineVisible?: boolean;
436
561
  };
437
562
  /**
438
563
  * Platform-agnostic props shared by every vroom chart component. Each platform
@@ -474,11 +599,17 @@ type VroomChartCoreProps = {
474
599
  */
475
600
  chartType?: ChartType;
476
601
  /**
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.
602
+ * Duration (ms) of the animated transitions: the candle↔line switch when
603
+ * `chartType` changes, and the candle reshape when the `candles` array is
604
+ * swapped for a different interval of the same asset. Default ~300. `0` snaps
605
+ * instantly. Ignored (snaps) when the OS requests reduced motion, which
606
+ * instead uses a plain cross-fade.
480
607
  */
481
608
  transitionMs?: number;
609
+ /**
610
+ * Easing curve applied to those transitions. Default `'ease-in-out'`.
611
+ */
612
+ transitionEasing?: TransitionEasing;
482
613
  theme?: VroomTheme;
483
614
  /** RSI indicator (pane below the candles). Omit/disable to hide it. */
484
615
  rsi?: RSIConfig;
@@ -490,6 +621,8 @@ type VroomChartCoreProps = {
490
621
  vwap?: VWAPConfig;
491
622
  /** Bollinger Bands overlay (three lines + fill on the price pane). */
492
623
  bollingerBands?: BollingerBandsConfig;
624
+ /** Volume bars under the candles. On by default; disable or restyle them here. */
625
+ volume?: VolumeConfig;
493
626
  /** Resting-order / order-book liquidity bands drawn behind the candles. */
494
627
  liquidity?: LiquidityConfig;
495
628
  /**
@@ -650,4 +783,4 @@ declare global {
650
783
  */
651
784
  declare function VroomChart(props: VroomChartProps): React.JSX.Element;
652
785
 
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 };
786
+ export { type BollingerBandsConfig, type Candle, type ChartType, type CrosshairEvent, 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 };