react-native-vroom-chart 0.6.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cpp/VroomChartHostObject.cpp +281 -33
- package/cpp/_core_include/vroom/vroom_chart.h +231 -36
- package/cpp/_core_src/bollinger.h +1 -1
- package/cpp/_core_src/candles.cpp +138 -41
- package/cpp/_core_src/candles.h +11 -1
- package/cpp/_core_src/chart.cpp +91 -40
- package/cpp/_core_src/chart.h +69 -29
- package/cpp/_core_src/chart_facade.cpp +247 -69
- package/cpp/_core_src/drawings.cpp +147 -4
- package/cpp/_core_src/drawings.h +10 -5
- package/cpp/_core_src/gradient.cpp +46 -0
- package/cpp/_core_src/gradient.h +31 -0
- package/cpp/_core_src/labels.cpp +49 -16
- package/cpp/_core_src/labels.h +33 -4
- package/cpp/_core_src/liquidity.cpp +3 -37
- package/cpp/_core_src/ma_overlay.cpp +174 -12
- package/cpp/_core_src/ma_overlay.h +55 -3
- package/cpp/_core_src/macd.cpp +13 -42
- package/cpp/_core_src/macd.h +11 -8
- package/cpp/_core_src/macd_pane.cpp +57 -27
- package/cpp/_core_src/price_line_layout.h +1 -1
- package/cpp/_core_src/rsi.cpp +4 -18
- package/cpp/_core_src/rsi.h +6 -6
- package/cpp/_core_src/rsi_pane.cpp +34 -19
- package/cpp/_core_src/series_ma.cpp +64 -0
- package/cpp/_core_src/series_ma.h +30 -0
- package/cpp/_core_src/style_inherit.h +35 -0
- package/cpp/_core_src/theme.cpp +2 -1
- package/cpp/_core_src/viewport.cpp +36 -12
- package/cpp/_core_src/viewport.h +50 -0
- package/cpp/_core_src/volume.cpp +33 -8
- package/cpp/_core_src/volume.h +12 -1
- package/cpp/_core_src/volume_anim.cpp +32 -0
- package/cpp/_core_src/volume_anim.h +41 -0
- package/lib/index.d.mts +206 -31
- package/lib/index.d.ts +206 -31
- package/lib/index.js +324 -44
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +329 -52
- package/lib/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/VroomChart.tsx +100 -17
- package/src/dataTransitions.ts +148 -0
- package/src/easing.ts +40 -0
- package/src/index.ts +9 -0
- package/src/jsi.d.ts +126 -19
- package/src/theme.ts +1 -0
- package/src/types.ts +3 -0
- package/src/useChartCore.ts +273 -30
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
// Mirror of packages/react/src/dataTransitions.ts — the platform packages don't
|
|
2
|
+
// depend on each other, and @vroomchart/types carries types only.
|
|
3
|
+
//
|
|
4
|
+
// Classifies how a new `candles` prop relates to the previous one so the chart
|
|
5
|
+
// can react appropriately: leave the viewport alone for streaming updates,
|
|
6
|
+
// re-anchor the time window for a timeframe switch, or fully reset the view
|
|
7
|
+
// for a different asset. Pure functions, no React — see useChartCore for the
|
|
8
|
+
// orchestration.
|
|
9
|
+
|
|
10
|
+
import type { Candle, VisibleRange } from '@vroomchart/types';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* How a new `candles` array relates to the one the chart already holds:
|
|
14
|
+
* `'initial'` is the first data, `'stream'` a live update to the same series,
|
|
15
|
+
* `'timeframe'` the same asset re-bucketed into a different interval, and
|
|
16
|
+
* `'reset'` a different series entirely.
|
|
17
|
+
*/
|
|
18
|
+
export type DataTransition = 'initial' | 'stream' | 'timeframe' | 'reset';
|
|
19
|
+
|
|
20
|
+
// A step change below this ratio is treated as the same timeframe. Real steps
|
|
21
|
+
// are exact integer ms; the tolerance only absorbs rounding/DST quirks (the
|
|
22
|
+
// smallest real timeframe jump, 1m -> 2m, is 100% apart).
|
|
23
|
+
const STEP_TOLERANCE = 0.01;
|
|
24
|
+
|
|
25
|
+
// Same-asset check for a timeframe switch: both series end "now", so their
|
|
26
|
+
// last closes must be close. No asset moves 25% between two consecutive prop
|
|
27
|
+
// pushes; distinct assets within 25% of each other are what `seriesKey` is for.
|
|
28
|
+
const MAX_SAME_ASSET_CLOSE_RATIO = 1.25;
|
|
29
|
+
|
|
30
|
+
// A coarser bucketing can shift the final bar's open by up to one coarse bar;
|
|
31
|
+
// allow that plus an in-flight bar when checking the two series end together.
|
|
32
|
+
const MAX_END_DRIFT_STEPS = 3;
|
|
33
|
+
|
|
34
|
+
// Streaming pushes may batch a few bars (e.g. a throttled background tab), but
|
|
35
|
+
// a jump of more than this many steps means the data was re-fetched elsewhere.
|
|
36
|
+
const MAX_STREAM_ADVANCE_STEPS = 5;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* The candle period in ms, inferred as the median of the first few intervals
|
|
40
|
+
* (robust to a single gap). Null when there are fewer than two candles.
|
|
41
|
+
*/
|
|
42
|
+
export function inferStepMs(candles: Candle[]): number | null {
|
|
43
|
+
if (candles.length < 2) return null;
|
|
44
|
+
const k = Math.min(candles.length - 1, 8);
|
|
45
|
+
const diffs: number[] = [];
|
|
46
|
+
for (let i = 0; i < k; i++) diffs.push(candles[i + 1].timeMs - candles[i].timeMs);
|
|
47
|
+
diffs.sort((a, b) => a - b);
|
|
48
|
+
const median = diffs[Math.floor(diffs.length / 2)];
|
|
49
|
+
return median > 0 ? median : null;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Index of the candle whose timeMs exactly equals `t`, or -1. Binary search over
|
|
53
|
+
// the ascending-by-time series, so it tolerates interior gaps (missing bars from
|
|
54
|
+
// downtime / illiquid periods) — unlike a uniform-grid index computed from the
|
|
55
|
+
// step, which assumes a hole-free grid.
|
|
56
|
+
function indexByTime(candles: Candle[], t: number): number {
|
|
57
|
+
let lo = 0;
|
|
58
|
+
let hi = candles.length - 1;
|
|
59
|
+
while (lo <= hi) {
|
|
60
|
+
const mid = (lo + hi) >>> 1;
|
|
61
|
+
const v = candles[mid].timeMs;
|
|
62
|
+
if (v === t) return mid;
|
|
63
|
+
if (v < t) lo = mid + 1;
|
|
64
|
+
else hi = mid - 1;
|
|
65
|
+
}
|
|
66
|
+
return -1;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Classify a candles-prop change. `prev` is the previously rendered array
|
|
71
|
+
* (null on first render); `seriesKeyChanged` forces `reset` regardless of the
|
|
72
|
+
* data (the explicit escape hatch).
|
|
73
|
+
*
|
|
74
|
+
* Constraint: detection compares two immutable snapshots. An array mutated in
|
|
75
|
+
* place (same reference) never reaches this code — React props must change
|
|
76
|
+
* identity to re-render.
|
|
77
|
+
*/
|
|
78
|
+
export function classifyTransition(
|
|
79
|
+
prev: Candle[] | null,
|
|
80
|
+
next: Candle[],
|
|
81
|
+
seriesKeyChanged: boolean,
|
|
82
|
+
): DataTransition {
|
|
83
|
+
if (!prev || prev.length === 0) return 'initial';
|
|
84
|
+
if (next.length === 0) return 'stream'; // nothing to reframe against
|
|
85
|
+
if (seriesKeyChanged) return 'reset';
|
|
86
|
+
|
|
87
|
+
const prevStep = inferStepMs(prev);
|
|
88
|
+
const nextStep = inferStepMs(next);
|
|
89
|
+
if (prevStep == null || nextStep == null) return 'reset'; // too little data to reason
|
|
90
|
+
|
|
91
|
+
const prevLast = prev[prev.length - 1];
|
|
92
|
+
const nextLast = next[next.length - 1];
|
|
93
|
+
|
|
94
|
+
if (Math.abs(nextStep - prevStep) <= prevStep * STEP_TOLERANCE) {
|
|
95
|
+
// Same step: streaming iff prev's last bar still appears in next (covers
|
|
96
|
+
// append, update-last, and rolling buffers that drop old bars from the
|
|
97
|
+
// front) and the series only advanced by a few bars. Locate that bar by
|
|
98
|
+
// timestamp, not by a step-derived index — real series have interior gaps
|
|
99
|
+
// (downtime / illiquid periods), so a uniform-grid index would miss it and
|
|
100
|
+
// misread a harmless in-place tick as a reset.
|
|
101
|
+
// Time alignment alone isn't enough: two assets on the same exchange share
|
|
102
|
+
// the bar grid, so the bar at the shared timestamp must also be (nearly) the
|
|
103
|
+
// same bar — update-last moves the close, but never by the same-asset ratio.
|
|
104
|
+
const idx = indexByTime(next, prevLast.timeMs);
|
|
105
|
+
const aligned = idx >= 0;
|
|
106
|
+
const sharedBarRatio =
|
|
107
|
+
aligned && next[idx].close > 0 && prevLast.close > 0
|
|
108
|
+
? Math.max(next[idx].close / prevLast.close, prevLast.close / next[idx].close)
|
|
109
|
+
: Infinity;
|
|
110
|
+
const advanced =
|
|
111
|
+
nextLast.timeMs >= prevLast.timeMs &&
|
|
112
|
+
nextLast.timeMs - prevLast.timeMs <= MAX_STREAM_ADVANCE_STEPS * nextStep;
|
|
113
|
+
return sharedBarRatio <= MAX_SAME_ASSET_CLOSE_RATIO && advanced ? 'stream' : 'reset';
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Step changed: a timeframe switch iff it still looks like the same asset —
|
|
117
|
+
// last closes near each other and both series ending around the same time.
|
|
118
|
+
const closeRatio =
|
|
119
|
+
prevLast.close > 0 && nextLast.close > 0
|
|
120
|
+
? Math.max(nextLast.close / prevLast.close, prevLast.close / nextLast.close)
|
|
121
|
+
: Infinity;
|
|
122
|
+
const prevEnd = prevLast.timeMs + prevStep;
|
|
123
|
+
const nextEnd = nextLast.timeMs + nextStep;
|
|
124
|
+
const endsTogether =
|
|
125
|
+
Math.abs(nextEnd - prevEnd) <= MAX_END_DRIFT_STEPS * Math.max(prevStep, nextStep);
|
|
126
|
+
return closeRatio <= MAX_SAME_ASSET_CLOSE_RATIO && endsTogether ? 'timeframe' : 'reset';
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* The visible window to apply after a timeframe switch so each candle keeps
|
|
131
|
+
* the exact pixel width it had before: the visible slot count is preserved and
|
|
132
|
+
* the right edge re-anchors on the newest candle (any future-gap overshoot is
|
|
133
|
+
* carried over in slots, clamped to the core's 3/4-window cap). The new start
|
|
134
|
+
* may precede the first candle — that gap is intentional, width wins.
|
|
135
|
+
*/
|
|
136
|
+
export function timeframeWindow(
|
|
137
|
+
oldWindow: VisibleRange,
|
|
138
|
+
oldStepMs: number,
|
|
139
|
+
oldLastMs: number,
|
|
140
|
+
newStepMs: number,
|
|
141
|
+
newLastMs: number,
|
|
142
|
+
): VisibleRange {
|
|
143
|
+
const slots = (oldWindow.endMs - oldWindow.startMs) / oldStepMs;
|
|
144
|
+
const offsetRaw = (oldWindow.endMs - oldLastMs) / oldStepMs;
|
|
145
|
+
const offsetSlots = Math.min(Math.max(offsetRaw, 0), slots * 0.75);
|
|
146
|
+
const endMs = Math.round(newLastMs + offsetSlots * newStepMs);
|
|
147
|
+
return { startMs: Math.round(endMs - slots * newStepMs), endMs };
|
|
148
|
+
}
|
package/src/easing.ts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// Mirror of packages/react/src/easing.ts — the platform packages don't depend on
|
|
2
|
+
// each other, and @vroomchart/types carries types only.
|
|
3
|
+
|
|
4
|
+
import type { TransitionEasing } from '@vroomchart/types';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Maps linear animation progress (0..1) to eased progress (0..1) for the chart's
|
|
8
|
+
* transitions. Unknown values fall back to `'ease-in-out'`, which is a
|
|
9
|
+
* smoothstep — the curve the candle↔line transition has always used.
|
|
10
|
+
*/
|
|
11
|
+
export function ease(kind: TransitionEasing | undefined, p: number): number {
|
|
12
|
+
switch (kind) {
|
|
13
|
+
case 'linear':
|
|
14
|
+
return p;
|
|
15
|
+
case 'ease-in':
|
|
16
|
+
return p * p;
|
|
17
|
+
case 'ease-out':
|
|
18
|
+
return p * (2 - p);
|
|
19
|
+
default:
|
|
20
|
+
return p * p * (3 - 2 * p);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Index order matches VroomEasing in vroom_chart.h.
|
|
25
|
+
const EASINGS: readonly TransitionEasing[] = [
|
|
26
|
+
'linear',
|
|
27
|
+
'ease-in',
|
|
28
|
+
'ease-out',
|
|
29
|
+
'ease-in-out',
|
|
30
|
+
];
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* The curve as a `VroomEasing` index, for the animations the core paces itself
|
|
34
|
+
* (see `setVolumeCollapse`) rather than taking pre-eased progress. Falls back to
|
|
35
|
+
* `'ease-in-out'`, matching {@link ease}.
|
|
36
|
+
*/
|
|
37
|
+
export function easingIndex(kind: TransitionEasing | undefined): number {
|
|
38
|
+
const i = kind ? EASINGS.indexOf(kind) : -1;
|
|
39
|
+
return i < 0 ? EASINGS.indexOf('ease-in-out') : i;
|
|
40
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
export { VroomChart } from './VroomChart';
|
|
2
|
+
export {
|
|
3
|
+
classifyTransition,
|
|
4
|
+
inferStepMs,
|
|
5
|
+
timeframeWindow,
|
|
6
|
+
type DataTransition,
|
|
7
|
+
} from './dataTransitions';
|
|
2
8
|
export type {
|
|
3
9
|
VroomChartProps,
|
|
4
10
|
Candle,
|
|
@@ -9,10 +15,13 @@ export type {
|
|
|
9
15
|
RSIConfig,
|
|
10
16
|
MACDConfig,
|
|
11
17
|
MASource,
|
|
18
|
+
MAKind,
|
|
12
19
|
MovingAverageOverlay,
|
|
13
20
|
VWAPConfig,
|
|
14
21
|
BollingerBandsConfig,
|
|
22
|
+
VolumeConfig,
|
|
15
23
|
ChartType,
|
|
24
|
+
TransitionEasing,
|
|
16
25
|
PriceLine,
|
|
17
26
|
PriceLinesStyle,
|
|
18
27
|
} from './types';
|
package/src/jsi.d.ts
CHANGED
|
@@ -27,6 +27,57 @@ export interface ChartHandle {
|
|
|
27
27
|
setChartType(mode: number): void;
|
|
28
28
|
/** Candle↔line morph blend: collapse folds candles to close, fade crossfades. */
|
|
29
29
|
setMorph(collapse: number, fade: number): void;
|
|
30
|
+
/** The current visible time window. {startMs: 0, endMs: 0} = uninitialized. */
|
|
31
|
+
getVisibleRange(): { startMs: number; endMs: number };
|
|
32
|
+
/**
|
|
33
|
+
* Reset to the fresh-mount view: frame the most recent ~80 candles and
|
|
34
|
+
* re-enable continuous y auto-fit (the price range follows the visible
|
|
35
|
+
* candles until the next manual y gesture). Use when the data series is
|
|
36
|
+
* wholesale replaced — e.g. switching assets.
|
|
37
|
+
*/
|
|
38
|
+
resetView(): void;
|
|
39
|
+
/**
|
|
40
|
+
* Re-enable continuous y auto-fit only; the time window is untouched. Use
|
|
41
|
+
* after repositioning the window for a same-asset data swap (e.g. a
|
|
42
|
+
* timeframe switch) so the price scale re-fits the newly visible candles.
|
|
43
|
+
*/
|
|
44
|
+
resetPriceScale(): void;
|
|
45
|
+
/**
|
|
46
|
+
* The visible price *envelope* — the min low / max high across the currently
|
|
47
|
+
* visible candles, i.e. the extent the candles occupy rather than the (wider)
|
|
48
|
+
* axis range. Null when no candles are visible.
|
|
49
|
+
*/
|
|
50
|
+
getVisiblePriceEnvelope(): { low: number; high: number } | null;
|
|
51
|
+
/**
|
|
52
|
+
* Scale lock for a same-asset data swap that re-buckets the same price action
|
|
53
|
+
* into a different high-low span (a timeframe switch). Rescales a *manual*
|
|
54
|
+
* price range so the visible envelope keeps the exact pixel height and
|
|
55
|
+
* position the given pre-swap envelope had — so candles don't suddenly shrink
|
|
56
|
+
* or grow when the interval changes.
|
|
57
|
+
*
|
|
58
|
+
* Call after setCandles + setVisibleRange, passing the envelope read by
|
|
59
|
+
* getVisiblePriceEnvelope before the swap. A no-op in auto-y mode (auto-fit is
|
|
60
|
+
* already span-invariant); falls back to resetPriceScale when either envelope
|
|
61
|
+
* is degenerate.
|
|
62
|
+
*/
|
|
63
|
+
preservePriceEnvelope(prevLow: number, prevHigh: number): void;
|
|
64
|
+
/**
|
|
65
|
+
* Capture the visible candle geometry so the next data swap can animate as a
|
|
66
|
+
* reshape rather than a jump: each candle's wick and body slide and stretch
|
|
67
|
+
* into the shape of its counterpart in the new data.
|
|
68
|
+
*
|
|
69
|
+
* Candles are paired by *slot* — position counting back from the right edge of
|
|
70
|
+
* the visible window, which a timeframe switch preserves. Call before
|
|
71
|
+
* setCandles, then drive setIntervalMorph from 0 to 1.
|
|
72
|
+
*/
|
|
73
|
+
beginIntervalMorph(): void;
|
|
74
|
+
/**
|
|
75
|
+
* Advance the interval morph started by beginIntervalMorph. `t` (clamped to
|
|
76
|
+
* 0..1) is the eased progress: 0 renders the captured geometry pixel-
|
|
77
|
+
* identically to the pre-swap frame, 1 renders the new candles and releases
|
|
78
|
+
* the capture. Driven per-frame by the host animation loop.
|
|
79
|
+
*/
|
|
80
|
+
setIntervalMorph(t: number): void;
|
|
30
81
|
/** Shifts the visible range by `dx`/`dy` pixels and returns a fresh picture. */
|
|
31
82
|
pan(dx: number, dy: number): SkPicture | null;
|
|
32
83
|
/**
|
|
@@ -102,22 +153,53 @@ export interface ChartHandle {
|
|
|
102
153
|
} | null;
|
|
103
154
|
} | null;
|
|
104
155
|
/**
|
|
105
|
-
* Configures the RSI pane
|
|
106
|
-
*
|
|
156
|
+
* Configures the RSI pane. maKind mirrors setOverlays' kind encoding; colors
|
|
157
|
+
* are packed 0xAARRGGBB where 0 means inherit, and a non-positive width
|
|
158
|
+
* inherits the default stroke.
|
|
107
159
|
*/
|
|
108
|
-
setRSI(
|
|
109
|
-
enabled: boolean
|
|
110
|
-
period: number
|
|
111
|
-
upperBand: number
|
|
112
|
-
lowerBand: number
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
160
|
+
setRSI(spec: {
|
|
161
|
+
enabled: boolean;
|
|
162
|
+
period: number;
|
|
163
|
+
upperBand: number;
|
|
164
|
+
lowerBand: number;
|
|
165
|
+
maPeriod: number;
|
|
166
|
+
maKind: number;
|
|
167
|
+
maVisible: boolean;
|
|
168
|
+
lineColor: number;
|
|
169
|
+
lineWidth: number;
|
|
170
|
+
lineVisible: boolean;
|
|
171
|
+
maColor: number;
|
|
172
|
+
maWidth: number;
|
|
173
|
+
bandColor: number;
|
|
174
|
+
bandsVisible: boolean;
|
|
175
|
+
}): void;
|
|
116
176
|
/**
|
|
117
|
-
* Configures the MACD pane
|
|
118
|
-
*
|
|
177
|
+
* Configures the MACD pane. source/maKind mirror setOverlays' encodings;
|
|
178
|
+
* colors are packed 0xAARRGGBB where 0 means inherit, and a non-positive
|
|
179
|
+
* width inherits the default stroke.
|
|
119
180
|
*/
|
|
120
|
-
setMACD(
|
|
181
|
+
setMACD(spec: {
|
|
182
|
+
enabled: boolean;
|
|
183
|
+
fast: number;
|
|
184
|
+
slow: number;
|
|
185
|
+
signal: number;
|
|
186
|
+
source: number;
|
|
187
|
+
maKind: number;
|
|
188
|
+
signalMaKind: number;
|
|
189
|
+
lineColor: number;
|
|
190
|
+
lineWidth: number;
|
|
191
|
+
lineVisible: boolean;
|
|
192
|
+
signalColor: number;
|
|
193
|
+
signalWidth: number;
|
|
194
|
+
signalVisible: boolean;
|
|
195
|
+
histVisible: boolean;
|
|
196
|
+
histUpColor: number;
|
|
197
|
+
histUpFadingColor: number;
|
|
198
|
+
histDownColor: number;
|
|
199
|
+
histDownFadingColor: number;
|
|
200
|
+
zeroColor: number;
|
|
201
|
+
zeroVisible: boolean;
|
|
202
|
+
}): void;
|
|
121
203
|
/**
|
|
122
204
|
* Replaces the full set of MA/EMA overlay lines drawn on the price pane.
|
|
123
205
|
* kind: 0=SMA, 1=EMA; source: 0=close,1=open,2=high,3=low,4=hl2,5=hlc3,6=ohlc4;
|
|
@@ -136,12 +218,12 @@ export interface ChartHandle {
|
|
|
136
218
|
* Configures the session VWAP overlay. `resetOffsetMin` shifts the session
|
|
137
219
|
* boundary from UTC midnight (minutes); `color` is packed 0xAARRGGBB.
|
|
138
220
|
*/
|
|
139
|
-
setVWAP(
|
|
140
|
-
enabled: boolean
|
|
141
|
-
resetOffsetMin: number
|
|
142
|
-
color: number
|
|
143
|
-
width: number
|
|
144
|
-
): void;
|
|
221
|
+
setVWAP(spec: {
|
|
222
|
+
enabled: boolean;
|
|
223
|
+
resetOffsetMin: number;
|
|
224
|
+
color: number;
|
|
225
|
+
width: number;
|
|
226
|
+
}): void;
|
|
145
227
|
/**
|
|
146
228
|
* Configures the Bollinger Bands overlay (three price-pane lines + optional
|
|
147
229
|
* fill between the bands). source/basisKind mirror setOverlays' encodings;
|
|
@@ -162,6 +244,31 @@ export interface ChartHandle {
|
|
|
162
244
|
fillEnabled: boolean;
|
|
163
245
|
fillOpacity: number;
|
|
164
246
|
}): void;
|
|
247
|
+
/**
|
|
248
|
+
* Configures the volume bars under the candles. `heightFrac` is the tallest
|
|
249
|
+
* bar as a fraction of the price pane. The style fields carry an inherit
|
|
250
|
+
* sentinel: a negative number or a transparent color falls back to the
|
|
251
|
+
* matching theme key.
|
|
252
|
+
*/
|
|
253
|
+
setVolume(spec: {
|
|
254
|
+
enabled: boolean;
|
|
255
|
+
heightFrac: number;
|
|
256
|
+
opacity: number;
|
|
257
|
+
radiusPx: number;
|
|
258
|
+
upColor: number;
|
|
259
|
+
downColor: number;
|
|
260
|
+
}): void;
|
|
261
|
+
/**
|
|
262
|
+
* Staggered volume-bar collapse: 0 = full height, 1 = all bars flat. Bars fall
|
|
263
|
+
* tallest-first and land together; drive 1 → 0 to reveal them, which plays the
|
|
264
|
+
* cascade in reverse (shortest bar home first).
|
|
265
|
+
*
|
|
266
|
+
* Unlike setMorph, `t` must be **linear** progress — the core eases each bar
|
|
267
|
+
* over its own slice of the timeline, so the curve is applied there. `easing`
|
|
268
|
+
* indexes `linear | ease-in | ease-out | ease-in-out`. setVolume snaps this to
|
|
269
|
+
* match its `enabled`, so it's only needed while animating.
|
|
270
|
+
*/
|
|
271
|
+
setVolumeCollapse(t: number, easing: number): void;
|
|
165
272
|
/**
|
|
166
273
|
* The continuous data coordinate at pixel (x, y) — not snapped to a candle
|
|
167
274
|
* slot. Null when there are no candles or the viewport is degenerate. Cheap to
|
package/src/theme.ts
CHANGED
|
@@ -27,6 +27,7 @@ export const FLOAT_KEYS: Partial<Record<keyof VroomTheme, number>> = {
|
|
|
27
27
|
candleRadius: 8, // VROOM_FLOAT_CANDLE_RADIUS_PX
|
|
28
28
|
volumeRadius: 10, // VROOM_FLOAT_VOLUME_RADIUS_PX
|
|
29
29
|
lineWidth: 11, // VROOM_FLOAT_LINE_WIDTH_PX
|
|
30
|
+
lineGradientOpacity: 12, // VROOM_FLOAT_LINE_GRADIENT_OPACITY
|
|
30
31
|
};
|
|
31
32
|
|
|
32
33
|
// Maps each boolean VroomTheme field to its VroomFloatKey index (pushed as 0/1).
|
package/src/types.ts
CHANGED
|
@@ -12,11 +12,14 @@ export type {
|
|
|
12
12
|
VisibleRange,
|
|
13
13
|
RSIConfig,
|
|
14
14
|
MASource,
|
|
15
|
+
MAKind,
|
|
15
16
|
MovingAverageOverlay,
|
|
16
17
|
VWAPConfig,
|
|
17
18
|
BollingerBandsConfig,
|
|
19
|
+
VolumeConfig,
|
|
18
20
|
MACDConfig,
|
|
19
21
|
ChartType,
|
|
22
|
+
TransitionEasing,
|
|
20
23
|
PriceLine,
|
|
21
24
|
PriceLinesStyle,
|
|
22
25
|
} from '@vroomchart/types';
|