react-native-wagmi-charts 1.8.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (213) hide show
  1. package/.DS_Store +0 -0
  2. package/README.md +331 -196
  3. package/example/.DS_Store +0 -0
  4. package/example/src/LineChart.tsx +10 -4
  5. package/example/src/data/line-data.json +20 -20
  6. package/lib/commonjs/charts/candle/utils/getDomain.js +19 -0
  7. package/lib/commonjs/charts/candle/utils/getDomain.js.map +1 -0
  8. package/lib/commonjs/charts/candle/utils/getHeight.js +19 -0
  9. package/lib/commonjs/charts/candle/utils/getHeight.js.map +1 -0
  10. package/lib/commonjs/charts/candle/utils/getPrice.js +20 -0
  11. package/lib/commonjs/charts/candle/utils/getPrice.js.map +1 -0
  12. package/lib/commonjs/charts/candle/utils/getY.js +19 -0
  13. package/lib/commonjs/charts/candle/utils/getY.js.map +1 -0
  14. package/lib/commonjs/charts/candle/utils/index.js +58 -0
  15. package/lib/commonjs/charts/candle/utils/index.js.map +1 -0
  16. package/lib/commonjs/charts/line/Chart.js +9 -3
  17. package/lib/commonjs/charts/line/Chart.js.map +1 -1
  18. package/lib/commonjs/charts/line/ChartPath.js +73 -17
  19. package/lib/commonjs/charts/line/ChartPath.js.map +1 -1
  20. package/lib/commonjs/charts/line/Context.js +1 -0
  21. package/lib/commonjs/charts/line/Context.js.map +1 -1
  22. package/lib/commonjs/charts/line/Cursor.js +1 -0
  23. package/lib/commonjs/charts/line/Cursor.js.map +1 -1
  24. package/lib/commonjs/charts/line/CursorCrosshair.js +10 -3
  25. package/lib/commonjs/charts/line/CursorCrosshair.js.map +1 -1
  26. package/lib/commonjs/charts/line/CursorLine.js +6 -6
  27. package/lib/commonjs/charts/line/CursorLine.js.map +1 -1
  28. package/lib/commonjs/charts/line/DatetimeText.js +2 -0
  29. package/lib/commonjs/charts/line/DatetimeText.js.map +1 -1
  30. package/lib/commonjs/charts/line/Dot.js +67 -62
  31. package/lib/commonjs/charts/line/Dot.js.map +1 -1
  32. package/lib/commonjs/charts/line/Gradient.js +8 -25
  33. package/lib/commonjs/charts/line/Gradient.js.map +1 -1
  34. package/lib/commonjs/charts/line/Group.js +5 -25
  35. package/lib/commonjs/charts/line/Group.js.map +1 -1
  36. package/lib/commonjs/charts/line/Highlight.js +92 -0
  37. package/lib/commonjs/charts/line/Highlight.js.map +1 -0
  38. package/lib/commonjs/charts/line/HorizontalLine.js +6 -6
  39. package/lib/commonjs/charts/line/HorizontalLine.js.map +1 -1
  40. package/lib/commonjs/charts/line/Path.js +19 -30
  41. package/lib/commonjs/charts/line/Path.js.map +1 -1
  42. package/lib/commonjs/charts/line/PriceText.js +2 -0
  43. package/lib/commonjs/charts/line/PriceText.js.map +1 -1
  44. package/lib/commonjs/charts/line/Tooltip.js +2 -0
  45. package/lib/commonjs/charts/line/Tooltip.js.map +1 -1
  46. package/lib/commonjs/charts/line/index.js +47 -20
  47. package/lib/commonjs/charts/line/index.js.map +1 -1
  48. package/lib/commonjs/charts/line/useAnimatedPath.js +44 -0
  49. package/lib/commonjs/charts/line/useAnimatedPath.js.map +1 -0
  50. package/lib/commonjs/charts/line/{utils.js → utils/getArea.js} +2 -49
  51. package/lib/commonjs/charts/line/utils/getArea.js.map +1 -0
  52. package/lib/commonjs/charts/line/utils/getDomain.js +16 -0
  53. package/lib/commonjs/charts/line/utils/getDomain.js.map +1 -0
  54. package/lib/commonjs/charts/line/utils/getPath.js +34 -0
  55. package/lib/commonjs/charts/line/utils/getPath.js.map +1 -0
  56. package/lib/commonjs/charts/line/utils/index.js +71 -0
  57. package/lib/commonjs/charts/line/utils/index.js.map +1 -0
  58. package/lib/commonjs/charts/line/{interpolatePath.js → utils/interpolatePath.js} +1 -1
  59. package/lib/commonjs/charts/line/{interpolatePath.js.map → utils/interpolatePath.js.map} +1 -1
  60. package/lib/commonjs/charts/line/utils/lineChartDataPropToArray.js +27 -0
  61. package/lib/commonjs/charts/line/utils/lineChartDataPropToArray.js.map +1 -0
  62. package/lib/commonjs/index.js +8 -8
  63. package/lib/commonjs/index.js.map +1 -1
  64. package/lib/commonjs/utils/formatDatetime.js +21 -0
  65. package/lib/commonjs/utils/formatDatetime.js.map +1 -0
  66. package/lib/commonjs/utils/formatPrice.js +46 -0
  67. package/lib/commonjs/utils/formatPrice.js.map +1 -0
  68. package/lib/commonjs/utils/index.js +45 -0
  69. package/lib/commonjs/utils/index.js.map +1 -0
  70. package/lib/commonjs/{utils.js → utils/usePrevious.js} +1 -57
  71. package/lib/commonjs/utils/usePrevious.js.map +1 -0
  72. package/lib/module/charts/candle/utils/getDomain.js +12 -0
  73. package/lib/module/charts/candle/utils/getDomain.js.map +1 -0
  74. package/lib/module/charts/candle/utils/getHeight.js +11 -0
  75. package/lib/module/charts/candle/utils/getHeight.js.map +1 -0
  76. package/lib/module/charts/candle/utils/getPrice.js +12 -0
  77. package/lib/module/charts/candle/utils/getPrice.js.map +1 -0
  78. package/lib/module/charts/candle/utils/getY.js +11 -0
  79. package/lib/module/charts/candle/utils/getY.js.map +1 -0
  80. package/lib/module/charts/candle/utils/index.js +5 -0
  81. package/lib/module/charts/candle/utils/index.js.map +1 -0
  82. package/lib/module/charts/line/Chart.js +9 -4
  83. package/lib/module/charts/line/Chart.js.map +1 -1
  84. package/lib/module/charts/line/ChartPath.js +69 -17
  85. package/lib/module/charts/line/ChartPath.js.map +1 -1
  86. package/lib/module/charts/line/Context.js +1 -0
  87. package/lib/module/charts/line/Context.js.map +1 -1
  88. package/lib/module/charts/line/Cursor.js +1 -0
  89. package/lib/module/charts/line/Cursor.js.map +1 -1
  90. package/lib/module/charts/line/CursorCrosshair.js +10 -4
  91. package/lib/module/charts/line/CursorCrosshair.js.map +1 -1
  92. package/lib/module/charts/line/CursorLine.js +4 -3
  93. package/lib/module/charts/line/CursorLine.js.map +1 -1
  94. package/lib/module/charts/line/DatetimeText.js +1 -0
  95. package/lib/module/charts/line/DatetimeText.js.map +1 -1
  96. package/lib/module/charts/line/Dot.js +66 -63
  97. package/lib/module/charts/line/Dot.js.map +1 -1
  98. package/lib/module/charts/line/Gradient.js +8 -24
  99. package/lib/module/charts/line/Gradient.js.map +1 -1
  100. package/lib/module/charts/line/Group.js +2 -24
  101. package/lib/module/charts/line/Group.js.map +1 -1
  102. package/lib/module/charts/line/Highlight.js +69 -0
  103. package/lib/module/charts/line/Highlight.js.map +1 -0
  104. package/lib/module/charts/line/HorizontalLine.js +4 -3
  105. package/lib/module/charts/line/HorizontalLine.js.map +1 -1
  106. package/lib/module/charts/line/Path.js +17 -29
  107. package/lib/module/charts/line/Path.js.map +1 -1
  108. package/lib/module/charts/line/PriceText.js +1 -0
  109. package/lib/module/charts/line/PriceText.js.map +1 -1
  110. package/lib/module/charts/line/Tooltip.js +1 -0
  111. package/lib/module/charts/line/Tooltip.js.map +1 -1
  112. package/lib/module/charts/line/index.js +12 -8
  113. package/lib/module/charts/line/index.js.map +1 -1
  114. package/lib/module/charts/line/useAnimatedPath.js +34 -0
  115. package/lib/module/charts/line/useAnimatedPath.js.map +1 -0
  116. package/lib/module/charts/line/utils/getArea.js +19 -0
  117. package/lib/module/charts/line/utils/getArea.js.map +1 -0
  118. package/lib/module/charts/line/utils/getDomain.js +9 -0
  119. package/lib/module/charts/line/utils/getDomain.js.map +1 -0
  120. package/lib/module/charts/line/utils/getPath.js +21 -0
  121. package/lib/module/charts/line/utils/getPath.js.map +1 -0
  122. package/lib/module/charts/line/utils/index.js +6 -0
  123. package/lib/module/charts/line/utils/index.js.map +1 -0
  124. package/lib/module/charts/line/{interpolatePath.js → utils/interpolatePath.js} +1 -1
  125. package/lib/module/charts/line/{interpolatePath.js.map → utils/interpolatePath.js.map} +1 -1
  126. package/lib/module/charts/line/utils/lineChartDataPropToArray.js +20 -0
  127. package/lib/module/charts/line/utils/lineChartDataPropToArray.js.map +1 -0
  128. package/lib/module/index.js +1 -1
  129. package/lib/module/index.js.map +1 -1
  130. package/lib/module/utils/formatDatetime.js +14 -0
  131. package/lib/module/utils/formatDatetime.js.map +1 -0
  132. package/lib/module/{utils.js → utils/formatPrice.js} +1 -29
  133. package/lib/module/utils/formatPrice.js.map +1 -0
  134. package/lib/module/utils/index.js +4 -0
  135. package/lib/module/utils/index.js.map +1 -0
  136. package/lib/module/utils/usePrevious.js +14 -0
  137. package/lib/module/utils/usePrevious.js.map +1 -0
  138. package/lib/typescript/src/charts/candle/utils/getDomain.d.ts +2 -0
  139. package/lib/typescript/src/charts/candle/utils/getHeight.d.ts +6 -0
  140. package/lib/typescript/src/charts/candle/utils/getPrice.d.ts +6 -0
  141. package/lib/typescript/src/charts/candle/utils/getY.d.ts +6 -0
  142. package/lib/typescript/src/charts/candle/utils/index.d.ts +4 -0
  143. package/lib/typescript/src/charts/line/Chart.d.ts +5 -1
  144. package/lib/typescript/src/charts/line/ChartPath.d.ts +10 -1
  145. package/lib/typescript/src/charts/line/Context.d.ts +3 -0
  146. package/lib/typescript/src/charts/line/Cursor.d.ts +3 -0
  147. package/lib/typescript/src/charts/line/CursorCrosshair.d.ts +4 -1
  148. package/lib/typescript/src/charts/line/CursorLine.d.ts +4 -1
  149. package/lib/typescript/src/charts/line/DatetimeText.d.ts +3 -0
  150. package/lib/typescript/src/charts/line/Dot.d.ts +10 -7
  151. package/lib/typescript/src/charts/line/Gradient.d.ts +3 -0
  152. package/lib/typescript/src/charts/line/Group.d.ts +1 -2
  153. package/lib/typescript/src/charts/line/Highlight.d.ts +15 -0
  154. package/lib/typescript/src/charts/line/HorizontalLine.d.ts +4 -1
  155. package/lib/typescript/src/charts/line/Path.d.ts +5 -1
  156. package/lib/typescript/src/charts/line/PriceText.d.ts +3 -0
  157. package/lib/typescript/src/charts/line/Tooltip.d.ts +3 -0
  158. package/lib/typescript/src/charts/line/index.d.ts +15 -25
  159. package/lib/typescript/src/charts/line/useAnimatedPath.d.ts +8 -0
  160. package/lib/typescript/src/charts/line/utils/getArea.d.ts +9 -0
  161. package/lib/typescript/src/charts/line/utils/getDomain.d.ts +2 -0
  162. package/lib/typescript/src/charts/line/utils/getPath.d.ts +11 -0
  163. package/lib/typescript/src/charts/line/utils/index.d.ts +5 -0
  164. package/lib/typescript/src/charts/line/{interpolatePath.d.ts → utils/interpolatePath.d.ts} +1 -1
  165. package/lib/typescript/src/charts/line/utils/lineChartDataPropToArray.d.ts +2 -0
  166. package/lib/typescript/src/index.d.ts +1 -1
  167. package/lib/typescript/src/utils/formatDatetime.d.ts +8 -0
  168. package/lib/typescript/src/utils/formatPrice.d.ts +8 -0
  169. package/lib/typescript/src/utils/index.d.ts +3 -0
  170. package/lib/typescript/src/utils/usePrevious.d.ts +1 -0
  171. package/package.json +4 -2
  172. package/src/charts/candle/utils/getDomain.ts +9 -0
  173. package/src/charts/candle/utils/getHeight.ts +21 -0
  174. package/src/charts/candle/utils/getPrice.ts +17 -0
  175. package/src/charts/candle/utils/getY.ts +16 -0
  176. package/src/charts/candle/utils/index.ts +4 -0
  177. package/src/charts/line/Chart.tsx +9 -3
  178. package/src/charts/line/ChartPath.tsx +109 -33
  179. package/src/charts/line/Context.tsx +2 -0
  180. package/src/charts/line/Cursor.tsx +2 -0
  181. package/src/charts/line/CursorCrosshair.tsx +20 -5
  182. package/src/charts/line/CursorLine.tsx +5 -3
  183. package/src/charts/line/DatetimeText.tsx +2 -0
  184. package/src/charts/line/Dot.tsx +83 -86
  185. package/src/charts/line/Gradient.tsx +7 -34
  186. package/src/charts/line/Group.tsx +4 -47
  187. package/src/charts/line/Highlight.tsx +78 -0
  188. package/src/charts/line/HorizontalLine.tsx +5 -3
  189. package/src/charts/line/Path.tsx +14 -38
  190. package/src/charts/line/PriceText.tsx +2 -0
  191. package/src/charts/line/Tooltip.tsx +2 -0
  192. package/src/charts/line/index.ts +11 -7
  193. package/src/charts/line/useAnimatedPath.ts +47 -0
  194. package/src/charts/line/utils/getArea.ts +38 -0
  195. package/src/charts/line/utils/getDomain.ts +7 -0
  196. package/src/charts/line/utils/getPath.ts +48 -0
  197. package/src/charts/line/utils/index.ts +5 -0
  198. package/src/charts/line/{interpolatePath.ts → utils/interpolatePath.ts} +1 -1
  199. package/src/charts/line/utils/lineChartDataPropToArray.ts +25 -0
  200. package/src/index.ts +1 -1
  201. package/src/utils/formatDatetime.ts +16 -0
  202. package/src/{utils.ts → utils/formatPrice.ts} +0 -31
  203. package/src/utils/index.ts +3 -0
  204. package/src/utils/usePrevious.ts +13 -0
  205. package/yarn.lock +8 -1
  206. package/lib/commonjs/charts/line/utils.js.map +0 -1
  207. package/lib/commonjs/utils.js.map +0 -1
  208. package/lib/module/charts/line/utils.js +0 -60
  209. package/lib/module/charts/line/utils.js.map +0 -1
  210. package/lib/module/utils.js.map +0 -1
  211. package/lib/typescript/src/charts/line/utils.d.ts +0 -20
  212. package/lib/typescript/src/utils.d.ts +0 -17
  213. package/src/charts/line/utils.ts +0 -100
