react-native-livechart 3.2.0 → 3.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/README.md +6 -1
- package/dist/components/LiveChart.d.ts.map +1 -1
- package/dist/components/LiveChartSeries.d.ts.map +1 -1
- package/dist/components/ReferenceLineOverlay.d.ts +10 -3
- package/dist/components/ReferenceLineOverlay.d.ts.map +1 -1
- package/dist/components/ScrubActionOverlay.d.ts +32 -0
- package/dist/components/ScrubActionOverlay.d.ts.map +1 -0
- package/dist/components/SegmentDividerOverlay.d.ts +19 -0
- package/dist/components/SegmentDividerOverlay.d.ts.map +1 -0
- package/dist/components/XAxisOverlay.d.ts.map +1 -1
- package/dist/constants.d.ts +4 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/core/resolveConfig.d.ts +23 -1
- package/dist/core/resolveConfig.d.ts.map +1 -1
- package/dist/core/resolveSegment.d.ts +42 -0
- package/dist/core/resolveSegment.d.ts.map +1 -0
- package/dist/hooks/crosshairShared.d.ts +110 -0
- package/dist/hooks/crosshairShared.d.ts.map +1 -1
- package/dist/hooks/useCrosshair.d.ts +14 -2
- package/dist/hooks/useCrosshair.d.ts.map +1 -1
- package/dist/hooks/useMarkers.d.ts +2 -0
- package/dist/hooks/useMarkers.d.ts.map +1 -1
- package/dist/hooks/useReferenceLine.d.ts +36 -3
- package/dist/hooks/useReferenceLine.d.ts.map +1 -1
- package/dist/hooks/useReferenceLinePress.d.ts +23 -0
- package/dist/hooks/useReferenceLinePress.d.ts.map +1 -0
- package/dist/hooks/useSegmentDivider.d.ts +28 -0
- package/dist/hooks/useSegmentDivider.d.ts.map +1 -0
- package/dist/hooks/useSegmentLineGradient.d.ts +20 -0
- package/dist/hooks/useSegmentLineGradient.d.ts.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/math/referenceLines.d.ts +23 -0
- package/dist/math/referenceLines.d.ts.map +1 -1
- package/dist/math/segments.d.ts +46 -0
- package/dist/math/segments.d.ts.map +1 -0
- package/dist/types.d.ts +184 -6
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/LiveChart.tsx +242 -26
- package/src/components/LiveChartSeries.tsx +39 -2
- package/src/components/ReferenceLineOverlay.tsx +121 -94
- package/src/components/ScrubActionOverlay.tsx +187 -0
- package/src/components/SegmentDividerOverlay.tsx +84 -0
- package/src/components/XAxisOverlay.tsx +2 -1
- package/src/constants.ts +5 -0
- package/src/core/resolveConfig.ts +40 -0
- package/src/core/resolveSegment.ts +62 -0
- package/src/hooks/crosshairShared.ts +293 -0
- package/src/hooks/useCrosshair.ts +340 -6
- package/src/hooks/useMarkers.ts +18 -2
- package/src/hooks/useReferenceLine.ts +259 -14
- package/src/hooks/useReferenceLinePress.ts +92 -0
- package/src/hooks/useSegmentDivider.ts +84 -0
- package/src/hooks/useSegmentLineGradient.ts +57 -0
- package/src/index.ts +4 -0
- package/src/math/referenceLines.ts +55 -0
- package/src/math/segments.ts +173 -0
- package/src/types.ts +192 -6
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import type { ResolvedSegment } from "../core/resolveSegment";
|
|
2
|
+
|
|
3
|
+
/** Screen-space x-extent of a segment band, recomputed each frame. */
|
|
4
|
+
export interface SegmentBandX {
|
|
5
|
+
visible: boolean;
|
|
6
|
+
/** Band left edge (px), clamped into the plot. */
|
|
7
|
+
bx1: number;
|
|
8
|
+
/** Band right edge (px), clamped into the plot. */
|
|
9
|
+
bx2: number;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const INVISIBLE_BAND: SegmentBandX = { visible: false, bx1: 0, bx2: 0 };
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Project a segment's `[from, to]` time range (unix seconds) to a clamped x-pixel
|
|
16
|
+
* band within the plot `[x1, x2]`. Mirrors the time-band logic in
|
|
17
|
+
* `useReferenceLine`: an omitted `from` extends to the left edge (window start),
|
|
18
|
+
* an omitted `to` extends to the live edge (`now = winStart + win`). Swaps a
|
|
19
|
+
* reversed range, culls a fully off-screen one, and clamps a partial one.
|
|
20
|
+
*/
|
|
21
|
+
export function segmentBandX(
|
|
22
|
+
from: number | undefined,
|
|
23
|
+
to: number | undefined,
|
|
24
|
+
winStart: number,
|
|
25
|
+
win: number,
|
|
26
|
+
x1: number,
|
|
27
|
+
x2: number,
|
|
28
|
+
): SegmentBandX {
|
|
29
|
+
"worklet";
|
|
30
|
+
if (win <= 0 || x2 <= x1) return INVISIBLE_BAND;
|
|
31
|
+
const chartW = x2 - x1;
|
|
32
|
+
const f = from ?? winStart;
|
|
33
|
+
const t = to ?? winStart + win;
|
|
34
|
+
|
|
35
|
+
let bx1 = x1 + ((f - winStart) / win) * chartW;
|
|
36
|
+
let bx2 = x1 + ((t - winStart) / win) * chartW;
|
|
37
|
+
if (bx2 < bx1) {
|
|
38
|
+
const tmp = bx1;
|
|
39
|
+
bx1 = bx2;
|
|
40
|
+
bx2 = tmp;
|
|
41
|
+
}
|
|
42
|
+
if (bx2 < x1 || bx1 > x2) return INVISIBLE_BAND;
|
|
43
|
+
if (bx1 < x1) bx1 = x1;
|
|
44
|
+
if (bx2 > x2) bx2 = x2;
|
|
45
|
+
return { visible: true, bx1, bx2 };
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** Horizontal stroke gradient for the recolored line segments. */
|
|
49
|
+
export interface SegmentGradient {
|
|
50
|
+
colors: string[];
|
|
51
|
+
positions: number[];
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Build the horizontal gradient applied to the line stroke itself, implementing
|
|
56
|
+
* "scrub focus" (the Robinhood model): the whole line is its plain `baseColor`
|
|
57
|
+
* until the user scrubs (or a segment is forced `active`). While focused, the
|
|
58
|
+
* segment under the scrub — or the `active` one — stays `baseColor` (full), and
|
|
59
|
+
* every OTHER `recolorLine` segment is de-emphasized with its own `mutedColor` /
|
|
60
|
+
* `mutedColors` (a different hue and/or a reduced alpha that fades it). Because it
|
|
61
|
+
* paints the line directly (not a layer on top), an alpha-reduced color genuinely
|
|
62
|
+
* lowers the line's opacity there.
|
|
63
|
+
*
|
|
64
|
+
* Stop positions are fractions of the full canvas width — the same coordinate
|
|
65
|
+
* space as the gradient's `start`/`end` vectors. Each de-emphasized segment
|
|
66
|
+
* contributes `base@f1 → color(s) across [f1,f2] → base@f2`, with duplicate
|
|
67
|
+
* positions at the boundaries producing hard edges. The Skia gradient requires
|
|
68
|
+
* non-decreasing positions, so stops are emitted in ascending x order and never
|
|
69
|
+
* allowed to step backwards — overlapping/reversed/clamped segments can therefore
|
|
70
|
+
* never feed a non-monotonic array.
|
|
71
|
+
*
|
|
72
|
+
* Returns `null` when the line should be uniform: not scrubbing and nothing
|
|
73
|
+
* `active`, or when every segment is the focused one (nothing to de-emphasize).
|
|
74
|
+
* The caller then strokes the line with its plain solid color.
|
|
75
|
+
*/
|
|
76
|
+
export function segmentLineGradient(
|
|
77
|
+
segments: ResolvedSegment[],
|
|
78
|
+
winStart: number,
|
|
79
|
+
win: number,
|
|
80
|
+
canvasWidth: number,
|
|
81
|
+
plotLeft: number,
|
|
82
|
+
plotRight: number,
|
|
83
|
+
baseColor: string,
|
|
84
|
+
scrubActive: boolean,
|
|
85
|
+
scrubX: number,
|
|
86
|
+
): SegmentGradient | null {
|
|
87
|
+
"worklet";
|
|
88
|
+
if (win <= 0 || canvasWidth <= 0 || plotRight <= plotLeft) return null;
|
|
89
|
+
|
|
90
|
+
// Focus mode is on only while scrubbing or when a segment is forced `active`.
|
|
91
|
+
// Off → the whole line is its plain base color (segments are indistinguishable).
|
|
92
|
+
let focusMode = scrubActive;
|
|
93
|
+
if (!focusMode) {
|
|
94
|
+
for (let i = 0; i < segments.length; i++) {
|
|
95
|
+
if (segments[i].recolorLine && segments[i].active) {
|
|
96
|
+
focusMode = true;
|
|
97
|
+
break;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
if (!focusMode) return null;
|
|
102
|
+
|
|
103
|
+
const chartW = plotRight - plotLeft;
|
|
104
|
+
|
|
105
|
+
// Collect the NON-focused segments — they get de-emphasized (their mutedColor);
|
|
106
|
+
// the focused segment (under the scrub, or `active`) stays the base color.
|
|
107
|
+
const spans: { f1: number; f2: number; cols: string[] }[] = [];
|
|
108
|
+
for (let i = 0; i < segments.length; i++) {
|
|
109
|
+
const seg = segments[i];
|
|
110
|
+
if (!seg.recolorLine) continue;
|
|
111
|
+
|
|
112
|
+
const from = seg.from ?? winStart;
|
|
113
|
+
const to = seg.to ?? winStart + win;
|
|
114
|
+
let px1 = plotLeft + ((from - winStart) / win) * chartW;
|
|
115
|
+
let px2 = plotLeft + ((to - winStart) / win) * chartW;
|
|
116
|
+
if (px2 < px1) {
|
|
117
|
+
const tmp = px1;
|
|
118
|
+
px1 = px2;
|
|
119
|
+
px2 = tmp;
|
|
120
|
+
}
|
|
121
|
+
if (px2 < plotLeft || px1 > plotRight) continue;
|
|
122
|
+
if (px1 < plotLeft) px1 = plotLeft;
|
|
123
|
+
if (px2 > plotRight) px2 = plotRight;
|
|
124
|
+
|
|
125
|
+
const focused =
|
|
126
|
+
(scrubActive && scrubX >= px1 && scrubX <= px2) || seg.active;
|
|
127
|
+
if (focused) continue; // the focused segment keeps the full base color
|
|
128
|
+
|
|
129
|
+
const f1 = px1 / canvasWidth;
|
|
130
|
+
const f2 = px2 / canvasWidth;
|
|
131
|
+
if (f2 <= f1) continue;
|
|
132
|
+
const cols =
|
|
133
|
+
seg.mutedColors && seg.mutedColors.length >= 2
|
|
134
|
+
? seg.mutedColors
|
|
135
|
+
: [seg.mutedColor];
|
|
136
|
+
spans.push({ f1, f2, cols });
|
|
137
|
+
}
|
|
138
|
+
if (spans.length === 0) return null; // nothing to de-emphasize → uniform line
|
|
139
|
+
|
|
140
|
+
spans.sort((a, b) => a.f1 - b.f1);
|
|
141
|
+
|
|
142
|
+
const colors: string[] = [];
|
|
143
|
+
const positions: number[] = [];
|
|
144
|
+
let last = 0;
|
|
145
|
+
const push = (color: string, pos: number) => {
|
|
146
|
+
// Stops must be non-decreasing for Skia. `px` is already clamped to the plot
|
|
147
|
+
// (⊆ [0, canvasWidth]) so `pos` is within [0,1]; only the monotonic guard is
|
|
148
|
+
// needed — it keeps overlapping/reversed spans from stepping backwards.
|
|
149
|
+
const p = pos < last ? last : pos;
|
|
150
|
+
colors.push(color);
|
|
151
|
+
positions.push(p);
|
|
152
|
+
last = p;
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
push(baseColor, 0);
|
|
156
|
+
for (let i = 0; i < spans.length; i++) {
|
|
157
|
+
const span = spans[i];
|
|
158
|
+
push(baseColor, span.f1); // hard edge: base line up to the segment start
|
|
159
|
+
const n = span.cols.length;
|
|
160
|
+
if (n === 1) {
|
|
161
|
+
push(span.cols[0], span.f1);
|
|
162
|
+
push(span.cols[0], span.f2);
|
|
163
|
+
} else {
|
|
164
|
+
for (let k = 0; k < n; k++) {
|
|
165
|
+
push(span.cols[k], span.f1 + (k / (n - 1)) * (span.f2 - span.f1));
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
push(baseColor, span.f2); // hard edge: back to the base line after the segment
|
|
169
|
+
}
|
|
170
|
+
push(baseColor, 1);
|
|
171
|
+
|
|
172
|
+
return { colors, positions };
|
|
173
|
+
}
|
package/src/types.ts
CHANGED
|
@@ -100,21 +100,112 @@ export interface ReferenceLine {
|
|
|
100
100
|
*/
|
|
101
101
|
excludeFromRange?: boolean;
|
|
102
102
|
/**
|
|
103
|
-
*
|
|
104
|
-
*
|
|
103
|
+
* Render the Form-A value as a **pill badge** — an icon and/or text tag pinned
|
|
104
|
+
* to a plot edge at the line's value, with a dashed connector running to the
|
|
105
|
+
* opposite edge (instead of a plain gutter label that collides with the Y-axis
|
|
106
|
+
* ticks). Auto-pins to the nearest edge with a directional chevron once the
|
|
107
|
+
* value scrolls off-screen. Ideal for working orders, price alerts, and targets.
|
|
108
|
+
*
|
|
109
|
+
* `true` = defaults (left-pinned, the line's label/value), or a
|
|
110
|
+
* {@link ReferenceLineBadgeConfig} for an `icon`, `text` toggle (icon-only), and
|
|
111
|
+
* `position`. Supersedes the legacy `offAxisBadge`. Default off.
|
|
112
|
+
*/
|
|
113
|
+
badge?: boolean | ReferenceLineBadgeConfig;
|
|
114
|
+
/**
|
|
115
|
+
* Legacy: when a Form-A `value` falls outside the visible plot, render a pinned
|
|
116
|
+
* edge badge with a directional chevron instead of culling the off-screen line.
|
|
117
|
+
* Prefer {@link badge} (which also shows the tag in-range and supports an icon).
|
|
105
118
|
* Typically paired with `excludeFromRange`. Default `false`.
|
|
106
119
|
*/
|
|
107
120
|
offAxisBadge?: boolean;
|
|
108
|
-
/** Localized word shown in the off-axis badge (e.g. "Target"). Falls back to `label`. */
|
|
121
|
+
/** Localized word shown in the legacy off-axis badge (e.g. "Target"). Falls back to `label`. */
|
|
109
122
|
offAxisBadgeLabel?: string;
|
|
110
|
-
/**
|
|
123
|
+
/** Badge pill background. Default: theme `tooltipBg`. (Fallback for `badge.background`.) */
|
|
111
124
|
badgeBackground?: string;
|
|
112
|
-
/**
|
|
125
|
+
/** Badge pill border color. Default: the line `color`. (Fallback for `badge.borderColor`.) */
|
|
113
126
|
badgeBorderColor?: string;
|
|
114
|
-
/**
|
|
127
|
+
/** Badge pill corner radius in pixels. Default `5`. (Fallback for `badge.radius`.) */
|
|
115
128
|
badgeRadius?: number;
|
|
116
129
|
}
|
|
117
130
|
|
|
131
|
+
/**
|
|
132
|
+
* Pill-badge presentation for a Form-A {@link ReferenceLine} — a working order,
|
|
133
|
+
* price alert, or target tag. The badge sits at the line's value (pinned to
|
|
134
|
+
* `position`) with a dashed connector to the opposite edge, and pins to the
|
|
135
|
+
* nearest edge with a chevron once the value scrolls off-screen.
|
|
136
|
+
*/
|
|
137
|
+
export interface ReferenceLineBadgeConfig {
|
|
138
|
+
/** Which plot edge the badge pins to. Default `"left"`. */
|
|
139
|
+
position?: "left" | "right";
|
|
140
|
+
/**
|
|
141
|
+
* Leading glyph drawn in the badge — rendered with the chart font, so pass an
|
|
142
|
+
* emoji-capable font (via the chart `font` prop) for emoji. Like `Marker.icon`.
|
|
143
|
+
*/
|
|
144
|
+
icon?: string;
|
|
145
|
+
/**
|
|
146
|
+
* Show the text label (the line's `label`, plus the value when `showValue`).
|
|
147
|
+
* Default `true`. Set `false` for an **icon-only** badge.
|
|
148
|
+
*/
|
|
149
|
+
text?: boolean;
|
|
150
|
+
/** Pill background. Falls back to `badgeBackground`, then theme `tooltipBg`. */
|
|
151
|
+
background?: string;
|
|
152
|
+
/** Pill border color. Falls back to `badgeBorderColor`, then the line `color`. */
|
|
153
|
+
borderColor?: string;
|
|
154
|
+
/** Pill corner radius in pixels. Falls back to `badgeRadius`, then `5`. */
|
|
155
|
+
radius?: number;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* A time-range segment of the chart — e.g. a pre-market / regular / after-hours
|
|
160
|
+
* session — distinguished with a **scrub-focus** interaction (Robinhood-style
|
|
161
|
+
* extended-hours segmentation). At rest the whole line is one uniform color;
|
|
162
|
+
* while the user scrubs (or when a segment is `active`) the focused segment keeps
|
|
163
|
+
* the base color and every other segment is de-emphasized by recoloring the line
|
|
164
|
+
* stroke itself (no overlay). An optional dashed `divider` + `label` mark a
|
|
165
|
+
* segment's leading edge.
|
|
166
|
+
*/
|
|
167
|
+
export interface ChartSegment {
|
|
168
|
+
/** Segment start, unix seconds. Omit to extend to the chart's left edge. */
|
|
169
|
+
from?: number;
|
|
170
|
+
/** Segment end, unix seconds. Omit to extend to the live edge (now). */
|
|
171
|
+
to?: number;
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Participate in scrub-focus line styling. At rest the line is one uniform
|
|
175
|
+
* color; while scrubbing (or when a segment is `active`), the focused segment
|
|
176
|
+
* keeps the base line color and every OTHER `recolorLine` segment is
|
|
177
|
+
* de-emphasized with `mutedColor` / `mutedColors`. Default `true`.
|
|
178
|
+
*/
|
|
179
|
+
recolorLine?: boolean;
|
|
180
|
+
/** De-emphasis line color, used when this segment is NOT the focused one. An
|
|
181
|
+
* alpha-reduced color (e.g. `"rgba(154,160,166,0.4)"`) fades the line — it
|
|
182
|
+
* paints the stroke directly, not a layer on top. Defaults to the chart's muted
|
|
183
|
+
* palette color (`palette.gridLabel`). */
|
|
184
|
+
mutedColor?: string;
|
|
185
|
+
/**
|
|
186
|
+
* Two or more CSS colors → horizontal gradient across the segment's sub-range
|
|
187
|
+
* (left → right) for the de-emphasized state, mirroring `LineConfig.colors`.
|
|
188
|
+
* Takes precedence over `mutedColor` when set.
|
|
189
|
+
*/
|
|
190
|
+
mutedColors?: string[];
|
|
191
|
+
|
|
192
|
+
/** Force this segment to be the focused one without scrubbing — it stays full
|
|
193
|
+
* while the others are de-emphasized (e.g. the session is currently after-hours). */
|
|
194
|
+
active?: boolean;
|
|
195
|
+
|
|
196
|
+
/** Draw a vertical dashed divider at the `from` edge (market-close marker). Default `false`. */
|
|
197
|
+
divider?: boolean;
|
|
198
|
+
/** Divider color. Defaults to the chart's reference-line color (`palette.refLine`). */
|
|
199
|
+
dividerColor?: string;
|
|
200
|
+
|
|
201
|
+
/** Optional label captioning the divider at the top of the segment. Shown only
|
|
202
|
+
* when `divider` is set; drawn in the chart's reference-label color
|
|
203
|
+
* (`palette.refLabel`). */
|
|
204
|
+
label?: string;
|
|
205
|
+
/** Label horizontal anchor within the segment. Default `"left"`. */
|
|
206
|
+
labelPosition?: "left" | "right";
|
|
207
|
+
}
|
|
208
|
+
|
|
118
209
|
/** Per-instance grid-line styling for the horizontal value-axis grid. */
|
|
119
210
|
export interface GridStyleConfig {
|
|
120
211
|
/** Stroke color. Defaults to palette `gridLine`. */
|
|
@@ -242,6 +333,71 @@ export interface ScrubConfig {
|
|
|
242
333
|
panGestureDelay?: number;
|
|
243
334
|
}
|
|
244
335
|
|
|
336
|
+
/**
|
|
337
|
+
* Scrub-action ("order ticket") mode for the single-series `LiveChart` (line and
|
|
338
|
+
* candle). Tap to drop a locked crosshair, drag to fine-tune a **price level**,
|
|
339
|
+
* then press the right-gutter action badge to fire {@link LiveChartProps.onScrubAction}.
|
|
340
|
+
*
|
|
341
|
+
* The reported price is the value at the reticle's **Y position** (a free price
|
|
342
|
+
* level you choose — the inverse of the value→pixel mapping), NOT the line/candle
|
|
343
|
+
* value at the reticle's X. That matches how a limit price works (a horizontal
|
|
344
|
+
* level) and the crosshair badge in pro charting tools. Opt-in (default off).
|
|
345
|
+
*/
|
|
346
|
+
export interface ScrubActionConfig {
|
|
347
|
+
/** Glyph drawn in the action badge (rendered as chart text, like `Marker.icon`). Default `"+"`. */
|
|
348
|
+
icon?: string;
|
|
349
|
+
/** Action-badge background color. Defaults to the accent / badge color. */
|
|
350
|
+
background?: string;
|
|
351
|
+
/** Action-badge icon + price text color. Defaults to the badge text color. */
|
|
352
|
+
iconColor?: string;
|
|
353
|
+
/** Horizontal level-line color. Defaults to `palette.crosshairLine`. */
|
|
354
|
+
lineColor?: string;
|
|
355
|
+
/**
|
|
356
|
+
* Show the price readout inside the action badge. Default `true`. Set `false`
|
|
357
|
+
* for an **icon-only** pill (mirrors {@link ReferenceLineBadgeConfig.text}).
|
|
358
|
+
*/
|
|
359
|
+
text?: boolean;
|
|
360
|
+
/**
|
|
361
|
+
* Show a date/time pill where the reticle's vertical line meets the x-axis,
|
|
362
|
+
* formatted by the chart's `formatTime`. Off by default — for order entry the
|
|
363
|
+
* reticle's X (time) is incidental to a price *level*; enable it when the time
|
|
364
|
+
* under the reticle is meaningful (annotations, time-relevant actions, or a full
|
|
365
|
+
* crosshair readout). Reuses `background` / `iconColor`. Default `false`.
|
|
366
|
+
*/
|
|
367
|
+
timeBadge?: boolean;
|
|
368
|
+
/**
|
|
369
|
+
* Round the reported price to this increment (e.g. `0.01` for cents, `0.5` for
|
|
370
|
+
* a tick size) so the badge reads round numbers. Omit for the raw value.
|
|
371
|
+
*/
|
|
372
|
+
snap?: number;
|
|
373
|
+
/**
|
|
374
|
+
* A tap on empty plot (outside the reticle + action badge) dismisses the lock
|
|
375
|
+
* instead of moving it. Default `false` (an empty-plot tap re-places the reticle).
|
|
376
|
+
*/
|
|
377
|
+
dismissOnTapOutside?: boolean;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
/**
|
|
381
|
+
* Payload for {@link LiveChartProps.onScrubAction} — the chosen price **level**
|
|
382
|
+
* (from the locked reticle's Y), not the line value at that time.
|
|
383
|
+
*
|
|
384
|
+
* The library asserts no buy/sell semantics: derive the side from `price` versus
|
|
385
|
+
* your own current price (`price < last` is the usual buy-below / sell-above
|
|
386
|
+
* convention, but stop orders invert it).
|
|
387
|
+
*/
|
|
388
|
+
export interface ScrubActionPoint {
|
|
389
|
+
/** Chosen price level — the value at the reticle Y, optionally `snap`-rounded. */
|
|
390
|
+
price: number;
|
|
391
|
+
/** Unix timestamp in seconds at the reticle X. */
|
|
392
|
+
time: number;
|
|
393
|
+
/** Canvas X coordinate of the reticle. */
|
|
394
|
+
x: number;
|
|
395
|
+
/** Canvas Y coordinate of the reticle. */
|
|
396
|
+
y: number;
|
|
397
|
+
/** In candle mode, the OHLC data of the candle under the reticle X (context only). */
|
|
398
|
+
candle?: CandlePoint;
|
|
399
|
+
}
|
|
400
|
+
|
|
245
401
|
/**
|
|
246
402
|
* Props passed to a custom {@link SelectionDotConfig.component} — the dot drawn
|
|
247
403
|
* at the scrub intersection while scrubbing. All positional inputs are
|
|
@@ -871,6 +1027,13 @@ export interface LiveChartProps extends LiveChartCoreProps {
|
|
|
871
1027
|
dot?: boolean | DotConfig;
|
|
872
1028
|
/** Horizontal dashed line at the current live value. `true` = defaults, or pass `ValueLineConfig`. */
|
|
873
1029
|
valueLine?: boolean | ValueLineConfig;
|
|
1030
|
+
/**
|
|
1031
|
+
* Time-range segments (sessions, after-hours, overnight, etc.). At rest the
|
|
1032
|
+
* line is one uniform color; scrubbing a {@link ChartSegment} — or marking one
|
|
1033
|
+
* `active` — keeps it full while the others de-emphasize (`mutedColor` /
|
|
1034
|
+
* `mutedColors`). Optional dashed `divider` + `label` mark a segment's edge.
|
|
1035
|
+
*/
|
|
1036
|
+
segments?: ChartSegment[];
|
|
874
1037
|
/** Render the live value as a large text overlay in the top-left. Default `false`. */
|
|
875
1038
|
showValue?: boolean;
|
|
876
1039
|
/** Tint the `showValue` text by momentum (green up / red down). Default `false`. */
|
|
@@ -904,6 +1067,29 @@ export interface LiveChartProps extends LiveChartCoreProps {
|
|
|
904
1067
|
static?: boolean;
|
|
905
1068
|
/** Called when the user scrubs the crosshair. `null` when scrub ends. */
|
|
906
1069
|
onScrub?: (point: ScrubPoint | null) => void;
|
|
1070
|
+
/**
|
|
1071
|
+
* Scrub-action ("order ticket") mode: tap to drop a locked crosshair, drag to
|
|
1072
|
+
* fine-tune a **price level**, then press the right-gutter action badge to fire
|
|
1073
|
+
* {@link onScrubAction}. `true` = defaults, `false`/omitted = off, or pass
|
|
1074
|
+
* {@link ScrubActionConfig}. Coexists with `scrub`/`onScrub`. Default off.
|
|
1075
|
+
*/
|
|
1076
|
+
scrubAction?: boolean | ScrubActionConfig;
|
|
1077
|
+
/**
|
|
1078
|
+
* Called on the JS thread when the user presses the scrub-action badge. The
|
|
1079
|
+
* payload's `price` is the value at the locked reticle's Y (a chosen price
|
|
1080
|
+
* level), not the line value at that time. See {@link ScrubActionPoint}.
|
|
1081
|
+
*/
|
|
1082
|
+
onScrubAction?: (point: ScrubActionPoint) => void;
|
|
1083
|
+
/**
|
|
1084
|
+
* Called on the JS thread when the user taps a reference line's **badge** — the
|
|
1085
|
+
* pill tag drawn for a working order / alert / target (a `ReferenceLine` with a
|
|
1086
|
+
* {@link ReferenceLine.badge}). Receives the tapped line and its index in the
|
|
1087
|
+
* `referenceLines` array, e.g. to open a cancel/edit sheet for that order. Only
|
|
1088
|
+
* badge-tagged Form-A (value) lines are pressable — a plain line has no discrete
|
|
1089
|
+
* hit target. Coexists with `scrub`/`scrubAction`/`markers` (a tap on a badge is
|
|
1090
|
+
* routed here, not to reticle placement). Single-series only.
|
|
1091
|
+
*/
|
|
1092
|
+
onReferenceLinePress?: (line: ReferenceLine, index: number) => void;
|
|
907
1093
|
/**
|
|
908
1094
|
* Called on the JS thread when degen chart shake starts (momentum swing with shake enabled).
|
|
909
1095
|
* Not called when `degen` is off or `DegenOptions.shake` is `false`.
|