react-native-vroom-chart 0.1.1 → 0.1.3
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/_core_include/vroom/vroom_chart.h +85 -0
- package/cpp/_core_src/candles.cpp +33 -7
- package/cpp/_core_src/chart.cpp +8 -2
- package/cpp/_core_src/chart.h +31 -4
- package/cpp/_core_src/chart_facade.cpp +217 -37
- package/cpp/_core_src/drawings.cpp +108 -0
- package/cpp/_core_src/drawings.h +34 -0
- package/cpp/_core_src/labels.cpp +1 -1
- package/cpp/_core_src/macd_pane.cpp +6 -3
- package/cpp/_core_src/price_indicator.cpp +1 -1
- package/cpp/_core_src/rsi_pane.cpp +6 -1
- package/cpp/_core_src/theme.cpp +6 -0
- package/cpp/_core_src/viewport.cpp +33 -0
- package/cpp/_core_src/viewport.h +24 -0
- package/cpp/_core_src/volume.cpp +2 -2
- package/lib/index.d.mts +75 -2
- package/lib/index.d.ts +75 -2
- package/lib/index.js +13 -1
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +13 -1
- package/lib/index.mjs.map +1 -1
- package/package.json +11 -10
- package/src/theme.ts +6 -0
- package/LICENSE +0 -21
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
#include "drawings.h"
|
|
2
|
+
|
|
3
|
+
#pragma clang diagnostic push
|
|
4
|
+
#pragma clang diagnostic ignored "-Wdocumentation"
|
|
5
|
+
#include "include/core/SkCanvas.h"
|
|
6
|
+
#include "include/core/SkColor.h"
|
|
7
|
+
#include "include/core/SkPaint.h"
|
|
8
|
+
#include "include/core/SkPoint.h"
|
|
9
|
+
#include "include/core/SkRect.h"
|
|
10
|
+
#pragma clang diagnostic pop
|
|
11
|
+
|
|
12
|
+
#include "chart.h"
|
|
13
|
+
|
|
14
|
+
namespace vroom::drawings {
|
|
15
|
+
|
|
16
|
+
namespace {
|
|
17
|
+
// Node-dot styling (fixed for v1, not themed): a 4px black dot with a 2px blue
|
|
18
|
+
// ring around it. kNodeFillRadius is the black core; the blue stroke is centered
|
|
19
|
+
// at kNodeRingRadius so it sits just outside the core.
|
|
20
|
+
constexpr SkColor kNodeFill = 0xff000000; // black core
|
|
21
|
+
constexpr SkColor kNodeBorder = 0xff2962ff; // blue ring
|
|
22
|
+
constexpr float kNodeFillRadius = 2.f; // 4px diameter
|
|
23
|
+
constexpr float kNodeBorderWidth = 2.f;
|
|
24
|
+
constexpr float kNodeRingRadius = 3.f; // ring centered outside the core
|
|
25
|
+
|
|
26
|
+
// Maps a data-space point to pixels in the price pane.
|
|
27
|
+
SkPoint to_px(const VroomChart& chart, const Layout& lay, const PriceBounds& bounds,
|
|
28
|
+
int64_t window_ms, const VroomDrawPoint& p) {
|
|
29
|
+
const float x = vroom::x_at_time(lay, chart.visible_start_ms, window_ms, p.time_ms);
|
|
30
|
+
const float y = vroom::price_to_y(lay, bounds, p.price);
|
|
31
|
+
return SkPoint{x, y};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
void draw_node(SkCanvas* canvas, SkPoint pt) {
|
|
35
|
+
SkPaint fill;
|
|
36
|
+
fill.setAntiAlias(true);
|
|
37
|
+
fill.setColor(kNodeFill);
|
|
38
|
+
canvas->drawCircle(pt.fX, pt.fY, kNodeFillRadius, fill);
|
|
39
|
+
|
|
40
|
+
SkPaint border;
|
|
41
|
+
border.setAntiAlias(true);
|
|
42
|
+
border.setColor(kNodeBorder);
|
|
43
|
+
border.setStyle(SkPaint::kStroke_Style);
|
|
44
|
+
border.setStrokeWidth(kNodeBorderWidth);
|
|
45
|
+
canvas->drawCircle(pt.fX, pt.fY, kNodeRingRadius, border);
|
|
46
|
+
}
|
|
47
|
+
} // namespace
|
|
48
|
+
|
|
49
|
+
void draw(SkCanvas* canvas,
|
|
50
|
+
const VroomChart& chart,
|
|
51
|
+
const Layout& lay,
|
|
52
|
+
const PriceBounds& bounds,
|
|
53
|
+
float candle_right,
|
|
54
|
+
float candle_area_h) {
|
|
55
|
+
if (!canvas || candle_right <= 0.f || candle_area_h <= 0.f) return;
|
|
56
|
+
const int64_t window_ms = chart.visible_end_ms - chart.visible_start_ms;
|
|
57
|
+
if (window_ms <= 0) return;
|
|
58
|
+
|
|
59
|
+
const SkRect clip = SkRect::MakeLTRB(0.f, 0.f, candle_right, candle_area_h);
|
|
60
|
+
|
|
61
|
+
// 1. Committed line segments, clipped to the candle area.
|
|
62
|
+
if (!chart.drawings.empty()) {
|
|
63
|
+
canvas->save();
|
|
64
|
+
canvas->clipRect(clip);
|
|
65
|
+
for (const VroomDrawing& d : chart.drawings) {
|
|
66
|
+
const SkPoint a = to_px(chart, lay, bounds, window_ms, d.a);
|
|
67
|
+
const SkPoint b = to_px(chart, lay, bounds, window_ms, d.b);
|
|
68
|
+
SkPaint line;
|
|
69
|
+
line.setAntiAlias(true);
|
|
70
|
+
line.setColor(static_cast<SkColor>(d.color));
|
|
71
|
+
line.setStyle(SkPaint::kStroke_Style);
|
|
72
|
+
line.setStrokeWidth(d.width > 0.f ? d.width : 2.f);
|
|
73
|
+
canvas->drawLine(a, b, line);
|
|
74
|
+
}
|
|
75
|
+
canvas->restore();
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (!chart.draft_active) return;
|
|
79
|
+
|
|
80
|
+
const SkPoint a = to_px(chart, lay, bounds, window_ms, chart.draft_a);
|
|
81
|
+
const bool has_b = chart.draft_has_b;
|
|
82
|
+
const SkPoint b =
|
|
83
|
+
has_b ? to_px(chart, lay, bounds, window_ms, chart.draft_b) : a;
|
|
84
|
+
|
|
85
|
+
// 2. Guideline preview (A->B), clipped to the candle area. Only while the
|
|
86
|
+
// second point is still being placed (draft_guide); once committed, the
|
|
87
|
+
// solid segment comes from chart.drawings instead.
|
|
88
|
+
if (chart.draft_guide && has_b) {
|
|
89
|
+
canvas->save();
|
|
90
|
+
canvas->clipRect(clip);
|
|
91
|
+
SkPaint guide;
|
|
92
|
+
guide.setAntiAlias(true);
|
|
93
|
+
guide.setColor(static_cast<SkColor>(chart.draft_color));
|
|
94
|
+
guide.setStyle(SkPaint::kStroke_Style);
|
|
95
|
+
guide.setStrokeWidth(chart.draft_width > 0.f ? chart.draft_width : 2.f);
|
|
96
|
+
canvas->drawLine(a, b, guide);
|
|
97
|
+
canvas->restore();
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// 3. Node dots on top (not clipped, so an edge dot still renders fully).
|
|
101
|
+
// While guiding (placing the second point) only the anchor dot shows; the
|
|
102
|
+
// moving end is conveyed by the guideline. Once selected (committed) both
|
|
103
|
+
// endpoints show dots.
|
|
104
|
+
draw_node(canvas, a);
|
|
105
|
+
if (has_b && !chart.draft_guide) draw_node(canvas, b);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
} // namespace vroom::drawings
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// Drawing annotations — user-placed line tools rendered on the price pane.
|
|
2
|
+
//
|
|
3
|
+
// Two kinds of geometry are drawn here:
|
|
4
|
+
// * Committed lines (chart.drawings) — two-point trendlines anchored in data
|
|
5
|
+
// space, so they stay glued to the candles as the user pans/zooms.
|
|
6
|
+
// * The transient "draft" (chart.draft_*) — the in-progress node dots and the
|
|
7
|
+
// live guideline shown while the user is placing a line.
|
|
8
|
+
//
|
|
9
|
+
// Like ma_overlay / crosshair this is its own module so the chart orchestrator
|
|
10
|
+
// stays thin. Drawn after the overlays and before the axis backgrounds.
|
|
11
|
+
|
|
12
|
+
#pragma once
|
|
13
|
+
|
|
14
|
+
#include "viewport.h"
|
|
15
|
+
#include "vroom/vroom_chart.h"
|
|
16
|
+
|
|
17
|
+
class SkCanvas;
|
|
18
|
+
struct VroomChart;
|
|
19
|
+
|
|
20
|
+
namespace vroom::drawings {
|
|
21
|
+
|
|
22
|
+
// Draws the committed line drawings and the in-progress draft. `candle_right` is
|
|
23
|
+
// the x of the y-axis strip and `candle_area_h` the price-pane bottom; geometry
|
|
24
|
+
// is clipped to that rectangle so lines never bleed into the axis strips or the
|
|
25
|
+
// indicator panes below. Node dots are exempt from the clip so a dot placed at
|
|
26
|
+
// the very edge still renders fully.
|
|
27
|
+
void draw(SkCanvas* canvas,
|
|
28
|
+
const VroomChart& chart,
|
|
29
|
+
const vroom::Layout& lay,
|
|
30
|
+
const vroom::PriceBounds& bounds,
|
|
31
|
+
float candle_right,
|
|
32
|
+
float candle_area_h);
|
|
33
|
+
|
|
34
|
+
} // namespace vroom::drawings
|
package/cpp/_core_src/labels.cpp
CHANGED
|
@@ -318,7 +318,7 @@ void recompute_axis_width(VroomChart& chart) {
|
|
|
318
318
|
return;
|
|
319
319
|
}
|
|
320
320
|
double hi, lo;
|
|
321
|
-
if (chart.
|
|
321
|
+
if (chart.price_bounds_manual) {
|
|
322
322
|
hi = chart.price_bounds.max;
|
|
323
323
|
lo = chart.price_bounds.min;
|
|
324
324
|
} else if (!chart.candles.empty()) {
|
|
@@ -52,7 +52,10 @@ void draw(SkCanvas* canvas,
|
|
|
52
52
|
if (band_h <= 0.f) return;
|
|
53
53
|
|
|
54
54
|
const float mid = (pane_top + pane_bottom) * 0.5f;
|
|
55
|
-
|
|
55
|
+
// User y-zoom scales the amplitude about the zero line (mid). 1.0 = the
|
|
56
|
+
// default auto-fit; >1 zooms in, <1 zooms out.
|
|
57
|
+
const float half =
|
|
58
|
+
band_h * 0.5f * kPadFrac * static_cast<float>(chart.macd_y_scale);
|
|
56
59
|
|
|
57
60
|
// Auto-scale symmetric about zero across all visible finite values.
|
|
58
61
|
double scale = 0.0;
|
|
@@ -100,8 +103,8 @@ void draw(SkCanvas* canvas,
|
|
|
100
103
|
vroom::candle_body_width(lay, window_ms, candle_duration_ms);
|
|
101
104
|
const float half_body = body_w * 0.5f;
|
|
102
105
|
const float zero_y = y_for(0.0);
|
|
103
|
-
const SkColor bull = chart.theme.colors[
|
|
104
|
-
const SkColor bear = chart.theme.colors[
|
|
106
|
+
const SkColor bull = chart.theme.colors[VROOM_COLOR_ACCENT_BULL];
|
|
107
|
+
const SkColor bear = chart.theme.colors[VROOM_COLOR_ACCENT_BEAR];
|
|
105
108
|
for (std::size_t i = 0; i < n; ++i) {
|
|
106
109
|
const double h = hist_visible[i];
|
|
107
110
|
if (!std::isfinite(h)) continue;
|
|
@@ -43,7 +43,7 @@ void draw(SkCanvas* canvas,
|
|
|
43
43
|
const ::VroomCandle& last = chart.candles.back();
|
|
44
44
|
const bool bull = last.close >= last.open;
|
|
45
45
|
const SkColor color =
|
|
46
|
-
chart.theme.colors[bull ?
|
|
46
|
+
chart.theme.colors[bull ? VROOM_COLOR_ACCENT_BULL : VROOM_COLOR_ACCENT_BEAR];
|
|
47
47
|
|
|
48
48
|
const float y = vroom::price_to_y(lay, bounds, last.close);
|
|
49
49
|
if (y < 0.f || y > candle_area_h) return; // price scrolled off-range
|
|
@@ -50,8 +50,13 @@ void draw(SkCanvas* canvas,
|
|
|
50
50
|
const float band_h = pane_bottom - pane_top;
|
|
51
51
|
if (band_h <= 0.f) return;
|
|
52
52
|
|
|
53
|
+
// Map 0..100 about the pane center so the user y-zoom scales symmetrically
|
|
54
|
+
// around 50. z == 1 reproduces the default fit (0 -> pane_bottom, 100 ->
|
|
55
|
+
// pane_top); z > 1 zooms in (taller), z < 1 zooms out (flatter).
|
|
56
|
+
const float center_y = (pane_top + pane_bottom) * 0.5f;
|
|
57
|
+
const float z = static_cast<float>(chart.rsi_y_scale);
|
|
53
58
|
auto y_for = [&](double v) -> float {
|
|
54
|
-
return
|
|
59
|
+
return center_y - static_cast<float>((v - 50.0) / 100.0) * band_h * z;
|
|
55
60
|
};
|
|
56
61
|
|
|
57
62
|
// Mask the band with the background so candles/volume that overflow below
|
package/cpp/_core_src/theme.cpp
CHANGED
|
@@ -16,6 +16,12 @@ constexpr uint32_t kDefaultColors[VROOM_COLOR_COUNT_] = {
|
|
|
16
16
|
0xff161b22, // TOOLTIP_BG
|
|
17
17
|
0xffc9d1d9, // TOOLTIP_TEXT
|
|
18
18
|
0xff3e4855, // CROSSHAIR_TARGET — CROSSHAIR lightened 30% (prior derived ring)
|
|
19
|
+
0x00000000, // BORDER_BULL — transparent sentinel: inherit BULL fill
|
|
20
|
+
0x00000000, // BORDER_BEAR — transparent sentinel: inherit BEAR fill
|
|
21
|
+
0x00000000, // WICK_BULL — transparent sentinel: inherit BULL fill
|
|
22
|
+
0x00000000, // WICK_BEAR — transparent sentinel: inherit BEAR fill
|
|
23
|
+
0xff26a69a, // ACCENT_BULL — classic teal-green (price indicator, volume, MACD)
|
|
24
|
+
0xffef5350, // ACCENT_BEAR — classic red
|
|
19
25
|
};
|
|
20
26
|
|
|
21
27
|
constexpr float kDefaultFloats[VROOM_FLOAT_COUNT_] = {
|
|
@@ -35,6 +35,31 @@ float candle_center_x(const Layout& layout,
|
|
|
35
35
|
return static_cast<float>(static_cast<double>(usable) * frac);
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
+
int64_t time_at_x(const Layout& layout,
|
|
39
|
+
int64_t visible_start_ms,
|
|
40
|
+
int64_t window_ms,
|
|
41
|
+
float x_px) {
|
|
42
|
+
const float usable =
|
|
43
|
+
layout.width_px - layout.y_axis_width_px - layout.right_padding_px;
|
|
44
|
+
if (usable <= 0.f || window_ms <= 0) return visible_start_ms;
|
|
45
|
+
const double frac = static_cast<double>(x_px) / static_cast<double>(usable);
|
|
46
|
+
return visible_start_ms +
|
|
47
|
+
static_cast<int64_t>(std::llround(frac * static_cast<double>(window_ms)));
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
float x_at_time(const Layout& layout,
|
|
51
|
+
int64_t visible_start_ms,
|
|
52
|
+
int64_t window_ms,
|
|
53
|
+
int64_t time_ms) {
|
|
54
|
+
if (window_ms <= 0) return 0.f;
|
|
55
|
+
const float usable =
|
|
56
|
+
layout.width_px - layout.y_axis_width_px - layout.right_padding_px;
|
|
57
|
+
const double frac =
|
|
58
|
+
static_cast<double>(time_ms - visible_start_ms) /
|
|
59
|
+
static_cast<double>(window_ms);
|
|
60
|
+
return static_cast<float>(static_cast<double>(usable) * frac);
|
|
61
|
+
}
|
|
62
|
+
|
|
38
63
|
size_t snap_index_to_candle(const Layout& layout,
|
|
39
64
|
const ::VroomCandle* candles,
|
|
40
65
|
size_t count,
|
|
@@ -180,6 +205,14 @@ PriceBounds price_bounds(const ::VroomCandle* candles, size_t count) {
|
|
|
180
205
|
return b;
|
|
181
206
|
}
|
|
182
207
|
|
|
208
|
+
PriceBounds auto_price_bounds(const ::VroomCandle* candles, size_t count) {
|
|
209
|
+
PriceBounds b = price_bounds(candles, count);
|
|
210
|
+
if (count == 0) return b;
|
|
211
|
+
const double mid = (b.min + b.max) * 0.5;
|
|
212
|
+
const double half = (b.max - b.min) * 0.5 * kAutoYZoom;
|
|
213
|
+
return {mid - half, mid + half};
|
|
214
|
+
}
|
|
215
|
+
|
|
183
216
|
float price_to_y(const Layout& layout,
|
|
184
217
|
const PriceBounds& bounds,
|
|
185
218
|
double price) {
|
package/cpp/_core_src/viewport.h
CHANGED
|
@@ -113,9 +113,33 @@ float snap_x_to_candle(const Layout& layout,
|
|
|
113
113
|
int64_t window_ms,
|
|
114
114
|
float x_px);
|
|
115
115
|
|
|
116
|
+
// Free (non-snapped, non-candle-centered) mapping between time and pixel x,
|
|
117
|
+
// used for drawing-tool endpoints that can sit anywhere — not just on a candle
|
|
118
|
+
// slot. `x_at_time` is the exact inverse of `time_at_x`:
|
|
119
|
+
// frac = (time - start) / window; x = usable * frac
|
|
120
|
+
// where `usable` is the candle area width (width - y-axis - right padding).
|
|
121
|
+
// Returns 0 / visible_start_ms respectively for a degenerate window/usable.
|
|
122
|
+
int64_t time_at_x(const Layout& layout,
|
|
123
|
+
int64_t visible_start_ms,
|
|
124
|
+
int64_t window_ms,
|
|
125
|
+
float x_px);
|
|
126
|
+
float x_at_time(const Layout& layout,
|
|
127
|
+
int64_t visible_start_ms,
|
|
128
|
+
int64_t window_ms,
|
|
129
|
+
int64_t time_ms);
|
|
130
|
+
|
|
116
131
|
// Min/max of (low..high) across the given range.
|
|
117
132
|
PriceBounds price_bounds(const ::VroomCandle* candles, size_t count);
|
|
118
133
|
|
|
134
|
+
// Widening applied to auto-fit price bounds so candles keep some headroom
|
|
135
|
+
// instead of touching the pane edges. 1.0 = snug; larger = wider.
|
|
136
|
+
constexpr double kAutoYZoom = 1.5;
|
|
137
|
+
|
|
138
|
+
// price_bounds() widened about its midpoint by kAutoYZoom. This is the y-range
|
|
139
|
+
// used whenever the price scale is in auto (follow-the-data) mode. Returns the
|
|
140
|
+
// {0, 1} sentinel when count == 0 (callers keep their previous bounds).
|
|
141
|
+
PriceBounds auto_price_bounds(const ::VroomCandle* candles, size_t count);
|
|
142
|
+
|
|
119
143
|
// Map a price to y in pixels. y=0 is top of the chart.
|
|
120
144
|
float price_to_y(const Layout& layout, const PriceBounds& bounds, double price);
|
|
121
145
|
|
package/cpp/_core_src/volume.cpp
CHANGED
|
@@ -43,12 +43,12 @@ void draw(SkCanvas* canvas,
|
|
|
43
43
|
const float opacity = theme.floats[VROOM_FLOAT_VOLUME_OPACITY];
|
|
44
44
|
SkPaint bull_paint;
|
|
45
45
|
bull_paint.setAntiAlias(true);
|
|
46
|
-
bull_paint.setColor(theme.colors[
|
|
46
|
+
bull_paint.setColor(theme.colors[VROOM_COLOR_ACCENT_BULL]);
|
|
47
47
|
bull_paint.setAlphaf(opacity);
|
|
48
48
|
|
|
49
49
|
SkPaint bear_paint;
|
|
50
50
|
bear_paint.setAntiAlias(true);
|
|
51
|
-
bear_paint.setColor(theme.colors[
|
|
51
|
+
bear_paint.setColor(theme.colors[VROOM_COLOR_ACCENT_BEAR]);
|
|
52
52
|
bear_paint.setAlphaf(opacity);
|
|
53
53
|
|
|
54
54
|
for (std::size_t i = 0; i < n; ++i) {
|
package/lib/index.d.mts
CHANGED
|
@@ -52,10 +52,22 @@ type VroomColor = string | number;
|
|
|
52
52
|
type VroomTheme = {
|
|
53
53
|
/** Chart + axis-strip background. */
|
|
54
54
|
background?: VroomColor;
|
|
55
|
-
/** Up
|
|
55
|
+
/** Up candle body fill. Wick and border default to this unless overridden. */
|
|
56
56
|
bull?: VroomColor;
|
|
57
|
-
/** Down
|
|
57
|
+
/** Down candle body fill. Wick and border default to this unless overridden. */
|
|
58
58
|
bear?: VroomColor;
|
|
59
|
+
/** Generic up color for the price indicator, volume bars, and MACD histogram. Defaults to teal-green; independent of `bull`. */
|
|
60
|
+
accentBull?: VroomColor;
|
|
61
|
+
/** Generic down color for the price indicator, volume bars, and MACD histogram. Defaults to red; independent of `bear`. */
|
|
62
|
+
accentBear?: VroomColor;
|
|
63
|
+
/** Up candle body 1px border. Defaults to the bull fill color. */
|
|
64
|
+
borderBull?: VroomColor;
|
|
65
|
+
/** Down candle body 1px border. Defaults to the bear fill color. */
|
|
66
|
+
borderBear?: VroomColor;
|
|
67
|
+
/** Up candle wick color. Defaults to the bull fill color. */
|
|
68
|
+
wickBull?: VroomColor;
|
|
69
|
+
/** Down candle wick color. Defaults to the bear fill color. */
|
|
70
|
+
wickBear?: VroomColor;
|
|
59
71
|
/** Gridlines. */
|
|
60
72
|
grid?: VroomColor;
|
|
61
73
|
/** Axis label text (price + time). */
|
|
@@ -72,6 +84,38 @@ type VisibleRange = {
|
|
|
72
84
|
/** Window end (inclusive), Unix epoch milliseconds. */
|
|
73
85
|
endMs: number;
|
|
74
86
|
};
|
|
87
|
+
/**
|
|
88
|
+
* Chart interaction mode.
|
|
89
|
+
* 'pan' — default: drag to pan, pinch/wheel to zoom, hover/long-press crosshair.
|
|
90
|
+
* 'draw' — left-clicks place drawing points; panning/zooming are suppressed.
|
|
91
|
+
*/
|
|
92
|
+
type ChartMode = 'pan' | 'draw';
|
|
93
|
+
/** Active drawing tool while in `draw` mode. `null` draws nothing. */
|
|
94
|
+
type DrawTool = null | 'line';
|
|
95
|
+
/** A drawing anchor in data space, so it stays glued to the candles on pan/zoom. */
|
|
96
|
+
type DrawPoint = {
|
|
97
|
+
/** Anchor time as Unix epoch milliseconds (not snapped to a candle slot). */
|
|
98
|
+
timeMs: number;
|
|
99
|
+
/** Anchor price. */
|
|
100
|
+
price: number;
|
|
101
|
+
};
|
|
102
|
+
/**
|
|
103
|
+
* A committed drawing. Pass an array of these via the `drawings` prop to render
|
|
104
|
+
* persisted annotations; the chart appends a new one (via `onDrawingComplete`)
|
|
105
|
+
* each time the user finishes drawing. For now only the `'line'` (two-point
|
|
106
|
+
* trendline) type exists.
|
|
107
|
+
*/
|
|
108
|
+
type Drawing = {
|
|
109
|
+
/** Stable unique id (the chart generates one for drawings it creates). */
|
|
110
|
+
id: string;
|
|
111
|
+
type: 'line';
|
|
112
|
+
/** The two endpoints, in data space. */
|
|
113
|
+
points: [DrawPoint, DrawPoint];
|
|
114
|
+
/** Line color (hex string or packed ARGB number). Default solid blue. */
|
|
115
|
+
color?: VroomColor;
|
|
116
|
+
/** Stroke width in px. Default 2. */
|
|
117
|
+
width?: number;
|
|
118
|
+
};
|
|
75
119
|
/** RSI indicator config. Rendered in a pane below the candles when enabled. */
|
|
76
120
|
type RSIConfig = {
|
|
77
121
|
enabled?: boolean;
|
|
@@ -135,6 +179,14 @@ type MACDConfig = {
|
|
|
135
179
|
type VroomChartCoreProps = {
|
|
136
180
|
/** OHLCV bars to render. The only required prop. */
|
|
137
181
|
candles: Candle[];
|
|
182
|
+
/**
|
|
183
|
+
* Identity of the data series (e.g. "BTC-USD"). When it changes between
|
|
184
|
+
* renders the chart resets to the default view (most recent candles + price
|
|
185
|
+
* auto-fit), regardless of what the data heuristics conclude — the escape
|
|
186
|
+
* hatch for ambiguous switches like two assets trading at similar prices.
|
|
187
|
+
* Omit to rely on automatic detection from the candle data alone.
|
|
188
|
+
*/
|
|
189
|
+
seriesKey?: string;
|
|
138
190
|
/**
|
|
139
191
|
* Explicit size overrides in logical px. When omitted, the chart fills its
|
|
140
192
|
* parent (measured at runtime). Prefer layout-driven sizing via the
|
|
@@ -159,6 +211,27 @@ type VroomChartCoreProps = {
|
|
|
159
211
|
* touch x. Default 40.
|
|
160
212
|
*/
|
|
161
213
|
crosshairOffset?: number;
|
|
214
|
+
/**
|
|
215
|
+
* Interaction mode. Default `'pan'`. Set to `'draw'` (with a `tool`) to let
|
|
216
|
+
* the user place drawing points; panning/zooming are suppressed while drawing.
|
|
217
|
+
*/
|
|
218
|
+
mode?: ChartMode;
|
|
219
|
+
/** Active drawing tool while in `draw` mode. Default `null` (draws nothing). */
|
|
220
|
+
tool?: DrawTool;
|
|
221
|
+
/**
|
|
222
|
+
* Committed drawings to render, anchored to data so they track the candles on
|
|
223
|
+
* pan/zoom. This is a controlled prop: append the value the chart hands you in
|
|
224
|
+
* `onDrawingComplete` to persist it.
|
|
225
|
+
*/
|
|
226
|
+
drawings?: Drawing[];
|
|
227
|
+
/** Fired with the finished drawing when the user completes one. */
|
|
228
|
+
onDrawingComplete?: (drawing: Drawing) => void;
|
|
229
|
+
/**
|
|
230
|
+
* Fired when the chart wants the mode changed — e.g. it requests `'pan'` after
|
|
231
|
+
* the user clicks away from a just-drawn line. Since `mode` is controlled, the
|
|
232
|
+
* host should apply the requested mode.
|
|
233
|
+
*/
|
|
234
|
+
onModeChange?: (mode: ChartMode) => void;
|
|
162
235
|
onCrosshair?: (e: CrosshairEvent) => void;
|
|
163
236
|
onViewportChange?: (startMs: number, endMs: number) => void;
|
|
164
237
|
};
|
package/lib/index.d.ts
CHANGED
|
@@ -52,10 +52,22 @@ type VroomColor = string | number;
|
|
|
52
52
|
type VroomTheme = {
|
|
53
53
|
/** Chart + axis-strip background. */
|
|
54
54
|
background?: VroomColor;
|
|
55
|
-
/** Up
|
|
55
|
+
/** Up candle body fill. Wick and border default to this unless overridden. */
|
|
56
56
|
bull?: VroomColor;
|
|
57
|
-
/** Down
|
|
57
|
+
/** Down candle body fill. Wick and border default to this unless overridden. */
|
|
58
58
|
bear?: VroomColor;
|
|
59
|
+
/** Generic up color for the price indicator, volume bars, and MACD histogram. Defaults to teal-green; independent of `bull`. */
|
|
60
|
+
accentBull?: VroomColor;
|
|
61
|
+
/** Generic down color for the price indicator, volume bars, and MACD histogram. Defaults to red; independent of `bear`. */
|
|
62
|
+
accentBear?: VroomColor;
|
|
63
|
+
/** Up candle body 1px border. Defaults to the bull fill color. */
|
|
64
|
+
borderBull?: VroomColor;
|
|
65
|
+
/** Down candle body 1px border. Defaults to the bear fill color. */
|
|
66
|
+
borderBear?: VroomColor;
|
|
67
|
+
/** Up candle wick color. Defaults to the bull fill color. */
|
|
68
|
+
wickBull?: VroomColor;
|
|
69
|
+
/** Down candle wick color. Defaults to the bear fill color. */
|
|
70
|
+
wickBear?: VroomColor;
|
|
59
71
|
/** Gridlines. */
|
|
60
72
|
grid?: VroomColor;
|
|
61
73
|
/** Axis label text (price + time). */
|
|
@@ -72,6 +84,38 @@ type VisibleRange = {
|
|
|
72
84
|
/** Window end (inclusive), Unix epoch milliseconds. */
|
|
73
85
|
endMs: number;
|
|
74
86
|
};
|
|
87
|
+
/**
|
|
88
|
+
* Chart interaction mode.
|
|
89
|
+
* 'pan' — default: drag to pan, pinch/wheel to zoom, hover/long-press crosshair.
|
|
90
|
+
* 'draw' — left-clicks place drawing points; panning/zooming are suppressed.
|
|
91
|
+
*/
|
|
92
|
+
type ChartMode = 'pan' | 'draw';
|
|
93
|
+
/** Active drawing tool while in `draw` mode. `null` draws nothing. */
|
|
94
|
+
type DrawTool = null | 'line';
|
|
95
|
+
/** A drawing anchor in data space, so it stays glued to the candles on pan/zoom. */
|
|
96
|
+
type DrawPoint = {
|
|
97
|
+
/** Anchor time as Unix epoch milliseconds (not snapped to a candle slot). */
|
|
98
|
+
timeMs: number;
|
|
99
|
+
/** Anchor price. */
|
|
100
|
+
price: number;
|
|
101
|
+
};
|
|
102
|
+
/**
|
|
103
|
+
* A committed drawing. Pass an array of these via the `drawings` prop to render
|
|
104
|
+
* persisted annotations; the chart appends a new one (via `onDrawingComplete`)
|
|
105
|
+
* each time the user finishes drawing. For now only the `'line'` (two-point
|
|
106
|
+
* trendline) type exists.
|
|
107
|
+
*/
|
|
108
|
+
type Drawing = {
|
|
109
|
+
/** Stable unique id (the chart generates one for drawings it creates). */
|
|
110
|
+
id: string;
|
|
111
|
+
type: 'line';
|
|
112
|
+
/** The two endpoints, in data space. */
|
|
113
|
+
points: [DrawPoint, DrawPoint];
|
|
114
|
+
/** Line color (hex string or packed ARGB number). Default solid blue. */
|
|
115
|
+
color?: VroomColor;
|
|
116
|
+
/** Stroke width in px. Default 2. */
|
|
117
|
+
width?: number;
|
|
118
|
+
};
|
|
75
119
|
/** RSI indicator config. Rendered in a pane below the candles when enabled. */
|
|
76
120
|
type RSIConfig = {
|
|
77
121
|
enabled?: boolean;
|
|
@@ -135,6 +179,14 @@ type MACDConfig = {
|
|
|
135
179
|
type VroomChartCoreProps = {
|
|
136
180
|
/** OHLCV bars to render. The only required prop. */
|
|
137
181
|
candles: Candle[];
|
|
182
|
+
/**
|
|
183
|
+
* Identity of the data series (e.g. "BTC-USD"). When it changes between
|
|
184
|
+
* renders the chart resets to the default view (most recent candles + price
|
|
185
|
+
* auto-fit), regardless of what the data heuristics conclude — the escape
|
|
186
|
+
* hatch for ambiguous switches like two assets trading at similar prices.
|
|
187
|
+
* Omit to rely on automatic detection from the candle data alone.
|
|
188
|
+
*/
|
|
189
|
+
seriesKey?: string;
|
|
138
190
|
/**
|
|
139
191
|
* Explicit size overrides in logical px. When omitted, the chart fills its
|
|
140
192
|
* parent (measured at runtime). Prefer layout-driven sizing via the
|
|
@@ -159,6 +211,27 @@ type VroomChartCoreProps = {
|
|
|
159
211
|
* touch x. Default 40.
|
|
160
212
|
*/
|
|
161
213
|
crosshairOffset?: number;
|
|
214
|
+
/**
|
|
215
|
+
* Interaction mode. Default `'pan'`. Set to `'draw'` (with a `tool`) to let
|
|
216
|
+
* the user place drawing points; panning/zooming are suppressed while drawing.
|
|
217
|
+
*/
|
|
218
|
+
mode?: ChartMode;
|
|
219
|
+
/** Active drawing tool while in `draw` mode. Default `null` (draws nothing). */
|
|
220
|
+
tool?: DrawTool;
|
|
221
|
+
/**
|
|
222
|
+
* Committed drawings to render, anchored to data so they track the candles on
|
|
223
|
+
* pan/zoom. This is a controlled prop: append the value the chart hands you in
|
|
224
|
+
* `onDrawingComplete` to persist it.
|
|
225
|
+
*/
|
|
226
|
+
drawings?: Drawing[];
|
|
227
|
+
/** Fired with the finished drawing when the user completes one. */
|
|
228
|
+
onDrawingComplete?: (drawing: Drawing) => void;
|
|
229
|
+
/**
|
|
230
|
+
* Fired when the chart wants the mode changed — e.g. it requests `'pan'` after
|
|
231
|
+
* the user clicks away from a just-drawn line. Since `mode` is controlled, the
|
|
232
|
+
* host should apply the requested mode.
|
|
233
|
+
*/
|
|
234
|
+
onModeChange?: (mode: ChartMode) => void;
|
|
162
235
|
onCrosshair?: (e: CrosshairEvent) => void;
|
|
163
236
|
onViewportChange?: (startMs: number, endMs: number) => void;
|
|
164
237
|
};
|
package/lib/index.js
CHANGED
|
@@ -80,8 +80,20 @@ var COLOR_KEYS = {
|
|
|
80
80
|
// VROOM_COLOR_AXIS_TEXT
|
|
81
81
|
crosshair: 6,
|
|
82
82
|
// VROOM_COLOR_CROSSHAIR
|
|
83
|
-
crosshairTarget: 9
|
|
83
|
+
crosshairTarget: 9,
|
|
84
84
|
// VROOM_COLOR_CROSSHAIR_TARGET
|
|
85
|
+
borderBull: 10,
|
|
86
|
+
// VROOM_COLOR_BORDER_BULL
|
|
87
|
+
borderBear: 11,
|
|
88
|
+
// VROOM_COLOR_BORDER_BEAR
|
|
89
|
+
wickBull: 12,
|
|
90
|
+
// VROOM_COLOR_WICK_BULL
|
|
91
|
+
wickBear: 13,
|
|
92
|
+
// VROOM_COLOR_WICK_BEAR
|
|
93
|
+
accentBull: 14,
|
|
94
|
+
// VROOM_COLOR_ACCENT_BULL
|
|
95
|
+
accentBear: 15
|
|
96
|
+
// VROOM_COLOR_ACCENT_BEAR
|
|
85
97
|
};
|
|
86
98
|
function parseColor(value) {
|
|
87
99
|
if (typeof value === "number") {
|