@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
|
@@ -2,10 +2,7 @@ import { useTheme } from '@ledgerhq/lumen-ui-rnative';
|
|
|
2
2
|
import { useMemo } from 'react';
|
|
3
3
|
import { G, Line as SvgLine, Text as SvgText } from 'react-native-svg';
|
|
4
4
|
|
|
5
|
-
import {
|
|
6
|
-
buildTicksData,
|
|
7
|
-
isTickOnYAxisDomainEdge,
|
|
8
|
-
} from '../../../utils/ticks/ticks';
|
|
5
|
+
import { buildTicksData } from '../../../utils/ticks/ticks';
|
|
9
6
|
import { useCartesianChartContext } from '../../CartesianChart/context';
|
|
10
7
|
|
|
11
8
|
import type { YAxisProps } from './types';
|
|
@@ -20,6 +17,7 @@ export const YAxis = ({
|
|
|
20
17
|
showGrid = false,
|
|
21
18
|
showLine = false,
|
|
22
19
|
showTickMark = false,
|
|
20
|
+
showLabels = true,
|
|
23
21
|
gridLineStyle = 'dashed',
|
|
24
22
|
ticks: ticksProp,
|
|
25
23
|
tickLabelFormatter,
|
|
@@ -56,20 +54,18 @@ export const YAxis = ({
|
|
|
56
54
|
return (
|
|
57
55
|
<G>
|
|
58
56
|
{showGrid &&
|
|
59
|
-
ticksData
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
/>
|
|
72
|
-
))}
|
|
57
|
+
ticksData.map((tick, i) => (
|
|
58
|
+
<SvgLine
|
|
59
|
+
key={`grid-${tick.value}-${i}`}
|
|
60
|
+
x1={drawingArea.x}
|
|
61
|
+
y1={tick.position}
|
|
62
|
+
x2={drawingArea.x + drawingArea.width}
|
|
63
|
+
y2={tick.position}
|
|
64
|
+
stroke={gridStroke}
|
|
65
|
+
strokeWidth={STROKE_WIDTH}
|
|
66
|
+
strokeDasharray={gridLineStyle === 'dashed' ? '3 3' : undefined}
|
|
67
|
+
/>
|
|
68
|
+
))}
|
|
73
69
|
|
|
74
70
|
{showLine && (
|
|
75
71
|
<SvgLine
|
|
@@ -96,20 +92,21 @@ export const YAxis = ({
|
|
|
96
92
|
/>
|
|
97
93
|
))}
|
|
98
94
|
|
|
99
|
-
{
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
95
|
+
{showLabels &&
|
|
96
|
+
ticksData.map((tick, i) => (
|
|
97
|
+
<SvgText
|
|
98
|
+
key={`label-${tick.value}-${i}`}
|
|
99
|
+
x={labelX}
|
|
100
|
+
y={tick.position}
|
|
101
|
+
dy={labelDy}
|
|
102
|
+
textAnchor={position === 'start' ? 'end' : 'start'}
|
|
103
|
+
fill={textFill}
|
|
104
|
+
fontSize={theme.typographies.body4.fontSize}
|
|
105
|
+
fontFamily={theme.fontFamilies.sans}
|
|
106
|
+
>
|
|
107
|
+
{tick.label}
|
|
108
|
+
</SvgText>
|
|
109
|
+
))}
|
|
113
110
|
</G>
|
|
114
111
|
);
|
|
115
112
|
};
|
|
@@ -5,7 +5,7 @@ import { Svg } from 'react-native-svg';
|
|
|
5
5
|
import { MagneticPointsProvider } from '../Point/pointContext';
|
|
6
6
|
import { ScrubberProvider } from '../Scrubber/ScrubberProvider';
|
|
7
7
|
import { CartesianChartProvider, useBuildChartContext } from './context';
|
|
8
|
-
import {
|
|
8
|
+
import { RevealAnimationProvider } from './RevealAnimation';
|
|
9
9
|
import type { CartesianChartProps } from './types';
|
|
10
10
|
import {
|
|
11
11
|
DEFAULT_HEIGHT,
|
|
@@ -24,6 +24,8 @@ export function CartesianChart({
|
|
|
24
24
|
inset,
|
|
25
25
|
axisPadding,
|
|
26
26
|
ariaLabel = 'Chart',
|
|
27
|
+
ariaBusy = false,
|
|
28
|
+
overlay,
|
|
27
29
|
children,
|
|
28
30
|
enableScrubbing = false,
|
|
29
31
|
onScrubberPositionChange,
|
|
@@ -75,6 +77,7 @@ export function CartesianChart({
|
|
|
75
77
|
onLayout={needsMeasurement ? handleLayout : undefined}
|
|
76
78
|
accessibilityRole='image'
|
|
77
79
|
accessibilityLabel={ariaLabel}
|
|
80
|
+
accessibilityState={{ busy: ariaBusy }}
|
|
78
81
|
style={{
|
|
79
82
|
width: needsMeasurement ? undefined : resolvedWidth,
|
|
80
83
|
height,
|
|
@@ -82,33 +85,36 @@ export function CartesianChart({
|
|
|
82
85
|
}}
|
|
83
86
|
>
|
|
84
87
|
{resolvedWidth > 0 && (
|
|
85
|
-
|
|
86
|
-
<
|
|
87
|
-
<
|
|
88
|
-
|
|
89
|
-
height={svgHeight}
|
|
90
|
-
enableScrubbing={enableScrubbing}
|
|
91
|
-
onScrubberPositionChange={onScrubberPositionChange}
|
|
92
|
-
style={OVERFLOW_OFFSET}
|
|
93
|
-
magnetRadius={magnetRadius}
|
|
94
|
-
>
|
|
95
|
-
<Svg
|
|
96
|
-
testID='chart-svg'
|
|
88
|
+
<>
|
|
89
|
+
<CartesianChartProvider value={contextValue}>
|
|
90
|
+
<MagneticPointsProvider>
|
|
91
|
+
<ScrubberProvider
|
|
97
92
|
width={svgWidth}
|
|
98
93
|
height={svgHeight}
|
|
99
|
-
|
|
94
|
+
enableScrubbing={enableScrubbing}
|
|
95
|
+
onScrubberPositionChange={onScrubberPositionChange}
|
|
96
|
+
style={OVERFLOW_OFFSET}
|
|
97
|
+
magnetRadius={magnetRadius}
|
|
100
98
|
>
|
|
101
|
-
<
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
99
|
+
<Svg
|
|
100
|
+
testID='chart-svg'
|
|
101
|
+
width={svgWidth}
|
|
102
|
+
height={svgHeight}
|
|
103
|
+
style={{ overflow: 'visible' }}
|
|
105
104
|
>
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
105
|
+
<RevealAnimationProvider
|
|
106
|
+
drawingArea={contextValue.drawingArea}
|
|
107
|
+
series={series}
|
|
108
|
+
animate={animate}
|
|
109
|
+
>
|
|
110
|
+
{children}
|
|
111
|
+
</RevealAnimationProvider>
|
|
112
|
+
</Svg>
|
|
113
|
+
</ScrubberProvider>
|
|
114
|
+
</MagneticPointsProvider>
|
|
115
|
+
</CartesianChartProvider>
|
|
116
|
+
{overlay}
|
|
117
|
+
</>
|
|
112
118
|
)}
|
|
113
119
|
</View>
|
|
114
120
|
);
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { Text, useStyleSheet } from '@ledgerhq/lumen-ui-rnative';
|
|
2
|
+
import type { ReactNode } from 'react';
|
|
3
|
+
import { View } from 'react-native';
|
|
4
|
+
|
|
5
|
+
type ChartEmptyLabelProps = {
|
|
6
|
+
children: ReactNode;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
const useStyles = () => {
|
|
10
|
+
return useStyleSheet(
|
|
11
|
+
(t) => ({
|
|
12
|
+
container: {
|
|
13
|
+
position: 'absolute',
|
|
14
|
+
top: 0,
|
|
15
|
+
left: 0,
|
|
16
|
+
right: 0,
|
|
17
|
+
bottom: 0,
|
|
18
|
+
alignItems: 'center',
|
|
19
|
+
justifyContent: 'center',
|
|
20
|
+
},
|
|
21
|
+
pill: {
|
|
22
|
+
backgroundColor: t.colors.bg.muted,
|
|
23
|
+
borderRadius: t.borderRadius.xs,
|
|
24
|
+
paddingHorizontal: t.spacings.s12,
|
|
25
|
+
paddingVertical: t.spacings.s6,
|
|
26
|
+
},
|
|
27
|
+
label: {
|
|
28
|
+
color: t.colors.text.muted,
|
|
29
|
+
...t.typographies.body3,
|
|
30
|
+
},
|
|
31
|
+
}),
|
|
32
|
+
[],
|
|
33
|
+
);
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Centered overlay label shown when a chart has no data (and is not loading).
|
|
38
|
+
* Rendered through the `overlay` slot of `CartesianChart` so it shares the
|
|
39
|
+
* chart's positioned container and aligns with the chart footprint. Shared
|
|
40
|
+
* across cartesian charts (LineChart, future BarChart).
|
|
41
|
+
*
|
|
42
|
+
* This is the lib's only non-SVG (View/Text) element, so unlike the chart
|
|
43
|
+
* visuals (which read raw theme colors for `react-native-svg`) it is styled with
|
|
44
|
+
* the design system's themed stylesheet, consistent with the components in
|
|
45
|
+
* `ui-rnative`.
|
|
46
|
+
*/
|
|
47
|
+
export function ChartEmptyLabel({ children }: Readonly<ChartEmptyLabelProps>) {
|
|
48
|
+
const styles = useStyles();
|
|
49
|
+
|
|
50
|
+
return (
|
|
51
|
+
<View
|
|
52
|
+
pointerEvents='none'
|
|
53
|
+
accessibilityElementsHidden={true}
|
|
54
|
+
importantForAccessibility='no-hide-descendants'
|
|
55
|
+
style={styles.container}
|
|
56
|
+
>
|
|
57
|
+
<View style={styles.pill}>
|
|
58
|
+
<Text
|
|
59
|
+
testID='chart-empty-label'
|
|
60
|
+
style={styles.label}
|
|
61
|
+
accessible={false}
|
|
62
|
+
>
|
|
63
|
+
{children}
|
|
64
|
+
</Text>
|
|
65
|
+
</View>
|
|
66
|
+
</View>
|
|
67
|
+
);
|
|
68
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { ChartEmptyLabel } from './ChartEmptyLabel';
|
|
@@ -7,8 +7,8 @@ import { Svg } from 'react-native-svg';
|
|
|
7
7
|
import type { DrawingArea, Series } from '../../../utils/types';
|
|
8
8
|
import { OVERFLOW_BUFFER } from '../utils';
|
|
9
9
|
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
10
|
+
import { usePathReveal, usePointReveal } from './context';
|
|
11
|
+
import { RevealAnimationProvider } from './RevealAnimationProvider';
|
|
12
12
|
|
|
13
13
|
const drawingArea: DrawingArea = {
|
|
14
14
|
x: 10,
|
|
@@ -20,10 +20,15 @@ const drawingArea: DrawingArea = {
|
|
|
20
20
|
const series: Series[] = [{ id: 'a', stroke: '#000', data: [1, 2, 3] }];
|
|
21
21
|
|
|
22
22
|
function ClipConsumer() {
|
|
23
|
-
const clipPath =
|
|
23
|
+
const clipPath = usePathReveal();
|
|
24
24
|
return <Svg testID='consumer' clipPath={clipPath} />;
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
+
function PointConsumer() {
|
|
28
|
+
const pointOpacity = usePointReveal();
|
|
29
|
+
return <Svg testID='point-consumer' opacity={pointOpacity ? 1 : 0} />;
|
|
30
|
+
}
|
|
31
|
+
|
|
27
32
|
const renderInSvg = (ui: React.ReactElement) =>
|
|
28
33
|
render(
|
|
29
34
|
<ThemeProvider themes={ledgerLiveThemes} colorScheme='light'>
|
|
@@ -31,16 +36,16 @@ const renderInSvg = (ui: React.ReactElement) =>
|
|
|
31
36
|
</ThemeProvider>,
|
|
32
37
|
);
|
|
33
38
|
|
|
34
|
-
describe('
|
|
39
|
+
describe('RevealAnimationProvider', () => {
|
|
35
40
|
it('renders children', () => {
|
|
36
41
|
const { getByTestId } = renderInSvg(
|
|
37
|
-
<
|
|
42
|
+
<RevealAnimationProvider
|
|
38
43
|
drawingArea={drawingArea}
|
|
39
44
|
series={series}
|
|
40
45
|
transitions={{ enter: { duration: 0.5 } }}
|
|
41
46
|
>
|
|
42
47
|
<Svg testID='child' />
|
|
43
|
-
</
|
|
48
|
+
</RevealAnimationProvider>,
|
|
44
49
|
);
|
|
45
50
|
|
|
46
51
|
expect(getByTestId('child')).toBeTruthy();
|
|
@@ -48,13 +53,13 @@ describe('RevealClipDefs', () => {
|
|
|
48
53
|
|
|
49
54
|
it('renders a ClipPath with a Rect when animate is true', () => {
|
|
50
55
|
const { UNSAFE_root } = renderInSvg(
|
|
51
|
-
<
|
|
56
|
+
<RevealAnimationProvider
|
|
52
57
|
drawingArea={drawingArea}
|
|
53
58
|
series={series}
|
|
54
59
|
transitions={{ enter: { duration: 0.5 } }}
|
|
55
60
|
>
|
|
56
61
|
<Svg testID='child' />
|
|
57
|
-
</
|
|
62
|
+
</RevealAnimationProvider>,
|
|
58
63
|
);
|
|
59
64
|
|
|
60
65
|
const clipPaths = UNSAFE_root.findAllByType('ClipPath' as any);
|
|
@@ -71,26 +76,45 @@ describe('RevealClipDefs', () => {
|
|
|
71
76
|
);
|
|
72
77
|
});
|
|
73
78
|
|
|
74
|
-
it('provides clipPathAttr to consumers via
|
|
79
|
+
it('provides clipPathAttr to consumers via usePathReveal', () => {
|
|
75
80
|
const { UNSAFE_root } = renderInSvg(
|
|
76
|
-
<
|
|
81
|
+
<RevealAnimationProvider
|
|
77
82
|
drawingArea={drawingArea}
|
|
78
83
|
series={series}
|
|
79
84
|
transitions={{ enter: { duration: 0.5 } }}
|
|
80
85
|
>
|
|
81
86
|
<ClipConsumer />
|
|
82
|
-
</
|
|
87
|
+
</RevealAnimationProvider>,
|
|
83
88
|
);
|
|
84
89
|
|
|
85
90
|
const consumer = UNSAFE_root.findByProps({ testID: 'consumer' });
|
|
86
91
|
expect(consumer.props.clipPath).toMatch(/^url\(#/);
|
|
87
92
|
});
|
|
88
93
|
|
|
94
|
+
it('provides a point opacity shared value via usePointReveal', () => {
|
|
95
|
+
const { UNSAFE_root } = renderInSvg(
|
|
96
|
+
<RevealAnimationProvider
|
|
97
|
+
drawingArea={drawingArea}
|
|
98
|
+
series={series}
|
|
99
|
+
transitions={{ enter: { duration: 0.5 } }}
|
|
100
|
+
>
|
|
101
|
+
<PointConsumer />
|
|
102
|
+
</RevealAnimationProvider>,
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
const consumer = UNSAFE_root.findByProps({ testID: 'point-consumer' });
|
|
106
|
+
expect(consumer.props.opacity).toBe(1);
|
|
107
|
+
});
|
|
108
|
+
|
|
89
109
|
it('skips ClipPath when animate is false', () => {
|
|
90
110
|
const { UNSAFE_root, getByTestId } = renderInSvg(
|
|
91
|
-
<
|
|
111
|
+
<RevealAnimationProvider
|
|
112
|
+
drawingArea={drawingArea}
|
|
113
|
+
series={series}
|
|
114
|
+
animate={false}
|
|
115
|
+
>
|
|
92
116
|
<Svg testID='child' />
|
|
93
|
-
</
|
|
117
|
+
</RevealAnimationProvider>,
|
|
94
118
|
);
|
|
95
119
|
|
|
96
120
|
expect(getByTestId('child')).toBeTruthy();
|
|
@@ -101,24 +125,43 @@ describe('RevealClipDefs', () => {
|
|
|
101
125
|
|
|
102
126
|
it('does not provide clipPathAttr when animate is false', () => {
|
|
103
127
|
const { UNSAFE_root } = renderInSvg(
|
|
104
|
-
<
|
|
128
|
+
<RevealAnimationProvider
|
|
129
|
+
drawingArea={drawingArea}
|
|
130
|
+
series={series}
|
|
131
|
+
animate={false}
|
|
132
|
+
>
|
|
105
133
|
<ClipConsumer />
|
|
106
|
-
</
|
|
134
|
+
</RevealAnimationProvider>,
|
|
107
135
|
);
|
|
108
136
|
|
|
109
137
|
const consumer = UNSAFE_root.findByProps({ testID: 'consumer' });
|
|
110
138
|
expect(consumer.props.clipPath).toBeUndefined();
|
|
111
139
|
});
|
|
112
140
|
|
|
141
|
+
it('does not provide a point opacity value when animate is false', () => {
|
|
142
|
+
const { UNSAFE_root } = renderInSvg(
|
|
143
|
+
<RevealAnimationProvider
|
|
144
|
+
drawingArea={drawingArea}
|
|
145
|
+
series={series}
|
|
146
|
+
animate={false}
|
|
147
|
+
>
|
|
148
|
+
<PointConsumer />
|
|
149
|
+
</RevealAnimationProvider>,
|
|
150
|
+
);
|
|
151
|
+
|
|
152
|
+
const consumer = UNSAFE_root.findByProps({ testID: 'point-consumer' });
|
|
153
|
+
expect(consumer.props.opacity).toBe(0);
|
|
154
|
+
});
|
|
155
|
+
|
|
113
156
|
it('renders without crashing when transitions.enter is not defined', () => {
|
|
114
157
|
const { UNSAFE_root, getByTestId } = renderInSvg(
|
|
115
|
-
<
|
|
158
|
+
<RevealAnimationProvider
|
|
116
159
|
drawingArea={drawingArea}
|
|
117
160
|
series={series}
|
|
118
161
|
transitions={{}}
|
|
119
162
|
>
|
|
120
163
|
<Svg testID='child' />
|
|
121
|
-
</
|
|
164
|
+
</RevealAnimationProvider>,
|
|
122
165
|
);
|
|
123
166
|
|
|
124
167
|
expect(getByTestId('child')).toBeTruthy();
|
|
@@ -6,21 +6,21 @@ import { ClipPath, Defs, Rect } from 'react-native-svg';
|
|
|
6
6
|
|
|
7
7
|
import { OVERFLOW_BUFFER } from '../utils';
|
|
8
8
|
|
|
9
|
-
import {
|
|
10
|
-
import type {
|
|
11
|
-
import {
|
|
9
|
+
import { RevealAnimationContext } from './context';
|
|
10
|
+
import type { RevealAnimationProps } from './types';
|
|
11
|
+
import { useDataFingerprint, useRevealAnimation } from './utils';
|
|
12
12
|
|
|
13
13
|
const DEFAULT_DURATION_IN_SECONDS = 0.8;
|
|
14
14
|
|
|
15
15
|
const AnimatedRect = Animated.createAnimatedComponent(Rect);
|
|
16
16
|
|
|
17
|
-
export function
|
|
17
|
+
export function RevealAnimationProvider({
|
|
18
18
|
children,
|
|
19
19
|
drawingArea,
|
|
20
20
|
series,
|
|
21
21
|
animate = true,
|
|
22
22
|
transitions,
|
|
23
|
-
}:
|
|
23
|
+
}: RevealAnimationProps) {
|
|
24
24
|
/**
|
|
25
25
|
* Disable reveal animation on Android devices due to issues with SVG clip-path animation support.
|
|
26
26
|
* On Android, the animation does not render correctly, so we opt out for a consistent user experience.
|
|
@@ -29,16 +29,16 @@ export function RevealClipDefs({
|
|
|
29
29
|
const durationMs =
|
|
30
30
|
(transitions?.enter?.duration ?? DEFAULT_DURATION_IN_SECONDS) * 1000;
|
|
31
31
|
|
|
32
|
-
const dataFingerprint =
|
|
33
|
-
const { clipId, animatedRectProps } =
|
|
32
|
+
const dataFingerprint = useDataFingerprint(series);
|
|
33
|
+
const { clipId, animatedRectProps, pointOpacity } = useRevealAnimation({
|
|
34
34
|
durationMs,
|
|
35
35
|
drawingArea,
|
|
36
36
|
dataFingerprint,
|
|
37
37
|
});
|
|
38
38
|
|
|
39
39
|
const contextValue = useMemo(
|
|
40
|
-
() => ({ clipPathAttr: `url(#${clipId})
|
|
41
|
-
[clipId],
|
|
40
|
+
() => ({ clipPathAttr: `url(#${clipId})`, pointOpacity }),
|
|
41
|
+
[clipId, pointOpacity],
|
|
42
42
|
);
|
|
43
43
|
|
|
44
44
|
if (isDisabled) {
|
|
@@ -46,7 +46,7 @@ export function RevealClipDefs({
|
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
return (
|
|
49
|
-
<
|
|
49
|
+
<RevealAnimationContext.Provider value={contextValue}>
|
|
50
50
|
<Defs>
|
|
51
51
|
<ClipPath id={clipId}>
|
|
52
52
|
<AnimatedRect
|
|
@@ -60,6 +60,6 @@ export function RevealClipDefs({
|
|
|
60
60
|
</ClipPath>
|
|
61
61
|
</Defs>
|
|
62
62
|
{children}
|
|
63
|
-
</
|
|
63
|
+
</RevealAnimationContext.Provider>
|
|
64
64
|
);
|
|
65
65
|
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { createContext, useContext } from 'react';
|
|
2
|
+
import type { SharedValue } from 'react-native-reanimated';
|
|
3
|
+
import { useAnimatedProps } from 'react-native-reanimated';
|
|
4
|
+
|
|
5
|
+
import type { RevealAnimationContextValue } from './types';
|
|
6
|
+
|
|
7
|
+
export const RevealAnimationContext = createContext<
|
|
8
|
+
RevealAnimationContextValue | undefined
|
|
9
|
+
>(undefined);
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Clip-path attribute for path-based consumers (e.g. `Line`).
|
|
13
|
+
* Returns `undefined` when the reveal animation is disabled.
|
|
14
|
+
*/
|
|
15
|
+
export const usePathReveal = (): string | undefined => {
|
|
16
|
+
return useContext(RevealAnimationContext)?.clipPathAttr;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Raw shared opacity value for the point/accessory fade. Returns `undefined`
|
|
21
|
+
* when the reveal animation is disabled. Prefer {@link useRevealFadeProps} in
|
|
22
|
+
* components; this is the low-level primitive for custom needs.
|
|
23
|
+
*/
|
|
24
|
+
export const usePointReveal = (): SharedValue<number> | undefined => {
|
|
25
|
+
return useContext(RevealAnimationContext)?.pointOpacity;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Ready-to-use animated props for accessory components (e.g. `Point`) that
|
|
30
|
+
* fade in with the reveal instead of being clipped. Spread directly onto any
|
|
31
|
+
* animated SVG element via `animatedProps`
|
|
32
|
+
*/
|
|
33
|
+
export const useRevealFadeProps = (): ReturnType<typeof useAnimatedProps> => {
|
|
34
|
+
const pointOpacity = usePointReveal();
|
|
35
|
+
return useAnimatedProps(
|
|
36
|
+
() => ({ opacity: pointOpacity?.value ?? 1 }),
|
|
37
|
+
[pointOpacity],
|
|
38
|
+
);
|
|
39
|
+
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
|
+
import type { SharedValue } from 'react-native-reanimated';
|
|
2
3
|
|
|
3
|
-
import type { DrawingArea, Series } from '../../../utils';
|
|
4
|
+
import type { DrawingArea, Series } from '../../../utils/types';
|
|
4
5
|
|
|
5
6
|
export type EnterTransitionConfig = {
|
|
6
7
|
/**
|
|
@@ -14,7 +15,7 @@ export type EnterTransitionConfig = {
|
|
|
14
15
|
easing?: string;
|
|
15
16
|
};
|
|
16
17
|
|
|
17
|
-
export type
|
|
18
|
+
export type RevealAnimationProps = {
|
|
18
19
|
children: ReactNode;
|
|
19
20
|
/**
|
|
20
21
|
* The drawing area whose bounds define the clip rectangle.
|
|
@@ -36,3 +37,16 @@ export type RevealClipDefsProps = {
|
|
|
36
37
|
*/
|
|
37
38
|
series: Series[];
|
|
38
39
|
};
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Value shared by the reveal animation provider.
|
|
43
|
+
*
|
|
44
|
+
* - `clipPathAttr` drives the left-to-right clip wipe consumed by path-based
|
|
45
|
+
* components (e.g. `Line`, `LineChartEmptyState`).
|
|
46
|
+
* - `pointOpacity` is the shared opacity value for accessory components (e.g.
|
|
47
|
+
* `Point`) that must not be clipped, so they fade in after the wipe instead.
|
|
48
|
+
*/
|
|
49
|
+
export type RevealAnimationContextValue = {
|
|
50
|
+
clipPathAttr: string;
|
|
51
|
+
pointOpacity: SharedValue<number>;
|
|
52
|
+
};
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { useEffect, useId, useMemo, useRef } from 'react';
|
|
2
|
+
import {
|
|
3
|
+
useAnimatedProps,
|
|
4
|
+
useSharedValue,
|
|
5
|
+
withDelay,
|
|
6
|
+
withTiming,
|
|
7
|
+
} from 'react-native-reanimated';
|
|
8
|
+
|
|
9
|
+
import type { DrawingArea, Series } from '../../../utils/types';
|
|
10
|
+
import { OVERFLOW_BUFFER } from '../utils';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Duration in ms of an individual point's opacity fade-in.
|
|
14
|
+
*/
|
|
15
|
+
const POINT_FADE_DURATION_IN_MS = 200;
|
|
16
|
+
const POINT_FADE_IN_AFTER_CLIP_IN_MS = -100;
|
|
17
|
+
|
|
18
|
+
type RevealAnimationConfig = {
|
|
19
|
+
durationMs: number;
|
|
20
|
+
drawingArea: DrawingArea;
|
|
21
|
+
dataFingerprint: string;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
type RevealAnimationResult = {
|
|
25
|
+
clipId: string;
|
|
26
|
+
animatedRectProps: ReturnType<typeof useAnimatedProps>;
|
|
27
|
+
pointOpacity: ReturnType<typeof useSharedValue<number>>;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Drives the two reveal animations:
|
|
32
|
+
* - the left-to-right clip-path wipe (animated `Rect` width, including the
|
|
33
|
+
* {@link OVERFLOW_BUFFER} so edge content is revealed too), and
|
|
34
|
+
* - the point fade-in, delayed so points appear as the wipe finishes.
|
|
35
|
+
*
|
|
36
|
+
* On a data change the shared values are reset to `0` (hidden) *synchronously
|
|
37
|
+
* during render* — before the new line/points are committed and painted — so
|
|
38
|
+
* they never paint once at the previous cycle's end values (a visible flash).
|
|
39
|
+
* The effect then animates them back in.
|
|
40
|
+
*/
|
|
41
|
+
export const useRevealAnimation = ({
|
|
42
|
+
durationMs,
|
|
43
|
+
drawingArea,
|
|
44
|
+
dataFingerprint,
|
|
45
|
+
}: RevealAnimationConfig): RevealAnimationResult => {
|
|
46
|
+
const clipId = useId();
|
|
47
|
+
const clipWidth = useSharedValue(0);
|
|
48
|
+
const pointOpacity = useSharedValue(0);
|
|
49
|
+
|
|
50
|
+
const previousFingerprint = useRef<string | null>(null);
|
|
51
|
+
if (previousFingerprint.current !== dataFingerprint) {
|
|
52
|
+
previousFingerprint.current = dataFingerprint;
|
|
53
|
+
clipWidth.value = 0;
|
|
54
|
+
pointOpacity.value = 0;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
useEffect(() => {
|
|
58
|
+
clipWidth.value = withTiming(
|
|
59
|
+
drawingArea.width + OVERFLOW_BUFFER.left + OVERFLOW_BUFFER.right,
|
|
60
|
+
{ duration: durationMs },
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
pointOpacity.value = withDelay(
|
|
64
|
+
Math.max(durationMs + POINT_FADE_IN_AFTER_CLIP_IN_MS, 0),
|
|
65
|
+
withTiming(1, { duration: POINT_FADE_DURATION_IN_MS }),
|
|
66
|
+
);
|
|
67
|
+
}, [drawingArea.width, durationMs, clipWidth, pointOpacity, dataFingerprint]);
|
|
68
|
+
|
|
69
|
+
const animatedRectProps = useAnimatedProps(() => ({
|
|
70
|
+
width: clipWidth.value,
|
|
71
|
+
}));
|
|
72
|
+
|
|
73
|
+
return { clipId, animatedRectProps, pointOpacity };
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Stable signature of every series' data points, memoized on the `series`
|
|
78
|
+
* reference. Used to key the reveal provider so the reveal animation only
|
|
79
|
+
* replays when the underlying data actually changes — not on unrelated
|
|
80
|
+
* re-renders such as scrubbing or hover.
|
|
81
|
+
*/
|
|
82
|
+
export const useDataFingerprint = (series: Series[]): string => {
|
|
83
|
+
return useMemo(
|
|
84
|
+
() => series.map((s) => s.data?.join(',') ?? '').join('|'),
|
|
85
|
+
[series],
|
|
86
|
+
);
|
|
87
|
+
};
|