react-native-livechart 4.11.0 → 4.13.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/dist/components/CrosshairLine.d.ts +12 -2
- package/dist/components/CrosshairLine.d.ts.map +1 -1
- package/dist/components/CrosshairOverlay.d.ts +12 -2
- package/dist/components/CrosshairOverlay.d.ts.map +1 -1
- package/dist/components/CustomReferenceLineOverlay.d.ts +15 -10
- package/dist/components/CustomReferenceLineOverlay.d.ts.map +1 -1
- package/dist/components/CustomTooltipOverlay.d.ts +5 -2
- package/dist/components/CustomTooltipOverlay.d.ts.map +1 -1
- package/dist/components/DotOverlay.d.ts +3 -5
- package/dist/components/DotOverlay.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/PerSeriesTooltipOverlay.d.ts +21 -0
- package/dist/components/PerSeriesTooltipOverlay.d.ts.map +1 -0
- package/dist/components/ReferenceLineOverlay.d.ts +27 -6
- package/dist/components/ReferenceLineOverlay.d.ts.map +1 -1
- package/dist/components/YAxisOverlay.d.ts +8 -2
- package/dist/components/YAxisOverlay.d.ts.map +1 -1
- package/dist/core/liveIndicatorVisibility.d.ts +9 -0
- package/dist/core/liveIndicatorVisibility.d.ts.map +1 -0
- package/dist/core/resolveConfig.d.ts +45 -0
- package/dist/core/resolveConfig.d.ts.map +1 -1
- package/dist/draw/grid.d.ts +13 -0
- package/dist/draw/grid.d.ts.map +1 -1
- package/dist/hooks/crosshairSeries.d.ts +10 -2
- package/dist/hooks/crosshairSeries.d.ts.map +1 -1
- package/dist/hooks/crosshairShared.d.ts +55 -5
- package/dist/hooks/crosshairShared.d.ts.map +1 -1
- package/dist/hooks/delayedPanGuard.d.ts +66 -8
- package/dist/hooks/delayedPanGuard.d.ts.map +1 -1
- package/dist/hooks/useChartPaths.d.ts +5 -9
- package/dist/hooks/useChartPaths.d.ts.map +1 -1
- package/dist/hooks/useCrosshair.d.ts +13 -1
- package/dist/hooks/useCrosshair.d.ts.map +1 -1
- package/dist/hooks/useCrosshairSeries.d.ts +27 -3
- package/dist/hooks/useCrosshairSeries.d.ts.map +1 -1
- package/dist/hooks/useCrosshairVisibleOpacity.d.ts +8 -0
- package/dist/hooks/useCrosshairVisibleOpacity.d.ts.map +1 -0
- package/dist/hooks/useMomentum.d.ts +1 -1
- package/dist/hooks/useMomentum.d.ts.map +1 -1
- package/dist/hooks/usePanScroll.d.ts +15 -1
- package/dist/hooks/usePanScroll.d.ts.map +1 -1
- package/dist/hooks/useReferenceLine.d.ts +10 -1
- package/dist/hooks/useReferenceLine.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/math/lerp.d.ts.map +1 -1
- package/dist/math/momentum.d.ts +1 -1
- package/dist/math/momentum.d.ts.map +1 -1
- package/dist/math/referenceLines.d.ts +7 -0
- package/dist/math/referenceLines.d.ts.map +1 -1
- package/dist/types.d.ts +207 -18
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/CrosshairLine.tsx +39 -8
- package/src/components/CrosshairOverlay.tsx +49 -15
- package/src/components/CustomReferenceLineOverlay.tsx +42 -13
- package/src/components/CustomTooltipOverlay.tsx +15 -3
- package/src/components/DotOverlay.tsx +24 -8
- package/src/components/LiveChart.tsx +182 -39
- package/src/components/LiveChartSeries.tsx +195 -16
- package/src/components/PerSeriesTooltipOverlay.tsx +290 -0
- package/src/components/ReferenceLineOverlay.tsx +288 -141
- package/src/components/YAxisOverlay.tsx +39 -10
- package/src/core/liveIndicatorVisibility.ts +25 -0
- package/src/core/resolveConfig.ts +115 -0
- package/src/draw/grid.ts +33 -0
- package/src/hooks/crosshairSeries.ts +262 -33
- package/src/hooks/crosshairShared.ts +117 -6
- package/src/hooks/delayedPanGuard.ts +111 -6
- package/src/hooks/useChartPaths.ts +25 -15
- package/src/hooks/useCrosshair.ts +103 -32
- package/src/hooks/useCrosshairSeries.ts +126 -11
- package/src/hooks/useCrosshairVisibleOpacity.ts +57 -0
- package/src/hooks/useMomentum.ts +8 -1
- package/src/hooks/usePanScroll.ts +46 -5
- package/src/hooks/useReferenceLine.ts +26 -1
- package/src/index.ts +1 -0
- package/src/math/lerp.ts +7 -0
- package/src/math/momentum.ts +22 -5
- package/src/math/referenceLines.ts +38 -0
- package/src/types.ts +215 -18
|
@@ -28,7 +28,6 @@ import {
|
|
|
28
28
|
lineStyleSignatureFromArray,
|
|
29
29
|
resolveMultiSeriesLineColorsSnapshot,
|
|
30
30
|
resolveMultiSeriesLineStylesSnapshot,
|
|
31
|
-
type SeriesLineStyle,
|
|
32
31
|
} from "../core/multiSeriesLayout";
|
|
33
32
|
import {
|
|
34
33
|
resolveAxisLabel,
|
|
@@ -53,8 +52,10 @@ import { pulseRadialOutset } from "../draw/line";
|
|
|
53
52
|
import { resolveChartLayout } from "../hooks/resolveChartLayout";
|
|
54
53
|
import { useCanvasLayout } from "../hooks/useCanvasLayout";
|
|
55
54
|
import { useChartReveal } from "../hooks/useChartReveal";
|
|
55
|
+
import { useChartOverlayContext } from "../hooks/useChartOverlayContext";
|
|
56
56
|
import { useChartSkiaFont } from "../hooks/useChartSkiaFont";
|
|
57
57
|
import { useCrosshairSeries } from "../hooks/useCrosshairSeries";
|
|
58
|
+
import { useCrosshairVisibleOpacity } from "../hooks/useCrosshairVisibleOpacity";
|
|
58
59
|
import { useMarkers } from "../hooks/useMarkers";
|
|
59
60
|
import { useMultiSeriesDegen } from "../hooks/useMultiSeriesDegen";
|
|
60
61
|
import { useMultiSeriesLinePaths } from "../hooks/useMultiSeriesLinePaths";
|
|
@@ -70,7 +71,10 @@ import {
|
|
|
70
71
|
} from "../lib/format";
|
|
71
72
|
import { measureFontTextWidth } from "../lib/measureFontTextWidth";
|
|
72
73
|
import { MONO_FONT_FAMILY } from "../lib/monoFontFamily";
|
|
73
|
-
import {
|
|
74
|
+
import {
|
|
75
|
+
collectReferenceValues,
|
|
76
|
+
referenceLineReactKeys,
|
|
77
|
+
} from "../math/referenceLines";
|
|
74
78
|
import {
|
|
75
79
|
applyPaletteOverride,
|
|
76
80
|
leftEdgeFadeColorsFromBgRgb,
|
|
@@ -78,6 +82,7 @@ import {
|
|
|
78
82
|
} from "../theme";
|
|
79
83
|
import type { LiveChartSeriesProps, Marker, SeriesConfig } from "../types";
|
|
80
84
|
import { AxisLabelOverlay } from "./AxisLabelOverlay";
|
|
85
|
+
import { ChartOverlayLayer } from "./ChartOverlayLayer";
|
|
81
86
|
import {
|
|
82
87
|
ExtremaConnectorOverlay,
|
|
83
88
|
labelConnector,
|
|
@@ -96,6 +101,7 @@ import { MultiSeriesDots } from "./MultiSeriesDots";
|
|
|
96
101
|
import { MultiSeriesStroke } from "./MultiSeriesStroke";
|
|
97
102
|
import { MultiSeriesValueLabels } from "./MultiSeriesValueLabels";
|
|
98
103
|
import { MultiSeriesValueLines } from "./MultiSeriesValueLines";
|
|
104
|
+
import { PerSeriesTooltipOverlay } from "./PerSeriesTooltipOverlay";
|
|
99
105
|
import { ReferenceLineOverlay } from "./ReferenceLineOverlay";
|
|
100
106
|
import { SeriesToggleChips } from "./SeriesToggleChips";
|
|
101
107
|
import { XAxisOverlay } from "./XAxisOverlay";
|
|
@@ -177,7 +183,9 @@ function useLiveChartSeriesController({
|
|
|
177
183
|
markerHitRadius = 16,
|
|
178
184
|
markerCluster,
|
|
179
185
|
renderMarker,
|
|
186
|
+
renderOverlay,
|
|
180
187
|
renderReferenceLine,
|
|
188
|
+
renderOffAxisReferenceLine,
|
|
181
189
|
leftEdgeFade = true,
|
|
182
190
|
}: LiveChartSeriesProps) {
|
|
183
191
|
const emptyMarkers = useSharedValue<Marker[]>([]);
|
|
@@ -190,6 +198,10 @@ function useLiveChartSeriesController({
|
|
|
190
198
|
const bottomLabelCfg = resolveAxisLabel(bottomLabel);
|
|
191
199
|
const scrubCfg = resolveScrub(scrub);
|
|
192
200
|
const scrubEnabled = scrubCfg !== null;
|
|
201
|
+
// Opt-in and subordinate to the existing master `tooltip` switch. Keeping
|
|
202
|
+
// this null by default preserves LiveChartSeries' historical guide-only scrub.
|
|
203
|
+
const seriesTooltipCfg =
|
|
204
|
+
scrubCfg?.tooltip === true ? scrubCfg.seriesTooltip : null;
|
|
193
205
|
|
|
194
206
|
// Time-scroll + pinch-zoom (mirrors LiveChart). LiveChartSeries has no static
|
|
195
207
|
// mode, so these gate on the props alone. `holdToScrub` requires the scrub
|
|
@@ -216,8 +228,8 @@ function useLiveChartSeriesController({
|
|
|
216
228
|
|
|
217
229
|
// Multi-series defaults the scrub selection dot OFF: it can only track one
|
|
218
230
|
// line (the leading series), which reads as a bug next to the other series.
|
|
219
|
-
// The crosshair line
|
|
220
|
-
// Passing `selectionDot` explicitly
|
|
231
|
+
// The crosshair line (and the opt-in tooltip's per-series intersection dots)
|
|
232
|
+
// mark the scrub point. Passing `selectionDot` explicitly still opts it in.
|
|
221
233
|
const selectionDotCfg = resolveSelectionDot(selectionDot ?? false);
|
|
222
234
|
const gridStyleCfg = resolveGridStyle(gridStyle);
|
|
223
235
|
const dotCfg = resolveMultiSeriesDot(dotProp);
|
|
@@ -237,6 +249,17 @@ function useLiveChartSeriesController({
|
|
|
237
249
|
allRefLines,
|
|
238
250
|
renderReferenceLine,
|
|
239
251
|
);
|
|
252
|
+
// A full custom tag owns both states, so it takes precedence over an
|
|
253
|
+
// off-axis-only renderer for the same line.
|
|
254
|
+
const refLineOffAxisCustom = customReferenceLineFlags(
|
|
255
|
+
allRefLines,
|
|
256
|
+
renderOffAxisReferenceLine,
|
|
257
|
+
"off-axis",
|
|
258
|
+
).map((custom, index) => custom && !refLineCustom[index]);
|
|
259
|
+
const refLineKeys = referenceLineReactKeys(allRefLines);
|
|
260
|
+
// RN custom tags report their measured widths here so the Skia connector can
|
|
261
|
+
// start after the native badge instead of the hidden built-in pill.
|
|
262
|
+
const refLineCustomTagWidths = useSharedValue<number[]>([]);
|
|
240
263
|
|
|
241
264
|
const palette = applyPaletteOverride(
|
|
242
265
|
resolveTheme(accentColor, theme),
|
|
@@ -266,6 +289,7 @@ function useLiveChartSeriesController({
|
|
|
266
289
|
// render scope for memoization, which trips Reanimated's strict-mode warning;
|
|
267
290
|
// it leaves the `.get()` method call inside the effect.
|
|
268
291
|
// react-doctor-disable-next-line react-hooks-js/set-state-in-effect -- Reanimated: seeding from a SharedValue off render is the warning-free path
|
|
292
|
+
// eslint-disable-next-line react-hooks/set-state-in-effect -- Reanimated: seed from the SharedValue outside render to avoid strict-mode access warnings
|
|
269
293
|
setSeriesSnapshot(series.get().slice());
|
|
270
294
|
}, [series]);
|
|
271
295
|
|
|
@@ -407,6 +431,20 @@ function useLiveChartSeriesController({
|
|
|
407
431
|
skiaFont,
|
|
408
432
|
);
|
|
409
433
|
|
|
434
|
+
// Cross-gesture arbitration for the one-finger touch. `Gesture.Race` below is
|
|
435
|
+
// NOT arbitration — RNGH's Race adds no relation between its children, so both
|
|
436
|
+
// pans recognize independently and each can activate while the other already
|
|
437
|
+
// owns the touch. This latch (written by the scroll pan, read by the scrub's
|
|
438
|
+
// long-press guard) makes "the scroll already won" a hard fact; `scrubActive`
|
|
439
|
+
// (written by the crosshair, read by the scroll pan) is the mirror image.
|
|
440
|
+
const scrollActive = useSharedValue(false);
|
|
441
|
+
// `liveEdge` includes the optional right breathing-room buffer. The time pill
|
|
442
|
+
// must clamp against the real "now" anchor so its live bucket never ends in
|
|
443
|
+
// that future buffer.
|
|
444
|
+
const tooltipMaxTime = useDerivedValue(
|
|
445
|
+
() => engine.liveEdge.get() - windowBuffer * timeWindow,
|
|
446
|
+
);
|
|
447
|
+
|
|
410
448
|
const crosshair = useCrosshairSeries(
|
|
411
449
|
engine,
|
|
412
450
|
effectivePadding,
|
|
@@ -415,6 +453,18 @@ function useLiveChartSeriesController({
|
|
|
415
453
|
scrubHoldMs,
|
|
416
454
|
onGestureStart,
|
|
417
455
|
onGestureEnd,
|
|
456
|
+
scrollActive,
|
|
457
|
+
seriesTooltipCfg
|
|
458
|
+
? {
|
|
459
|
+
config: seriesTooltipCfg,
|
|
460
|
+
formatValue,
|
|
461
|
+
formatTime,
|
|
462
|
+
font: skiaFont,
|
|
463
|
+
colors: lineColors,
|
|
464
|
+
maxTime: tooltipMaxTime,
|
|
465
|
+
}
|
|
466
|
+
: undefined,
|
|
467
|
+
scrubCfg?.clampToPlot ?? false,
|
|
418
468
|
);
|
|
419
469
|
|
|
420
470
|
// Capture only the shared value in the worklets below. Referencing
|
|
@@ -458,6 +508,10 @@ function useLiveChartSeriesController({
|
|
|
458
508
|
minTime: scrollMinTime,
|
|
459
509
|
enabled: timeScrollEnabled,
|
|
460
510
|
mode: scrollGestureMode,
|
|
511
|
+
scrollActive,
|
|
512
|
+
// Once a scrub is engaged the chart is locked: scrolling goes inert so the
|
|
513
|
+
// finger only moves the price indicator across a fixed window.
|
|
514
|
+
scrubActive: crosshairScrubActive,
|
|
461
515
|
onScrollStart: () => {
|
|
462
516
|
"worklet";
|
|
463
517
|
crosshairScrubActive.set(false);
|
|
@@ -535,6 +589,7 @@ function useLiveChartSeriesController({
|
|
|
535
589
|
yAxisCfg,
|
|
536
590
|
xAxisCfg,
|
|
537
591
|
scrubCfg,
|
|
592
|
+
seriesTooltipCfg,
|
|
538
593
|
gridStyleCfg,
|
|
539
594
|
dotCfg,
|
|
540
595
|
dotOuterRadius,
|
|
@@ -542,7 +597,10 @@ function useLiveChartSeriesController({
|
|
|
542
597
|
degenCfg,
|
|
543
598
|
metricsCfg,
|
|
544
599
|
allRefLines,
|
|
600
|
+
refLineKeys,
|
|
545
601
|
refLineCustom,
|
|
602
|
+
refLineOffAxisCustom,
|
|
603
|
+
refLineCustomTagWidths,
|
|
546
604
|
leftEdgeFadeCfg,
|
|
547
605
|
// theme / layout / fonts
|
|
548
606
|
palette,
|
|
@@ -580,7 +638,9 @@ function useLiveChartSeriesController({
|
|
|
580
638
|
markerGroupOpacity,
|
|
581
639
|
overlayScrubFade,
|
|
582
640
|
renderMarker,
|
|
641
|
+
renderOverlay,
|
|
583
642
|
renderReferenceLine,
|
|
643
|
+
renderOffAxisReferenceLine,
|
|
584
644
|
// selection dot: resolved config + fallback color (the leading series' color)
|
|
585
645
|
selectionDot: selectionDotCfg,
|
|
586
646
|
selectionColor: lineColors[0],
|
|
@@ -638,6 +698,7 @@ function SeriesChartStack({ model }: { model: LiveChartSeriesModel }) {
|
|
|
638
698
|
loadingSpeed,
|
|
639
699
|
canvasMode,
|
|
640
700
|
activeSeriesCount,
|
|
701
|
+
refLineKeys,
|
|
641
702
|
} = model;
|
|
642
703
|
|
|
643
704
|
return (
|
|
@@ -653,25 +714,27 @@ function SeriesChartStack({ model }: { model: LiveChartSeriesModel }) {
|
|
|
653
714
|
badge={false}
|
|
654
715
|
seriesLabelInset={seriesLabelInset}
|
|
655
716
|
gridStyle={gridStyleCfg}
|
|
717
|
+
labelRightMargin={yAxisCfg.labelRightMargin}
|
|
718
|
+
gridEndGap={yAxisCfg.gridEndGap}
|
|
656
719
|
/>
|
|
657
720
|
</Group>
|
|
658
721
|
)}
|
|
659
722
|
|
|
660
|
-
{/*
|
|
661
|
-
|
|
662
|
-
keep both orders mounted without collapsing them to one React child.
|
|
663
|
-
Fade group lets `scrub.hideOverlaysOnScrub` ease the lines out. */}
|
|
723
|
+
{/* Fade group lets `scrub.hideOverlaysOnScrub` ease the lines out. Explicit
|
|
724
|
+
ids keep each reference line mounted when the caller reorders it. */}
|
|
664
725
|
<Group opacity={overlayScrubFade}>
|
|
665
726
|
{allRefLines.map((rl, i) => (
|
|
666
|
-
/* react-doctor-disable-next-line react-doctor/no-array-index-as-key */
|
|
667
727
|
<ReferenceLineOverlay
|
|
668
|
-
key={i}
|
|
728
|
+
key={refLineKeys[i]}
|
|
669
729
|
engine={engine}
|
|
670
730
|
padding={effectivePadding}
|
|
671
731
|
line={rl}
|
|
672
732
|
palette={palette}
|
|
673
733
|
formatValue={formatValue}
|
|
674
734
|
font={skiaFont}
|
|
735
|
+
yAxisEntries={yAxisEntries}
|
|
736
|
+
labelRightMargin={yAxisCfg?.labelRightMargin}
|
|
737
|
+
gridEndGap={yAxisCfg?.gridEndGap}
|
|
675
738
|
/>
|
|
676
739
|
))}
|
|
677
740
|
</Group>
|
|
@@ -823,23 +886,26 @@ function SeriesValueLabelLayer({ model }: { model: LiveChartSeriesModel }) {
|
|
|
823
886
|
function SeriesRefBadgeLayer({ model }: { model: LiveChartSeriesModel }) {
|
|
824
887
|
const {
|
|
825
888
|
allRefLines,
|
|
889
|
+
refLineKeys,
|
|
826
890
|
refLineCustom,
|
|
891
|
+
refLineOffAxisCustom,
|
|
892
|
+
refLineCustomTagWidths,
|
|
827
893
|
engine,
|
|
828
894
|
effectivePadding,
|
|
829
895
|
palette,
|
|
830
896
|
formatValue,
|
|
831
897
|
skiaFont,
|
|
898
|
+
yAxisCfg,
|
|
899
|
+
yAxisEntries,
|
|
832
900
|
degenShakeTransform,
|
|
833
901
|
overlayScrubFade,
|
|
834
|
-
canvasMode,
|
|
835
902
|
} = model;
|
|
836
903
|
if (allRefLines.length === 0) return null;
|
|
837
904
|
return (
|
|
838
905
|
<Group transform={degenShakeTransform} opacity={overlayScrubFade}>
|
|
839
906
|
{allRefLines.map((rl, i) => (
|
|
840
|
-
/* react-doctor-disable-next-line react-doctor/no-array-index-as-key */
|
|
841
907
|
<ReferenceLineOverlay
|
|
842
|
-
key={i}
|
|
908
|
+
key={refLineKeys[i]}
|
|
843
909
|
engine={engine}
|
|
844
910
|
padding={effectivePadding}
|
|
845
911
|
line={rl}
|
|
@@ -848,12 +914,71 @@ function SeriesRefBadgeLayer({ model }: { model: LiveChartSeriesModel }) {
|
|
|
848
914
|
font={skiaFont}
|
|
849
915
|
badgeLayer
|
|
850
916
|
suppressTag={refLineCustom[i]}
|
|
917
|
+
suppressTagWhenOffAxis={refLineOffAxisCustom[i]}
|
|
918
|
+
customTagWidths={refLineCustomTagWidths}
|
|
919
|
+
yAxisEntries={yAxisEntries}
|
|
920
|
+
labelRightMargin={yAxisCfg?.labelRightMargin}
|
|
921
|
+
gridEndGap={yAxisCfg?.gridEndGap}
|
|
851
922
|
/>
|
|
852
923
|
))}
|
|
853
924
|
</Group>
|
|
854
925
|
);
|
|
855
926
|
}
|
|
856
927
|
|
|
928
|
+
/** Owns the price/time projection worklets for the multi-series custom overlay. */
|
|
929
|
+
function SeriesCustomConsumerOverlay({ model }: { model: LiveChartSeriesModel }) {
|
|
930
|
+
const { engine, effectivePadding, renderOverlay } = model;
|
|
931
|
+
const overlayContext = useChartOverlayContext(engine, effectivePadding);
|
|
932
|
+
return <ChartOverlayLayer render={renderOverlay!} context={overlayContext} />;
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
/** Keeps the extra fade mapper opt-in with the per-series tooltip itself. */
|
|
936
|
+
function SeriesTooltipLayer({
|
|
937
|
+
model,
|
|
938
|
+
config,
|
|
939
|
+
}: {
|
|
940
|
+
model: LiveChartSeriesModel;
|
|
941
|
+
config: NonNullable<LiveChartSeriesModel["seriesTooltipCfg"]>;
|
|
942
|
+
}) {
|
|
943
|
+
const {
|
|
944
|
+
crosshair,
|
|
945
|
+
engine,
|
|
946
|
+
effectivePadding,
|
|
947
|
+
scrubCfg,
|
|
948
|
+
skiaFont,
|
|
949
|
+
palette,
|
|
950
|
+
activeSeriesCount,
|
|
951
|
+
} = model;
|
|
952
|
+
const activeOpacity = useCrosshairVisibleOpacity(
|
|
953
|
+
crosshair.scrubX,
|
|
954
|
+
engine.canvasWidth,
|
|
955
|
+
effectivePadding.right,
|
|
956
|
+
crosshair.scrubActive,
|
|
957
|
+
scrubCfg?.crosshairFade ?? true,
|
|
958
|
+
scrubCfg?.crosshairFadeDistance ?? 4,
|
|
959
|
+
);
|
|
960
|
+
const scrubActive = crosshair.scrubActive;
|
|
961
|
+
const alwaysShow = config.alwaysShow;
|
|
962
|
+
const opacity = useDerivedValue(
|
|
963
|
+
() => (scrubActive.get() ? activeOpacity.get() : alwaysShow ? 1 : 0),
|
|
964
|
+
[scrubActive, activeOpacity, alwaysShow],
|
|
965
|
+
);
|
|
966
|
+
|
|
967
|
+
return (
|
|
968
|
+
<PerSeriesTooltipOverlay
|
|
969
|
+
layout={crosshair.tooltipLayout}
|
|
970
|
+
font={skiaFont}
|
|
971
|
+
palette={palette}
|
|
972
|
+
config={config}
|
|
973
|
+
seriesCount={activeSeriesCount}
|
|
974
|
+
opacity={opacity}
|
|
975
|
+
tooltipBackground={scrubCfg?.tooltipBackground}
|
|
976
|
+
tooltipColor={scrubCfg?.tooltipColor}
|
|
977
|
+
tooltipBorderColor={scrubCfg?.tooltipBorderColor}
|
|
978
|
+
/>
|
|
979
|
+
);
|
|
980
|
+
}
|
|
981
|
+
|
|
857
982
|
export function LiveChartSeries(props: LiveChartSeriesProps) {
|
|
858
983
|
const model = useLiveChartSeriesController(props);
|
|
859
984
|
const {
|
|
@@ -871,6 +996,7 @@ export function LiveChartSeries(props: LiveChartSeriesProps) {
|
|
|
871
996
|
effectivePadding,
|
|
872
997
|
engine,
|
|
873
998
|
scrubCfg,
|
|
999
|
+
seriesTooltipCfg,
|
|
874
1000
|
crosshair,
|
|
875
1001
|
palette,
|
|
876
1002
|
dotCfg,
|
|
@@ -886,9 +1012,13 @@ export function LiveChartSeries(props: LiveChartSeriesProps) {
|
|
|
886
1012
|
markersSV,
|
|
887
1013
|
markerClusterCfg,
|
|
888
1014
|
renderMarker,
|
|
1015
|
+
renderOverlay,
|
|
889
1016
|
renderReferenceLine,
|
|
1017
|
+
renderOffAxisReferenceLine,
|
|
890
1018
|
allRefLines,
|
|
891
1019
|
refLineCustom,
|
|
1020
|
+
refLineOffAxisCustom,
|
|
1021
|
+
refLineCustomTagWidths,
|
|
892
1022
|
overlayScrubFade,
|
|
893
1023
|
canvasMode,
|
|
894
1024
|
} = model;
|
|
@@ -988,8 +1118,23 @@ export function LiveChartSeries(props: LiveChartSeriesProps) {
|
|
|
988
1118
|
selectionColor={selectionColor}
|
|
989
1119
|
dimOpacity={scrubCfg.dimOpacity}
|
|
990
1120
|
liveDotExtent={liveDotExtent}
|
|
991
|
-
crosshairLineColor={
|
|
992
|
-
|
|
1121
|
+
crosshairLineColor={
|
|
1122
|
+
seriesTooltipCfg?.guideColor ??
|
|
1123
|
+
scrubCfg.crosshairLineColor
|
|
1124
|
+
}
|
|
1125
|
+
crosshairStrokeWidth={
|
|
1126
|
+
seriesTooltipCfg?.guideWidth ??
|
|
1127
|
+
scrubCfg.crosshairStrokeWidth
|
|
1128
|
+
}
|
|
1129
|
+
crosshairOvershoot={scrubCfg.crosshairOvershoot}
|
|
1130
|
+
crosshairFade={scrubCfg.crosshairFade}
|
|
1131
|
+
crosshairFadeDistance={scrubCfg.crosshairFadeDistance}
|
|
1132
|
+
crosshairLineCap={scrubCfg.crosshairLineCap}
|
|
1133
|
+
crosshairDash={
|
|
1134
|
+
seriesTooltipCfg
|
|
1135
|
+
? seriesTooltipCfg.guideDashPattern
|
|
1136
|
+
: scrubCfg.crosshairDash
|
|
1137
|
+
}
|
|
993
1138
|
crosshairDimColor={scrubCfg.crosshairDimColor}
|
|
994
1139
|
opaqueCanvas={canvasMode === "opaque"}
|
|
995
1140
|
/>
|
|
@@ -1017,7 +1162,8 @@ export function LiveChartSeries(props: LiveChartSeriesProps) {
|
|
|
1017
1162
|
above the left-edge fade and scrub overlay. The box-none fade wrapper
|
|
1018
1163
|
keeps `scrub.hideOverlaysOnScrub` behavior aligned with Skia. */}
|
|
1019
1164
|
{((markersActive && renderMarker) ||
|
|
1020
|
-
(renderReferenceLine
|
|
1165
|
+
((renderReferenceLine || renderOffAxisReferenceLine) &&
|
|
1166
|
+
allRefLines.length > 0)) && (
|
|
1021
1167
|
<Animated.View
|
|
1022
1168
|
pointerEvents="box-none"
|
|
1023
1169
|
style={[StyleSheet.absoluteFill, overlayFadeStyle]}
|
|
@@ -1040,10 +1186,43 @@ export function LiveChartSeries(props: LiveChartSeriesProps) {
|
|
|
1040
1186
|
engine={engine}
|
|
1041
1187
|
padding={effectivePadding}
|
|
1042
1188
|
formatValue={formatValue}
|
|
1189
|
+
tagWidths={refLineCustomTagWidths}
|
|
1190
|
+
/>
|
|
1191
|
+
)}
|
|
1192
|
+
{renderOffAxisReferenceLine && allRefLines.length > 0 && (
|
|
1193
|
+
<CustomReferenceLineOverlay
|
|
1194
|
+
lines={allRefLines}
|
|
1195
|
+
renderReferenceLine={renderOffAxisReferenceLine}
|
|
1196
|
+
custom={refLineOffAxisCustom}
|
|
1197
|
+
engine={engine}
|
|
1198
|
+
padding={effectivePadding}
|
|
1199
|
+
formatValue={formatValue}
|
|
1200
|
+
tagWidths={refLineCustomTagWidths}
|
|
1201
|
+
offAxisOnly
|
|
1043
1202
|
/>
|
|
1044
1203
|
)}
|
|
1045
1204
|
</Animated.View>
|
|
1046
1205
|
)}
|
|
1206
|
+
|
|
1207
|
+
{/* A dedicated transparent Canvas keeps the UI-thread tooltip above
|
|
1208
|
+
custom RN annotations. Rendering it in the primary Canvas would
|
|
1209
|
+
put every post-Canvas `renderReferenceLine` sibling above it and
|
|
1210
|
+
produce mixed stacking through translucent custom tags. */}
|
|
1211
|
+
{seriesTooltipCfg && (
|
|
1212
|
+
<View
|
|
1213
|
+
testID="live-chart-series-tooltip-overlay"
|
|
1214
|
+
pointerEvents="none"
|
|
1215
|
+
style={StyleSheet.absoluteFill}
|
|
1216
|
+
>
|
|
1217
|
+
<Canvas style={StyleSheet.absoluteFill}>
|
|
1218
|
+
<SeriesTooltipLayer model={model} config={seriesTooltipCfg} />
|
|
1219
|
+
</Canvas>
|
|
1220
|
+
</View>
|
|
1221
|
+
)}
|
|
1222
|
+
|
|
1223
|
+
{/* Custom consumer overlay — topmost RN sibling with the live plot
|
|
1224
|
+
rect, including this multi-series chart's resolved axis inset. */}
|
|
1225
|
+
{renderOverlay && <SeriesCustomConsumerOverlay model={model} />}
|
|
1047
1226
|
</View>
|
|
1048
1227
|
</GestureDetector>
|
|
1049
1228
|
{legendCfg.position === "bottom" ? legend : null}
|