react-native-livechart 4.13.0 → 4.13.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/LiveChart.d.ts.map +1 -1
- package/dist/components/SegmentLineGradient.d.ts +23 -0
- package/dist/components/SegmentLineGradient.d.ts.map +1 -0
- package/dist/hooks/useSegmentLineGradient.d.ts.map +1 -1
- package/dist/math/segments.d.ts +4 -0
- package/dist/math/segments.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/LiveChart.tsx +9 -21
- package/src/components/SegmentLineGradient.tsx +57 -0
- package/src/hooks/useSegmentLineGradient.ts +13 -5
- package/src/math/segments.ts +26 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LiveChart.d.ts","sourceRoot":"","sources":["../../src/components/LiveChart.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"LiveChart.d.ts","sourceRoot":"","sources":["../../src/components/LiveChart.tsx"],"names":[],"mappings":"AA2HA,OAAO,KAAK,EAGV,cAAc,EAEf,MAAM,UAAU,CAAC;AA08ElB,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,+BAS9C"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { SharedValue } from "react-native-reanimated";
|
|
2
|
+
import type { ResolvedSegment } from "../core/resolveSegment";
|
|
3
|
+
import type { ChartEngineLayout } from "../core/useLiveChartEngine";
|
|
4
|
+
import type { ChartPadding } from "../draw/line";
|
|
5
|
+
interface SegmentLineGradientProps {
|
|
6
|
+
engine: ChartEngineLayout;
|
|
7
|
+
segments: ResolvedSegment[];
|
|
8
|
+
padding: ChartPadding;
|
|
9
|
+
baseColor: string;
|
|
10
|
+
scrubX: SharedValue<number>;
|
|
11
|
+
scrubActive: SharedValue<boolean>;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Keeps the two SharedValues passed to Skia on one stop-count lifecycle.
|
|
15
|
+
*
|
|
16
|
+
* Scrubbing can change which stops are visible without changing `stopCount`, so
|
|
17
|
+
* padding keeps those mapper updates safe. When the segment props themselves
|
|
18
|
+
* change the count, the keyed child remounts both SharedValues together instead
|
|
19
|
+
* of letting one retain the previous length for a frame.
|
|
20
|
+
*/
|
|
21
|
+
export declare function SegmentLineGradient(props: SegmentLineGradientProps): import("react").JSX.Element;
|
|
22
|
+
export {};
|
|
23
|
+
//# sourceMappingURL=SegmentLineGradient.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SegmentLineGradient.d.ts","sourceRoot":"","sources":["../../src/components/SegmentLineGradient.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAE3D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AACpE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAIjD,UAAU,wBAAwB;IAChC,MAAM,EAAE,iBAAiB,CAAC;IAC1B,QAAQ,EAAE,eAAe,EAAE,CAAC;IAC5B,OAAO,EAAE,YAAY,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC5B,WAAW,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC;CACnC;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,wBAAwB,+BAGlE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useSegmentLineGradient.d.ts","sourceRoot":"","sources":["../../src/hooks/useSegmentLineGradient.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAG5E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AACpE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"useSegmentLineGradient.d.ts","sourceRoot":"","sources":["../../src/hooks/useSegmentLineGradient.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAG5E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AACpE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AASjD;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,iBAAiB,EACzB,QAAQ,EAAE,eAAe,EAAE,EAC3B,OAAO,EAAE,YAAY,EACrB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,EAC3B,WAAW,EAAE,WAAW,CAAC,OAAO,CAAC;;;;EAkClC"}
|
package/dist/math/segments.d.ts
CHANGED
|
@@ -43,4 +43,8 @@ export interface SegmentGradient {
|
|
|
43
43
|
* The caller then strokes the line with its plain solid color.
|
|
44
44
|
*/
|
|
45
45
|
export declare function segmentLineGradient(segments: ResolvedSegment[], winStart: number, win: number, canvasWidth: number, plotLeft: number, plotRight: number, baseColor: string, scrubActive: boolean, scrubX: number): SegmentGradient | null;
|
|
46
|
+
/** Stops {@link segmentLineGradient} can emit for `segments` — no per-frame state. */
|
|
47
|
+
export declare function segmentGradientStopCount(segments: ResolvedSegment[]): number;
|
|
48
|
+
/** Resize `stops` to `count` by repeating its last entry. */
|
|
49
|
+
export declare function padGradientStops<T>(stops: T[], count: number): T[];
|
|
46
50
|
//# sourceMappingURL=segments.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"segments.d.ts","sourceRoot":"","sources":["../../src/math/segments.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAE9D,sEAAsE;AACtE,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,kDAAkD;IAClD,GAAG,EAAE,MAAM,CAAC;IACZ,mDAAmD;IACnD,GAAG,EAAE,MAAM,CAAC;CACb;AAID;;;;;;GAMG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,MAAM,GAAG,SAAS,EACxB,EAAE,EAAE,MAAM,GAAG,SAAS,EACtB,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM,EACX,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,GACT,YAAY,CAkBd;AAED,kEAAkE;AAClE,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,eAAe,EAAE,EAC3B,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM,EACX,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,OAAO,EACpB,MAAM,EAAE,MAAM,GACb,eAAe,GAAG,IAAI,CAuFxB"}
|
|
1
|
+
{"version":3,"file":"segments.d.ts","sourceRoot":"","sources":["../../src/math/segments.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAE9D,sEAAsE;AACtE,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,kDAAkD;IAClD,GAAG,EAAE,MAAM,CAAC;IACZ,mDAAmD;IACnD,GAAG,EAAE,MAAM,CAAC;CACb;AAID;;;;;;GAMG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,MAAM,GAAG,SAAS,EACxB,EAAE,EAAE,MAAM,GAAG,SAAS,EACtB,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM,EACX,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,GACT,YAAY,CAkBd;AAED,kEAAkE;AAClE,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,eAAe,EAAE,EAC3B,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM,EACX,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,OAAO,EACpB,MAAM,EAAE,MAAM,GACb,eAAe,GAAG,IAAI,CAuFxB;AAED,sFAAsF;AACtF,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,eAAe,EAAE,GAAG,MAAM,CAa5E;AAED,6DAA6D;AAC7D,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,CAAC,EAAE,CAOlE"}
|
package/package.json
CHANGED
|
@@ -89,7 +89,6 @@ import {
|
|
|
89
89
|
import { AXIS_GRAB_MIN_PX, usePanScroll } from "../hooks/usePanScroll";
|
|
90
90
|
import { usePinchZoom } from "../hooks/usePinchZoom";
|
|
91
91
|
import { useVisibleRange } from "../hooks/useVisibleRange";
|
|
92
|
-
import { useSegmentLineGradient } from "../hooks/useSegmentLineGradient";
|
|
93
92
|
import { useSingleChartReverseMorphInputs } from "../hooks/useReverseMorphEngineInputs";
|
|
94
93
|
import {
|
|
95
94
|
useThreshold,
|
|
@@ -162,6 +161,7 @@ import { ReferenceLineGroupOverlay } from "./ReferenceLineGroupOverlay";
|
|
|
162
161
|
import { ReferenceLineOverlay } from "./ReferenceLineOverlay";
|
|
163
162
|
import { ScrubActionOverlay } from "./ScrubActionOverlay";
|
|
164
163
|
import { SegmentDividerOverlay } from "./SegmentDividerOverlay";
|
|
164
|
+
import { SegmentLineGradient } from "./SegmentLineGradient";
|
|
165
165
|
import { TradeStreamOverlay } from "./TradeStreamOverlay";
|
|
166
166
|
import { ValueLineOverlay } from "./ValueLineOverlay";
|
|
167
167
|
import { XAxisOverlay } from "./XAxisOverlay";
|
|
@@ -1200,19 +1200,6 @@ function useLiveChartController({
|
|
|
1200
1200
|
effectivePadding,
|
|
1201
1201
|
);
|
|
1202
1202
|
|
|
1203
|
-
// Scrub-focus gradient painted onto the line stroke: uniform at rest, and while
|
|
1204
|
-
// scrubbing (or with an `active` segment) the focused segment stays full while
|
|
1205
|
-
// the others are de-emphasized. Declared after `crosshair` so it can read the
|
|
1206
|
-
// live scrub state.
|
|
1207
|
-
const segmentGradient = useSegmentLineGradient(
|
|
1208
|
-
engine,
|
|
1209
|
-
resolvedSegments,
|
|
1210
|
-
effectivePadding,
|
|
1211
|
-
lineProp?.color ?? palette.line,
|
|
1212
|
-
crosshair.scrubX,
|
|
1213
|
-
crosshair.scrubActive,
|
|
1214
|
-
);
|
|
1215
|
-
|
|
1216
1203
|
// Hide the live dot while scrubbing when a selection dot is marking the scrub
|
|
1217
1204
|
// point instead — otherwise both dots show at once. Applies on static charts
|
|
1218
1205
|
// too, now that they're scrubbable.
|
|
@@ -1326,7 +1313,6 @@ function useLiveChartController({
|
|
|
1326
1313
|
refGroupFormat,
|
|
1327
1314
|
resolvedSegments,
|
|
1328
1315
|
hasRecolorSegments,
|
|
1329
|
-
segmentGradient,
|
|
1330
1316
|
thresholdCfg,
|
|
1331
1317
|
thresholdGeom,
|
|
1332
1318
|
thresholdStrokeColors: thresholdStopColors?.stroke ?? null,
|
|
@@ -1764,7 +1750,7 @@ function ChartStack({
|
|
|
1764
1750
|
dragValues,
|
|
1765
1751
|
resolvedSegments,
|
|
1766
1752
|
hasRecolorSegments,
|
|
1767
|
-
|
|
1753
|
+
crosshair,
|
|
1768
1754
|
thresholdCfg,
|
|
1769
1755
|
thresholdGeom,
|
|
1770
1756
|
thresholdStrokeColors,
|
|
@@ -1905,11 +1891,13 @@ function ChartStack({
|
|
|
1905
1891
|
positions={thresholdGeom.splitPositions}
|
|
1906
1892
|
/>
|
|
1907
1893
|
) : hasRecolorSegments ? (
|
|
1908
|
-
<
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1894
|
+
<SegmentLineGradient
|
|
1895
|
+
engine={engine}
|
|
1896
|
+
segments={resolvedSegments}
|
|
1897
|
+
padding={effectivePadding}
|
|
1898
|
+
baseColor={lineProp?.color ?? palette.line}
|
|
1899
|
+
scrubX={crosshair.scrubX}
|
|
1900
|
+
scrubActive={crosshair.scrubActive}
|
|
1913
1901
|
/>
|
|
1914
1902
|
) : lineProp?.colors?.length ? (
|
|
1915
1903
|
<LinearGradient
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { LinearGradient, vec } from "@shopify/react-native-skia";
|
|
2
|
+
import type { SharedValue } from "react-native-reanimated";
|
|
3
|
+
|
|
4
|
+
import type { ResolvedSegment } from "../core/resolveSegment";
|
|
5
|
+
import type { ChartEngineLayout } from "../core/useLiveChartEngine";
|
|
6
|
+
import type { ChartPadding } from "../draw/line";
|
|
7
|
+
import { useSegmentLineGradient } from "../hooks/useSegmentLineGradient";
|
|
8
|
+
import { segmentGradientStopCount } from "../math/segments";
|
|
9
|
+
|
|
10
|
+
interface SegmentLineGradientProps {
|
|
11
|
+
engine: ChartEngineLayout;
|
|
12
|
+
segments: ResolvedSegment[];
|
|
13
|
+
padding: ChartPadding;
|
|
14
|
+
baseColor: string;
|
|
15
|
+
scrubX: SharedValue<number>;
|
|
16
|
+
scrubActive: SharedValue<boolean>;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Keeps the two SharedValues passed to Skia on one stop-count lifecycle.
|
|
21
|
+
*
|
|
22
|
+
* Scrubbing can change which stops are visible without changing `stopCount`, so
|
|
23
|
+
* padding keeps those mapper updates safe. When the segment props themselves
|
|
24
|
+
* change the count, the keyed child remounts both SharedValues together instead
|
|
25
|
+
* of letting one retain the previous length for a frame.
|
|
26
|
+
*/
|
|
27
|
+
export function SegmentLineGradient(props: SegmentLineGradientProps) {
|
|
28
|
+
const stopCount = segmentGradientStopCount(props.segments);
|
|
29
|
+
return <SegmentLineGradientPaint key={stopCount} {...props} />;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function SegmentLineGradientPaint({
|
|
33
|
+
engine,
|
|
34
|
+
segments,
|
|
35
|
+
padding,
|
|
36
|
+
baseColor,
|
|
37
|
+
scrubX,
|
|
38
|
+
scrubActive,
|
|
39
|
+
}: SegmentLineGradientProps) {
|
|
40
|
+
const gradient = useSegmentLineGradient(
|
|
41
|
+
engine,
|
|
42
|
+
segments,
|
|
43
|
+
padding,
|
|
44
|
+
baseColor,
|
|
45
|
+
scrubX,
|
|
46
|
+
scrubActive,
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
<LinearGradient
|
|
51
|
+
start={vec(0, 0)}
|
|
52
|
+
end={gradient.gradientEnd}
|
|
53
|
+
colors={gradient.colors}
|
|
54
|
+
positions={gradient.positions}
|
|
55
|
+
/>
|
|
56
|
+
);
|
|
57
|
+
}
|
|
@@ -4,7 +4,11 @@ import { vec } from "@shopify/react-native-skia";
|
|
|
4
4
|
import type { ChartEngineLayout } from "../core/useLiveChartEngine";
|
|
5
5
|
import type { ResolvedSegment } from "../core/resolveSegment";
|
|
6
6
|
import type { ChartPadding } from "../draw/line";
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
padGradientStops,
|
|
9
|
+
segmentGradientStopCount,
|
|
10
|
+
segmentLineGradient,
|
|
11
|
+
} from "../math/segments";
|
|
8
12
|
|
|
9
13
|
const FALLBACK_POSITIONS = [0, 1];
|
|
10
14
|
|
|
@@ -43,11 +47,15 @@ export function useSegmentLineGradient(
|
|
|
43
47
|
);
|
|
44
48
|
});
|
|
45
49
|
|
|
46
|
-
|
|
47
|
-
|
|
50
|
+
// Fixed stop count: `colors`/`positions` tear independently and Skia treats a
|
|
51
|
+
// length mismatch as a fatal UI-thread throw.
|
|
52
|
+
const stopCount = segmentGradientStopCount(segments);
|
|
53
|
+
|
|
54
|
+
const colors = useDerivedValue(() =>
|
|
55
|
+
padGradientStops(data.value?.colors ?? [baseColor, baseColor], stopCount),
|
|
48
56
|
);
|
|
49
|
-
const positions = useDerivedValue(
|
|
50
|
-
(
|
|
57
|
+
const positions = useDerivedValue(() =>
|
|
58
|
+
padGradientStops(data.value?.positions ?? FALLBACK_POSITIONS, stopCount),
|
|
51
59
|
);
|
|
52
60
|
const gradientEnd = useDerivedValue(() =>
|
|
53
61
|
vec(Math.max(1, engine.canvasWidth.value), 0),
|
package/src/math/segments.ts
CHANGED
|
@@ -171,3 +171,29 @@ export function segmentLineGradient(
|
|
|
171
171
|
|
|
172
172
|
return { colors, positions };
|
|
173
173
|
}
|
|
174
|
+
|
|
175
|
+
/** Stops {@link segmentLineGradient} can emit for `segments` — no per-frame state. */
|
|
176
|
+
export function segmentGradientStopCount(segments: ResolvedSegment[]): number {
|
|
177
|
+
"worklet";
|
|
178
|
+
let n = 2;
|
|
179
|
+
for (let i = 0; i < segments.length; i++) {
|
|
180
|
+
const seg = segments[i];
|
|
181
|
+
if (!seg.recolorLine) continue;
|
|
182
|
+
const cols =
|
|
183
|
+
seg.mutedColors && seg.mutedColors.length >= 2
|
|
184
|
+
? seg.mutedColors.length
|
|
185
|
+
: 2;
|
|
186
|
+
n += cols + 2;
|
|
187
|
+
}
|
|
188
|
+
return n;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/** Resize `stops` to `count` by repeating its last entry. */
|
|
192
|
+
export function padGradientStops<T>(stops: T[], count: number): T[] {
|
|
193
|
+
"worklet";
|
|
194
|
+
if (stops.length === count || stops.length === 0) return stops;
|
|
195
|
+
const out = stops.slice(0, count);
|
|
196
|
+
const last = stops[stops.length - 1];
|
|
197
|
+
while (out.length < count) out.push(last);
|
|
198
|
+
return out;
|
|
199
|
+
}
|