@@ -3,17 +3,28 @@ import { StyleSheet, View } from 'react-native';
3
3
  import { Svg } from 'react-native-svg';
4
4
  import Animated, {
5
5
  useAnimatedProps,
6
+ useSharedValue,
6
7
  withTiming,
7
8
  } from 'react-native-reanimated';
9
+ import flattenChildren from 'react-keyed-flatten-children';
8
10
 
9
11
  import { LineChartDimensionsContext } from './Chart';
10
12
  import { LineChartPath, LineChartPathProps } from './Path';
11
13
  import { useLineChart } from './useLineChart';
12
14
 
15
+ const BACKGROUND_COMPONENTS = [
16
+ 'LineChartHighlight',
17
+ 'LineChartHorizontalLine',
18
+ 'LineChartGradient',
19
+ 'LineChartDot',
20
+ ];
21
+ const FOREGROUND_COMPONENTS = ['LineChartHighlight', 'LineChartDot'];
22
+
13
23
  const AnimatedSVG = Animated.createAnimatedComponent(Svg);
14
24
 
15
25
  export const LineChartPathContext = React.createContext({
16
26
  color: '',
27
+ isInactive: false,
17
28
  isTransitionEnabled: true,
18
29
  });
19
30
 
@@ -22,65 +33,130 @@ type LineChartPathWrapperProps = {
22
33
  animationProps?: Partial<Animated.WithTimingConfig>;
23
34
  children?: React.ReactNode;
24
35
  color?: string;
36
+ inactiveColor?: string;
25
37
  width?: number;
38
+ widthOffset?: number;
26
39
  pathProps?: Partial<LineChartPathProps>;
27
40
  showInactivePath?: boolean;
41
+ animateOnMount?: 'foreground';
42
+ mountAnimationDuration?: number;
43
+ mountAnimationProps?: Partial<Animated.WithTimingConfig>;
28
44
  };
