@ledgerhq/lumen-ui-rnative-visualization 0.1.17 → 0.1.19
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/module/lib/Components/Axis/XAxis/XAxis.js +4 -3
- package/dist/module/lib/Components/Axis/XAxis/XAxis.js.map +1 -1
- package/dist/module/lib/Components/Axis/XAxis/XAxis.test.js +14 -0
- package/dist/module/lib/Components/Axis/XAxis/XAxis.test.js.map +1 -1
- package/dist/module/lib/Components/Axis/YAxis/YAxis.js +4 -3
- package/dist/module/lib/Components/Axis/YAxis/YAxis.js.map +1 -1
- package/dist/module/lib/Components/Axis/YAxis/YAxis.test.js +14 -0
- package/dist/module/lib/Components/Axis/YAxis/YAxis.test.js.map +1 -1
- package/dist/module/lib/Components/CartesianChart/CartesianChart.js +30 -23
- package/dist/module/lib/Components/CartesianChart/CartesianChart.js.map +1 -1
- package/dist/module/lib/Components/CartesianChart/ChartEmptyLabel/ChartEmptyLabel.js +61 -0
- package/dist/module/lib/Components/CartesianChart/ChartEmptyLabel/ChartEmptyLabel.js.map +1 -0
- package/dist/module/lib/Components/CartesianChart/ChartEmptyLabel/index.js +4 -0
- package/dist/module/lib/Components/CartesianChart/ChartEmptyLabel/index.js.map +1 -0
- package/dist/module/lib/Components/CartesianChart/{RevealClip/RevealClipDefs.js → RevealAnimation/RevealAnimationProvider.js} +13 -13
- package/dist/module/lib/Components/CartesianChart/RevealAnimation/RevealAnimationProvider.js.map +1 -0
- package/dist/module/lib/Components/CartesianChart/{RevealClip/RevealClipDefs.test.js → RevealAnimation/RevealAnimationProvider.test.js} +51 -12
- package/dist/module/lib/Components/CartesianChart/RevealAnimation/RevealAnimationProvider.test.js.map +1 -0
- package/dist/module/lib/Components/CartesianChart/RevealAnimation/context.js +35 -0
- package/dist/module/lib/Components/CartesianChart/RevealAnimation/context.js.map +1 -0
- package/dist/module/lib/Components/CartesianChart/RevealAnimation/index.js +5 -0
- package/dist/module/lib/Components/CartesianChart/RevealAnimation/index.js.map +1 -0
- package/dist/module/lib/Components/CartesianChart/RevealAnimation/types.js.map +1 -0
- package/dist/module/lib/Components/CartesianChart/RevealAnimation/utils.js +64 -0
- package/dist/module/lib/Components/CartesianChart/RevealAnimation/utils.js.map +1 -0
- package/dist/module/lib/Components/CartesianChart/hooks/useShimmerAnimation.js +37 -0
- package/dist/module/lib/Components/CartesianChart/hooks/useShimmerAnimation.js.map +1 -0
- package/dist/module/lib/Components/CartesianChart/utils.js +1 -1
- package/dist/module/lib/Components/CartesianChart/utils.js.map +1 -1
- package/dist/module/lib/Components/Line/Line.js +18 -11
- package/dist/module/lib/Components/Line/Line.js.map +1 -1
- package/dist/module/lib/Components/Line/constants.js +5 -0
- package/dist/module/lib/Components/Line/constants.js.map +1 -0
- package/dist/module/lib/Components/Line/types.js +2 -0
- package/dist/module/lib/Components/Line/utils.js +38 -11
- package/dist/module/lib/Components/Line/utils.js.map +1 -1
- package/dist/module/lib/Components/Line/utils.test.js +49 -3
- package/dist/module/lib/Components/Line/utils.test.js.map +1 -1
- package/dist/module/lib/Components/LineChart/LineChart.js +131 -27
- package/dist/module/lib/Components/LineChart/LineChart.js.map +1 -1
- package/dist/module/lib/Components/LineChart/LineChart.test.js +147 -0
- package/dist/module/lib/Components/LineChart/LineChart.test.js.map +1 -1
- package/dist/module/lib/Components/LineChart/LineChartEmptyState/LineChartEmptyState.js +72 -0
- package/dist/module/lib/Components/LineChart/LineChartEmptyState/LineChartEmptyState.js.map +1 -0
- package/dist/module/lib/Components/LineChart/LineChartEmptyState/LineChartEmptyState.test.js +47 -0
- package/dist/module/lib/Components/LineChart/LineChartEmptyState/LineChartEmptyState.test.js.map +1 -0
- package/dist/module/lib/Components/LineChart/LineChartEmptyState/index.js +4 -0
- package/dist/module/lib/Components/LineChart/LineChartEmptyState/index.js.map +1 -0
- package/dist/module/lib/Components/LineChart/LineChartEmptyState/types.js +4 -0
- package/dist/module/lib/Components/LineChart/LineChartEmptyState/types.js.map +1 -0
- package/dist/module/lib/Components/LineChart/LineChartEmptyState/utils.js +22 -0
- package/dist/module/lib/Components/LineChart/LineChartEmptyState/utils.js.map +1 -0
- package/dist/module/lib/Components/LineChart/LineChartEmptyState/utils.test.js +21 -0
- package/dist/module/lib/Components/LineChart/LineChartEmptyState/utils.test.js.map +1 -0
- package/dist/module/lib/Components/LineChart/utils.js +83 -0
- package/dist/module/lib/Components/LineChart/utils.js.map +1 -0
- package/dist/module/lib/Components/LineChart/utils.test.js +174 -0
- package/dist/module/lib/Components/LineChart/utils.test.js.map +1 -0
- package/dist/module/lib/Components/Point/Point.js +6 -4
- package/dist/module/lib/Components/Point/Point.js.map +1 -1
- package/dist/module/lib/Components/ReferenceLine/ReferenceLine.js +4 -4
- package/dist/module/lib/Components/ReferenceLine/ReferenceLine.js.map +1 -1
- package/dist/module/lib/Components/ReferenceLine/constants.js +2 -2
- package/dist/module/lib/Components/ReferenceLine/constants.js.map +1 -1
- package/dist/module/lib/Components/ReferenceLine/utils.js +2 -1
- package/dist/module/lib/Components/ReferenceLine/utils.js.map +1 -1
- package/dist/module/lib/Components/Scrubber/DefaultScrubberTooltip/utils.js +2 -1
- package/dist/module/lib/Components/Scrubber/DefaultScrubberTooltip/utils.js.map +1 -1
- package/dist/module/lib/Components/Scrubber/Scrubber.js +2 -2
- package/dist/module/lib/Components/Scrubber/Scrubber.js.map +1 -1
- package/dist/module/lib/Components/Scrubber/ScrubberProvider.js +10 -2
- package/dist/module/lib/Components/Scrubber/ScrubberProvider.js.map +1 -1
- package/dist/module/lib/Components/Scrubber/ScrubberProvider.test.js +79 -1
- package/dist/module/lib/Components/Scrubber/ScrubberProvider.test.js.map +1 -1
- package/dist/module/lib/Components/Scrubber/utils.js +3 -2
- package/dist/module/lib/Components/Scrubber/utils.js.map +1 -1
- package/dist/module/lib/utils/numbers.js +16 -0
- package/dist/module/lib/utils/numbers.js.map +1 -0
- package/dist/module/lib/utils/ticks/ticks.js +0 -16
- package/dist/module/lib/utils/ticks/ticks.js.map +1 -1
- package/dist/typescript/src/lib/Components/Axis/Axis.types.d.ts +6 -0
- package/dist/typescript/src/lib/Components/Axis/Axis.types.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/Axis/XAxis/XAxis.d.ts +1 -1
- package/dist/typescript/src/lib/Components/Axis/XAxis/XAxis.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/Axis/YAxis/YAxis.d.ts +1 -1
- package/dist/typescript/src/lib/Components/Axis/YAxis/YAxis.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/CartesianChart/CartesianChart.d.ts +1 -1
- package/dist/typescript/src/lib/Components/CartesianChart/CartesianChart.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/CartesianChart/ChartEmptyLabel/ChartEmptyLabel.d.ts +18 -0
- package/dist/typescript/src/lib/Components/CartesianChart/ChartEmptyLabel/ChartEmptyLabel.d.ts.map +1 -0
- package/dist/typescript/src/lib/Components/CartesianChart/ChartEmptyLabel/index.d.ts +2 -0
- package/dist/typescript/src/lib/Components/CartesianChart/ChartEmptyLabel/index.d.ts.map +1 -0
- package/dist/typescript/src/lib/Components/CartesianChart/RevealAnimation/RevealAnimationProvider.d.ts +3 -0
- package/dist/typescript/src/lib/Components/CartesianChart/RevealAnimation/RevealAnimationProvider.d.ts.map +1 -0
- package/dist/typescript/src/lib/Components/CartesianChart/RevealAnimation/context.d.ts +22 -0
- package/dist/typescript/src/lib/Components/CartesianChart/RevealAnimation/context.d.ts.map +1 -0
- package/dist/typescript/src/lib/Components/CartesianChart/RevealAnimation/index.d.ts +3 -0
- package/dist/typescript/src/lib/Components/CartesianChart/RevealAnimation/index.d.ts.map +1 -0
- package/dist/typescript/src/lib/Components/CartesianChart/{RevealClip → RevealAnimation}/types.d.ts +15 -2
- package/dist/typescript/src/lib/Components/CartesianChart/RevealAnimation/types.d.ts.map +1 -0
- package/dist/typescript/src/lib/Components/CartesianChart/RevealAnimation/utils.d.ts +33 -0
- package/dist/typescript/src/lib/Components/CartesianChart/RevealAnimation/utils.d.ts.map +1 -0
- package/dist/typescript/src/lib/Components/CartesianChart/hooks/useShimmerAnimation.d.ts +13 -0
- package/dist/typescript/src/lib/Components/CartesianChart/hooks/useShimmerAnimation.d.ts.map +1 -0
- package/dist/typescript/src/lib/Components/CartesianChart/types.d.ts +12 -0
- package/dist/typescript/src/lib/Components/CartesianChart/types.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/CartesianChart/utils.d.ts +1 -1
- package/dist/typescript/src/lib/Components/CartesianChart/utils.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/Line/Line.d.ts +1 -1
- package/dist/typescript/src/lib/Components/Line/Line.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/Line/constants.d.ts +3 -0
- package/dist/typescript/src/lib/Components/Line/constants.d.ts.map +1 -0
- package/dist/typescript/src/lib/Components/Line/index.d.ts +1 -1
- package/dist/typescript/src/lib/Components/Line/index.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/Line/types.d.ts +15 -0
- package/dist/typescript/src/lib/Components/Line/types.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/Line/utils.d.ts +11 -6
- package/dist/typescript/src/lib/Components/Line/utils.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/LineChart/LineChart.d.ts +1 -1
- package/dist/typescript/src/lib/Components/LineChart/LineChart.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/LineChart/LineChartEmptyState/LineChartEmptyState.d.ts +9 -0
- package/dist/typescript/src/lib/Components/LineChart/LineChartEmptyState/LineChartEmptyState.d.ts.map +1 -0
- package/dist/typescript/src/lib/Components/LineChart/LineChartEmptyState/index.d.ts +3 -0
- package/dist/typescript/src/lib/Components/LineChart/LineChartEmptyState/index.d.ts.map +1 -0
- package/dist/typescript/src/lib/Components/LineChart/LineChartEmptyState/types.d.ts +3 -0
- package/dist/typescript/src/lib/Components/LineChart/LineChartEmptyState/types.d.ts.map +1 -0
- package/dist/typescript/src/lib/Components/LineChart/LineChartEmptyState/utils.d.ts +14 -0
- package/dist/typescript/src/lib/Components/LineChart/LineChartEmptyState/utils.d.ts.map +1 -0
- package/dist/typescript/src/lib/Components/LineChart/types.d.ts +41 -1
- package/dist/typescript/src/lib/Components/LineChart/types.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/LineChart/utils.d.ts +43 -0
- package/dist/typescript/src/lib/Components/LineChart/utils.d.ts.map +1 -0
- package/dist/typescript/src/lib/Components/Point/Point.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/ReferenceLine/ReferenceLine.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/ReferenceLine/constants.d.ts +2 -2
- package/dist/typescript/src/lib/Components/ReferenceLine/constants.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/ReferenceLine/utils.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/Scrubber/DefaultScrubberTooltip/utils.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/Scrubber/Scrubber.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/Scrubber/ScrubberProvider.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/Scrubber/utils.d.ts.map +1 -1
- package/dist/typescript/src/lib/utils/index.d.ts +1 -1
- package/dist/typescript/src/lib/utils/index.d.ts.map +1 -1
- package/dist/typescript/src/lib/utils/numbers.d.ts +13 -0
- package/dist/typescript/src/lib/utils/numbers.d.ts.map +1 -0
- package/dist/typescript/src/lib/utils/ticks/ticks.d.ts +1 -11
- package/dist/typescript/src/lib/utils/ticks/ticks.d.ts.map +1 -1
- package/dist/typescript/src/lib/utils/types.d.ts +27 -2
- package/dist/typescript/src/lib/utils/types.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/lib/Components/Axis/Axis.types.ts +6 -0
- package/src/lib/Components/Axis/XAxis/XAxis.test.tsx +12 -0
- package/src/lib/Components/Axis/XAxis/XAxis.tsx +29 -32
- package/src/lib/Components/Axis/YAxis/YAxis.test.tsx +12 -0
- package/src/lib/Components/Axis/YAxis/YAxis.tsx +29 -32
- package/src/lib/Components/CartesianChart/CartesianChart.tsx +30 -24
- package/src/lib/Components/CartesianChart/ChartEmptyLabel/ChartEmptyLabel.tsx +68 -0
- package/src/lib/Components/CartesianChart/ChartEmptyLabel/index.ts +1 -0
- package/src/lib/Components/CartesianChart/{RevealClip/RevealClipDefs.test.tsx → RevealAnimation/RevealAnimationProvider.test.tsx} +60 -17
- package/src/lib/Components/CartesianChart/{RevealClip/RevealClipDefs.tsx → RevealAnimation/RevealAnimationProvider.tsx} +11 -11
- package/src/lib/Components/CartesianChart/RevealAnimation/context.ts +39 -0
- package/src/lib/Components/CartesianChart/RevealAnimation/index.ts +2 -0
- package/src/lib/Components/CartesianChart/{RevealClip → RevealAnimation}/types.ts +16 -2
- package/src/lib/Components/CartesianChart/RevealAnimation/utils.ts +87 -0
- package/src/lib/Components/CartesianChart/hooks/useShimmerAnimation.ts +52 -0
- package/src/lib/Components/CartesianChart/types.ts +12 -0
- package/src/lib/Components/CartesianChart/utils.ts +2 -1
- package/src/lib/Components/Line/Line.tsx +26 -14
- package/src/lib/Components/Line/constants.ts +2 -0
- package/src/lib/Components/Line/index.ts +1 -1
- package/src/lib/Components/Line/types.ts +17 -0
- package/src/lib/Components/Line/utils.test.ts +77 -3
- package/src/lib/Components/Line/utils.ts +63 -12
- package/src/lib/Components/LineChart/LineChart.test.tsx +135 -0
- package/src/lib/Components/LineChart/LineChart.tsx +157 -38
- package/src/lib/Components/LineChart/LineChartEmptyState/LineChartEmptyState.test.tsx +39 -0
- package/src/lib/Components/LineChart/LineChartEmptyState/LineChartEmptyState.tsx +72 -0
- package/src/lib/Components/LineChart/LineChartEmptyState/index.ts +2 -0
- package/src/lib/Components/LineChart/LineChartEmptyState/types.ts +3 -0
- package/src/lib/Components/LineChart/LineChartEmptyState/utils.test.ts +22 -0
- package/src/lib/Components/LineChart/LineChartEmptyState/utils.ts +24 -0
- package/src/lib/Components/LineChart/types.ts +49 -1
- package/src/lib/Components/LineChart/utils.test.ts +196 -0
- package/src/lib/Components/LineChart/utils.ts +107 -0
- package/src/lib/Components/Point/Point.tsx +7 -4
- package/src/lib/Components/ReferenceLine/ReferenceLine.tsx +8 -4
- package/src/lib/Components/ReferenceLine/constants.ts +2 -2
- package/src/lib/Components/ReferenceLine/utils.ts +2 -1
- package/src/lib/Components/Scrubber/DefaultScrubberTooltip/utils.ts +2 -1
- package/src/lib/Components/Scrubber/Scrubber.tsx +13 -2
- package/src/lib/Components/Scrubber/ScrubberProvider.test.tsx +83 -1
- package/src/lib/Components/Scrubber/ScrubberProvider.tsx +17 -2
- package/src/lib/Components/Scrubber/utils.ts +3 -5
- package/src/lib/utils/index.ts +1 -0
- package/src/lib/utils/numbers.ts +15 -0
- package/src/lib/utils/ticks/ticks.ts +1 -23
- package/src/lib/utils/types.ts +35 -2
- package/dist/module/lib/Components/CartesianChart/RevealClip/RevealClipDefs.js.map +0 -1
- package/dist/module/lib/Components/CartesianChart/RevealClip/RevealClipDefs.test.js.map +0 -1
- package/dist/module/lib/Components/CartesianChart/RevealClip/context.js +0 -8
- package/dist/module/lib/Components/CartesianChart/RevealClip/context.js.map +0 -1
- package/dist/module/lib/Components/CartesianChart/RevealClip/index.js +0 -5
- package/dist/module/lib/Components/CartesianChart/RevealClip/index.js.map +0 -1
- package/dist/module/lib/Components/CartesianChart/RevealClip/types.js.map +0 -1
- package/dist/module/lib/Components/CartesianChart/RevealClip/utils.js +0 -32
- package/dist/module/lib/Components/CartesianChart/RevealClip/utils.js.map +0 -1
- package/dist/typescript/src/lib/Components/CartesianChart/RevealClip/RevealClipDefs.d.ts +0 -3
- package/dist/typescript/src/lib/Components/CartesianChart/RevealClip/RevealClipDefs.d.ts.map +0 -1
- package/dist/typescript/src/lib/Components/CartesianChart/RevealClip/context.d.ts +0 -7
- package/dist/typescript/src/lib/Components/CartesianChart/RevealClip/context.d.ts.map +0 -1
- package/dist/typescript/src/lib/Components/CartesianChart/RevealClip/index.d.ts +0 -3
- package/dist/typescript/src/lib/Components/CartesianChart/RevealClip/index.d.ts.map +0 -1
- package/dist/typescript/src/lib/Components/CartesianChart/RevealClip/types.d.ts.map +0 -1
- package/dist/typescript/src/lib/Components/CartesianChart/RevealClip/utils.d.ts +0 -17
- package/dist/typescript/src/lib/Components/CartesianChart/RevealClip/utils.d.ts.map +0 -1
- package/src/lib/Components/CartesianChart/RevealClip/context.ts +0 -13
- package/src/lib/Components/CartesianChart/RevealClip/index.ts +0 -2
- package/src/lib/Components/CartesianChart/RevealClip/utils.ts +0 -51
- /package/dist/module/lib/Components/CartesianChart/{RevealClip → RevealAnimation}/types.js +0 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
|
+
import {
|
|
3
|
+
cancelAnimation,
|
|
4
|
+
Easing,
|
|
5
|
+
useAnimatedProps,
|
|
6
|
+
useReducedMotion,
|
|
7
|
+
useSharedValue,
|
|
8
|
+
withRepeat,
|
|
9
|
+
withTiming,
|
|
10
|
+
} from 'react-native-reanimated';
|
|
11
|
+
|
|
12
|
+
const HALF_PULSE_DURATION_IN_MS = 1000;
|
|
13
|
+
const MIN_OPACITY = 0.5;
|
|
14
|
+
|
|
15
|
+
type ShimmerAnimationResult = {
|
|
16
|
+
animatedProps: ReturnType<typeof useAnimatedProps>;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Self-contained shimmer (opacity pulse) for SVG content, the RN counterpart of
|
|
21
|
+
* the web's CSS-keyframe shimmer. Shared by the initial loading placeholder and
|
|
22
|
+
* the transition-loading line. Honors the user's reduced-motion preference by
|
|
23
|
+
* keeping the content fully opaque.
|
|
24
|
+
*/
|
|
25
|
+
export const useShimmerAnimation = (animate = true): ShimmerAnimationResult => {
|
|
26
|
+
const opacity = useSharedValue(1);
|
|
27
|
+
const reducedMotion = useReducedMotion();
|
|
28
|
+
|
|
29
|
+
useEffect(() => {
|
|
30
|
+
if (animate && !reducedMotion) {
|
|
31
|
+
opacity.value = withRepeat(
|
|
32
|
+
withTiming(MIN_OPACITY, {
|
|
33
|
+
duration: HALF_PULSE_DURATION_IN_MS,
|
|
34
|
+
easing: Easing.inOut(Easing.ease),
|
|
35
|
+
}),
|
|
36
|
+
-1,
|
|
37
|
+
true,
|
|
38
|
+
);
|
|
39
|
+
} else {
|
|
40
|
+
cancelAnimation(opacity);
|
|
41
|
+
opacity.value = 1;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return () => {
|
|
45
|
+
cancelAnimation(opacity);
|
|
46
|
+
};
|
|
47
|
+
}, [animate, reducedMotion, opacity]);
|
|
48
|
+
|
|
49
|
+
const animatedProps = useAnimatedProps(() => ({ opacity: opacity.value }));
|
|
50
|
+
|
|
51
|
+
return { animatedProps };
|
|
52
|
+
};
|
|
@@ -43,6 +43,18 @@ export type CartesianChartProps = {
|
|
|
43
43
|
* @default 'Chart'
|
|
44
44
|
*/
|
|
45
45
|
ariaLabel?: string;
|
|
46
|
+
/**
|
|
47
|
+
* Marks the chart as busy for assistive technologies (via the container's
|
|
48
|
+
* accessibility state) to signal that its content is loading.
|
|
49
|
+
* @default false
|
|
50
|
+
*/
|
|
51
|
+
ariaBusy?: boolean;
|
|
52
|
+
/**
|
|
53
|
+
* Content rendered as an absolutely-positioned overlay above the chart SVG,
|
|
54
|
+
* within the same positioned container (so it aligns with the chart
|
|
55
|
+
* footprint). Used for e.g. an empty-state label.
|
|
56
|
+
*/
|
|
57
|
+
overlay?: ReactNode;
|
|
46
58
|
/**
|
|
47
59
|
* SVG content rendered inside the chart's context provider.
|
|
48
60
|
*/
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ChartInset } from '../../utils/types';
|
|
2
2
|
import type { CartesianChartProps } from './types';
|
|
3
3
|
|
|
4
|
-
export const DEFAULT_HEIGHT =
|
|
4
|
+
export const DEFAULT_HEIGHT = 228;
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Internal buffer added around the drawing area so SVG content (labels, points,
|
|
@@ -30,6 +30,7 @@ export const OVERFLOW_OFFSET = {
|
|
|
30
30
|
top: -OVERFLOW_BUFFER.top,
|
|
31
31
|
left: -OVERFLOW_BUFFER.left,
|
|
32
32
|
};
|
|
33
|
+
|
|
33
34
|
export const ZERO_PADDING: ChartInset = {
|
|
34
35
|
top: 0,
|
|
35
36
|
right: 0,
|
|
@@ -1,53 +1,65 @@
|
|
|
1
|
+
import { useTheme } from '@ledgerhq/lumen-ui-rnative';
|
|
1
2
|
import { useId, useMemo } from 'react';
|
|
2
3
|
import { Defs, G, LinearGradient, Path, Stop } from 'react-native-svg';
|
|
3
4
|
|
|
4
5
|
import { isNumericScale } from '../../utils/scales/scales';
|
|
5
6
|
import { useCartesianChartContext } from '../CartesianChart/context';
|
|
6
|
-
import {
|
|
7
|
+
import { usePathReveal } from '../CartesianChart/RevealAnimation';
|
|
7
8
|
|
|
9
|
+
import { LINE_AREA_GRADIENT_OPACITY, LINE_STROKE_WIDTH } from './constants';
|
|
8
10
|
import type { LineProps } from './types';
|
|
9
11
|
import { buildAreaPath, buildLinePath, toScaledPoints } from './utils';
|
|
10
12
|
|
|
11
|
-
const STROKE_WIDTH = 2;
|
|
12
|
-
const AREA_GRADIENT_OPACITY = 0.2;
|
|
13
|
-
|
|
14
13
|
export const Line = ({
|
|
15
14
|
seriesId,
|
|
16
15
|
stroke,
|
|
17
16
|
showArea = false,
|
|
18
17
|
areaType: _areaType = 'gradient',
|
|
18
|
+
curve,
|
|
19
|
+
connectNulls,
|
|
19
20
|
}: LineProps) => {
|
|
20
21
|
const { getXScale, getYScale, getXAxisConfig, drawingArea, seriesMap } =
|
|
21
22
|
useCartesianChartContext();
|
|
22
|
-
const clipPath =
|
|
23
|
+
const clipPath = usePathReveal();
|
|
23
24
|
|
|
24
25
|
const xScale = getXScale();
|
|
25
26
|
const yScale = getYScale();
|
|
26
27
|
const xAxisConfig = getXAxisConfig();
|
|
27
28
|
|
|
29
|
+
const { theme } = useTheme();
|
|
28
30
|
const gradientId = useId();
|
|
29
31
|
const seriesData = seriesMap.get(seriesId);
|
|
30
|
-
const resolvedStroke =
|
|
32
|
+
const resolvedStroke =
|
|
33
|
+
stroke ?? seriesData?.stroke ?? theme.colors.border.muted;
|
|
34
|
+
const resolvedCurve = curve ?? seriesData?.curve;
|
|
35
|
+
const resolvedConnectNulls =
|
|
36
|
+
connectNulls ?? seriesData?.connectNulls ?? false;
|
|
31
37
|
|
|
32
38
|
const points = useMemo(
|
|
33
39
|
() =>
|
|
34
40
|
seriesData?.data && xScale && yScale && isNumericScale(yScale)
|
|
35
|
-
? toScaledPoints(
|
|
41
|
+
? toScaledPoints(
|
|
42
|
+
seriesData.data,
|
|
43
|
+
xScale,
|
|
44
|
+
yScale,
|
|
45
|
+
xAxisConfig?.data,
|
|
46
|
+
resolvedConnectNulls,
|
|
47
|
+
)
|
|
36
48
|
: null,
|
|
37
|
-
[seriesData, xScale, yScale, xAxisConfig],
|
|
49
|
+
[seriesData, xScale, yScale, xAxisConfig, resolvedConnectNulls],
|
|
38
50
|
);
|
|
39
51
|
|
|
40
52
|
const linePath = useMemo(
|
|
41
|
-
() => (points ? buildLinePath(points) : null),
|
|
42
|
-
[points],
|
|
53
|
+
() => (points ? buildLinePath(points, resolvedCurve) : null),
|
|
54
|
+
[points, resolvedCurve],
|
|
43
55
|
);
|
|
44
56
|
|
|
45
57
|
const areaPath = useMemo(
|
|
46
58
|
() =>
|
|
47
59
|
showArea && points && drawingArea
|
|
48
|
-
? buildAreaPath(points, drawingArea)
|
|
60
|
+
? buildAreaPath(points, drawingArea, resolvedCurve)
|
|
49
61
|
: null,
|
|
50
|
-
[showArea, points, drawingArea],
|
|
62
|
+
[showArea, points, drawingArea, resolvedCurve],
|
|
51
63
|
);
|
|
52
64
|
|
|
53
65
|
if (!linePath) {
|
|
@@ -63,7 +75,7 @@ export const Line = ({
|
|
|
63
75
|
<Stop
|
|
64
76
|
offset='0%'
|
|
65
77
|
stopColor={resolvedStroke}
|
|
66
|
-
stopOpacity={
|
|
78
|
+
stopOpacity={LINE_AREA_GRADIENT_OPACITY}
|
|
67
79
|
/>
|
|
68
80
|
<Stop offset='100%' stopColor={resolvedStroke} stopOpacity={0} />
|
|
69
81
|
</LinearGradient>
|
|
@@ -81,7 +93,7 @@ export const Line = ({
|
|
|
81
93
|
d={linePath}
|
|
82
94
|
fill='none'
|
|
83
95
|
stroke={resolvedStroke}
|
|
84
|
-
strokeWidth={
|
|
96
|
+
strokeWidth={LINE_STROKE_WIDTH}
|
|
85
97
|
strokeLinecap='round'
|
|
86
98
|
strokeLinejoin='round'
|
|
87
99
|
/>
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { Line } from './Line';
|
|
2
|
-
export type { LineProps } from './types';
|
|
2
|
+
export type { CurveType, LineProps } from './types';
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import type { CurveType } from '../../utils/types';
|
|
2
|
+
|
|
3
|
+
export type { CurveType };
|
|
4
|
+
|
|
1
5
|
export type LineProps = {
|
|
2
6
|
/**
|
|
3
7
|
* The ID of the series to render.
|
|
@@ -20,4 +24,17 @@ export type LineProps = {
|
|
|
20
24
|
* @default 'gradient'
|
|
21
25
|
*/
|
|
22
26
|
areaType?: 'gradient';
|
|
27
|
+
/**
|
|
28
|
+
* Override interpolation used to draw the line between data points.
|
|
29
|
+
* When omitted, falls back to the `curve` defined on the series.
|
|
30
|
+
* @default 'bump'
|
|
31
|
+
*/
|
|
32
|
+
curve?: CurveType;
|
|
33
|
+
/**
|
|
34
|
+
* When true, skips null values and draws a continuous line across gaps.
|
|
35
|
+
* When false, null values create gaps in the line.
|
|
36
|
+
* When omitted, falls back to the `connectNulls` defined on the series.
|
|
37
|
+
* @default false
|
|
38
|
+
*/
|
|
39
|
+
connectNulls?: boolean;
|
|
23
40
|
};
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
getNumericScale,
|
|
6
6
|
} from '../../utils/scales/scales';
|
|
7
7
|
|
|
8
|
-
import { toScaledPoints } from './utils';
|
|
8
|
+
import { buildLinePath, toScaledPoints } from './utils';
|
|
9
9
|
|
|
10
10
|
const xScale = getNumericScale({
|
|
11
11
|
scaleType: 'linear',
|
|
@@ -44,17 +44,29 @@ describe('toScaledPoints', () => {
|
|
|
44
44
|
expect(points![points!.length - 1][0]).toBe(800);
|
|
45
45
|
});
|
|
46
46
|
|
|
47
|
-
it('
|
|
47
|
+
it('keeps null values as holes by default so the line breaks', () => {
|
|
48
48
|
const data: (number | null)[] = [10, null, 30, 40, 50, 60, 70, 80, 90];
|
|
49
49
|
const xData = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'];
|
|
50
50
|
|
|
51
51
|
const points = toScaledPoints(data, xScale, yScale, xData);
|
|
52
52
|
|
|
53
53
|
expect(points).not.toBeNull();
|
|
54
|
-
expect(points).toHaveLength(
|
|
54
|
+
expect(points).toHaveLength(8);
|
|
55
|
+
expect(points![1][1]).toBeNull();
|
|
55
56
|
expect(points![points!.length - 1][0]).toBe((800 / 7) * 7);
|
|
56
57
|
});
|
|
57
58
|
|
|
59
|
+
it('skips null values when connectNulls is true', () => {
|
|
60
|
+
const data: (number | null)[] = [10, null, 30, 40, 50, 60, 70, 80, 90];
|
|
61
|
+
const xData = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'];
|
|
62
|
+
|
|
63
|
+
const points = toScaledPoints(data, xScale, yScale, xData, true);
|
|
64
|
+
|
|
65
|
+
expect(points).not.toBeNull();
|
|
66
|
+
expect(points).toHaveLength(7);
|
|
67
|
+
expect(points!.every((p) => p[1] !== null)).toBe(true);
|
|
68
|
+
});
|
|
69
|
+
|
|
58
70
|
it('uses numeric xData values as the x input', () => {
|
|
59
71
|
const data = [10, 20, 30];
|
|
60
72
|
const customX = [0, 3.5, 7];
|
|
@@ -88,3 +100,65 @@ describe('toScaledPoints', () => {
|
|
|
88
100
|
expect(toScaledPoints(data, xScale, yScale, xData)).toBeNull();
|
|
89
101
|
});
|
|
90
102
|
});
|
|
103
|
+
|
|
104
|
+
describe('buildLinePath', () => {
|
|
105
|
+
const points: [number, number][] = [
|
|
106
|
+
[0, 100],
|
|
107
|
+
[50, 20],
|
|
108
|
+
[100, 60],
|
|
109
|
+
];
|
|
110
|
+
|
|
111
|
+
it('defaults to the bump curve (cubic beziers)', () => {
|
|
112
|
+
const path = buildLinePath(points);
|
|
113
|
+
|
|
114
|
+
expect(path).not.toBeNull();
|
|
115
|
+
expect(path).toContain('C');
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
it('draws straight segments for the linear curve', () => {
|
|
119
|
+
const path = buildLinePath(points, 'linear');
|
|
120
|
+
|
|
121
|
+
expect(path).toBe('M0,100L50,20L100,60');
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it('uses cubic beziers for smooth curves', () => {
|
|
125
|
+
expect(buildLinePath(points, 'natural')).toContain('C');
|
|
126
|
+
expect(buildLinePath(points, 'monotone')).toContain('C');
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
it('draws orthogonal segments for the step curve', () => {
|
|
130
|
+
const path = buildLinePath(points, 'step');
|
|
131
|
+
|
|
132
|
+
expect(path).not.toBeNull();
|
|
133
|
+
expect(path).not.toContain('C');
|
|
134
|
+
expect(path).toBe('M0,100L25,100L25,20L75,20L75,60L100,60');
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
it('falls back to the default curve for unknown values', () => {
|
|
138
|
+
const path = buildLinePath(points, 'unknown' as never);
|
|
139
|
+
|
|
140
|
+
expect(path).toBe(buildLinePath(points));
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
it('breaks the path into segments at null holes', () => {
|
|
144
|
+
const gapped: [number, number | null][] = [
|
|
145
|
+
[0, 100],
|
|
146
|
+
[50, 80],
|
|
147
|
+
[100, null],
|
|
148
|
+
[150, 60],
|
|
149
|
+
[200, 40],
|
|
150
|
+
];
|
|
151
|
+
|
|
152
|
+
const path = buildLinePath(gapped, 'linear');
|
|
153
|
+
|
|
154
|
+
expect(path).not.toBeNull();
|
|
155
|
+
expect(path!.match(/M/g)).toHaveLength(2);
|
|
156
|
+
expect(path).toBe('M0,100L50,80M150,60L200,40');
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
it('draws a single continuous segment when there are no holes', () => {
|
|
160
|
+
const path = buildLinePath(points, 'linear');
|
|
161
|
+
|
|
162
|
+
expect(path!.match(/M/g)).toHaveLength(1);
|
|
163
|
+
});
|
|
164
|
+
});
|
|
@@ -1,16 +1,47 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
area,
|
|
3
|
+
curveBumpX,
|
|
4
|
+
curveLinear,
|
|
5
|
+
curveMonotoneX,
|
|
6
|
+
curveNatural,
|
|
7
|
+
curveStep,
|
|
8
|
+
curveStepAfter,
|
|
9
|
+
curveStepBefore,
|
|
10
|
+
line,
|
|
11
|
+
type CurveFactory,
|
|
12
|
+
} from 'd3-shape';
|
|
2
13
|
|
|
14
|
+
import { isFiniteNumber } from '../../utils/numbers';
|
|
3
15
|
import { isCategoricalScale } from '../../utils/scales/scales';
|
|
4
16
|
import type {
|
|
5
17
|
ChartScaleFunction,
|
|
18
|
+
CurveType,
|
|
6
19
|
DrawingArea,
|
|
7
20
|
NumericScale,
|
|
8
21
|
} from '../../utils/types';
|
|
9
22
|
|
|
10
|
-
type Point = [x: number, y: number];
|
|
23
|
+
type Point = [x: number, y: number | null];
|
|
11
24
|
|
|
12
25
|
/**
|
|
13
|
-
*
|
|
26
|
+
* Maps the public `CurveType` values to their d3-shape curve factories.
|
|
27
|
+
*/
|
|
28
|
+
const CURVE_FACTORIES: Record<CurveType, CurveFactory> = {
|
|
29
|
+
bump: curveBumpX,
|
|
30
|
+
linear: curveLinear,
|
|
31
|
+
monotone: curveMonotoneX,
|
|
32
|
+
natural: curveNatural,
|
|
33
|
+
step: curveStep,
|
|
34
|
+
stepAfter: curveStepAfter,
|
|
35
|
+
stepBefore: curveStepBefore,
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const DEFAULT_CURVE: CurveType = 'bump';
|
|
39
|
+
|
|
40
|
+
const getCurveFactory = (curve: CurveType = DEFAULT_CURVE): CurveFactory =>
|
|
41
|
+
CURVE_FACTORIES[curve] ?? CURVE_FACTORIES[DEFAULT_CURVE];
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Project series data into scaled [x, y] pixel coordinates.
|
|
14
45
|
*
|
|
15
46
|
* When `xData` contains numeric values, those values are fed into the scale
|
|
16
47
|
* instead of the array index so the points honour a numeric X domain.
|
|
@@ -18,19 +49,28 @@ type Point = [x: number, y: number];
|
|
|
18
49
|
* When `xData` is provided, iteration is capped at `xData.length` so a series
|
|
19
50
|
* with more points than the axis has labels does not overflow past the right
|
|
20
51
|
* edge of the chart. The axis is treated as authoritative for the X domain.
|
|
52
|
+
*
|
|
53
|
+
* Non-finite values (e.g. `null`) are handled according to `connectNulls`:
|
|
54
|
+
* - `false` (default): kept as `[x, null]` holes so the line/area break into
|
|
55
|
+
* gaps via the generators' `.defined()` check.
|
|
56
|
+
* - `true`: skipped entirely so the line is drawn continuously across gaps.
|
|
21
57
|
*/
|
|
22
58
|
export const toScaledPoints = (
|
|
23
59
|
data: (number | null)[],
|
|
24
60
|
xScale: ChartScaleFunction,
|
|
25
61
|
yScale: NumericScale,
|
|
26
62
|
xData?: readonly (string | number)[],
|
|
63
|
+
connectNulls = false,
|
|
27
64
|
): Point[] | null => {
|
|
28
65
|
const pts: Point[] = [];
|
|
29
66
|
const limit = xData ? Math.min(data.length, xData.length) : data.length;
|
|
67
|
+
let finiteCount = 0;
|
|
30
68
|
|
|
31
69
|
for (let i = 0; i < limit; i++) {
|
|
32
70
|
const value = data[i];
|
|
33
|
-
|
|
71
|
+
const isFiniteValue = isFiniteNumber(value);
|
|
72
|
+
|
|
73
|
+
if (!isFiniteValue && connectNulls) continue;
|
|
34
74
|
|
|
35
75
|
const xInput =
|
|
36
76
|
xData && typeof xData[i] === 'number' ? (xData[i] as number) : i;
|
|
@@ -38,23 +78,32 @@ export const toScaledPoints = (
|
|
|
38
78
|
const x = isCategoricalScale(xScale)
|
|
39
79
|
? (xScale(xInput) ?? 0) + xScale.bandwidth() / 2
|
|
40
80
|
: xScale(xInput);
|
|
41
|
-
const y = yScale(value);
|
|
42
81
|
|
|
43
|
-
|
|
82
|
+
if (!isFiniteValue) {
|
|
83
|
+
pts.push([x as number, null]);
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
pts.push([x as number, yScale(value)]);
|
|
88
|
+
finiteCount++;
|
|
44
89
|
}
|
|
45
90
|
|
|
46
|
-
return
|
|
91
|
+
return finiteCount >= 2 ? pts : null;
|
|
47
92
|
};
|
|
48
93
|
|
|
49
94
|
/**
|
|
50
95
|
* Build the SVG `d` attribute for the line stroke.
|
|
51
96
|
*/
|
|
52
|
-
export const buildLinePath = (
|
|
97
|
+
export const buildLinePath = (
|
|
98
|
+
points: Point[],
|
|
99
|
+
curve?: CurveType,
|
|
100
|
+
): string | null => {
|
|
53
101
|
return (
|
|
54
102
|
line<Point>()
|
|
103
|
+
.defined((d) => d[1] !== null)
|
|
55
104
|
.x((d) => d[0])
|
|
56
|
-
.y((d) => d[1])
|
|
57
|
-
.curve(
|
|
105
|
+
.y((d) => d[1] as number)
|
|
106
|
+
.curve(getCurveFactory(curve))(points) ?? null
|
|
58
107
|
);
|
|
59
108
|
};
|
|
60
109
|
|
|
@@ -64,14 +113,16 @@ export const buildLinePath = (points: Point[]): string | null => {
|
|
|
64
113
|
export const buildAreaPath = (
|
|
65
114
|
points: Point[],
|
|
66
115
|
drawingArea: DrawingArea,
|
|
116
|
+
curve?: CurveType,
|
|
67
117
|
): string | null => {
|
|
68
118
|
const yBottom = drawingArea.y + drawingArea.height;
|
|
69
119
|
|
|
70
120
|
return (
|
|
71
121
|
area<Point>()
|
|
122
|
+
.defined((d) => d[1] !== null)
|
|
72
123
|
.x((d) => d[0])
|
|
73
124
|
.y0(yBottom)
|
|
74
|
-
.y1((d) => d[1])
|
|
75
|
-
.curve(
|
|
125
|
+
.y1((d) => d[1] as number)
|
|
126
|
+
.curve(getCurveFactory(curve))(points) ?? null
|
|
76
127
|
);
|
|
77
128
|
};
|
|
@@ -255,4 +255,139 @@ describe('LineChart', () => {
|
|
|
255
255
|
);
|
|
256
256
|
getByTestId('chart-svg');
|
|
257
257
|
});
|
|
258
|
+
|
|
259
|
+
describe('loading and empty states', () => {
|
|
260
|
+
it('renders the placeholder with no data while loading (state 1)', () => {
|
|
261
|
+
const { getByTestId, queryByTestId } = render(
|
|
262
|
+
<LineChartWrapper>
|
|
263
|
+
<LineChart width={400} height={200} loading />
|
|
264
|
+
</LineChartWrapper>,
|
|
265
|
+
);
|
|
266
|
+
|
|
267
|
+
getByTestId('chart-empty-state');
|
|
268
|
+
expect(queryByTestId('line-path')).toBeNull();
|
|
269
|
+
expect(queryByTestId('chart-empty-label')).toBeNull();
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
it('renders the placeholder with the empty label when there is no data and not loading (state 2)', () => {
|
|
273
|
+
const { getByTestId, queryByTestId } = render(
|
|
274
|
+
<LineChartWrapper>
|
|
275
|
+
<LineChart width={400} height={200} emptyLabel='Nothing here' />
|
|
276
|
+
</LineChartWrapper>,
|
|
277
|
+
);
|
|
278
|
+
|
|
279
|
+
getByTestId('chart-empty-state');
|
|
280
|
+
expect(
|
|
281
|
+
getByTestId('chart-empty-label', { includeHiddenElements: true }),
|
|
282
|
+
).toHaveTextContent('Nothing here');
|
|
283
|
+
expect(queryByTestId('line-path')).toBeNull();
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
it('defaults the empty label to "No data"', () => {
|
|
287
|
+
const { getByTestId } = render(
|
|
288
|
+
<LineChartWrapper>
|
|
289
|
+
<LineChart width={400} height={200} />
|
|
290
|
+
</LineChartWrapper>,
|
|
291
|
+
);
|
|
292
|
+
|
|
293
|
+
expect(
|
|
294
|
+
getByTestId('chart-empty-label', { includeHiddenElements: true }),
|
|
295
|
+
).toHaveTextContent('No data');
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
it('keeps rendering the real line during a transition load (state 3)', () => {
|
|
299
|
+
const { getByTestId, queryByTestId } = render(
|
|
300
|
+
<LineChartWrapper>
|
|
301
|
+
<LineChart series={sampleSeries} width={400} height={200} loading />
|
|
302
|
+
</LineChartWrapper>,
|
|
303
|
+
);
|
|
304
|
+
|
|
305
|
+
getByTestId('line-path');
|
|
306
|
+
expect(queryByTestId('chart-empty-state')).toBeNull();
|
|
307
|
+
expect(queryByTestId('chart-empty-label')).toBeNull();
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
it('renders the normal chart when idle with data (state 4)', () => {
|
|
311
|
+
const { getByTestId, queryByTestId } = render(
|
|
312
|
+
<LineChartWrapper>
|
|
313
|
+
<LineChart series={sampleSeries} width={400} height={200} />
|
|
314
|
+
</LineChartWrapper>,
|
|
315
|
+
);
|
|
316
|
+
|
|
317
|
+
getByTestId('line-path');
|
|
318
|
+
expect(queryByTestId('chart-empty-state')).toBeNull();
|
|
319
|
+
expect(queryByTestId('chart-empty-label')).toBeNull();
|
|
320
|
+
});
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
describe('null gaps and connectNulls', () => {
|
|
324
|
+
const gappedSeries = [
|
|
325
|
+
{
|
|
326
|
+
id: 'gapped',
|
|
327
|
+
stroke: '#000',
|
|
328
|
+
data: [10, 20, null, 40, 50],
|
|
329
|
+
curve: 'linear' as const,
|
|
330
|
+
},
|
|
331
|
+
];
|
|
332
|
+
|
|
333
|
+
const countMoves = (d: string): number => d.match(/M/g)?.length ?? 0;
|
|
334
|
+
|
|
335
|
+
it('breaks the line into segments at null values by default', () => {
|
|
336
|
+
const { getByTestId } = render(
|
|
337
|
+
<LineChartWrapper>
|
|
338
|
+
<LineChart series={gappedSeries} width={400} height={200} />
|
|
339
|
+
</LineChartWrapper>,
|
|
340
|
+
);
|
|
341
|
+
|
|
342
|
+
const d = getByTestId('line-path').props.d as string;
|
|
343
|
+
expect(countMoves(d)).toBe(2);
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
it('connects across nulls when connectNulls is set on the chart', () => {
|
|
347
|
+
const { getByTestId } = render(
|
|
348
|
+
<LineChartWrapper>
|
|
349
|
+
<LineChart
|
|
350
|
+
series={gappedSeries}
|
|
351
|
+
width={400}
|
|
352
|
+
height={200}
|
|
353
|
+
connectNulls
|
|
354
|
+
/>
|
|
355
|
+
</LineChartWrapper>,
|
|
356
|
+
);
|
|
357
|
+
|
|
358
|
+
const d = getByTestId('line-path').props.d as string;
|
|
359
|
+
expect(countMoves(d)).toBe(1);
|
|
360
|
+
});
|
|
361
|
+
|
|
362
|
+
it('honours connectNulls set per-series', () => {
|
|
363
|
+
const { getByTestId } = render(
|
|
364
|
+
<LineChartWrapper>
|
|
365
|
+
<LineChart
|
|
366
|
+
series={[{ ...gappedSeries[0], connectNulls: true }]}
|
|
367
|
+
width={400}
|
|
368
|
+
height={200}
|
|
369
|
+
/>
|
|
370
|
+
</LineChartWrapper>,
|
|
371
|
+
);
|
|
372
|
+
|
|
373
|
+
const d = getByTestId('line-path').props.d as string;
|
|
374
|
+
expect(countMoves(d)).toBe(1);
|
|
375
|
+
});
|
|
376
|
+
|
|
377
|
+
it('lets the chart-level prop override the per-series value', () => {
|
|
378
|
+
const { getByTestId } = render(
|
|
379
|
+
<LineChartWrapper>
|
|
380
|
+
<LineChart
|
|
381
|
+
series={[{ ...gappedSeries[0], connectNulls: true }]}
|
|
382
|
+
width={400}
|
|
383
|
+
height={200}
|
|
384
|
+
connectNulls={false}
|
|
385
|
+
/>
|
|
386
|
+
</LineChartWrapper>,
|
|
387
|
+
);
|
|
388
|
+
|
|
389
|
+
const d = getByTestId('line-path').props.d as string;
|
|
390
|
+
expect(countMoves(d)).toBe(2);
|
|
391
|
+
});
|
|
392
|
+
});
|
|
258
393
|
});
|