react-native-livechart 4.11.0 → 4.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/dist/components/CrosshairLine.d.ts +3 -1
- package/dist/components/CrosshairLine.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/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 +19 -0
- package/dist/components/PerSeriesTooltipOverlay.d.ts.map +1 -0
- package/dist/components/ReferenceLineOverlay.d.ts +20 -6
- package/dist/components/ReferenceLineOverlay.d.ts.map +1 -1
- package/dist/components/YAxisOverlay.d.ts +3 -1
- 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 +29 -0
- package/dist/core/resolveConfig.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 +33 -2
- 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 +7 -1
- package/dist/hooks/useCrosshair.d.ts.map +1 -1
- package/dist/hooks/useCrosshairSeries.d.ts +22 -3
- package/dist/hooks/useCrosshairSeries.d.ts.map +1 -1
- 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/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 +160 -18
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/CrosshairLine.tsx +4 -1
- package/src/components/CustomReferenceLineOverlay.tsx +42 -13
- package/src/components/DotOverlay.tsx +24 -8
- package/src/components/LiveChart.tsx +157 -37
- package/src/components/LiveChartSeries.tsx +128 -16
- package/src/components/PerSeriesTooltipOverlay.tsx +287 -0
- package/src/components/ReferenceLineOverlay.tsx +274 -141
- package/src/components/YAxisOverlay.tsx +5 -1
- package/src/core/liveIndicatorVisibility.ts +25 -0
- package/src/core/resolveConfig.ts +86 -0
- package/src/hooks/crosshairSeries.ts +262 -33
- package/src/hooks/crosshairShared.ts +36 -2
- package/src/hooks/delayedPanGuard.ts +111 -6
- package/src/hooks/useChartPaths.ts +25 -15
- package/src/hooks/useCrosshair.ts +57 -4
- package/src/hooks/useCrosshairSeries.ts +95 -7
- package/src/hooks/useMomentum.ts +8 -1
- package/src/hooks/usePanScroll.ts +46 -5
- 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 +168 -18
|
@@ -58,7 +58,11 @@ import {
|
|
|
58
58
|
resolveYAxis,
|
|
59
59
|
} from "../core/resolveConfig";
|
|
60
60
|
import type { ResolvedThresholdConfig } from "../core/resolveConfig";
|
|
61
|
-
import {
|
|
61
|
+
import {
|
|
62
|
+
liveIndicatorScrollOpacity,
|
|
63
|
+
resolveHideLiveOnScrollBack,
|
|
64
|
+
} from "../core/liveIndicatorVisibility";
|
|
65
|
+
import { resolveSegment, type ResolvedSegment } from "../core/resolveSegment";
|
|
62
66
|
import { useLiveChartEngine } from "../core/useLiveChartEngine";
|
|
63
67
|
import { pulseRadialOutset } from "../draw/line";
|
|
64
68
|
import { resolveChartLayout } from "../hooks/resolveChartLayout";
|
|
@@ -78,7 +82,10 @@ import { useMarkers } from "../hooks/useMarkers";
|
|
|
78
82
|
import { useReferenceDrag } from "../hooks/useReferenceDrag";
|
|
79
83
|
import { useReferenceLinePress } from "../hooks/useReferenceLinePress";
|
|
80
84
|
import { useModeBlend } from "../hooks/useModeBlend";
|
|
81
|
-
import {
|
|
85
|
+
import {
|
|
86
|
+
resolveMomentumProp,
|
|
87
|
+
useMomentum,
|
|
88
|
+
} from "../hooks/useMomentum";
|
|
82
89
|
import { AXIS_GRAB_MIN_PX, usePanScroll } from "../hooks/usePanScroll";
|
|
83
90
|
import { usePinchZoom } from "../hooks/usePinchZoom";
|
|
84
91
|
import { useVisibleRange } from "../hooks/useVisibleRange";
|
|
@@ -105,6 +112,7 @@ import {
|
|
|
105
112
|
import {
|
|
106
113
|
collectReferenceValues,
|
|
107
114
|
referenceLineForm,
|
|
115
|
+
referenceLineReactKeys,
|
|
108
116
|
resolveReferenceGroupBadge,
|
|
109
117
|
} from "../math/referenceLines";
|
|
110
118
|
import {
|
|
@@ -311,6 +319,7 @@ function useLiveChartController({
|
|
|
311
319
|
renderTooltip,
|
|
312
320
|
renderOverlay,
|
|
313
321
|
renderReferenceLine,
|
|
322
|
+
renderOffAxisReferenceLine,
|
|
314
323
|
referenceLineGrouping,
|
|
315
324
|
leftEdgeFade = true,
|
|
316
325
|
|
|
@@ -387,18 +396,18 @@ function useLiveChartController({
|
|
|
387
396
|
const seededRef = useRef<(number | undefined)[]>([]);
|
|
388
397
|
const refValueSig = allRefLines.map((l) => l.value ?? "_").join(",");
|
|
389
398
|
useEffect(() => {
|
|
390
|
-
const active = dragActive.
|
|
391
|
-
const cur = dragValues.
|
|
399
|
+
const active = dragActive.get();
|
|
400
|
+
const cur = dragValues.get();
|
|
392
401
|
const seeded = seededRef.current;
|
|
393
|
-
dragValues.
|
|
402
|
+
dragValues.set(allRefLines.map((l, i) => {
|
|
394
403
|
const prop = l.value ?? 0;
|
|
395
404
|
if (active[i]) return cur[i] ?? prop; // mid-drag → keep the dragged value
|
|
396
405
|
if (l.value !== seeded[i]) return prop; // prop changed → adopt (controlled)
|
|
397
406
|
return cur[i] ?? prop; // unchanged → keep current (uncontrolled persist)
|
|
398
|
-
});
|
|
407
|
+
}));
|
|
399
408
|
seededRef.current = allRefLines.map((l) => l.value);
|
|
400
|
-
if (dragActive.
|
|
401
|
-
dragActive.
|
|
409
|
+
if (dragActive.get().length !== allRefLines.length) {
|
|
410
|
+
dragActive.set(allRefLines.map((_, i) => active[i] ?? false));
|
|
402
411
|
}
|
|
403
412
|
// allRefLines is rebuilt every render; key off the value signature + length.
|
|
404
413
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
@@ -410,6 +419,17 @@ function useLiveChartController({
|
|
|
410
419
|
allRefLines,
|
|
411
420
|
renderReferenceLine,
|
|
412
421
|
);
|
|
422
|
+
// An off-axis renderer replaces only the edge-pinned tag. A full custom tag
|
|
423
|
+
// takes precedence for the same line to avoid mounting two native tags.
|
|
424
|
+
const refLineOffAxisCustom = customReferenceLineFlags(
|
|
425
|
+
allRefLines,
|
|
426
|
+
renderOffAxisReferenceLine,
|
|
427
|
+
"off-axis",
|
|
428
|
+
).map((custom, index) => custom && !refLineCustom[index]);
|
|
429
|
+
const refLineKeys = referenceLineReactKeys(allRefLines);
|
|
430
|
+
// RN custom tags report their measured widths here so the Skia connector can
|
|
431
|
+
// start after the native badge instead of the hidden built-in pill.
|
|
432
|
+
const refLineCustomTagWidths = useSharedValue<number[]>([]);
|
|
413
433
|
|
|
414
434
|
// Live Y values of the *draggable* Form-A lines, folded into the engine's
|
|
415
435
|
// axis-range fit so dragging a line toward / past the visible edge expands the
|
|
@@ -421,13 +441,17 @@ function useLiveChartController({
|
|
|
421
441
|
// contributes its live value; a series contributes its window min/max
|
|
422
442
|
// (respecting `extendToNow`), so an off-range break-even expands the axis and
|
|
423
443
|
// stays on-plot like a reference line would.
|
|
424
|
-
const draggableRefIdx =
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
444
|
+
const draggableRefIdx: number[] = [];
|
|
445
|
+
for (let i = 0; i < allRefLines.length; i++) {
|
|
446
|
+
const line = allRefLines[i];
|
|
447
|
+
if (
|
|
448
|
+
line.draggable &&
|
|
449
|
+
!line.excludeFromRange &&
|
|
450
|
+
referenceLineForm(line) === "line"
|
|
451
|
+
) {
|
|
452
|
+
draggableRefIdx.push(i);
|
|
453
|
+
}
|
|
454
|
+
}
|
|
431
455
|
const thresholdInRange = thresholdCfg?.includeInRange === true;
|
|
432
456
|
// Constant benchmark → its live value rides this channel. A series threshold
|
|
433
457
|
// is folded inside the engine tick instead (`thresholdRangePoints`), which
|
|
@@ -572,6 +596,7 @@ function useLiveChartController({
|
|
|
572
596
|
// react-doctor-disable-next-line react-doctor/no-derived-state-effect -- Reanimated: must read the SharedValue off the render path
|
|
573
597
|
useLayoutEffect(() => {
|
|
574
598
|
// react-doctor-disable-next-line react-hooks-js/set-state-in-effect -- Reanimated: seeding from a SharedValue off render is the warning-free path
|
|
599
|
+
// eslint-disable-next-line react-hooks/set-state-in-effect -- Reanimated: seed from the SharedValue outside render to avoid strict-mode access warnings
|
|
575
600
|
setValueLayoutSample(value.get());
|
|
576
601
|
}, [value]);
|
|
577
602
|
|
|
@@ -721,7 +746,7 @@ function useLiveChartController({
|
|
|
721
746
|
if (
|
|
722
747
|
referenceLineForm(l) !== "line" ||
|
|
723
748
|
l.value === undefined ||
|
|
724
|
-
refLineCustom[i]
|
|
749
|
+
refLineCustom[i] || refLineOffAxisCustom[i]
|
|
725
750
|
) {
|
|
726
751
|
ys.push(-1);
|
|
727
752
|
continue;
|
|
@@ -866,11 +891,8 @@ function useLiveChartController({
|
|
|
866
891
|
// polyline passed as the last arg below).
|
|
867
892
|
thresholdCfg?.fill && !thresholdIsSeries ? thresholdGeom.lineY : undefined,
|
|
868
893
|
lineIsLinear,
|
|
869
|
-
//
|
|
870
|
-
//
|
|
871
|
-
// live value when `followViewEdge` tracks the scrolled-back window.
|
|
872
|
-
engine.edgeValue,
|
|
873
|
-
badgeCfg?.followViewEdge ?? false,
|
|
894
|
+
// The plotted line independently selects the visible edge while historical;
|
|
895
|
+
// badge/live-indicator options affect overlays only.
|
|
874
896
|
// Match the standalone loading squiggle's wave during the reveal morph.
|
|
875
897
|
loadingCfg?.amplitude,
|
|
876
898
|
loadingCfg?.speed,
|
|
@@ -906,6 +928,15 @@ function useLiveChartController({
|
|
|
906
928
|
);
|
|
907
929
|
|
|
908
930
|
const momentumSV = useMomentum(engine, momentum);
|
|
931
|
+
// A follow-edge badge must derive its color from the same historical point
|
|
932
|
+
// as its value and position. While following live, reuse the normal momentum
|
|
933
|
+
// result; while scrolled back, detect against the data prefix ending at the
|
|
934
|
+
// visible right-edge timestamp so incoming live ticks cannot change the pill.
|
|
935
|
+
const badgeMomentumSV = useDerivedValue(() =>
|
|
936
|
+
badgeCfg?.followViewEdge && engine.viewEnd.value !== null
|
|
937
|
+
? resolveMomentumProp(momentum, engine.data.value, engine.timestamp.value)
|
|
938
|
+
: momentumSV.value,
|
|
939
|
+
);
|
|
909
940
|
|
|
910
941
|
// ── Overlay hooks ─────────────────────────────────────────────────────
|
|
911
942
|
// Scrub/crosshair must see the same stash-backed candles as the engine.
|
|
@@ -997,6 +1028,14 @@ function useLiveChartController({
|
|
|
997
1028
|
? (timeScrollHoldMs ?? (scrubCfg?.panGestureDelay || HOLD_TO_SCRUB_MS))
|
|
998
1029
|
: (scrubCfg?.panGestureDelay ?? 0);
|
|
999
1030
|
|
|
1031
|
+
// Cross-gesture arbitration for the one-finger touch. `Gesture.Race` below is
|
|
1032
|
+
// NOT arbitration — RNGH's Race adds no relation between its children, so both
|
|
1033
|
+
// pans recognize independently and each can activate while the other already
|
|
1034
|
+
// owns the touch. This latch (written by the scroll pan, read by the scrub's
|
|
1035
|
+
// long-press guard) makes "the scroll already won" a hard fact; `scrubActive`
|
|
1036
|
+
// (written by the crosshair, read by the scroll pan) is the mirror image.
|
|
1037
|
+
const scrollActive = useSharedValue(false);
|
|
1038
|
+
|
|
1000
1039
|
const crosshair = useCrosshair(
|
|
1001
1040
|
engine,
|
|
1002
1041
|
effectivePadding,
|
|
@@ -1026,6 +1065,7 @@ function useLiveChartController({
|
|
|
1026
1065
|
timeScrollEnabled && scrollGestureMode === "axisDrag"
|
|
1027
1066
|
? Math.max(effectivePadding.bottom, AXIS_GRAB_MIN_PX)
|
|
1028
1067
|
: 0,
|
|
1068
|
+
scrollActive,
|
|
1029
1069
|
);
|
|
1030
1070
|
|
|
1031
1071
|
// Capture only the shared value in the worklets below. Referencing
|
|
@@ -1048,6 +1088,10 @@ function useLiveChartController({
|
|
|
1048
1088
|
minTime: scrollMinTime,
|
|
1049
1089
|
enabled: timeScrollEnabled,
|
|
1050
1090
|
mode: scrollGestureMode,
|
|
1091
|
+
scrollActive,
|
|
1092
|
+
// Once a scrub is engaged the chart is locked: scrolling goes inert so the
|
|
1093
|
+
// finger only moves the price indicator across a fixed window.
|
|
1094
|
+
scrubActive: crosshairScrubActive,
|
|
1051
1095
|
// Clear any live crosshair when a scroll drag takes over.
|
|
1052
1096
|
onScrollStart: () => {
|
|
1053
1097
|
"worklet";
|
|
@@ -1172,10 +1216,40 @@ function useLiveChartController({
|
|
|
1172
1216
|
// point instead — otherwise both dots show at once. Applies on static charts
|
|
1173
1217
|
// too, now that they're scrubbable.
|
|
1174
1218
|
const selectionDotDuringScrub = scrubCfg !== null && selectionDotCfg !== null;
|
|
1219
|
+
// While scrolled back, the badge, dot, and value line still point at the live
|
|
1220
|
+
// price even though the window is showing history. Hide that live-priced group
|
|
1221
|
+
// together. `badge.followViewEdge` opts back in because all three then track
|
|
1222
|
+
// the visible edge price; `hideLiveOnScrollBack: false` keeps the legacy group.
|
|
1223
|
+
const hideLiveOnScrollBack = resolveHideLiveOnScrollBack(
|
|
1224
|
+
timeScroll,
|
|
1225
|
+
badgeCfg?.followViewEdge ?? false,
|
|
1226
|
+
);
|
|
1175
1227
|
const liveDotOpacity = useDerivedValue(
|
|
1176
1228
|
() =>
|
|
1177
1229
|
reveal.dotOpacity.value *
|
|
1178
|
-
(selectionDotDuringScrub && crosshairScrubActive.value ? 0 : 1)
|
|
1230
|
+
(selectionDotDuringScrub && crosshairScrubActive.value ? 0 : 1) *
|
|
1231
|
+
liveIndicatorScrollOpacity(
|
|
1232
|
+
hideLiveOnScrollBack,
|
|
1233
|
+
engine.viewEnd.value,
|
|
1234
|
+
),
|
|
1235
|
+
);
|
|
1236
|
+
// Same scrolled-back gating for the value line: it would draw a dashed line
|
|
1237
|
+
// at the live value's Y — a price that isn't in the scrolled-back view.
|
|
1238
|
+
const valueLineOpacity = useDerivedValue(
|
|
1239
|
+
() =>
|
|
1240
|
+
reveal.lineOpacity.value *
|
|
1241
|
+
liveIndicatorScrollOpacity(
|
|
1242
|
+
hideLiveOnScrollBack,
|
|
1243
|
+
engine.viewEnd.value,
|
|
1244
|
+
),
|
|
1245
|
+
);
|
|
1246
|
+
const liveBadgeOpacity = useDerivedValue(
|
|
1247
|
+
() =>
|
|
1248
|
+
reveal.badgeOpacity.value *
|
|
1249
|
+
liveIndicatorScrollOpacity(
|
|
1250
|
+
hideLiveOnScrollBack,
|
|
1251
|
+
engine.viewEnd.value,
|
|
1252
|
+
),
|
|
1179
1253
|
);
|
|
1180
1254
|
|
|
1181
1255
|
// Fade the annotation overlays (markers + reference lines) out while scrubbing
|
|
@@ -1235,10 +1309,14 @@ function useLiveChartController({
|
|
|
1235
1309
|
leftEdgeFadeCfg,
|
|
1236
1310
|
metricsCfg,
|
|
1237
1311
|
allRefLines,
|
|
1312
|
+
refLineKeys,
|
|
1238
1313
|
refLineCustom,
|
|
1314
|
+
refLineOffAxisCustom,
|
|
1315
|
+
refLineCustomTagWidths,
|
|
1239
1316
|
dragValues,
|
|
1240
1317
|
dragActive,
|
|
1241
1318
|
renderReferenceLine,
|
|
1319
|
+
renderOffAxisReferenceLine,
|
|
1242
1320
|
refGroupingActive: refGroupingRadius != null,
|
|
1243
1321
|
refGroupResult,
|
|
1244
1322
|
groupHidden,
|
|
@@ -1311,9 +1389,12 @@ function useLiveChartController({
|
|
|
1311
1389
|
dotX,
|
|
1312
1390
|
dotY,
|
|
1313
1391
|
liveDotOpacity,
|
|
1392
|
+
valueLineOpacity,
|
|
1393
|
+
liveBadgeOpacity,
|
|
1314
1394
|
overlayScrubFade,
|
|
1315
1395
|
markerGroupOpacity,
|
|
1316
1396
|
momentumSV,
|
|
1397
|
+
badgeMomentumSV,
|
|
1317
1398
|
onDegenShake,
|
|
1318
1399
|
crosshair,
|
|
1319
1400
|
rootGesture,
|
|
@@ -1414,6 +1495,7 @@ function ChartYAxisLayer({
|
|
|
1414
1495
|
metricsCfg,
|
|
1415
1496
|
gridStyleCfg,
|
|
1416
1497
|
yAxisFloat,
|
|
1498
|
+
liveBadgeOpacity,
|
|
1417
1499
|
} = model;
|
|
1418
1500
|
return (
|
|
1419
1501
|
<Group opacity={reveal.yAxisOpacity}>
|
|
@@ -1431,6 +1513,7 @@ function ChartYAxisLayer({
|
|
|
1431
1513
|
badgeCenterY={badgeUsesRightGutter ? dotY : undefined}
|
|
1432
1514
|
badgeFontSize={badgeUsesRightGutter ? badgeFont.getSize() : undefined}
|
|
1433
1515
|
badgeOffsetY={badgeCfg?.offsetY ?? 0}
|
|
1516
|
+
badgeOpacity={badgeUsesRightGutter ? liveBadgeOpacity : undefined}
|
|
1434
1517
|
gridStyle={gridStyleCfg}
|
|
1435
1518
|
/>
|
|
1436
1519
|
</Group>
|
|
@@ -1670,8 +1753,10 @@ function ChartStack({
|
|
|
1670
1753
|
fontProp,
|
|
1671
1754
|
badgeCfg,
|
|
1672
1755
|
valueLineCfg,
|
|
1756
|
+
valueLineOpacity,
|
|
1673
1757
|
dotY,
|
|
1674
1758
|
allRefLines,
|
|
1759
|
+
refLineKeys,
|
|
1675
1760
|
dragValues,
|
|
1676
1761
|
resolvedSegments,
|
|
1677
1762
|
hasRecolorSegments,
|
|
@@ -1722,9 +1807,9 @@ function ChartStack({
|
|
|
1722
1807
|
<Group transform={degen?.shakeTransform}>
|
|
1723
1808
|
{/* Segment dividers + labels (behind the line). The scrub-focus emphasis is
|
|
1724
1809
|
painted on the line stroke itself, below — this overlay draws no fill. */}
|
|
1725
|
-
{resolvedSegments.map((seg
|
|
1810
|
+
{resolvedSegments.map((seg) => (
|
|
1726
1811
|
<SegmentDividerOverlay
|
|
1727
|
-
key={
|
|
1812
|
+
key={segmentReactKey(seg)}
|
|
1728
1813
|
engine={engine}
|
|
1729
1814
|
padding={effectivePadding}
|
|
1730
1815
|
segment={seg}
|
|
@@ -1734,7 +1819,7 @@ function ChartStack({
|
|
|
1734
1819
|
|
|
1735
1820
|
{/* Value line + reference line (behind chart line) */}
|
|
1736
1821
|
{valueLineCfg && (
|
|
1737
|
-
<Group opacity={
|
|
1822
|
+
<Group opacity={valueLineOpacity}>
|
|
1738
1823
|
<ValueLineOverlay
|
|
1739
1824
|
dotY={dotY}
|
|
1740
1825
|
engine={engine}
|
|
@@ -1746,14 +1831,12 @@ function ChartStack({
|
|
|
1746
1831
|
</Group>
|
|
1747
1832
|
)}
|
|
1748
1833
|
|
|
1749
|
-
{/*
|
|
1750
|
-
|
|
1751
|
-
content-derived key would collapse to one. Wrapped in a fade group so
|
|
1752
|
-
`scrub.hideOverlaysOnScrub` can ease the lines out while scrubbing. */}
|
|
1834
|
+
{/* Wrapped in a fade group so `scrub.hideOverlaysOnScrub` can ease lines
|
|
1835
|
+
out while scrubbing. Explicit ids keep lines stable when reordered. */}
|
|
1753
1836
|
<Group opacity={overlayScrubFade}>
|
|
1754
1837
|
{allRefLines.map((rl, i) => (
|
|
1755
1838
|
<ReferenceLineOverlay
|
|
1756
|
-
key={i}
|
|
1839
|
+
key={refLineKeys[i]}
|
|
1757
1840
|
engine={engine}
|
|
1758
1841
|
padding={effectivePadding}
|
|
1759
1842
|
line={rl}
|
|
@@ -1857,7 +1940,6 @@ function ChartStack({
|
|
|
1857
1940
|
dotX={dotX}
|
|
1858
1941
|
dotY={dotY}
|
|
1859
1942
|
palette={palette}
|
|
1860
|
-
engine={engine}
|
|
1861
1943
|
pulse={pulseCfg}
|
|
1862
1944
|
radius={dotCfg.radius}
|
|
1863
1945
|
ring={dotCfg.ring}
|
|
@@ -2064,6 +2146,19 @@ function ChartScrubLayer({
|
|
|
2064
2146
|
);
|
|
2065
2147
|
}
|
|
2066
2148
|
|
|
2149
|
+
/** A segment's time range and presentation uniquely identify its divider view. */
|
|
2150
|
+
function segmentReactKey(segment: ResolvedSegment): string {
|
|
2151
|
+
return [
|
|
2152
|
+
"seg",
|
|
2153
|
+
segment.from ?? "start",
|
|
2154
|
+
segment.to ?? "end",
|
|
2155
|
+
segment.divider,
|
|
2156
|
+
segment.dividerColor,
|
|
2157
|
+
segment.label ?? "",
|
|
2158
|
+
segment.labelPosition,
|
|
2159
|
+
].join(":");
|
|
2160
|
+
}
|
|
2161
|
+
|
|
2067
2162
|
/** Live-value text drawn as its own canvas layer, above both the area gradient
|
|
2068
2163
|
* and the left-edge fade, so the large number stays crisp at the left edge
|
|
2069
2164
|
* instead of being washed out by the fade's `dstOut` blend. */
|
|
@@ -2115,14 +2210,14 @@ function ChartBadgeLayer({
|
|
|
2115
2210
|
}) {
|
|
2116
2211
|
const {
|
|
2117
2212
|
badgeFont,
|
|
2118
|
-
reveal,
|
|
2119
2213
|
engine,
|
|
2120
2214
|
effectivePadding,
|
|
2121
2215
|
palette,
|
|
2122
2216
|
formatValue,
|
|
2123
|
-
|
|
2217
|
+
badgeMomentumSV,
|
|
2124
2218
|
metricsCfg,
|
|
2125
2219
|
yAxisFloat,
|
|
2220
|
+
liveBadgeOpacity,
|
|
2126
2221
|
} = model;
|
|
2127
2222
|
const badgeCfg = model.badgeCfg!;
|
|
2128
2223
|
const badgeData = useBadge(
|
|
@@ -2133,7 +2228,7 @@ function ChartBadgeLayer({
|
|
|
2133
2228
|
badgeFont,
|
|
2134
2229
|
badgeCfg.variant,
|
|
2135
2230
|
badgeCfg.tail,
|
|
2136
|
-
|
|
2231
|
+
badgeMomentumSV,
|
|
2137
2232
|
badgeCfg.position,
|
|
2138
2233
|
badgeCfg.background,
|
|
2139
2234
|
metricsCfg.badge,
|
|
@@ -2146,7 +2241,7 @@ function ChartBadgeLayer({
|
|
|
2146
2241
|
);
|
|
2147
2242
|
return (
|
|
2148
2243
|
<Group transform={degen?.shakeTransform}>
|
|
2149
|
-
<Group opacity={
|
|
2244
|
+
<Group opacity={liveBadgeOpacity}>
|
|
2150
2245
|
<BadgeOverlay
|
|
2151
2246
|
badge={badgeData}
|
|
2152
2247
|
font={badgeFont}
|
|
@@ -2173,7 +2268,10 @@ function ChartRefBadgeLayer({
|
|
|
2173
2268
|
}) {
|
|
2174
2269
|
const {
|
|
2175
2270
|
allRefLines,
|
|
2271
|
+
refLineKeys,
|
|
2176
2272
|
refLineCustom,
|
|
2273
|
+
refLineOffAxisCustom,
|
|
2274
|
+
refLineCustomTagWidths,
|
|
2177
2275
|
dragValues,
|
|
2178
2276
|
groupHidden,
|
|
2179
2277
|
refGroupResult,
|
|
@@ -2194,7 +2292,7 @@ function ChartRefBadgeLayer({
|
|
|
2194
2292
|
<Group transform={degen?.shakeTransform} opacity={overlayScrubFade}>
|
|
2195
2293
|
{allRefLines.map((rl, i) => (
|
|
2196
2294
|
<ReferenceLineOverlay
|
|
2197
|
-
key={i}
|
|
2295
|
+
key={refLineKeys[i]}
|
|
2198
2296
|
engine={engine}
|
|
2199
2297
|
padding={effectivePadding}
|
|
2200
2298
|
line={rl}
|
|
@@ -2206,6 +2304,8 @@ function ChartRefBadgeLayer({
|
|
|
2206
2304
|
dragValues={dragValues}
|
|
2207
2305
|
index={i}
|
|
2208
2306
|
suppressTag={refLineCustom[i]}
|
|
2307
|
+
suppressTagWhenOffAxis={refLineOffAxisCustom[i]}
|
|
2308
|
+
customTagWidths={refLineCustomTagWidths}
|
|
2209
2309
|
groupHidden={refGroupingActive ? groupHidden : undefined}
|
|
2210
2310
|
/>
|
|
2211
2311
|
))}
|
|
@@ -2276,8 +2376,11 @@ function ChartCustomAnnotations({ model }: { model: LiveChartModel }) {
|
|
|
2276
2376
|
markerClusterCfg,
|
|
2277
2377
|
renderMarker,
|
|
2278
2378
|
renderReferenceLine,
|
|
2379
|
+
renderOffAxisReferenceLine,
|
|
2279
2380
|
allRefLines,
|
|
2280
2381
|
refLineCustom,
|
|
2382
|
+
refLineOffAxisCustom,
|
|
2383
|
+
refLineCustomTagWidths,
|
|
2281
2384
|
dragValues,
|
|
2282
2385
|
dragActive,
|
|
2283
2386
|
engine,
|
|
@@ -2316,6 +2419,21 @@ function ChartCustomAnnotations({ model }: { model: LiveChartModel }) {
|
|
|
2316
2419
|
formatValue={formatValue}
|
|
2317
2420
|
dragValues={dragValues}
|
|
2318
2421
|
dragActive={dragActive}
|
|
2422
|
+
tagWidths={refLineCustomTagWidths}
|
|
2423
|
+
/>
|
|
2424
|
+
)}
|
|
2425
|
+
{renderOffAxisReferenceLine && allRefLines.length > 0 && (
|
|
2426
|
+
<CustomReferenceLineOverlay
|
|
2427
|
+
lines={allRefLines}
|
|
2428
|
+
renderReferenceLine={renderOffAxisReferenceLine}
|
|
2429
|
+
custom={refLineOffAxisCustom}
|
|
2430
|
+
engine={engine}
|
|
2431
|
+
padding={effectivePadding}
|
|
2432
|
+
formatValue={formatValue}
|
|
2433
|
+
dragValues={dragValues}
|
|
2434
|
+
dragActive={dragActive}
|
|
2435
|
+
tagWidths={refLineCustomTagWidths}
|
|
2436
|
+
offAxisOnly
|
|
2319
2437
|
/>
|
|
2320
2438
|
)}
|
|
2321
2439
|
</Animated.View>
|
|
@@ -2357,6 +2475,7 @@ function ChartView({
|
|
|
2357
2475
|
renderTooltip,
|
|
2358
2476
|
renderOverlay,
|
|
2359
2477
|
renderReferenceLine,
|
|
2478
|
+
renderOffAxisReferenceLine,
|
|
2360
2479
|
allRefLines,
|
|
2361
2480
|
scrubCfg,
|
|
2362
2481
|
crosshair,
|
|
@@ -2466,7 +2585,8 @@ function ChartView({
|
|
|
2466
2585
|
Skia markers (the wrapper is full-bleed; children keep their own
|
|
2467
2586
|
absolute positions). */}
|
|
2468
2587
|
{((markersActive && renderMarker) ||
|
|
2469
|
-
(renderReferenceLine
|
|
2588
|
+
((renderReferenceLine || renderOffAxisReferenceLine) &&
|
|
2589
|
+
allRefLines.length > 0)) && (
|
|
2470
2590
|
<ChartCustomAnnotations model={model} />
|
|
2471
2591
|
)}
|
|
2472
2592
|
|