29
45
 
46
+ LineChartPathWrapper.displayName = 'LineChartPathWrapper';
47
+
30
48
  export function LineChartPathWrapper({
31
49
  animationDuration = 300,
32
50
  animationProps = {},
33
51
  children,
34
52
  color = 'black',
53
+ inactiveColor,
35
54
  width: strokeWidth = 3,
55
+ widthOffset = 20,
36
56
  pathProps = {},
37
57
  showInactivePath = true,
58
+ animateOnMount,
59
+ mountAnimationDuration = animationDuration,
60
+ mountAnimationProps = animationProps,
38
61
  }: LineChartPathWrapperProps) {
39
62
  const { height, pathWidth, width } = React.useContext(
40
63
  LineChartDimensionsContext
41
64
  );
42
65
  const { currentX, isActive } = useLineChart();
66
+ const isMounted = useSharedValue(false);
67
+ const hasMountedAnimation = useSharedValue(false);
68
+
69
+ React.useEffect(() => {
70
+ isMounted.value = true;
71
+ // eslint-disable-next-line react-hooks/exhaustive-deps
72
+ }, []);
43
73
 
44
74
  ////////////////////////////////////////////////
45
75
 
46
- const svgProps = useAnimatedProps(() => ({
47
- width: isActive.value
48
- ? // on Web, <svg /> elements don't support negative widths
49
- // https://github.com/coinjar/react-native-wagmi-charts/issues/24#issuecomment-955789904
50
- Math.max(currentX.value, 0)
51
- : withTiming(
52
- pathWidth,
53
- Object.assign({ duration: animationDuration }, animationProps)
54
- ),
55
- }));
76
+ const svgProps = useAnimatedProps(() => {
77
+ const shouldAnimateOnMount = animateOnMount === 'foreground';
78
+ const inactiveWidth =
79
+ !isMounted.value && shouldAnimateOnMount ? 0 : pathWidth;
80
+
81
+ const duration =
82
+ shouldAnimateOnMount && !hasMountedAnimation.value
83
+ ? mountAnimationDuration
84
+ : animationDuration;
85
+ const props =
86
+ shouldAnimateOnMount && !hasMountedAnimation.value
87
+ ? mountAnimationProps
88
+ : animationProps;
89
+
90
+ return {
91
+ width: isActive.value
92
+ ? // on Web, <svg /> elements don't support negative widths
93
+ // https://github.com/coinjar/react-native-wagmi-charts/issues/24#issuecomment-955789904
94
+ Math.max(currentX.value, 0)
95
+ : withTiming(
96
+ inactiveWidth + widthOffset,
97
+ Object.assign({ duration }, props),
98
+ () => {
99
+ hasMountedAnimation.value = true;
100
+ }
101
+ ),
102
+ };
103
+ });
56
104
 
57
105
  const viewSize = React.useMemo(() => ({ width, height }), [width, height]);
58
106
 
59
107
  ////////////////////////////////////////////////
60
108
 
109
+ let backgroundChildren;
110
+ let foregroundChildren;
111
+ if (children) {
112
+ const iterableChildren = flattenChildren(children);
113
+ backgroundChildren = iterableChildren.filter((child) =>
114
+ // @ts-ignore
115
+ BACKGROUND_COMPONENTS.includes(child?.type?.displayName)
116
+ );
117
+ foregroundChildren = iterableChildren.filter((child) =>
118
+ // @ts-ignore
119
+ FOREGROUND_COMPONENTS.includes(child?.type?.displayName)
120
+ );
121
+ }
122
+
123
+ ////////////////////////////////////////////////
124
+
61
125
  return (
62
- <LineChartPathContext.Provider
63
- value={{
64
- color,
65
- isTransitionEnabled: pathProps.isTransitionEnabled ?? true,
66
- }}
67
- >
68
- <View style={viewSize}>
69
- <Svg width={width} height={height}>
70
- {children}
71
- <LineChartPath
72
- color={color}
73
- width={strokeWidth}
74
- isInactive={showInactivePath}
75
- {...pathProps}
76
- />
77
- </Svg>
78
- </View>
79
- <View style={StyleSheet.absoluteFill}>
80
- <AnimatedSVG animatedProps={svgProps} height={height}>
81
- <LineChartPath color={color} width={strokeWidth} {...pathProps} />
82
- </AnimatedSVG>
83
- </View>
84
- </LineChartPathContext.Provider>
126
+ <>
127
+ <LineChartPathContext.Provider
128
+ value={{
129
+ color,
130
+ isInactive: showInactivePath,
131
+ isTransitionEnabled: pathProps.isTransitionEnabled ?? true,
132
+ }}
133
+ >
134
+ <View style={viewSize}>
135
+ <Svg width={width} height={height}>
136
+ <LineChartPath
137
+ color={color}
138
+ inactiveColor={inactiveColor}
139
+ width={strokeWidth}
140
+ {...pathProps}
141
+ />
142
+ {backgroundChildren}
143
+ </Svg>
144
+ </View>
145
+ </LineChartPathContext.Provider>
146
+ <LineChartPathContext.Provider
147
+ value={{
148
+ color,
149
+ isInactive: false,
150
+ isTransitionEnabled: pathProps.isTransitionEnabled ?? true,
151
+ }}
152
+ >
153
+ <View style={StyleSheet.absoluteFill}>
154
+ <AnimatedSVG animatedProps={svgProps} height={height}>
155
+ <LineChartPath color={color} width={strokeWidth} {...pathProps} />
156
+ {foregroundChildren}
157
+ </AnimatedSVG>
158
+ </View>
159
+ </LineChartPathContext.Provider>
160
+ </>
85
161
  );
86
162
  }
