react-native-vroom-chart 0.1.4 → 0.4.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/cpp/VroomChartHostObject.cpp +76 -1
- package/cpp/_core_include/vroom/vroom_chart.h +126 -11
- package/cpp/_core_src/candles.cpp +75 -10
- package/cpp/_core_src/candles.h +8 -1
- package/cpp/_core_src/chart.cpp +28 -3
- package/cpp/_core_src/chart.h +45 -4
- package/cpp/_core_src/chart_facade.cpp +207 -4
- package/cpp/_core_src/drawings.cpp +313 -15
- package/cpp/_core_src/drawings.h +23 -0
- package/cpp/_core_src/liquidity.cpp +112 -0
- package/cpp/_core_src/liquidity.h +35 -0
- package/cpp/_core_src/ma_overlay.cpp +9 -1
- package/cpp/_core_src/ma_overlay.h +2 -1
- package/cpp/_core_src/theme.cpp +5 -0
- package/cpp/_core_src/volume.cpp +15 -3
- package/lib/index.d.mts +179 -15
- package/lib/index.d.ts +179 -15
- package/lib/index.js +96 -4
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +96 -4
- package/lib/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/VroomChart.tsx +71 -0
- package/src/index.ts +1 -0
- package/src/jsi.d.ts +15 -0
- package/src/theme.ts +31 -6
- package/src/types.ts +1 -0
- package/src/useChartCore.ts +24 -1
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
#include "liquidity.h"
|
|
2
|
+
|
|
3
|
+
#include <algorithm>
|
|
4
|
+
#include <cstdint>
|
|
5
|
+
|
|
6
|
+
#pragma clang diagnostic push
|
|
7
|
+
#pragma clang diagnostic ignored "-Wdocumentation"
|
|
8
|
+
#include "include/core/SkCanvas.h"
|
|
9
|
+
#include "include/core/SkColor.h"
|
|
10
|
+
#include "include/core/SkPaint.h"
|
|
11
|
+
#include "include/core/SkPoint.h"
|
|
12
|
+
#include "include/core/SkRect.h"
|
|
13
|
+
#include "include/core/SkShader.h"
|
|
14
|
+
#include "include/core/SkTileMode.h"
|
|
15
|
+
// Skia's linear-gradient API differs across the Skia versions we build against:
|
|
16
|
+
// the WASM build uses a newer Skia (SkGradient.h + SkShaders::LinearGradient),
|
|
17
|
+
// while react-native-skia bundles an older one (SkGradientShader::MakeLinear).
|
|
18
|
+
// Neither ships both headers, so select whichever is present.
|
|
19
|
+
#if __has_include("include/effects/SkGradient.h")
|
|
20
|
+
# include "include/core/SkSpan.h"
|
|
21
|
+
# include "include/effects/SkGradient.h"
|
|
22
|
+
# define VROOM_SK_MODERN_GRADIENT 1
|
|
23
|
+
#else
|
|
24
|
+
# include "include/effects/SkGradientShader.h"
|
|
25
|
+
# define VROOM_SK_MODERN_GRADIENT 0
|
|
26
|
+
#endif
|
|
27
|
+
#pragma clang diagnostic pop
|
|
28
|
+
|
|
29
|
+
#include "chart.h"
|
|
30
|
+
|
|
31
|
+
namespace vroom::liquidity {
|
|
32
|
+
namespace {
|
|
33
|
+
|
|
34
|
+
// A horizontal shader fading from transparent at the left of `pts` to `base` at
|
|
35
|
+
// opacity `alpha` on the right, keeping RGB constant so the faded edge doesn't
|
|
36
|
+
// darken toward black. Abstracts over the two Skia gradient APIs above.
|
|
37
|
+
sk_sp<SkShader> left_fade_shader(const SkPoint pts[2], SkColor base, float alpha) {
|
|
38
|
+
#if VROOM_SK_MODERN_GRADIENT
|
|
39
|
+
const float r = SkColorGetR(base) / 255.f;
|
|
40
|
+
const float g = SkColorGetG(base) / 255.f;
|
|
41
|
+
const float b = SkColorGetB(base) / 255.f;
|
|
42
|
+
const SkColor4f colors[2] = {SkColor4f{r, g, b, 0.f}, SkColor4f{r, g, b, alpha}};
|
|
43
|
+
const SkGradient::Colors grad_colors(
|
|
44
|
+
SkSpan<const SkColor4f>(colors, 2), SkTileMode::kClamp);
|
|
45
|
+
const SkGradient grad(grad_colors, SkGradient::Interpolation{});
|
|
46
|
+
return SkShaders::LinearGradient(pts, grad);
|
|
47
|
+
#else
|
|
48
|
+
const auto a = static_cast<U8CPU>(alpha * 255.f + 0.5f);
|
|
49
|
+
const SkColor colors[2] = {SkColorSetA(base, 0), SkColorSetA(base, a)};
|
|
50
|
+
return SkGradientShader::MakeLinear(pts, colors, nullptr, 2, SkTileMode::kClamp);
|
|
51
|
+
#endif
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
} // namespace
|
|
55
|
+
|
|
56
|
+
void draw(SkCanvas* canvas,
|
|
57
|
+
const VroomChart& chart,
|
|
58
|
+
const Layout& lay,
|
|
59
|
+
const PriceBounds& bounds,
|
|
60
|
+
float candle_right,
|
|
61
|
+
float candle_area_h) {
|
|
62
|
+
if (!canvas || candle_right <= 0.f || candle_area_h <= 0.f) return;
|
|
63
|
+
if (chart.bands.empty()) return;
|
|
64
|
+
|
|
65
|
+
const VroomLiquidityStyle& style = chart.liquidity_style;
|
|
66
|
+
|
|
67
|
+
// Leftward reach: the smaller of the px cap and the pane-fraction, clamped so
|
|
68
|
+
// the band never starts left of the pane.
|
|
69
|
+
const float frac_reach = style.width_frac > 0.f ? style.width_frac * candle_right
|
|
70
|
+
: candle_right;
|
|
71
|
+
const float px_reach = style.width_px > 0.f ? style.width_px : candle_right;
|
|
72
|
+
const float reach = std::min(px_reach, frac_reach);
|
|
73
|
+
const float left_x = std::max(0.f, candle_right - reach);
|
|
74
|
+
|
|
75
|
+
// Volume that maps to peak opacity: explicit, or the largest band's volume.
|
|
76
|
+
double max_vol = style.max_volume;
|
|
77
|
+
if (max_vol <= 0.0) {
|
|
78
|
+
for (const VroomBand& b : chart.bands) max_vol = std::max(max_vol, b.volume);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const float min_op = std::clamp(style.min_opacity, 0.f, 1.f);
|
|
82
|
+
const float max_op = std::clamp(style.max_opacity, 0.f, 1.f);
|
|
83
|
+
|
|
84
|
+
canvas->save();
|
|
85
|
+
canvas->clipRect(SkRect::MakeLTRB(0.f, 0.f, candle_right, candle_area_h));
|
|
86
|
+
|
|
87
|
+
const SkPoint pts[2] = {SkPoint{left_x, 0.f}, SkPoint{candle_right, 0.f}};
|
|
88
|
+
|
|
89
|
+
for (const VroomBand& b : chart.bands) {
|
|
90
|
+
// Higher price -> smaller y, so max_price is the top edge.
|
|
91
|
+
const float y_top = vroom::price_to_y(lay, bounds, b.max_price);
|
|
92
|
+
const float y_bot = vroom::price_to_y(lay, bounds, b.min_price);
|
|
93
|
+
if (y_bot < 0.f || y_top > candle_area_h) continue; // fully off-pane
|
|
94
|
+
|
|
95
|
+
const SkColor base =
|
|
96
|
+
static_cast<SkColor>(b.side == 0 ? style.buy_color : style.sell_color);
|
|
97
|
+
|
|
98
|
+
const double t = max_vol > 0.0
|
|
99
|
+
? std::clamp(b.volume / max_vol, 0.0, 1.0)
|
|
100
|
+
: 0.0;
|
|
101
|
+
const float alpha = min_op + (max_op - min_op) * static_cast<float>(t);
|
|
102
|
+
|
|
103
|
+
SkPaint paint;
|
|
104
|
+
paint.setAntiAlias(true);
|
|
105
|
+
paint.setShader(left_fade_shader(pts, base, alpha));
|
|
106
|
+
canvas->drawRect(SkRect::MakeLTRB(left_x, y_top, candle_right, y_bot), paint);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
canvas->restore();
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
} // namespace vroom::liquidity
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// Liquidity bands — resting-order / order-book depth rendered on the price pane.
|
|
2
|
+
//
|
|
3
|
+
// Each band (chart.bands) is a price interval carrying a total size on one side
|
|
4
|
+
// of the book. It is drawn as a horizontal rectangle anchored at the inner edge
|
|
5
|
+
// of the price axis (`candle_right`), stretching left by the configured reach
|
|
6
|
+
// and fading to transparent with a left->right gradient. Color comes from the
|
|
7
|
+
// band's side (buy/sell); the band's alpha comes from its volume mapped into
|
|
8
|
+
// [min_opacity, max_opacity]. Because the vertical extent is derived from price
|
|
9
|
+
// via price_to_y, bands scale with the y-axis on zoom.
|
|
10
|
+
//
|
|
11
|
+
// Like ma_overlay / drawings this is its own module so the chart orchestrator
|
|
12
|
+
// stays thin. Drawn BEHIND the candles (before candles::draw) so candle bodies
|
|
13
|
+
// paint over the bands.
|
|
14
|
+
|
|
15
|
+
#pragma once
|
|
16
|
+
|
|
17
|
+
#include "viewport.h"
|
|
18
|
+
#include "vroom/vroom_chart.h"
|
|
19
|
+
|
|
20
|
+
class SkCanvas;
|
|
21
|
+
struct VroomChart;
|
|
22
|
+
|
|
23
|
+
namespace vroom::liquidity {
|
|
24
|
+
|
|
25
|
+
// Draws the liquidity bands. `candle_right` is the x of the price-axis strip
|
|
26
|
+
// (bands' right edge); `candle_area_h` is the price-pane bottom. Geometry is
|
|
27
|
+
// clipped to that rectangle so bands never bleed into the axis strips.
|
|
28
|
+
void draw(SkCanvas* canvas,
|
|
29
|
+
const VroomChart& chart,
|
|
30
|
+
const vroom::Layout& lay,
|
|
31
|
+
const vroom::PriceBounds& bounds,
|
|
32
|
+
float candle_right,
|
|
33
|
+
float candle_area_h);
|
|
34
|
+
|
|
35
|
+
} // namespace vroom::liquidity
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
#include "include/core/SkRect.h"
|
|
11
11
|
#pragma clang diagnostic pop
|
|
12
12
|
|
|
13
|
+
#include <algorithm>
|
|
13
14
|
#include <cmath>
|
|
14
15
|
|
|
15
16
|
#include "viewport.h"
|
|
@@ -29,11 +30,14 @@ void draw(SkCanvas* canvas,
|
|
|
29
30
|
float candle_area_h,
|
|
30
31
|
uint32_t color,
|
|
31
32
|
float width,
|
|
32
|
-
const unsigned char* break_before
|
|
33
|
+
const unsigned char* break_before,
|
|
34
|
+
float opacity) {
|
|
33
35
|
if (!canvas || !values_visible || n == 0 || candle_right <= 0.f ||
|
|
34
36
|
candle_area_h <= 0.f) {
|
|
35
37
|
return;
|
|
36
38
|
}
|
|
39
|
+
opacity = std::clamp(opacity, 0.f, 1.f);
|
|
40
|
+
if (opacity <= 0.f) return;
|
|
37
41
|
|
|
38
42
|
// SkPathBuilder (not SkPath's edit methods, removed in newer Skia tips).
|
|
39
43
|
SkPathBuilder path;
|
|
@@ -59,6 +63,10 @@ void draw(SkCanvas* canvas,
|
|
|
59
63
|
SkPaint line;
|
|
60
64
|
line.setAntiAlias(true);
|
|
61
65
|
line.setColor(static_cast<SkColor>(color));
|
|
66
|
+
// Fade the line in during the candle→line morph (multiplies the color alpha).
|
|
67
|
+
if (opacity < 1.f) {
|
|
68
|
+
line.setAlphaf(line.getAlphaf() * opacity);
|
|
69
|
+
}
|
|
62
70
|
line.setStyle(SkPaint::kStroke_Style);
|
|
63
71
|
line.setStrokeWidth(width > 0.f ? width : 1.5f);
|
|
64
72
|
|
package/cpp/_core_src/theme.cpp
CHANGED
|
@@ -22,6 +22,7 @@ constexpr uint32_t kDefaultColors[VROOM_COLOR_COUNT_] = {
|
|
|
22
22
|
0x00000000, // WICK_BEAR — transparent sentinel: inherit BEAR fill
|
|
23
23
|
0xff26a69a, // ACCENT_BULL — classic teal-green (price indicator, volume, MACD)
|
|
24
24
|
0xffef5350, // ACCENT_BEAR — classic red
|
|
25
|
+
0xffc9d1d9, // LINE — line-chart close polyline; neutral foreground (AXIS_TEXT tone)
|
|
25
26
|
};
|
|
26
27
|
|
|
27
28
|
constexpr float kDefaultFloats[VROOM_FLOAT_COUNT_] = {
|
|
@@ -33,6 +34,10 @@ constexpr float kDefaultFloats[VROOM_FLOAT_COUNT_] = {
|
|
|
33
34
|
22.f, // X_AXIS_HEIGHT_PX — bottom strip for time labels
|
|
34
35
|
0.5f, // VOLUME_OPACITY — candle color at 50% transparency
|
|
35
36
|
0.20f, // INDICATOR_HEIGHT_FRAC — below-chart indicator pane = 20% of height
|
|
37
|
+
0.f, // CANDLE_RADIUS_PX — square by default
|
|
38
|
+
0.f, // WICK_ROUND_CAP — butt caps by default
|
|
39
|
+
0.f, // VOLUME_RADIUS_PX — square by default
|
|
40
|
+
1.5f, // LINE_WIDTH_PX — line-chart polyline stroke width
|
|
36
41
|
};
|
|
37
42
|
|
|
38
43
|
} // namespace
|
package/cpp/_core_src/volume.cpp
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
#pragma clang diagnostic ignored "-Wdocumentation"
|
|
5
5
|
#include "include/core/SkCanvas.h"
|
|
6
6
|
#include "include/core/SkPaint.h"
|
|
7
|
+
#include "include/core/SkRRect.h"
|
|
7
8
|
#include "include/core/SkRect.h"
|
|
8
9
|
#pragma clang diagnostic pop
|
|
9
10
|
|
|
@@ -41,6 +42,7 @@ void draw(SkCanvas* canvas,
|
|
|
41
42
|
const float half_body = body_w * 0.5f;
|
|
42
43
|
|
|
43
44
|
const float opacity = theme.floats[VROOM_FLOAT_VOLUME_OPACITY];
|
|
45
|
+
const float vol_r = theme.floats[VROOM_FLOAT_VOLUME_RADIUS_PX];
|
|
44
46
|
SkPaint bull_paint;
|
|
45
47
|
bull_paint.setAntiAlias(true);
|
|
46
48
|
bull_paint.setColor(theme.colors[VROOM_COLOR_ACCENT_BULL]);
|
|
@@ -61,9 +63,19 @@ void draw(SkCanvas* canvas,
|
|
|
61
63
|
visible_start_ms, window_ms);
|
|
62
64
|
const float h = std::max(
|
|
63
65
|
1.f, static_cast<float>(c.volume / max_vol) * region_h);
|
|
64
|
-
|
|
65
|
-
SkRect::MakeXYWH(cx - half_body, candle_area_h - h, body_w, h)
|
|
66
|
-
|
|
66
|
+
const SkRect rect =
|
|
67
|
+
SkRect::MakeXYWH(cx - half_body, candle_area_h - h, body_w, h);
|
|
68
|
+
const SkPaint& paint = bull ? bull_paint : bear_paint;
|
|
69
|
+
// Round only the top corners; clamp so short/narrow bars don't over-round.
|
|
70
|
+
const float r = std::min({vol_r, body_w * 0.5f, h});
|
|
71
|
+
if (r > 0.f) {
|
|
72
|
+
SkRRect rr;
|
|
73
|
+
const SkVector radii[4] = {{r, r}, {r, r}, {0, 0}, {0, 0}}; // TL, TR, BR, BL
|
|
74
|
+
rr.setRectRadii(rect, radii);
|
|
75
|
+
canvas->drawRRect(rr, paint);
|
|
76
|
+
} else {
|
|
77
|
+
canvas->drawRect(rect, paint);
|
|
78
|
+
}
|
|
67
79
|
}
|
|
68
80
|
}
|
|
69
81
|
|
package/lib/index.d.mts
CHANGED
|
@@ -68,14 +68,22 @@ type VroomTheme = {
|
|
|
68
68
|
accentBull?: VroomColor;
|
|
69
69
|
/** Generic down color for the price indicator, volume bars, and MACD histogram. Defaults to red; independent of `bear`. */
|
|
70
70
|
accentBear?: VroomColor;
|
|
71
|
-
/** Up candle body 1px
|
|
71
|
+
/** Up candle body border (1px, drawn *inside* the body so it never changes candle width). Omit or set to the bull fill color to hide it. */
|
|
72
72
|
borderBull?: VroomColor;
|
|
73
|
-
/** Down candle body 1px
|
|
73
|
+
/** Down candle body border (1px, drawn *inside* the body so it never changes candle width). Omit or set to the bear fill color to hide it. */
|
|
74
74
|
borderBear?: VroomColor;
|
|
75
75
|
/** Up candle wick color. Defaults to the bull fill color. */
|
|
76
76
|
wickBull?: VroomColor;
|
|
77
77
|
/** Down candle wick color. Defaults to the bear fill color. */
|
|
78
78
|
wickBear?: VroomColor;
|
|
79
|
+
/** Wick stroke width in px (applies to both up and down wicks). Defaults to 1. */
|
|
80
|
+
wickWidth?: number;
|
|
81
|
+
/** Corner radius (px) of candle bodies. Defaults to 0 (square). */
|
|
82
|
+
candleRadius?: number;
|
|
83
|
+
/** Round the wick end caps. Defaults to false. */
|
|
84
|
+
wickRoundCap?: boolean;
|
|
85
|
+
/** Corner radius (px) of the *top* of volume bars. Defaults to 0 (square). */
|
|
86
|
+
volumeRadius?: number;
|
|
79
87
|
/** Gridlines. */
|
|
80
88
|
grid?: VroomColor;
|
|
81
89
|
/** Axis label text (price + time). */
|
|
@@ -84,6 +92,10 @@ type VroomTheme = {
|
|
|
84
92
|
crosshair?: VroomColor;
|
|
85
93
|
/** Crosshair target — the hollow ring/dot at the intersection. */
|
|
86
94
|
crosshairTarget?: VroomColor;
|
|
95
|
+
/** Line-chart-mode close polyline color. Defaults to a neutral foreground. */
|
|
96
|
+
lineColor?: VroomColor;
|
|
97
|
+
/** Line-chart-mode polyline stroke width in px. Defaults to 1.5. */
|
|
98
|
+
lineWidth?: number;
|
|
87
99
|
};
|
|
88
100
|
/** A time window over the candle data, as Unix epoch milliseconds. */
|
|
89
101
|
type VisibleRange = {
|
|
@@ -98,8 +110,15 @@ type VisibleRange = {
|
|
|
98
110
|
* 'draw' — left-clicks place drawing points; panning/zooming are suppressed.
|
|
99
111
|
*/
|
|
100
112
|
type ChartMode = 'pan' | 'draw';
|
|
113
|
+
/**
|
|
114
|
+
* How the price series is drawn.
|
|
115
|
+
* 'candles' — default: candlestick bodies + wicks.
|
|
116
|
+
* 'line' — a single polyline through each candle's close. Volume, indicators,
|
|
117
|
+
* overlays, crosshair, and drawings still render.
|
|
118
|
+
*/
|
|
119
|
+
type ChartType = 'candles' | 'line';
|
|
101
120
|
/** Active drawing tool while in `draw` mode. `null` draws nothing. */
|
|
102
|
-
type DrawTool = null | 'line';
|
|
121
|
+
type DrawTool = null | 'line' | 'box' | 'pencil';
|
|
103
122
|
/** A drawing anchor in data space, so it stays glued to the candles on pan/zoom. */
|
|
104
123
|
type DrawPoint = {
|
|
105
124
|
/** Anchor time as Unix epoch milliseconds (not snapped to a candle slot). */
|
|
@@ -107,23 +126,81 @@ type DrawPoint = {
|
|
|
107
126
|
/** Anchor price. */
|
|
108
127
|
price: number;
|
|
109
128
|
};
|
|
110
|
-
/**
|
|
111
|
-
|
|
112
|
-
* persisted annotations; the chart appends a new one (via `onDrawingComplete`)
|
|
113
|
-
* each time the user finishes drawing. For now only the `'line'` (two-point
|
|
114
|
-
* trendline) type exists.
|
|
115
|
-
*/
|
|
116
|
-
type Drawing = {
|
|
129
|
+
/** Fields shared by every drawing type. */
|
|
130
|
+
type DrawingBase = {
|
|
117
131
|
/** Stable unique id (the chart generates one for drawings it creates). */
|
|
118
132
|
id: string;
|
|
119
|
-
|
|
120
|
-
/** The two endpoints, in data space. */
|
|
121
|
-
points: [DrawPoint, DrawPoint];
|
|
122
|
-
/** Line color (hex string or packed ARGB number). Default solid blue. */
|
|
133
|
+
/** Stroke color (hex string or packed ARGB number). Default solid blue. */
|
|
123
134
|
color?: VroomColor;
|
|
124
135
|
/** Stroke width in px. Default 2. */
|
|
125
136
|
width?: number;
|
|
126
137
|
};
|
|
138
|
+
/** A two-point trendline from `points[0]` to `points[1]`. */
|
|
139
|
+
type LineDrawing = DrawingBase & {
|
|
140
|
+
type: 'line';
|
|
141
|
+
/** The two endpoints, in data space. */
|
|
142
|
+
points: [DrawPoint, DrawPoint];
|
|
143
|
+
};
|
|
144
|
+
/**
|
|
145
|
+
* An axis-aligned rectangle whose two opposite corners are `points[0]` and
|
|
146
|
+
* `points[1]` (the other two corners are derived).
|
|
147
|
+
*/
|
|
148
|
+
type BoxDrawing = DrawingBase & {
|
|
149
|
+
type: 'box';
|
|
150
|
+
/** Two opposite corners, in data space. */
|
|
151
|
+
points: [DrawPoint, DrawPoint];
|
|
152
|
+
};
|
|
153
|
+
/**
|
|
154
|
+
* A freehand pencil stroke: an open path through `points`, in order. Unlike the
|
|
155
|
+
* other tools a stroke has a variable number of points, and once committed it
|
|
156
|
+
* can only be translated — never reshaped.
|
|
157
|
+
*/
|
|
158
|
+
type PencilDrawing = DrawingBase & {
|
|
159
|
+
type: 'pencil';
|
|
160
|
+
/** The path's points in draw order (at least 2), in data space. */
|
|
161
|
+
points: DrawPoint[];
|
|
162
|
+
};
|
|
163
|
+
/**
|
|
164
|
+
* A committed drawing. Pass an array of these via the `drawings` prop to render
|
|
165
|
+
* persisted annotations; the chart appends a new one (via `onDrawingComplete`)
|
|
166
|
+
* each time the user finishes drawing.
|
|
167
|
+
*
|
|
168
|
+
* 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
|
|
170
|
+
* `'line'` and `'box'` are always exactly two points.
|
|
171
|
+
*/
|
|
172
|
+
type Drawing = LineDrawing | BoxDrawing | PencilDrawing;
|
|
173
|
+
/**
|
|
174
|
+
* Storage adapter for **managed** drawing persistence. Provide it via the
|
|
175
|
+
* `drawingStore` prop and the chart owns the drawings array itself — loading and
|
|
176
|
+
* saving through this adapter instead of you wiring the controlled `drawings`
|
|
177
|
+
* prop + `onDrawing*` callbacks.
|
|
178
|
+
*
|
|
179
|
+
* The adapter is an **opaque string key-value store** — the chart serializes
|
|
180
|
+
* drawings into a **versioned envelope** (`{ v, drawings }`) and hands you the
|
|
181
|
+
* string; you just persist bytes. Because the library owns the schema and
|
|
182
|
+
* migrates old payloads on load, adding drawing tools or persisted fields later
|
|
183
|
+
* never changes this interface — your adapter is written once.
|
|
184
|
+
*
|
|
185
|
+
* `marketId` is the chart's `seriesKey`, so drawings are bucketed per market:
|
|
186
|
+
* they persist across timeframe changes (same key) but not across markets. Both
|
|
187
|
+
* methods may be async (localStorage is sync; AsyncStorage / MMKV / a REST
|
|
188
|
+
* backend are async). The chart debounces `save`. Consumers that only handle a
|
|
189
|
+
* single market can ignore `marketId`.
|
|
190
|
+
*/
|
|
191
|
+
type DrawingStore = {
|
|
192
|
+
/**
|
|
193
|
+
* Return the raw string previously handed to `save` for `marketId`, or
|
|
194
|
+
* `null`/`undefined`/`''` if nothing is stored. Sync or async.
|
|
195
|
+
*/
|
|
196
|
+
load: (marketId: string) => string | null | undefined | Promise<string | null | undefined>;
|
|
197
|
+
/**
|
|
198
|
+
* Persist the opaque `data` string for `marketId`. Sync or async; the chart
|
|
199
|
+
* debounces calls. The string is a versioned envelope owned by the library —
|
|
200
|
+
* store it verbatim, don't parse or reshape it.
|
|
201
|
+
*/
|
|
202
|
+
save: (marketId: string, data: string) => void | Promise<void>;
|
|
203
|
+
};
|
|
127
204
|
/** RSI indicator config. Rendered in a pane below the candles when enabled. */
|
|
128
205
|
type RSIConfig = {
|
|
129
206
|
enabled?: boolean;
|
|
@@ -169,6 +246,51 @@ type VWAPConfig = {
|
|
|
169
246
|
/** Stroke width in px. Default 1.5. */
|
|
170
247
|
width?: number;
|
|
171
248
|
};
|
|
249
|
+
/**
|
|
250
|
+
* A single resting-liquidity band: a price interval carrying a total order size
|
|
251
|
+
* on one side of the book. Consolidate raw L2 levels into these buckets before
|
|
252
|
+
* passing them. The vertical extent is defined in price space, so bands scale
|
|
253
|
+
* with the y-axis on zoom.
|
|
254
|
+
*/
|
|
255
|
+
type LiquidityBand = {
|
|
256
|
+
/** Bottom of the price interval. */
|
|
257
|
+
minPrice: number;
|
|
258
|
+
/** Top of the price interval. A per-level order uses a thin interval. */
|
|
259
|
+
maxPrice: number;
|
|
260
|
+
/** Which side of the book — selects the buy vs sell color. */
|
|
261
|
+
side: 'buy' | 'sell';
|
|
262
|
+
/** Total resting size in this band; drives the band's opacity. */
|
|
263
|
+
volume: number;
|
|
264
|
+
};
|
|
265
|
+
/**
|
|
266
|
+
* Resting-order / order-book liquidity overlay. Each band is drawn as a
|
|
267
|
+
* horizontal rectangle anchored at the inner edge of the price axis, stretching
|
|
268
|
+
* left (~`widthPx`/`widthFrac` of the pane) and fading out with a gradient,
|
|
269
|
+
* colored by side and made more opaque with volume. Rendered behind the candles.
|
|
270
|
+
* Omit the prop (or pass no bands) to hide the overlay.
|
|
271
|
+
*/
|
|
272
|
+
type LiquidityConfig = {
|
|
273
|
+
/** The bands to render. */
|
|
274
|
+
bands: LiquidityBand[];
|
|
275
|
+
/** Buy-side color (hex string or packed ARGB number). Default teal-green. */
|
|
276
|
+
buyColor?: VroomColor;
|
|
277
|
+
/** Sell-side color (hex string or packed ARGB number). Default red. */
|
|
278
|
+
sellColor?: VroomColor;
|
|
279
|
+
/**
|
|
280
|
+
* Volume mapped to the peak (`maxOpacity`) band. Omit to auto-scale to the
|
|
281
|
+
* largest band's volume each render.
|
|
282
|
+
*/
|
|
283
|
+
maxVolume?: number;
|
|
284
|
+
/** Opacity floor for the smallest band. Default 0.05. */
|
|
285
|
+
minOpacity?: number;
|
|
286
|
+
/** Opacity at `maxVolume`. Default 0.8. */
|
|
287
|
+
maxOpacity?: number;
|
|
288
|
+
/** Leftward reach from the axis in px. Default 300. */
|
|
289
|
+
widthPx?: number;
|
|
290
|
+
/** Leftward reach as a fraction of pane width. Default 0.25. The smaller of
|
|
291
|
+
* `widthPx` and `widthFrac * paneWidth` is used. */
|
|
292
|
+
widthFrac?: number;
|
|
293
|
+
};
|
|
172
294
|
/** MACD indicator config. Rendered in its own pane below the candles. */
|
|
173
295
|
type MACDConfig = {
|
|
174
296
|
enabled?: boolean;
|
|
@@ -204,6 +326,26 @@ type VroomChartCoreProps = {
|
|
|
204
326
|
height?: number;
|
|
205
327
|
/** Time window to render. Omit (or both 0) to show every candle. */
|
|
206
328
|
visibleRange?: VisibleRange;
|
|
329
|
+
/**
|
|
330
|
+
* Target candle *body* width in logical px for the INITIAL framing. Larger →
|
|
331
|
+
* more zoomed in (fewer candles); smaller → more zoomed out. Only affects
|
|
332
|
+
* first load / reset; an explicit `visibleRange` takes precedence. Omit for
|
|
333
|
+
* the default (~80 candles). Useful to keep candles a consistent size across
|
|
334
|
+
* devices of different widths.
|
|
335
|
+
*/
|
|
336
|
+
defaultCandleWidth?: number;
|
|
337
|
+
/**
|
|
338
|
+
* Price-series render style. `'candles'` (default) draws candlesticks;
|
|
339
|
+
* `'line'` draws a polyline through each candle's close (style it with
|
|
340
|
+
* `theme.lineColor` / `theme.lineWidth`). All other layers are unaffected.
|
|
341
|
+
*/
|
|
342
|
+
chartType?: ChartType;
|
|
343
|
+
/**
|
|
344
|
+
* Duration (ms) of the animated candle↔line transition when `chartType`
|
|
345
|
+
* changes. Default ~300. `0` snaps instantly. Ignored (snaps) when the OS
|
|
346
|
+
* requests reduced motion, which instead uses a plain cross-fade.
|
|
347
|
+
*/
|
|
348
|
+
transitionMs?: number;
|
|
207
349
|
theme?: VroomTheme;
|
|
208
350
|
/** RSI indicator (pane below the candles). Omit/disable to hide it. */
|
|
209
351
|
rsi?: RSIConfig;
|
|
@@ -213,6 +355,8 @@ type VroomChartCoreProps = {
|
|
|
213
355
|
movingAverages?: MovingAverageOverlay[];
|
|
214
356
|
/** VWAP overlay (session anchor, configurable reset). */
|
|
215
357
|
vwap?: VWAPConfig;
|
|
358
|
+
/** Resting-order / order-book liquidity bands drawn behind the candles. */
|
|
359
|
+
liquidity?: LiquidityConfig;
|
|
216
360
|
/**
|
|
217
361
|
* Pixels the crosshair dot / horizontal line sit *above* the touch point so
|
|
218
362
|
* they aren't hidden under the thumb. The vertical line stays centered on the
|
|
@@ -243,10 +387,30 @@ type VroomChartCoreProps = {
|
|
|
243
387
|
* Committed drawings to render, anchored to data so they track the candles on
|
|
244
388
|
* pan/zoom. This is a controlled prop: append the value the chart hands you in
|
|
245
389
|
* `onDrawingComplete` to persist it.
|
|
390
|
+
*
|
|
391
|
+
* Ignored when `drawingStore` is set (the chart then owns the array itself).
|
|
246
392
|
*/
|
|
247
393
|
drawings?: Drawing[];
|
|
394
|
+
/**
|
|
395
|
+
* Opt into **managed** drawing persistence: the chart owns the drawings array
|
|
396
|
+
* internally and loads/saves it through this adapter, keyed by `seriesKey`.
|
|
397
|
+
* When set, `drawings` and the `onDrawing*` callbacks are ignored. Web only.
|
|
398
|
+
* Requires `seriesKey` — without one, drawings work in-session but aren't saved.
|
|
399
|
+
*/
|
|
400
|
+
drawingStore?: DrawingStore;
|
|
248
401
|
/** Fired with the finished drawing when the user completes one. */
|
|
249
402
|
onDrawingComplete?: (drawing: Drawing) => void;
|
|
403
|
+
/**
|
|
404
|
+
* Fired after the user drags a selected line's endpoint handle. The payload is
|
|
405
|
+
* the same drawing (same `id`) with updated `points`; apply it to your
|
|
406
|
+
* controlled `drawings` state (replace by id). Web only.
|
|
407
|
+
*/
|
|
408
|
+
onDrawingChange?: (drawing: Drawing) => void;
|
|
409
|
+
/**
|
|
410
|
+
* Fired when the user deletes the selected line (Backspace/Delete). Remove the
|
|
411
|
+
* drawing with this `id` from your controlled `drawings` state. Web only.
|
|
412
|
+
*/
|
|
413
|
+
onDrawingDelete?: (id: string) => void;
|
|
250
414
|
/**
|
|
251
415
|
* Fired when the chart wants the mode changed — e.g. it requests `'pan'` after
|
|
252
416
|
* the user clicks away from a just-drawn line. Since `mode` is controlled, the
|
|
@@ -286,4 +450,4 @@ declare global {
|
|
|
286
450
|
*/
|
|
287
451
|
declare function VroomChart(props: VroomChartProps): React.JSX.Element;
|
|
288
452
|
|
|
289
|
-
export { type Candle, type CrosshairEvent, type MACDConfig, type MASource, type MovingAverageOverlay, type RSIConfig, type VWAPConfig, type VisibleRange, VroomChart, type VroomChartProps, type VroomColor, type VroomTheme };
|
|
453
|
+
export { type Candle, type ChartType, type CrosshairEvent, type MACDConfig, type MASource, type MovingAverageOverlay, type RSIConfig, type VWAPConfig, type VisibleRange, VroomChart, type VroomChartProps, type VroomColor, type VroomTheme };
|