react-native-livechart 4.20.0 → 4.21.1
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/dist/components/AxisLabelOverlay.d.ts +5 -1
- package/dist/components/AxisLabelOverlay.d.ts.map +1 -1
- package/dist/components/CrosshairOverlay.d.ts +4 -2
- package/dist/components/CrosshairOverlay.d.ts.map +1 -1
- package/dist/components/CustomMarkerOverlay.d.ts.map +1 -1
- package/dist/components/CustomThresholdBadgeOverlay.d.ts +18 -0
- package/dist/components/CustomThresholdBadgeOverlay.d.ts.map +1 -0
- package/dist/components/CustomTooltipOverlay.d.ts +4 -2
- package/dist/components/CustomTooltipOverlay.d.ts.map +1 -1
- package/dist/components/DegenParticlesOverlay.d.ts.map +1 -1
- package/dist/components/ExtremaConnectorOverlay.d.ts +5 -1
- package/dist/components/ExtremaConnectorOverlay.d.ts.map +1 -1
- package/dist/components/LiveChart.d.ts.map +1 -1
- package/dist/components/LiveChartSeries.d.ts.map +1 -1
- package/dist/components/MarkerOverlay.d.ts +4 -2
- package/dist/components/MarkerOverlay.d.ts.map +1 -1
- package/dist/components/ReferenceLineOverlay.d.ts +10 -5
- package/dist/components/ReferenceLineOverlay.d.ts.map +1 -1
- package/dist/components/ReferenceLineSeriesOverlay.d.ts +19 -0
- package/dist/components/ReferenceLineSeriesOverlay.d.ts.map +1 -0
- package/dist/core/chartDataPresence.d.ts +8 -0
- package/dist/core/chartDataPresence.d.ts.map +1 -0
- package/dist/core/liveChartEngineTick.d.ts +6 -1
- package/dist/core/liveChartEngineTick.d.ts.map +1 -1
- package/dist/core/resolveConfig.d.ts +32 -1
- package/dist/core/resolveConfig.d.ts.map +1 -1
- package/dist/core/useLiveChartEngine.d.ts +9 -1
- package/dist/core/useLiveChartEngine.d.ts.map +1 -1
- package/dist/core/useLiveChartSeriesEngine.d.ts.map +1 -1
- package/dist/draw/candle.d.ts +3 -1
- package/dist/draw/candle.d.ts.map +1 -1
- package/dist/draw/candleGap.d.ts +14 -0
- package/dist/draw/candleGap.d.ts.map +1 -0
- package/dist/draw/lineGap.d.ts +25 -0
- package/dist/draw/lineGap.d.ts.map +1 -0
- package/dist/draw/markerAtlas.d.ts +3 -2
- package/dist/draw/markerAtlas.d.ts.map +1 -1
- package/dist/hooks/crosshairShared.d.ts +7 -3
- package/dist/hooks/crosshairShared.d.ts.map +1 -1
- package/dist/hooks/useCandleGapPaths.d.ts +12 -0
- package/dist/hooks/useCandleGapPaths.d.ts.map +1 -0
- package/dist/hooks/useChartPaths.d.ts +4 -1
- package/dist/hooks/useChartPaths.d.ts.map +1 -1
- package/dist/hooks/useChartReveal.d.ts +1 -1
- package/dist/hooks/useChartReveal.d.ts.map +1 -1
- package/dist/hooks/useCrosshair.d.ts +9 -5
- package/dist/hooks/useCrosshair.d.ts.map +1 -1
- package/dist/hooks/useDegen.d.ts.map +1 -1
- package/dist/hooks/useLineGapPaths.d.ts +10 -0
- package/dist/hooks/useLineGapPaths.d.ts.map +1 -0
- package/dist/hooks/useLiveChartHasData.d.ts +2 -2
- package/dist/hooks/useLiveChartHasData.d.ts.map +1 -1
- package/dist/hooks/useReferenceLine.d.ts +4 -3
- package/dist/hooks/useReferenceLine.d.ts.map +1 -1
- package/dist/hooks/useReferenceLineSeries.d.ts +23 -0
- package/dist/hooks/useReferenceLineSeries.d.ts.map +1 -0
- package/dist/hooks/useReverseMorphEngineInputs.d.ts.map +1 -1
- package/dist/hooks/useThreshold.d.ts +13 -13
- package/dist/hooks/useThreshold.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/math/candleGaps.d.ts +18 -0
- package/dist/math/candleGaps.d.ts.map +1 -0
- package/dist/math/referenceLineSeries.d.ts +12 -0
- package/dist/math/referenceLineSeries.d.ts.map +1 -0
- package/dist/math/referenceLines.d.ts +5 -5
- package/dist/math/referenceLines.d.ts.map +1 -1
- package/dist/math/spline.d.ts +5 -1
- package/dist/math/spline.d.ts.map +1 -1
- package/dist/types.d.ts +191 -17
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/AxisLabelOverlay.tsx +162 -81
- package/src/components/CrosshairOverlay.tsx +394 -147
- package/src/components/CustomMarkerOverlay.tsx +9 -6
- package/src/components/CustomThresholdBadgeOverlay.tsx +74 -0
- package/src/components/CustomTooltipOverlay.tsx +7 -3
- package/src/components/DegenParticlesOverlay.tsx +34 -23
- package/src/components/ExtremaConnectorOverlay.tsx +43 -3
- package/src/components/LiveChart.tsx +1918 -974
- package/src/components/LiveChartSeries.tsx +445 -296
- package/src/components/MarkerOverlay.tsx +215 -156
- package/src/components/ReferenceLineOverlay.tsx +113 -55
- package/src/components/ReferenceLineSeriesOverlay.tsx +141 -0
- package/src/core/chartDataPresence.ts +24 -0
- package/src/core/liveChartEngineTick.ts +34 -1
- package/src/core/resolveConfig.ts +186 -0
- package/src/core/useLiveChartEngine.ts +36 -1
- package/src/core/useLiveChartSeriesEngine.ts +2 -0
- package/src/draw/candle.ts +1 -1
- package/src/draw/candleGap.ts +132 -0
- package/src/draw/lineGap.ts +180 -0
- package/src/draw/markerAtlas.ts +8 -3
- package/src/hooks/crosshairShared.ts +92 -11
- package/src/hooks/useCandleGapPaths.ts +88 -0
- package/src/hooks/useChartPaths.ts +81 -22
- package/src/hooks/useChartReveal.ts +1 -1
- package/src/hooks/useCrosshair.ts +178 -69
- package/src/hooks/useDegen.ts +82 -53
- package/src/hooks/useLineGapPaths.ts +76 -0
- package/src/hooks/useLiveChartHasData.ts +8 -4
- package/src/hooks/useReferenceLine.ts +6 -5
- package/src/hooks/useReferenceLineSeries.ts +101 -0
- package/src/hooks/useReverseMorphEngineInputs.ts +11 -20
- package/src/hooks/useThreshold.ts +31 -22
- package/src/index.ts +15 -0
- package/src/math/candleGaps.ts +120 -0
- package/src/math/referenceLineSeries.ts +83 -0
- package/src/math/referenceLines.ts +34 -6
- package/src/math/spline.ts +15 -5
- package/src/types.ts +202 -17
|
@@ -10,7 +10,7 @@ import type { ChartEngineLayout } from "../core/useLiveChartEngine";
|
|
|
10
10
|
import type { ChartPadding } from "../draw/line";
|
|
11
11
|
import type { TooltipLayout } from "../hooks/crosshairShared";
|
|
12
12
|
import { resolveCrosshairVisibleOpacity } from "../hooks/useCrosshairVisibleOpacity";
|
|
13
|
-
import type { CandlePoint, TooltipRenderProps } from "../types";
|
|
13
|
+
import type { CandleGap, CandlePoint, TooltipRenderProps } from "../types";
|
|
14
14
|
|
|
15
15
|
// Mirror the Skia tooltip's offsets (see crosshairShared.ts) so a custom pill
|
|
16
16
|
// lines up with where the built-in one would sit. The vertical edge gap is
|
|
@@ -42,6 +42,7 @@ export function CustomTooltipOverlay({
|
|
|
42
42
|
scrubTime,
|
|
43
43
|
scrubActive,
|
|
44
44
|
scrubCandle,
|
|
45
|
+
scrubGap,
|
|
45
46
|
tooltipLayout,
|
|
46
47
|
engine,
|
|
47
48
|
padding,
|
|
@@ -59,6 +60,8 @@ export function CustomTooltipOverlay({
|
|
|
59
60
|
scrubActive: SharedValue<boolean>;
|
|
60
61
|
/** OHLC candle under the crosshair (candle mode); omitted/`null` in line mode. */
|
|
61
62
|
scrubCandle?: SharedValue<CandlePoint | null>;
|
|
63
|
+
/** Explicit line or candle gap under the crosshair; omitted/`null` outside one. */
|
|
64
|
+
scrubGap?: SharedValue<CandleGap | null>;
|
|
62
65
|
tooltipLayout: SharedValue<TooltipLayout>;
|
|
63
66
|
engine: ChartEngineLayout;
|
|
64
67
|
padding: ChartPadding;
|
|
@@ -82,9 +85,9 @@ export function CustomTooltipOverlay({
|
|
|
82
85
|
// a worklet-safe formatter for the value/time.
|
|
83
86
|
const valueStr = useDerivedValue(() => tooltipLayout.get().valueStr);
|
|
84
87
|
const timeStr = useDerivedValue(() => tooltipLayout.get().timeStr);
|
|
85
|
-
//
|
|
86
|
-
// present (a SharedValue), regardless of mode.
|
|
88
|
+
// Stable null SharedValues keep both fields present regardless of mode.
|
|
87
89
|
const nullCandle = useSharedValue<CandlePoint | null>(null);
|
|
90
|
+
const nullGap = useSharedValue<CandleGap | null>(null);
|
|
88
91
|
|
|
89
92
|
const ctx: TooltipRenderProps = {
|
|
90
93
|
value: scrubValue,
|
|
@@ -93,6 +96,7 @@ export function CustomTooltipOverlay({
|
|
|
93
96
|
timeStr,
|
|
94
97
|
active: scrubActive,
|
|
95
98
|
candle: scrubCandle ?? nullCandle,
|
|
99
|
+
gap: scrubGap ?? nullGap,
|
|
96
100
|
};
|
|
97
101
|
const element = renderTooltip(ctx);
|
|
98
102
|
|
|
@@ -17,6 +17,36 @@ import type { ChartEngineLayout } from "../core/useLiveChartEngine";
|
|
|
17
17
|
|
|
18
18
|
type DegenPack = SharedValue<Float64Array<ArrayBuffer>>;
|
|
19
19
|
|
|
20
|
+
type ParticlePool = {
|
|
21
|
+
a: { transforms: SkRSXform[]; sprites: SkRect[]; colors: SkColor[] };
|
|
22
|
+
b: { transforms: SkRSXform[]; sprites: SkRect[]; colors: SkColor[] };
|
|
23
|
+
tick: boolean;
|
|
24
|
+
instances: ReturnType<typeof buildParticleInstances>;
|
|
25
|
+
instancePool: ReturnType<typeof buildParticleInstances>;
|
|
26
|
+
spriteRect: SkRect;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
function makeParticlePool(
|
|
30
|
+
particleSlotCount: number,
|
|
31
|
+
spriteSize: number,
|
|
32
|
+
): ParticlePool {
|
|
33
|
+
const instancePool = Array.from({ length: particleSlotCount }, () => ({
|
|
34
|
+
x: 0,
|
|
35
|
+
y: 0,
|
|
36
|
+
scale: 0,
|
|
37
|
+
alpha: 0,
|
|
38
|
+
colorIndex: 0,
|
|
39
|
+
}));
|
|
40
|
+
return {
|
|
41
|
+
a: { transforms: [], sprites: [], colors: [] },
|
|
42
|
+
b: { transforms: [], sprites: [], colors: [] },
|
|
43
|
+
tick: false,
|
|
44
|
+
instances: [],
|
|
45
|
+
instancePool,
|
|
46
|
+
spriteRect: Skia.XYWHRect(0, 0, spriteSize, spriteSize),
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
20
50
|
/**
|
|
21
51
|
* Renders the degen particle burst with a single `drawAtlas` call.
|
|
22
52
|
*
|
|
@@ -64,30 +94,11 @@ export function DegenParticlesOverlay({
|
|
|
64
94
|
// memoizes this on `colorList`.
|
|
65
95
|
const colorRgb = colorList.map((c) => parseColorRgb(c));
|
|
66
96
|
|
|
67
|
-
const poolRef = useRef<
|
|
68
|
-
a: { transforms: SkRSXform[]; sprites: SkRect[]; colors: SkColor[] };
|
|
69
|
-
b: { transforms: SkRSXform[]; sprites: SkRect[]; colors: SkColor[] };
|
|
70
|
-
tick: boolean;
|
|
71
|
-
instances: ReturnType<typeof buildParticleInstances>;
|
|
72
|
-
instancePool: ReturnType<typeof buildParticleInstances>;
|
|
73
|
-
spriteRect: SkRect;
|
|
74
|
-
} | null>(null);
|
|
97
|
+
const poolRef = useRef<ParticlePool | null>(null);
|
|
75
98
|
if (poolRef.current === null) {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
scale: 0,
|
|
80
|
-
alpha: 0,
|
|
81
|
-
colorIndex: 0,
|
|
82
|
-
}));
|
|
83
|
-
poolRef.current = {
|
|
84
|
-
a: { transforms: [], sprites: [], colors: [] },
|
|
85
|
-
b: { transforms: [], sprites: [], colors: [] },
|
|
86
|
-
tick: false,
|
|
87
|
-
instances: [],
|
|
88
|
-
instancePool,
|
|
89
|
-
spriteRect: Skia.XYWHRect(0, 0, sprite.size, sprite.size),
|
|
90
|
-
};
|
|
99
|
+
// React permits this predictable lazy-ref initialization: https://react.dev/reference/react/useRef#avoiding-recreating-the-ref-contents
|
|
100
|
+
// react-doctor-disable-next-line react-doctor/no-ref-current-in-render -- false positive for React's documented lazy-ref exception
|
|
101
|
+
poolRef.current = makeParticlePool(particleSlotCount, sprite.size);
|
|
91
102
|
}
|
|
92
103
|
|
|
93
104
|
// Single per-frame worklet. Reads `packRevision` so it re-runs each frame
|
|
@@ -11,7 +11,11 @@ import type {
|
|
|
11
11
|
} from "../core/useLiveChartEngine";
|
|
12
12
|
import type { ChartPadding } from "../draw/line";
|
|
13
13
|
import { usePathBuilder } from "../hooks/usePathBuilder";
|
|
14
|
-
import {
|
|
14
|
+
import {
|
|
15
|
+
EXTREMA_EDGE_INSET,
|
|
16
|
+
EXTREMA_LABEL_FONT_SIZE,
|
|
17
|
+
extremaPointsCoincide,
|
|
18
|
+
} from "./AxisLabelOverlay";
|
|
15
19
|
|
|
16
20
|
/** How far off-plot (px) the extremum may sit before the connector is dropped. */
|
|
17
21
|
const CONNECTOR_CULL = 24;
|
|
@@ -55,6 +59,7 @@ function ConnectorLine({
|
|
|
55
59
|
engine,
|
|
56
60
|
padding,
|
|
57
61
|
config,
|
|
62
|
+
suppressWhen,
|
|
58
63
|
}: {
|
|
59
64
|
side: "top" | "bottom";
|
|
60
65
|
timeSV: SharedValue<number>;
|
|
@@ -63,6 +68,10 @@ function ConnectorLine({
|
|
|
63
68
|
engine: ChartEngineLayout;
|
|
64
69
|
padding: ChartPadding;
|
|
65
70
|
config: ResolvedConnector;
|
|
71
|
+
suppressWhen?: {
|
|
72
|
+
timeSV: SharedValue<number>;
|
|
73
|
+
valueSV: SharedValue<number>;
|
|
74
|
+
};
|
|
66
75
|
}) {
|
|
67
76
|
const builder = usePathBuilder();
|
|
68
77
|
const { line, fontSize } = config;
|
|
@@ -88,6 +97,13 @@ function ConnectorLine({
|
|
|
88
97
|
|
|
89
98
|
if (
|
|
90
99
|
!Number.isFinite(value) ||
|
|
100
|
+
(suppressWhen != null &&
|
|
101
|
+
extremaPointsCoincide(
|
|
102
|
+
time,
|
|
103
|
+
value,
|
|
104
|
+
suppressWhen.timeSV.get(),
|
|
105
|
+
suppressWhen.valueSV.get(),
|
|
106
|
+
)) ||
|
|
91
107
|
cw === 0 ||
|
|
92
108
|
ch === 0 ||
|
|
93
109
|
chartW <= 0 ||
|
|
@@ -153,15 +169,29 @@ export function ExtremaConnectorOverlay({
|
|
|
153
169
|
extremaTimeOffset = 0,
|
|
154
170
|
top,
|
|
155
171
|
bottom,
|
|
172
|
+
hideExtrema = false,
|
|
173
|
+
suppressBottomWhenCoincident = false,
|
|
156
174
|
}: {
|
|
157
175
|
engine: ChartEngineLayout & Partial<ChartEngineExtrema>;
|
|
158
176
|
padding: ChartPadding;
|
|
159
177
|
extremaTimeOffset?: number;
|
|
160
178
|
top: ResolvedConnector | null;
|
|
161
179
|
bottom: ResolvedConnector | null;
|
|
180
|
+
/** Hide extrema connectors while the chart is showing its loading shell. */
|
|
181
|
+
hideExtrema?: boolean;
|
|
182
|
+
/** Drop the lower connector when both configured labels share one point. */
|
|
183
|
+
suppressBottomWhenCoincident?: boolean;
|
|
162
184
|
}) {
|
|
163
|
-
const hasTop =
|
|
164
|
-
|
|
185
|
+
const hasTop =
|
|
186
|
+
!hideExtrema &&
|
|
187
|
+
top != null &&
|
|
188
|
+
engine.extremaMaxTime != null &&
|
|
189
|
+
engine.extremaMaxValue != null;
|
|
190
|
+
const hasBottom =
|
|
191
|
+
!hideExtrema &&
|
|
192
|
+
bottom != null &&
|
|
193
|
+
engine.extremaMinTime != null &&
|
|
194
|
+
engine.extremaMinValue != null;
|
|
165
195
|
if (!hasTop && !hasBottom) return null;
|
|
166
196
|
|
|
167
197
|
return (
|
|
@@ -186,6 +216,16 @@ export function ExtremaConnectorOverlay({
|
|
|
186
216
|
engine={engine}
|
|
187
217
|
padding={padding}
|
|
188
218
|
config={bottom!}
|
|
219
|
+
suppressWhen={
|
|
220
|
+
suppressBottomWhenCoincident &&
|
|
221
|
+
engine.extremaMaxTime != null &&
|
|
222
|
+
engine.extremaMaxValue != null
|
|
223
|
+
? {
|
|
224
|
+
timeSV: engine.extremaMaxTime!,
|
|
225
|
+
valueSV: engine.extremaMaxValue!,
|
|
226
|
+
}
|
|
227
|
+
: undefined
|
|
228
|
+
}
|
|
189
229
|
/>
|
|
190
230
|
)}
|
|
191
231
|
</>
|