@@ -30,6 +30,8 @@ type LineChartProviderProps = {
30
30
  xLength?: number;
31
31
  };
32
32
 
33
+ LineChartProvider.displayName = 'LineChartProvider';
34
+
33
35
  export function LineChartProvider({
34
36
  children,
35
37
  data = [],
@@ -19,6 +19,8 @@ export type LineChartCursorProps = LongPressGestureHandlerProps & {
19
19
 
20
20
  export const CursorContext = React.createContext({ type: '' });
21
21
 
22
+ LineChartCursor.displayName = 'LineChartCursor';
23
+
22
24
  export function LineChartCursor({
23
25
  children,
24
26
  type,
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import { View, ViewProps } from 'react-native';
2
+ import { Platform, View, ViewProps } from 'react-native';
3
3
  import Animated, {
4
4
  useAnimatedStyle,
5
5
  withSpring,
@@ -8,7 +8,10 @@ import Animated, {
8
8
  import { LineChartCursor, LineChartCursorProps } from './Cursor';
9
9
  import { useLineChart } from './useLineChart';
10
10
 
11
- type LineChartCursorCrosshairProps = Omit<LineChartCursorProps, 'type'> & {
11
+ type LineChartCursorCrosshairProps = Omit<
12
+ LineChartCursorProps,
13
+ 'children' | 'type'
14
+ > & {
12
15
  children?: React.ReactNode;
13
16
  color?: string;
14
17
  size?: number;
@@ -18,6 +21,8 @@ type LineChartCursorCrosshairProps = Omit<LineChartCursorProps, 'type'> & {
18
21
  crosshairOuterProps?: ViewProps;
19
22
  };
20
23
 
24
+ LineChartCursorCrosshair.displayName = 'LineChartCursorCrosshair';
25
+
21
26
  export function LineChartCursorCrosshair({
22
27
  children,
23
28
  color = 'black',
@@ -30,14 +35,24 @@ export function LineChartCursorCrosshair({
30
35
  }: LineChartCursorCrosshairProps) {
31
36
  const { currentX, currentY, isActive } = useLineChart();
32
37
 
38
+ // It seems that enabling spring animation on initial render on Android causes a crash.
39
+ const [enableSpringAnimation, setEnableSpringAnimation] = React.useState(
40
+ Platform.OS === 'ios'
41
+ );
42
+ React.useEffect(() => {
43
+ setEnableSpringAnimation(true);
44
+ }, []);
45
+
33
46
  const animatedCursorStyle = useAnimatedStyle(() => ({
34
47
  transform: [
35
48
  { translateX: currentX.value - outerSize / 2 },
36
49
  { translateY: currentY.value - outerSize / 2 },
37
50
  {
38
- scale: withSpring(isActive.value ? 1 : 0, {
39
- damping: 10,
40
- }),
51
+ scale: enableSpringAnimation
52
+ ? withSpring(isActive.value ? 1 : 0, {
53
+ damping: 10,
54
+ })
55
+ : 0,
41
56
  },
42
57
  ],
43
58
  }));
@@ -13,11 +13,13 @@ type LineChartCursorLineProps = {
13
13
  lineProps?: Partial<LineProps>;
14
14
  };
15
15
 
16
- export const LineChartCursorLine = ({
16
+ LineChartCursorLine.displayName = 'LineChartCursorLine';
17
+
18
+ export function LineChartCursorLine({
17
19
  children,
18
20
  color = 'gray',
19
21
  lineProps = {},
20
- }: LineChartCursorLineProps) => {
22
+ }: LineChartCursorLineProps) {
21
23
  const { height } = React.useContext(LineChartDimensionsContext);
22
24
  const { currentX, isActive } = useLineChart();
23
25
 
@@ -46,7 +48,7 @@ export const LineChartCursorLine = ({
46
48
  {children}
47
49
  </LineChartCursor>
48
50
  );
49
- };
51
+ }
50
52
 
51
53
  const styles = StyleSheet.create({
52
54
  svg: {
@@ -14,6 +14,8 @@ type LineChartDatetimeProps = {
14
14
  style?: Animated.AnimateProps<RNTextProps>['style'];
15
15
  };
16
16
 
17
+ LineChartDatetimeText.displayName = 'LineChartDatetimeText';
18
+
17
19
  export function LineChartDatetimeText({
18
20
  locale,
19
21
  options,
@@ -1,36 +1,39 @@
1
1
  import * as React from 'react';
2
2
  import Animated, {
3
3
  Easing,
4
- useAnimatedStyle,
4
+ useAnimatedProps,
5
5
  useDerivedValue,
6
6
  withRepeat,
7
7
  withSequence,
8
8
  withTiming,
9
9
  } from 'react-native-reanimated';
10
- import { View } from 'react-native';
10
+ import { Circle, CircleProps } from 'react-native-svg';
11
11
  import { getYForX, parse } from 'react-native-redash';
12
- import { useMemo } from 'react';
13
12
 
14
13
  import { LineChartDimensionsContext } from './Chart';
14
+ import { LineChartPathContext } from './ChartPath';
15
15
  import { useLineChart } from './useLineChart';
16
- import type { ViewProps } from 'react-native';
16
+
17
+ const AnimatedCircle = Animated.createAnimatedComponent(Circle);
17
18
 
18
19
  export type LineChartDotProps = {
19
- dotProps?: ViewProps;
20
- outerDotProps?: ViewProps;
20
+ dotProps?: Animated.AnimateProps<CircleProps>;
21
+ outerDotProps?: Animated.AnimateProps<CircleProps>;
21
22
  color?: string;
23
+ inactiveColor?: string;
24
+ showInactiveColor?: boolean;
22
25
  at: number;
23
26
  size?: number;
27
+ hasPulse?: boolean;
28
+ hasOuterDot?: boolean;
24
29
  /**
25
30
  * If `always`, the outer dot will still animate when interaction is active.
26
31
  *
27
- * If `never`, the outer dot will never animate.
28
- *
29
32
  * If `while-inactive`, the outer dot will animate only when the interaction is inactive.
30
33
  *
31
34
  * Default: `while-inactive`
32
35
  */
33
- pulsesOuter?: 'always' | 'while-inactive' | 'never';
36
+ pulseBehaviour?: 'always' | 'while-inactive';
34
37
  /**
35
38
  * Defaults to `size * 4`
36
39
  */
@@ -41,52 +44,82 @@ export type LineChartDotProps = {
41
44
  LineChartDot.displayName = 'LineChartDot';
42
45
 
43
46
  export function LineChartDot({
44
- color = 'black',
45
47
  at,
46
- size = 8,
47
- pulsesOuter = 'while-inactive',
48
- outerSize = size * 4,
48
+ color: defaultColor = 'black',
49
49
  dotProps,
50
+ hasOuterDot: defaultHasOuterDot = false,
51
+ hasPulse = false,
52
+ inactiveColor,
50
53
  outerDotProps,
54
+ pulseBehaviour = 'while-inactive',
55
+ pulseDurationMs = 800,
56
+ showInactiveColor = true,
57
+ size = 4,
58
+ outerSize = size * 4,
51
59
  }: LineChartDotProps) {
52
60
  const { data, isActive } = useLineChart();
53
61
  const { path, pathWidth: width } = React.useContext(
54
62
  LineChartDimensionsContext
55
63
  );
56
64
 
65
+ ////////////////////////////////////////////////////////////
66
+
67
+ const { isInactive: _isInactive } = React.useContext(LineChartPathContext);
68
+ const isInactive = showInactiveColor && _isInactive;
69
+ const color = isInactive ? inactiveColor || defaultColor : defaultColor;
70
+ const opacity = isInactive && !inactiveColor ? 0.5 : 1;
71
+ const hasOuterDot = defaultHasOuterDot || hasPulse;
72
+
73
+ ////////////////////////////////////////////////////////////
74
+
57
75
  const parsedPath = React.useMemo(() => parse(path), [path]);
76
+
77
+ ////////////////////////////////////////////////////////////
78
+
58
79
  const pointWidth = React.useMemo(
59
80
  () => width / (data.length - 1),
60
81
  [data.length, width]
61
82
  );
62
83
 
84
+ ////////////////////////////////////////////////////////////
85
+
63
86
  const x = useDerivedValue(() => withTiming(pointWidth * at));
64
87
  const y = useDerivedValue(() =>
65
88
  withTiming(getYForX(parsedPath!, x.value) || 0)
66
89
  );
67
90
 
68
- const containerStyle = useAnimatedStyle(() => {
69
- return {
70
- transform: [
71
- { translateX: x.value - outerSize / 2 },
72
- { translateY: y.value - outerSize / 2 },
73
- ],
91
+ ////////////////////////////////////////////////////////////
92
+
93
+ const animatedDotProps = useAnimatedProps(() => ({
94
+ cx: x.value,
95
+ cy: y.value,
96
+ }));
97
+
98
+ const animatedOuterDotProps = useAnimatedProps(() => {
99
+ let defaultProps = {
100
+ cx: x.value,
101
+ cy: y.value,
102
+ opacity: 0.1,
103
+ r: outerSize,
74
104
  };
75
- });
76
- const outerStyle = useAnimatedStyle(() => {
77
- let opacity = 0.1;
78
- if (pulsesOuter === 'never') {
105
+
106
+ if (!hasPulse) {
107
+ return defaultProps;
108
+ }
109
+
110
+ if (isActive.value && pulseBehaviour === 'while-inactive') {
79
111
  return {
80
- opacity,
112
+ ...defaultProps,
113
+ r: 0,
81
114
  };
82
115
  }
83
- const enterMs = 800;
116
+
84
117
  const easing = Easing.out(Easing.sin);
85
118
  const animatedOpacity = withRepeat(
86
119
  withSequence(
87
120
  withTiming(0.8),
88
121
  withTiming(0, {
89
- duration: enterMs,
122
+ duration: pulseDurationMs,
90
123
  easing,
91
124
  })
92
125
  ),
@@ -96,8 +129,8 @@ export function LineChartDot({
96
129
  const scale = withRepeat(
97
130
  withSequence(
98
131
  withTiming(0),
99
- withTiming(1, {
100
- duration: enterMs,
132
+ withTiming(outerSize, {
133
+ duration: pulseDurationMs,
101
134
  easing,
102
135
  })
103
136
  ),
@@ -105,74 +138,38 @@ export function LineChartDot({
105
138
  false
106
139
  );
107
140
 
108
- if (pulsesOuter === 'while-inactive') {
141
+ if (pulseBehaviour === 'while-inactive') {
109
142
  return {
143
+ ...defaultProps,
110
144
  opacity: isActive.value ? withTiming(0) : animatedOpacity,
111
- transform: [
112
- {
113
- scale: isActive.value ? withTiming(0) : scale,
114
- },
115
- ],
145
+ r: isActive.value ? withTiming(0) : scale,
116
146
  };
117
147
  }
118
148
  return {
149
+ ...defaultProps,
119
150
  opacity: animatedOpacity,
120
- transform: [
121
- {
122
- scale,
123
- },
124
- ],
151
+ r: scale,
125
152
  };
126
- }, [pulsesOuter]);
153
+ }, [outerSize]);
154
+
155
+ ////////////////////////////////////////////////////////////
127
156
 
128
157
  return (
129
- <Animated.View
130
- pointerEvents="none"
131
- style={useMemo(
132
- () => [
133
- {
134
- width: outerSize,
135
- height: outerSize,
136
- alignItems: 'center',
137
- justifyContent: 'center',
138
- },
139
- containerStyle,
140
- ],
141
- [containerStyle, outerSize]
142
- )}
143
- >
144
- <Animated.View
145
- {...outerDotProps}
146
- style={useMemo(
147
- () => [
148
- {
149
- backgroundColor: color,
150
- width: outerSize,
151
- height: outerSize,
152
- borderRadius: outerSize,
153
- position: 'absolute',
154
- },
155
- outerStyle,
156
- outerDotProps?.style,
157
- ],
158
- [color, outerSize, outerStyle, outerDotProps?.style]
159
- )}
160
- />
161
- <View
158
+ <>
159
+ <AnimatedCircle
160
+ animatedProps={animatedDotProps}
161
+ r={size}
162
+ fill={color}
163
+ opacity={opacity}
162
164
  {...dotProps}
163
- style={useMemo(
164
- () => [
165
- {
166
- backgroundColor: color,
167
- width: size,
168
- height: size,
169
- borderRadius: size,
170
- },
171
- dotProps?.style,
172
- ],
173
- [color, size, dotProps?.style]
174
- )}
175
165
  />
176
- </Animated.View>
166
+ {hasOuterDot && (
167
+ <AnimatedCircle
168
+ animatedProps={animatedOuterDotProps}
169
+ fill={color}
170
+ {...outerDotProps}
171
+ />
172
+ )}
173
+ </>
177
174
  );
178
175
  }
@@ -1,16 +1,10 @@
1
1
  import * as React from 'react';
2
- import Animated, {
3
- useAnimatedProps,
4
- useAnimatedReaction,
5
- useSharedValue,
6
- withTiming,
7
- } from 'react-native-reanimated';
2
+ import Animated from 'react-native-reanimated';
8
3
  import { Defs, LinearGradient, Stop, Path, PathProps } from 'react-native-svg';
9
4
 
10
5
  import { LineChartDimensionsContext } from './Chart';
11
6
  import { LineChartPathContext } from './ChartPath';
12
- import interpolatePath from './interpolatePath';
13
- import { usePrevious } from '../../utils';
7
+ import useAnimatedPath from './useAnimatedPath';
14
8
 
15
9
  const AnimatedPath = Animated.createAnimatedComponent(Path);
16
10
 
@@ -21,6 +15,8 @@ export type LineChartGradientProps = Animated.AnimateProps<PathProps> & {
21
15
 
22
16
  let id = 0;
23
17
 
18
+ LineChartGradient.displayName = 'LineChartGradient';
19
+
24
20
  export function LineChartGradient({
25
21
  color: overrideColor = undefined,
26
22
  children,
@@ -34,32 +30,9 @@ export function LineChartGradient({
34
30
 
35
31
  ////////////////////////////////////////////////
36
32
 
37
- const transition = useSharedValue(0);
38
-
39
- const previousPath = usePrevious(area);
40
-
41
- useAnimatedReaction(
42
- () => {
43
- return area;
44
- },
45
- (_, previous) => {
46
- if (previous) {
47
- transition.value = 0;
48
- transition.value = withTiming(1);
49
- }
50
- },
51
- [area]
52
- );
53
-
54
- const animatedProps = useAnimatedProps(() => {
55
- let d = area || '';
56
- if (previousPath && isTransitionEnabled) {
57
- const pathInterpolator = interpolatePath(previousPath, area, null);
58
- d = pathInterpolator(transition.value);
59
- }
60
- return {
61
- d,
62
- };
33
+ const { animatedProps } = useAnimatedPath({
34
+ enabled: isTransitionEnabled,
35
+ path: area,
63
36
  });
64
37
 
65
38
  ////////////////////////////////////////////////
@@ -1,52 +1,9 @@
1
1
  import React from 'react';
2
-
3
- /* Returns React children into an array, flattening fragments.
4
-
5
- Forked from https://github.com/grrowl/react-keyed-flatten-children/blob/master/index.ts
6
- */
7
- import {
8
- ReactNode,
9
- ReactChild,
10
- Children,
11
- isValidElement,
12
- cloneElement,
13
- } from 'react';
2
+ import { ReactNode, Children, cloneElement } from 'react';
14
3
  import { ViewProps, View } from 'react-native';
15
- import { LineChart } from './Chart';
4
+ import flattenChildren from 'react-keyed-flatten-children';
16
5
 
17
- export default function flattenChildren(
18
- children: ReactNode,
19
- depth: number = 0,
20
- keys: (string | number)[] = []
21
- ): ReactChild[] {
22
- return Children.toArray(children).reduce(
23
- // eslint-disable-next-line
24
- (acc: ReactChild[], node: any, nodeIndex) => {
25
- if (node.type === React.Fragment) {
26
- acc.push.apply(
27
- acc,
28
- flattenChildren(
29
- node.props.children,
30
- depth + 1,
31
- keys.concat(node.key || nodeIndex)
32
- )
33
- );
34
- } else {
35
- if (isValidElement(node)) {
36
- acc.push(
37
- cloneElement(node, {
38
- key: keys.concat(String(node.key)).join('.'),
39
- })
40
- );
41
- } else if (typeof node === 'string' || typeof node === 'number') {
42
- acc.push(node);
43
- }
44
- }
45
- return acc;
46
- },
47
- []
48
- );
49
- }
6
+ import { LineChart } from './Chart';
50
7
 
51
8
  type Props = {
52
9
  children: ReactNode;
@@ -57,7 +14,7 @@ export function LineChartGroup({ children, ...props }: Props) {
57
14
  const flatChildrenCount = Children.count(flatChildren);
58
15
  return (
59
16
  <View {...props}>
60
- {/* eslint-disable-next-line */}
17
+ {/* eslint-disable-next-line @typescript-eslint/no-explicit-any */}
61
18
  {Children.map(flatChildren, (child: any, index) => {
62
19
  const isLast = index === flatChildrenCount - 1;
63
20
  if (!isLast && child.type === LineChart) {