react-native-vroom-chart 0.11.0 → 0.12.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 +22 -0
- package/cpp/_core_include/vroom/vroom_chart.h +46 -2
- package/cpp/_core_src/chart.cpp +5 -2
- package/cpp/_core_src/chart.h +9 -0
- package/cpp/_core_src/chart_facade.cpp +36 -0
- package/cpp/_core_src/crosshair.cpp +10 -5
- package/cpp/_core_src/drawing_bounds.h +70 -0
- package/cpp/_core_src/drawings.cpp +60 -11
- package/cpp/_core_src/drawings.h +15 -0
- package/cpp/_core_src/labels.cpp +7 -2
- package/cpp/_core_src/macd_pane.cpp +3 -2
- package/cpp/_core_src/price_indicator.cpp +9 -5
- package/cpp/_core_src/price_lines.cpp +9 -4
- package/cpp/_core_src/rsi_pane.cpp +3 -1
- package/cpp/_core_src/theme.cpp +2 -2
- package/cpp/_core_src/viewport.h +32 -0
- package/lib/index.d.mts +99 -7
- package/lib/index.d.ts +99 -7
- package/lib/index.js +102 -5
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +102 -5
- package/lib/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/VroomChart.tsx +129 -5
- package/src/jsi.d.ts +7 -0
- package/src/theme.ts +5 -0
package/cpp/_core_src/theme.cpp
CHANGED
|
@@ -13,8 +13,8 @@ constexpr uint32_t kDefaultColors[VROOM_COLOR_COUNT_] = {
|
|
|
13
13
|
0xff1a1e24, // GRID — ~20% darker than the crosshair so it recedes
|
|
14
14
|
0xffc9d1d9, // AXIS_TEXT
|
|
15
15
|
0xff303741, // CROSSHAIR — grid tone lightened ~44%; reads above GRID
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
0x00000000, // RESERVED_7_ — retired slot, never read
|
|
17
|
+
0xffffffff, // BADGE_TEXT — text on filled badges/pills
|
|
18
18
|
0xff3e4855, // CROSSHAIR_TARGET — CROSSHAIR lightened 30% (prior derived ring)
|
|
19
19
|
0x00000000, // BORDER_BULL — transparent sentinel: inherit BULL fill
|
|
20
20
|
0x00000000, // BORDER_BEAR — transparent sentinel: inherit BEAR fill
|
package/cpp/_core_src/viewport.h
CHANGED
|
@@ -20,8 +20,40 @@ struct Layout {
|
|
|
20
20
|
float top_padding_frac; // fraction of candle area; keeps prices off edges
|
|
21
21
|
float bottom_padding_frac;
|
|
22
22
|
float indicator_area_h; // height reserved for below-chart indicator panes
|
|
23
|
+
// Opacity of everything drawn *inside* an axis strip, 1 = shown, 0 = hidden.
|
|
24
|
+
// Separate from the strip's extent because the two ramp at different rates
|
|
25
|
+
// while an axis is being hidden or revealed (see axis_opacity).
|
|
26
|
+
float y_axis_opacity;
|
|
27
|
+
float x_axis_opacity;
|
|
23
28
|
};
|
|
24
29
|
|
|
30
|
+
// --- Axis show/hide ---------------------------------------------------------
|
|
31
|
+
// An axis is hidden by collapsing its strip to nothing rather than by zeroing
|
|
32
|
+
// the underlying dimension: the y-axis width is *measured* from the widest price
|
|
33
|
+
// label (labels::recompute_axis_width) and gets recomputed constantly, so a zero
|
|
34
|
+
// written there would not survive. `t` is the collapse progress the host eases,
|
|
35
|
+
// 0 = fully shown, 1 = fully hidden.
|
|
36
|
+
|
|
37
|
+
inline float clamp_collapse(float t) {
|
|
38
|
+
return t < 0.f ? 0.f : (t > 1.f ? 1.f : t);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// The strip's on-screen extent. Everything downstream (candle_area_width,
|
|
42
|
+
// price_pane_bottom) is derived from this, so the plot reclaims the space as
|
|
43
|
+
// the strip shrinks.
|
|
44
|
+
inline float axis_extent(float base, float t) {
|
|
45
|
+
return base * (1.f - clamp_collapse(t));
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Opacity of the strip's contents. Deliberately front-loaded: the labels are
|
|
49
|
+
// fully gone by the time the strip is halfway collapsed, so text never sits in
|
|
50
|
+
// a strip too narrow to hold it.
|
|
51
|
+
inline float axis_opacity(float t) {
|
|
52
|
+
constexpr float kFadeBy = 0.5f; // fraction of the collapse spent fading
|
|
53
|
+
const float p = clamp_collapse(t) / kFadeBy;
|
|
54
|
+
return p >= 1.f ? 0.f : 1.f - p;
|
|
55
|
+
}
|
|
56
|
+
|
|
25
57
|
// Bottom of the price (candle) pane = top of the indicator band. Shrinks when
|
|
26
58
|
// an indicator pane is present so candles, volume, and price labels reflow.
|
|
27
59
|
inline float price_pane_bottom(const Layout& l) {
|
package/lib/index.d.mts
CHANGED
|
@@ -93,6 +93,13 @@ type VroomTheme = {
|
|
|
93
93
|
grid?: VroomColor;
|
|
94
94
|
/** Axis label text (price + time). */
|
|
95
95
|
axisText?: VroomColor;
|
|
96
|
+
/**
|
|
97
|
+
* Text drawn on a filled badge — the current-price indicator, the crosshair's
|
|
98
|
+
* price and time badges, and price-line pills. Defaults to white, which reads
|
|
99
|
+
* against the saturated fills those badges use on a dark theme; light themes
|
|
100
|
+
* generally want a dark value here.
|
|
101
|
+
*/
|
|
102
|
+
badgeText?: VroomColor;
|
|
96
103
|
/** Crosshair dashed lines. */
|
|
97
104
|
crosshair?: VroomColor;
|
|
98
105
|
/** Crosshair target — the hollow ring/dot at the intersection. */
|
|
@@ -134,6 +141,26 @@ type VroomTheme = {
|
|
|
134
141
|
* continuously — leave it off for charts that should be able to go idle.
|
|
135
142
|
*/
|
|
136
143
|
lineTipPulse?: boolean;
|
|
144
|
+
/**
|
|
145
|
+
* Show the price (y) axis strip down the right edge. Defaults to `true`.
|
|
146
|
+
*
|
|
147
|
+
* Hiding it collapses the strip and hands the reclaimed width to the plot, so
|
|
148
|
+
* the candles widen to fill it. Its contents — price labels, the current-price
|
|
149
|
+
* badge, the crosshair price badge, price-line axis badges — fade out ahead of
|
|
150
|
+
* the collapse; gridlines and the price indicator's dotted line stay. Animated
|
|
151
|
+
* over `transitionMs` unless the OS asks for reduced motion.
|
|
152
|
+
*
|
|
153
|
+
* The axis drag-to-scale region goes with the strip, so a hidden axis can't be
|
|
154
|
+
* scaled by dragging it.
|
|
155
|
+
*/
|
|
156
|
+
showYAxis?: boolean;
|
|
157
|
+
/**
|
|
158
|
+
* Show the time (x) axis strip along the bottom. Defaults to `true`.
|
|
159
|
+
*
|
|
160
|
+
* Behaves like {@link VroomTheme.showYAxis}: the strip collapses, the plot
|
|
161
|
+
* grows into it, and the time labels and crosshair time badge fade first.
|
|
162
|
+
*/
|
|
163
|
+
showXAxis?: boolean;
|
|
137
164
|
};
|
|
138
165
|
/** A time window over the candle data, as Unix epoch milliseconds. */
|
|
139
166
|
type VisibleRange = {
|
|
@@ -177,6 +204,12 @@ type DrawingBase = {
|
|
|
177
204
|
color?: VroomColor;
|
|
178
205
|
/** Stroke width in px. Default 2. */
|
|
179
206
|
width?: number;
|
|
207
|
+
/**
|
|
208
|
+
* Protect the drawing from editing. A locked drawing still renders and can
|
|
209
|
+
* still be selected — so a toolbar can offer to unlock it — but it can't be
|
|
210
|
+
* dragged, reshaped or deleted, and its grab handles aren't drawn. Web only.
|
|
211
|
+
*/
|
|
212
|
+
locked?: boolean;
|
|
180
213
|
};
|
|
181
214
|
/** A two-point trendline from `points[0]` to `points[1]`. */
|
|
182
215
|
type LineDrawing = DrawingBase & {
|
|
@@ -192,6 +225,15 @@ type BoxDrawing = DrawingBase & {
|
|
|
192
225
|
type: 'box';
|
|
193
226
|
/** Two opposite corners, in data space. */
|
|
194
227
|
points: [DrawPoint, DrawPoint];
|
|
228
|
+
/**
|
|
229
|
+
* Interior fill, painted beneath the stroke. Omitted, the interior keeps its
|
|
230
|
+
* default tint of the stroke color at 10% alpha.
|
|
231
|
+
*
|
|
232
|
+
* A solid fill hides the candles the box was drawn around, so this usually
|
|
233
|
+
* wants an alpha — as the high byte of an 8-digit hex (`'#5400ce2c'` is a
|
|
234
|
+
* green at 33%), since vroom reads hex as `#aarrggbb`, not CSS `#rrggbbaa`.
|
|
235
|
+
*/
|
|
236
|
+
fill?: VroomColor;
|
|
195
237
|
};
|
|
196
238
|
/**
|
|
197
239
|
* A freehand pencil stroke: an open path through `points`, in order. Unlike the
|
|
@@ -224,6 +266,35 @@ type PathDrawing = DrawingBase & {
|
|
|
224
266
|
* `'line'` and `'box'` are always exactly two points.
|
|
225
267
|
*/
|
|
226
268
|
type Drawing = LineDrawing | BoxDrawing | PencilDrawing | PathDrawing;
|
|
269
|
+
/** An axis-aligned rectangle in CSS px, relative to the chart container. */
|
|
270
|
+
type DrawingRect = {
|
|
271
|
+
x: number;
|
|
272
|
+
y: number;
|
|
273
|
+
width: number;
|
|
274
|
+
height: number;
|
|
275
|
+
};
|
|
276
|
+
/** The currently selected drawing and where it sits on screen. */
|
|
277
|
+
type DrawingSelection = {
|
|
278
|
+
/**
|
|
279
|
+
* The selected drawing. While a drag or reshape is in flight this holds the
|
|
280
|
+
* last committed geometry — the edit reaches you through `onDrawingChange`
|
|
281
|
+
* on release — whereas `rect` tracks the shape live.
|
|
282
|
+
*/
|
|
283
|
+
drawing: Drawing;
|
|
284
|
+
/** The drawing's bounds in CSS px, relative to the chart container. */
|
|
285
|
+
rect: DrawingRect;
|
|
286
|
+
};
|
|
287
|
+
/**
|
|
288
|
+
* The subset of a drawing's appearance a host can change after the fact,
|
|
289
|
+
* through `restyle`. Fields left out are kept as they were.
|
|
290
|
+
*/
|
|
291
|
+
type DrawingStyle = {
|
|
292
|
+
color?: VroomColor;
|
|
293
|
+
width?: number;
|
|
294
|
+
/** Box interior fill; ignored by the other drawing types. */
|
|
295
|
+
fill?: VroomColor;
|
|
296
|
+
locked?: boolean;
|
|
297
|
+
};
|
|
227
298
|
/**
|
|
228
299
|
* Storage adapter for **managed** drawing persistence. Provide it via the
|
|
229
300
|
* `drawingStore` prop and the chart owns the drawings array itself — loading and
|
|
@@ -264,11 +335,11 @@ type UndoRedoState = {
|
|
|
264
335
|
canRedo: boolean;
|
|
265
336
|
};
|
|
266
337
|
/**
|
|
267
|
-
* Programmatic
|
|
268
|
-
* managed mode — for toolbar buttons and other UI outside
|
|
269
|
-
* keyboard shortcuts (⌘Z / ⇧⌘Z / Ctrl+Y) work without this.
|
|
338
|
+
* Programmatic controls over the chart's drawings, published through the
|
|
339
|
+
* `historyRef` prop in managed mode — for toolbar buttons and other UI outside
|
|
340
|
+
* the chart. The keyboard shortcuts (⌘Z / ⇧⌘Z / Ctrl+Y) work without this.
|
|
270
341
|
*/
|
|
271
|
-
type
|
|
342
|
+
type DrawingControls = {
|
|
272
343
|
/** Roll back the most recent committed drawing action. No-op when empty. */
|
|
273
344
|
undo: () => void;
|
|
274
345
|
/** Re-apply the most recently undone action. No-op when empty. */
|
|
@@ -279,6 +350,16 @@ type UndoRedoControls = {
|
|
|
279
350
|
* chart for what the user perceives as a brand-new context.
|
|
280
351
|
*/
|
|
281
352
|
clearHistory: () => void;
|
|
353
|
+
/**
|
|
354
|
+
* Restyle the drawing with this `id`, merging `patch` over its current
|
|
355
|
+
* appearance. No-op for an unknown id.
|
|
356
|
+
*
|
|
357
|
+
* In managed mode the chart owns the drawings array, so this is the only way
|
|
358
|
+
* to say "this drawing's color is now X" — the array is otherwise mutated by
|
|
359
|
+
* user gestures alone. The change records an undo step and persists like any
|
|
360
|
+
* other edit.
|
|
361
|
+
*/
|
|
362
|
+
restyle: (id: string, patch: DrawingStyle) => void;
|
|
282
363
|
};
|
|
283
364
|
/** Price source for a moving average. */
|
|
284
365
|
type MASource = 'close' | 'open' | 'high' | 'low' | 'hl2' | 'hlc3' | 'ohlc4';
|
|
@@ -749,6 +830,17 @@ type VroomChartCoreProps = {
|
|
|
749
830
|
* drawing with this `id` from your controlled `drawings` state. Web only.
|
|
750
831
|
*/
|
|
751
832
|
onDrawingDelete?: (id: string) => void;
|
|
833
|
+
/**
|
|
834
|
+
* Fired when the selected drawing changes, and again whenever its position on
|
|
835
|
+
* screen moves — panning, zooming, resizing, or dragging the shape itself.
|
|
836
|
+
* `null` on deselect.
|
|
837
|
+
*
|
|
838
|
+
* Anchor a floating toolbar to `selection.rect` and it will stay attached to
|
|
839
|
+
* the drawing: the rect is recomputed from live chart state once per painted
|
|
840
|
+
* frame, so it tracks 1:1 rather than settling after the gesture. Works in
|
|
841
|
+
* both controlled and managed mode. Web only.
|
|
842
|
+
*/
|
|
843
|
+
onSelectionChange?: (selection: DrawingSelection | null) => void;
|
|
752
844
|
/**
|
|
753
845
|
* Fired when the chart wants the mode changed — e.g. it requests `'pan'` after
|
|
754
846
|
* the user clicks away from a just-drawn line. Since `mode` is controlled, the
|
|
@@ -769,13 +861,13 @@ type VroomChartCoreProps = {
|
|
|
769
861
|
*/
|
|
770
862
|
onHistoryChange?: (state: UndoRedoState) => void;
|
|
771
863
|
/**
|
|
772
|
-
* Receives programmatic `undo`/`redo`/`clearHistory` controls in
|
|
773
|
-
* (e.g. `useRef<
|
|
864
|
+
* Receives programmatic `undo`/`redo`/`clearHistory`/`restyle` controls in
|
|
865
|
+
* managed mode (e.g. `useRef<DrawingControls | null>(null)` passed here, then
|
|
774
866
|
* `historyRef.current?.undo()` from a toolbar button). Set to `null` while
|
|
775
867
|
* unmounted or when no `drawingStore` is present. Web only.
|
|
776
868
|
*/
|
|
777
869
|
historyRef?: {
|
|
778
|
-
current:
|
|
870
|
+
current: DrawingControls | null;
|
|
779
871
|
};
|
|
780
872
|
/**
|
|
781
873
|
* Fired when the user presses the undo shortcut (⌘Z / Ctrl+Z) in controlled
|
package/lib/index.d.ts
CHANGED
|
@@ -93,6 +93,13 @@ type VroomTheme = {
|
|
|
93
93
|
grid?: VroomColor;
|
|
94
94
|
/** Axis label text (price + time). */
|
|
95
95
|
axisText?: VroomColor;
|
|
96
|
+
/**
|
|
97
|
+
* Text drawn on a filled badge — the current-price indicator, the crosshair's
|
|
98
|
+
* price and time badges, and price-line pills. Defaults to white, which reads
|
|
99
|
+
* against the saturated fills those badges use on a dark theme; light themes
|
|
100
|
+
* generally want a dark value here.
|
|
101
|
+
*/
|
|
102
|
+
badgeText?: VroomColor;
|
|
96
103
|
/** Crosshair dashed lines. */
|
|
97
104
|
crosshair?: VroomColor;
|
|
98
105
|
/** Crosshair target — the hollow ring/dot at the intersection. */
|
|
@@ -134,6 +141,26 @@ type VroomTheme = {
|
|
|
134
141
|
* continuously — leave it off for charts that should be able to go idle.
|
|
135
142
|
*/
|
|
136
143
|
lineTipPulse?: boolean;
|
|
144
|
+
/**
|
|
145
|
+
* Show the price (y) axis strip down the right edge. Defaults to `true`.
|
|
146
|
+
*
|
|
147
|
+
* Hiding it collapses the strip and hands the reclaimed width to the plot, so
|
|
148
|
+
* the candles widen to fill it. Its contents — price labels, the current-price
|
|
149
|
+
* badge, the crosshair price badge, price-line axis badges — fade out ahead of
|
|
150
|
+
* the collapse; gridlines and the price indicator's dotted line stay. Animated
|
|
151
|
+
* over `transitionMs` unless the OS asks for reduced motion.
|
|
152
|
+
*
|
|
153
|
+
* The axis drag-to-scale region goes with the strip, so a hidden axis can't be
|
|
154
|
+
* scaled by dragging it.
|
|
155
|
+
*/
|
|
156
|
+
showYAxis?: boolean;
|
|
157
|
+
/**
|
|
158
|
+
* Show the time (x) axis strip along the bottom. Defaults to `true`.
|
|
159
|
+
*
|
|
160
|
+
* Behaves like {@link VroomTheme.showYAxis}: the strip collapses, the plot
|
|
161
|
+
* grows into it, and the time labels and crosshair time badge fade first.
|
|
162
|
+
*/
|
|
163
|
+
showXAxis?: boolean;
|
|
137
164
|
};
|
|
138
165
|
/** A time window over the candle data, as Unix epoch milliseconds. */
|
|
139
166
|
type VisibleRange = {
|
|
@@ -177,6 +204,12 @@ type DrawingBase = {
|
|
|
177
204
|
color?: VroomColor;
|
|
178
205
|
/** Stroke width in px. Default 2. */
|
|
179
206
|
width?: number;
|
|
207
|
+
/**
|
|
208
|
+
* Protect the drawing from editing. A locked drawing still renders and can
|
|
209
|
+
* still be selected — so a toolbar can offer to unlock it — but it can't be
|
|
210
|
+
* dragged, reshaped or deleted, and its grab handles aren't drawn. Web only.
|
|
211
|
+
*/
|
|
212
|
+
locked?: boolean;
|
|
180
213
|
};
|
|
181
214
|
/** A two-point trendline from `points[0]` to `points[1]`. */
|
|
182
215
|
type LineDrawing = DrawingBase & {
|
|
@@ -192,6 +225,15 @@ type BoxDrawing = DrawingBase & {
|
|
|
192
225
|
type: 'box';
|
|
193
226
|
/** Two opposite corners, in data space. */
|
|
194
227
|
points: [DrawPoint, DrawPoint];
|
|
228
|
+
/**
|
|
229
|
+
* Interior fill, painted beneath the stroke. Omitted, the interior keeps its
|
|
230
|
+
* default tint of the stroke color at 10% alpha.
|
|
231
|
+
*
|
|
232
|
+
* A solid fill hides the candles the box was drawn around, so this usually
|
|
233
|
+
* wants an alpha — as the high byte of an 8-digit hex (`'#5400ce2c'` is a
|
|
234
|
+
* green at 33%), since vroom reads hex as `#aarrggbb`, not CSS `#rrggbbaa`.
|
|
235
|
+
*/
|
|
236
|
+
fill?: VroomColor;
|
|
195
237
|
};
|
|
196
238
|
/**
|
|
197
239
|
* A freehand pencil stroke: an open path through `points`, in order. Unlike the
|
|
@@ -224,6 +266,35 @@ type PathDrawing = DrawingBase & {
|
|
|
224
266
|
* `'line'` and `'box'` are always exactly two points.
|
|
225
267
|
*/
|
|
226
268
|
type Drawing = LineDrawing | BoxDrawing | PencilDrawing | PathDrawing;
|
|
269
|
+
/** An axis-aligned rectangle in CSS px, relative to the chart container. */
|
|
270
|
+
type DrawingRect = {
|
|
271
|
+
x: number;
|
|
272
|
+
y: number;
|
|
273
|
+
width: number;
|
|
274
|
+
height: number;
|
|
275
|
+
};
|
|
276
|
+
/** The currently selected drawing and where it sits on screen. */
|
|
277
|
+
type DrawingSelection = {
|
|
278
|
+
/**
|
|
279
|
+
* The selected drawing. While a drag or reshape is in flight this holds the
|
|
280
|
+
* last committed geometry — the edit reaches you through `onDrawingChange`
|
|
281
|
+
* on release — whereas `rect` tracks the shape live.
|
|
282
|
+
*/
|
|
283
|
+
drawing: Drawing;
|
|
284
|
+
/** The drawing's bounds in CSS px, relative to the chart container. */
|
|
285
|
+
rect: DrawingRect;
|
|
286
|
+
};
|
|
287
|
+
/**
|
|
288
|
+
* The subset of a drawing's appearance a host can change after the fact,
|
|
289
|
+
* through `restyle`. Fields left out are kept as they were.
|
|
290
|
+
*/
|
|
291
|
+
type DrawingStyle = {
|
|
292
|
+
color?: VroomColor;
|
|
293
|
+
width?: number;
|
|
294
|
+
/** Box interior fill; ignored by the other drawing types. */
|
|
295
|
+
fill?: VroomColor;
|
|
296
|
+
locked?: boolean;
|
|
297
|
+
};
|
|
227
298
|
/**
|
|
228
299
|
* Storage adapter for **managed** drawing persistence. Provide it via the
|
|
229
300
|
* `drawingStore` prop and the chart owns the drawings array itself — loading and
|
|
@@ -264,11 +335,11 @@ type UndoRedoState = {
|
|
|
264
335
|
canRedo: boolean;
|
|
265
336
|
};
|
|
266
337
|
/**
|
|
267
|
-
* Programmatic
|
|
268
|
-
* managed mode — for toolbar buttons and other UI outside
|
|
269
|
-
* keyboard shortcuts (⌘Z / ⇧⌘Z / Ctrl+Y) work without this.
|
|
338
|
+
* Programmatic controls over the chart's drawings, published through the
|
|
339
|
+
* `historyRef` prop in managed mode — for toolbar buttons and other UI outside
|
|
340
|
+
* the chart. The keyboard shortcuts (⌘Z / ⇧⌘Z / Ctrl+Y) work without this.
|
|
270
341
|
*/
|
|
271
|
-
type
|
|
342
|
+
type DrawingControls = {
|
|
272
343
|
/** Roll back the most recent committed drawing action. No-op when empty. */
|
|
273
344
|
undo: () => void;
|
|
274
345
|
/** Re-apply the most recently undone action. No-op when empty. */
|
|
@@ -279,6 +350,16 @@ type UndoRedoControls = {
|
|
|
279
350
|
* chart for what the user perceives as a brand-new context.
|
|
280
351
|
*/
|
|
281
352
|
clearHistory: () => void;
|
|
353
|
+
/**
|
|
354
|
+
* Restyle the drawing with this `id`, merging `patch` over its current
|
|
355
|
+
* appearance. No-op for an unknown id.
|
|
356
|
+
*
|
|
357
|
+
* In managed mode the chart owns the drawings array, so this is the only way
|
|
358
|
+
* to say "this drawing's color is now X" — the array is otherwise mutated by
|
|
359
|
+
* user gestures alone. The change records an undo step and persists like any
|
|
360
|
+
* other edit.
|
|
361
|
+
*/
|
|
362
|
+
restyle: (id: string, patch: DrawingStyle) => void;
|
|
282
363
|
};
|
|
283
364
|
/** Price source for a moving average. */
|
|
284
365
|
type MASource = 'close' | 'open' | 'high' | 'low' | 'hl2' | 'hlc3' | 'ohlc4';
|
|
@@ -749,6 +830,17 @@ type VroomChartCoreProps = {
|
|
|
749
830
|
* drawing with this `id` from your controlled `drawings` state. Web only.
|
|
750
831
|
*/
|
|
751
832
|
onDrawingDelete?: (id: string) => void;
|
|
833
|
+
/**
|
|
834
|
+
* Fired when the selected drawing changes, and again whenever its position on
|
|
835
|
+
* screen moves — panning, zooming, resizing, or dragging the shape itself.
|
|
836
|
+
* `null` on deselect.
|
|
837
|
+
*
|
|
838
|
+
* Anchor a floating toolbar to `selection.rect` and it will stay attached to
|
|
839
|
+
* the drawing: the rect is recomputed from live chart state once per painted
|
|
840
|
+
* frame, so it tracks 1:1 rather than settling after the gesture. Works in
|
|
841
|
+
* both controlled and managed mode. Web only.
|
|
842
|
+
*/
|
|
843
|
+
onSelectionChange?: (selection: DrawingSelection | null) => void;
|
|
752
844
|
/**
|
|
753
845
|
* Fired when the chart wants the mode changed — e.g. it requests `'pan'` after
|
|
754
846
|
* the user clicks away from a just-drawn line. Since `mode` is controlled, the
|
|
@@ -769,13 +861,13 @@ type VroomChartCoreProps = {
|
|
|
769
861
|
*/
|
|
770
862
|
onHistoryChange?: (state: UndoRedoState) => void;
|
|
771
863
|
/**
|
|
772
|
-
* Receives programmatic `undo`/`redo`/`clearHistory` controls in
|
|
773
|
-
* (e.g. `useRef<
|
|
864
|
+
* Receives programmatic `undo`/`redo`/`clearHistory`/`restyle` controls in
|
|
865
|
+
* managed mode (e.g. `useRef<DrawingControls | null>(null)` passed here, then
|
|
774
866
|
* `historyRef.current?.undo()` from a toolbar button). Set to `null` while
|
|
775
867
|
* unmounted or when no `drawingStore` is present. Web only.
|
|
776
868
|
*/
|
|
777
869
|
historyRef?: {
|
|
778
|
-
current:
|
|
870
|
+
current: DrawingControls | null;
|
|
779
871
|
};
|
|
780
872
|
/**
|
|
781
873
|
* Fired when the user presses the undo shortcut (⌘Z / Ctrl+Z) in controlled
|
package/lib/index.js
CHANGED
|
@@ -163,6 +163,8 @@ var COLOR_KEYS = {
|
|
|
163
163
|
// VROOM_COLOR_AXIS_TEXT
|
|
164
164
|
crosshair: 6,
|
|
165
165
|
// VROOM_COLOR_CROSSHAIR
|
|
166
|
+
badgeText: 8,
|
|
167
|
+
// VROOM_COLOR_BADGE_TEXT (7 is a retired slot)
|
|
166
168
|
crosshairTarget: 9,
|
|
167
169
|
// VROOM_COLOR_CROSSHAIR_TARGET
|
|
168
170
|
borderBull: 10,
|
|
@@ -638,9 +640,13 @@ function VroomChart(props) {
|
|
|
638
640
|
handle.setChartType(target);
|
|
639
641
|
const p = handle.render();
|
|
640
642
|
if (p) pictureSV.value = p;
|
|
643
|
+
maybeStartAnim();
|
|
644
|
+
return void 0;
|
|
645
|
+
}
|
|
646
|
+
if (morphFade.current === target) {
|
|
647
|
+
maybeStartAnim();
|
|
641
648
|
return void 0;
|
|
642
649
|
}
|
|
643
|
-
if (morphFade.current === target) return void 0;
|
|
644
650
|
if (morphRaf.current != null) {
|
|
645
651
|
cancelAnimationFrame(morphRaf.current);
|
|
646
652
|
morphRaf.current = null;
|
|
@@ -651,6 +657,7 @@ function VroomChart(props) {
|
|
|
651
657
|
handle.setChartType(target);
|
|
652
658
|
const p = handle.render();
|
|
653
659
|
if (p) pictureSV.value = p;
|
|
660
|
+
maybeStartAnim();
|
|
654
661
|
return void 0;
|
|
655
662
|
}
|
|
656
663
|
const from = morphFade.current;
|
|
@@ -671,6 +678,7 @@ function VroomChart(props) {
|
|
|
671
678
|
handle.setChartType(target);
|
|
672
679
|
const q = handle.render();
|
|
673
680
|
if (q) pictureSV.value = q;
|
|
681
|
+
maybeStartAnim();
|
|
674
682
|
}
|
|
675
683
|
};
|
|
676
684
|
morphRaf.current = requestAnimationFrame(step);
|
|
@@ -680,7 +688,7 @@ function VroomChart(props) {
|
|
|
680
688
|
morphRaf.current = null;
|
|
681
689
|
}
|
|
682
690
|
};
|
|
683
|
-
}, [handle, chartType, transitionMs, reduceMotion, pictureSV]);
|
|
691
|
+
}, [handle, chartType, transitionMs, reduceMotion, pictureSV, maybeStartAnim]);
|
|
684
692
|
const volumeRaf = (0, import_react2.useRef)(null);
|
|
685
693
|
const volumeHandle = (0, import_react2.useRef)(null);
|
|
686
694
|
(0, import_react2.useEffect)(() => {
|
|
@@ -690,9 +698,13 @@ function VroomChart(props) {
|
|
|
690
698
|
if (volumeHandle.current !== handle || volumeCollapseRef.current == null) {
|
|
691
699
|
volumeHandle.current = handle;
|
|
692
700
|
volumeCollapseRef.current = { t: target, easing };
|
|
701
|
+
maybeStartAnim();
|
|
702
|
+
return void 0;
|
|
703
|
+
}
|
|
704
|
+
if (volumeCollapseRef.current.t === target) {
|
|
705
|
+
maybeStartAnim();
|
|
693
706
|
return void 0;
|
|
694
707
|
}
|
|
695
|
-
if (volumeCollapseRef.current.t === target) return void 0;
|
|
696
708
|
if (volumeRaf.current != null) {
|
|
697
709
|
cancelAnimationFrame(volumeRaf.current);
|
|
698
710
|
volumeRaf.current = null;
|
|
@@ -703,6 +715,7 @@ function VroomChart(props) {
|
|
|
703
715
|
handle.setVolumeCollapse(target, easing);
|
|
704
716
|
const p = handle.render();
|
|
705
717
|
if (p) pictureSV.value = p;
|
|
718
|
+
maybeStartAnim();
|
|
706
719
|
return void 0;
|
|
707
720
|
}
|
|
708
721
|
const from = volumeCollapseRef.current.t;
|
|
@@ -716,7 +729,12 @@ function VroomChart(props) {
|
|
|
716
729
|
handle.setVolumeCollapse(t, kind);
|
|
717
730
|
const p = handle.render();
|
|
718
731
|
if (p) pictureSV.value = p;
|
|
719
|
-
|
|
732
|
+
if (prog < 1) {
|
|
733
|
+
volumeRaf.current = requestAnimationFrame(step);
|
|
734
|
+
} else {
|
|
735
|
+
volumeRaf.current = null;
|
|
736
|
+
maybeStartAnim();
|
|
737
|
+
}
|
|
720
738
|
};
|
|
721
739
|
volumeRaf.current = requestAnimationFrame(step);
|
|
722
740
|
return () => {
|
|
@@ -725,7 +743,86 @@ function VroomChart(props) {
|
|
|
725
743
|
volumeRaf.current = null;
|
|
726
744
|
}
|
|
727
745
|
};
|
|
728
|
-
}, [
|
|
746
|
+
}, [
|
|
747
|
+
handle,
|
|
748
|
+
volume?.enabled,
|
|
749
|
+
transitionMs,
|
|
750
|
+
reduceMotion,
|
|
751
|
+
pictureSV,
|
|
752
|
+
volumeCollapseRef,
|
|
753
|
+
maybeStartAnim
|
|
754
|
+
]);
|
|
755
|
+
const axisRaf = (0, import_react2.useRef)(null);
|
|
756
|
+
const axisHandle = (0, import_react2.useRef)(null);
|
|
757
|
+
const axisCollapse = (0, import_react2.useRef)(null);
|
|
758
|
+
const showYAxis = theme?.showYAxis ?? true;
|
|
759
|
+
const showXAxis = theme?.showXAxis ?? true;
|
|
760
|
+
(0, import_react2.useEffect)(() => {
|
|
761
|
+
if (!handle) return void 0;
|
|
762
|
+
const targetY = showYAxis ? 0 : 1;
|
|
763
|
+
const targetX = showXAxis ? 0 : 1;
|
|
764
|
+
if (axisHandle.current !== handle || axisCollapse.current == null) {
|
|
765
|
+
axisHandle.current = handle;
|
|
766
|
+
axisCollapse.current = { y: targetY, x: targetX };
|
|
767
|
+
handle.setAxisCollapse(targetY, targetX);
|
|
768
|
+
const p = handle.render();
|
|
769
|
+
if (p) pictureSV.value = p;
|
|
770
|
+
maybeStartAnim();
|
|
771
|
+
return void 0;
|
|
772
|
+
}
|
|
773
|
+
const fromY = axisCollapse.current.y;
|
|
774
|
+
const fromX = axisCollapse.current.x;
|
|
775
|
+
if (fromY === targetY && fromX === targetX) {
|
|
776
|
+
maybeStartAnim();
|
|
777
|
+
return void 0;
|
|
778
|
+
}
|
|
779
|
+
if (axisRaf.current != null) {
|
|
780
|
+
cancelAnimationFrame(axisRaf.current);
|
|
781
|
+
axisRaf.current = null;
|
|
782
|
+
}
|
|
783
|
+
const dur = Math.max(0, transitionMs ?? 300);
|
|
784
|
+
if (dur === 0 || reduceMotion) {
|
|
785
|
+
axisCollapse.current = { y: targetY, x: targetX };
|
|
786
|
+
handle.setAxisCollapse(targetY, targetX);
|
|
787
|
+
const p = handle.render();
|
|
788
|
+
if (p) pictureSV.value = p;
|
|
789
|
+
maybeStartAnim();
|
|
790
|
+
return void 0;
|
|
791
|
+
}
|
|
792
|
+
let startTs = null;
|
|
793
|
+
const step = (now) => {
|
|
794
|
+
if (startTs == null) startTs = now;
|
|
795
|
+
const prog = Math.min(1, (now - startTs) / dur);
|
|
796
|
+
const e = ease(easingRef.current, prog);
|
|
797
|
+
const y = prog < 1 ? fromY + (targetY - fromY) * e : targetY;
|
|
798
|
+
const x = prog < 1 ? fromX + (targetX - fromX) * e : targetX;
|
|
799
|
+
axisCollapse.current = { y, x };
|
|
800
|
+
handle.setAxisCollapse(y, x);
|
|
801
|
+
const p = handle.render();
|
|
802
|
+
if (p) pictureSV.value = p;
|
|
803
|
+
if (prog < 1) {
|
|
804
|
+
axisRaf.current = requestAnimationFrame(step);
|
|
805
|
+
} else {
|
|
806
|
+
axisRaf.current = null;
|
|
807
|
+
maybeStartAnim();
|
|
808
|
+
}
|
|
809
|
+
};
|
|
810
|
+
axisRaf.current = requestAnimationFrame(step);
|
|
811
|
+
return () => {
|
|
812
|
+
if (axisRaf.current != null) {
|
|
813
|
+
cancelAnimationFrame(axisRaf.current);
|
|
814
|
+
axisRaf.current = null;
|
|
815
|
+
}
|
|
816
|
+
};
|
|
817
|
+
}, [
|
|
818
|
+
handle,
|
|
819
|
+
showYAxis,
|
|
820
|
+
showXAxis,
|
|
821
|
+
transitionMs,
|
|
822
|
+
reduceMotion,
|
|
823
|
+
pictureSV,
|
|
824
|
+
maybeStartAnim
|
|
825
|
+
]);
|
|
729
826
|
const hitAxis = (0, import_react2.useCallback)(
|
|
730
827
|
(x, y) => {
|
|
731
828
|
if (!handle) return "chart";
|