react-native-gifted-charts 1.4.6 → 1.4.8

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/README.md CHANGED
@@ -15,12 +15,14 @@ The most complete library for Bar, Line, Area, Pie, Donut, Stacked Bar and Popul
15
15
  7. Detailed [documentation](https://gifted-charts.web.app/) with examples
16
16
  8. Support for **_combined_** Bar and Line charts
17
17
 
18
- ## [Release notes 🎉](release-notes/release-notes.md)
18
+ ## 📣 Announcement
19
+
20
+ The web counterpart of this library is public now. Try out our new reactJS library- [react-gifted-charts](https://github.com/Abhinandan-Kushwaha/react-gifted-charts) <br />
21
+ The exact same piece of code that you write to render charts in react-native, can be used to render charts in reactJS using this library!
19
22
 
20
- **Alert:**
21
23
 
22
- This library doesn't support web apps yet. Use this library if you are planning mobile first.</br>
23
- However, we are planning to add support for web which will be available soon.
24
+ ## [Release notes 🎉](release-notes/release-notes.md)
25
+
24
26
 
25
27
  <img src='/demos/bars.png' alt=''/>
26
28
  <img src='/demos/lineArea.png' alt=''/>
@@ -45,17 +47,19 @@ However, we are planning to add support for web which will be available soon.
45
47
 
46
48
  ## Installation
47
49
 
50
+ ### React Native CLI
51
+
48
52
  ```sh
49
53
  npm install react-native-gifted-charts react-native-linear-gradient react-native-svg
50
54
  ```
51
55
 
52
- For iOS-
56
+ ### Expo
53
57
 
54
58
  ```sh
55
- cd ios && pod install
59
+ npx expo install react-native-gifted-charts expo-linear-gradient react-native-svg
56
60
  ```
57
61
 
58
- Please note that `react-native-svg` and `react-native-linear-gradient` are needed for the library to work, so make sure they are installed in your project.
62
+ Please note that `react-native-svg` and `react-native-linear-gradient`/`expo-linear-gradient` are needed for the library to work, so make sure they are installed in your project.
59
63
 
60
64
  # Docs
61
65
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-gifted-charts",
3
- "version": "1.4.6",
3
+ "version": "1.4.8",
4
4
  "description": "The most complete library for Bar, Line, Area, Pie, Donut, Stacked Bar and Population Pyramid charts in React Native. Allows 2D, 3D, gradient, animations and live data updates.",
5
5
  "main": "src/index.tsx",
6
6
  "files": [
@@ -24,7 +24,7 @@
24
24
  "registry": "https://registry.npmjs.org/"
25
25
  },
26
26
  "dependencies": {
27
- "gifted-charts-core": "^0.0.18"
27
+ "gifted-charts-core": "^0.1.1"
28
28
  },
29
29
  "devDependencies": {
30
30
  "@babel/core": "^7.22.5",
@@ -51,8 +51,17 @@
51
51
  "react": "*",
52
52
  "react-native": "*",
53
53
  "react-native-linear-gradient": "*",
54
+ "expo-linear-gradient": "*",
54
55
  "react-native-svg": "*"
55
56
  },
57
+ "peerDependenciesMeta": {
58
+ "react-native-linear-gradient": {
59
+ "optional": true
60
+ },
61
+ "expo-linear-gradient": {
62
+ "optional": true
63
+ }
64
+ },
56
65
  "keywords": [
57
66
  "chart",
58
67
  "charts",
@@ -1,8 +1,8 @@
1
1
  import React, {useEffect, useState} from 'react';
2
2
  import {View, LayoutAnimation, Platform, UIManager, Text} from 'react-native';
3
- import LinearGradient from 'react-native-linear-gradient';
4
3
  import Svg, {Defs, Rect} from 'react-native-svg';
5
4
  import Cap from '../Components/BarSpecificComponents/cap';
5
+ import LinearGradient from "../Components/common/LinearGradient";
6
6
  import {Animated2DWithGradientPropsType} from 'gifted-charts-core';
7
7
 
8
8
  if (Platform.OS === 'android') {
@@ -32,6 +32,7 @@ const Animated2DWithGradient = (props: Animated2DWithGradientPropsType) => {
32
32
  topLabelTextStyle,
33
33
  commonStyleForBar,
34
34
  barStyleWithBackground,
35
+ yAxisOffset,
35
36
  } = props;
36
37
  const [height, setHeight] = useState(noAnimation ? props.height : 0.2);
37
38
  const [initialRender, setInitialRender] = useState(
@@ -72,16 +73,12 @@ const Animated2DWithGradient = (props: Animated2DWithGradientPropsType) => {
72
73
  <View
73
74
  style={{
74
75
  position: 'absolute',
75
- bottom: 0,
76
+ bottom: -0.5,
76
77
  width: '100%',
77
78
  overflow: 'hidden',
78
79
  height:
79
80
  (noAnimation
80
- ? Math.max(
81
- props.minHeight,
82
- (Math.abs(item.value) * (containerHeight || 200)) /
83
- (maxValue || 200),
84
- )
81
+ ? Math.max(props.minHeight, Math.abs(height))
85
82
  : height) - (barMarginBottom || 0),
86
83
  }}>
87
84
  <View
@@ -90,11 +87,7 @@ const Animated2DWithGradient = (props: Animated2DWithGradientPropsType) => {
90
87
  width: '100%',
91
88
  height:
92
89
  (noAnimation
93
- ? Math.max(
94
- props.minHeight,
95
- (Math.abs(item.value) * (containerHeight || 200)) /
96
- (maxValue || 200),
97
- )
90
+ ? Math.max(props.minHeight, Math.abs(height))
98
91
  : height) - (barMarginBottom || 0),
99
92
  },
100
93
  item.barStyle || barStyle,
@@ -157,12 +150,7 @@ const Animated2DWithGradient = (props: Animated2DWithGradientPropsType) => {
157
150
  x="1"
158
151
  y="1"
159
152
  width={item.barWidth || props.barWidth || 30}
160
- height={
161
- noAnimation
162
- ? (Math.abs(item.value) * (containerHeight || 200)) /
163
- (maxValue || 200)
164
- : height
165
- }
153
+ height={noAnimation ? Math.abs(height) : height}
166
154
  fill={`url(#${item.patternId || patternId})`}
167
155
  />
168
156
  </Svg>
@@ -196,7 +184,7 @@ const Animated2DWithGradient = (props: Animated2DWithGradientPropsType) => {
196
184
  topLabelContainerStyle ?? item.topLabelContainerStyle,
197
185
  ]}>
198
186
  {showValuesAsTopLabel ? (
199
- <Text style={topLabelTextStyle}>{item.value}</Text>
187
+ <Text style={topLabelTextStyle}>{item.value + yAxisOffset}</Text>
200
188
  ) : (
201
189
  item.topLabelComponent?.()
202
190
  )}
@@ -1,14 +1,15 @@
1
1
  import React from 'react';
2
2
  import {View, TouchableOpacity, Animated, Text} from 'react-native';
3
3
  import AnimatedThreeDBar from '../Components/AnimatedThreeDBar';
4
- import LinearGradient from 'react-native-linear-gradient';
5
4
  import Animated2DWithGradient from './Animated2DWithGradient';
6
5
  import Cap from '../Components/BarSpecificComponents/cap';
7
6
  import BarBackgroundPattern from '../Components/BarSpecificComponents/barBackgroundPattern';
7
+ import LinearGradient from "../Components/common/LinearGradient";
8
8
  import {
9
9
  getPropsForAnimated2DWithGradient,
10
10
  RenderBarsPropsType,
11
11
  barDataItem,
12
+ AxesAndRulesDefaults,
12
13
  } from 'gifted-charts-core';
13
14
 
14
15
  const RenderBars = (props: RenderBarsPropsType) => {
@@ -40,7 +41,7 @@ const RenderBars = (props: RenderBarsPropsType) => {
40
41
  initialSpacing,
41
42
  selectedIndex,
42
43
  setSelectedIndex,
43
- xAxisThickness,
44
+ xAxisThickness = AxesAndRulesDefaults.xAxisThickness,
44
45
  horizontal,
45
46
  rtl,
46
47
  intactTopLabel,
@@ -49,12 +50,13 @@ const RenderBars = (props: RenderBarsPropsType) => {
49
50
  topLabelTextStyle,
50
51
  pointerConfig,
51
52
  noOfSectionsBelowXAxis,
53
+ yAxisOffset,
52
54
  } = props;
53
55
 
54
56
  const barHeight = Math.max(
55
57
  minHeight,
56
58
  (Math.abs(item.value) * (containerHeight || 200)) / (maxValue || 200) -
57
- (xAxisThickness ?? 0),
59
+ xAxisThickness,
58
60
  );
59
61
 
60
62
  const {
@@ -128,7 +130,7 @@ const RenderBars = (props: RenderBarsPropsType) => {
128
130
  <Text
129
131
  style={[
130
132
  {textAlign: 'center'},
131
- rtl && {transform: [{rotate: '180deg'}]},
133
+ rtl && horizontal && {transform: [{rotate: '180deg'}]},
132
134
  labelTextStyle,
133
135
  ]}
134
136
  numberOfLines={xAxisTextNumberOfLines}>
@@ -190,7 +192,7 @@ const RenderBars = (props: RenderBarsPropsType) => {
190
192
  <Text
191
193
  style={[
192
194
  {textAlign: 'center'},
193
- rtl && {transform: [{rotate: '180deg'}]},
195
+ rtl && horizontal && {transform: [{rotate: '180deg'}]},
194
196
  labelTextStyle,
195
197
  ]}
196
198
  numberOfLines={xAxisTextNumberOfLines}>
@@ -262,7 +264,7 @@ const RenderBars = (props: RenderBarsPropsType) => {
262
264
  topLabelContainerStyle ?? item.topLabelContainerStyle,
263
265
  ]}>
264
266
  {showValuesAsTopLabel ? (
265
- <Text style={topLabelTextStyle}>{item.value}</Text>
267
+ <Text style={topLabelTextStyle}>{item.value + yAxisOffset}</Text>
266
268
  ) : (
267
269
  item.topLabelComponent?.()
268
270
  )}
@@ -280,7 +282,7 @@ const RenderBars = (props: RenderBarsPropsType) => {
280
282
  const barWrapperStyle = [
281
283
  {
282
284
  // overflow: 'visible',
283
- marginBottom: 60 + barMarginBottom + xAxisLabelsVerticalShift,
285
+ marginBottom: 60 + barMarginBottom + xAxisLabelsVerticalShift - 0.5,
284
286
  width: commonPropsFor2Dand3Dbars.barWidth,
285
287
  height: barHeight,
286
288
  marginRight: spacing,
@@ -7,8 +7,8 @@ import {
7
7
  Platform,
8
8
  UIManager,
9
9
  } from 'react-native';
10
- import LinearGradient from 'react-native-linear-gradient';
11
10
  import Svg, {Defs, Rect} from 'react-native-svg';
11
+ import LinearGradient from "../Components/common/LinearGradient";
12
12
  import {
13
13
  useRenderStackBars,
14
14
  BarDefaults,
@@ -3,9 +3,10 @@ import {Animated, Easing, View} from 'react-native';
3
3
  import RenderBars from './RenderBars';
4
4
  import RenderStackBars from './RenderStackBars';
5
5
  import BarAndLineChartsWrapper from '../Components/BarAndLineChartsWrapper';
6
- import {BarChartPropsType, useBarChart, screenWidth} from 'gifted-charts-core';
6
+ import {BarChartPropsType, useBarChart} from 'gifted-charts-core';
7
7
  import {StripAndLabel} from '../Components/common/StripAndLabel';
8
8
  import {Pointer} from '../Components/common/Pointer';
9
+ import {screenWidth} from '../utils';
9
10
 
10
11
  export const BarChart = (props: BarChartPropsType) => {
11
12
  const heightValue = useMemo(() => new Animated.Value(0), []);
@@ -7,9 +7,9 @@ import {
7
7
  UIManager,
8
8
  Text,
9
9
  } from 'react-native';
10
- import LinearGradient from 'react-native-linear-gradient';
11
10
  import Svg, {Defs, Rect} from 'react-native-svg';
12
11
  import {styles} from './styles';
12
+ import LinearGradient from "../common/LinearGradient";
13
13
  import {
14
14
  useAnimatedThreeDBar,
15
15
  animatedBarPropTypes,
@@ -49,8 +49,9 @@ const triangleStyles = StyleSheet.create({
49
49
  });
50
50
 
51
51
  const AnimatedThreeDBar = (props: animatedBarPropTypes) => {
52
+ const heightCopy = props.height;
52
53
  const [height, setHeight] = useState(
53
- props.isAnimated ? (Platform.OS === 'ios' ? 0 : 20) : props.height,
54
+ props.isAnimated ? (Platform.OS === 'ios' ? 0 : 20) : heightCopy,
54
55
  );
55
56
 
56
57
  const {
@@ -134,7 +135,7 @@ const AnimatedThreeDBar = (props: animatedBarPropTypes) => {
134
135
  <View
135
136
  style={{
136
137
  width: barWidth,
137
- height: barWidth * 0.4,
138
+ height: barWidth,
138
139
  // left: width / 2,
139
140
  backgroundColor: topColor,
140
141
  opacity: opacity,
@@ -145,7 +146,7 @@ const AnimatedThreeDBar = (props: animatedBarPropTypes) => {
145
146
  style={{
146
147
  position: 'absolute',
147
148
  top: sideWidth / -2,
148
- left: barWidth,
149
+ left: barWidth - 1,
149
150
  }}>
150
151
  <TriangleCorner
151
152
  color={topColor}
@@ -158,7 +159,7 @@ const AnimatedThreeDBar = (props: animatedBarPropTypes) => {
158
159
 
159
160
  {/*******************************************************************/}
160
161
 
161
- <View style={{marginTop: sideWidth / -2}}>
162
+ <View style={{marginTop: sideWidth / -2 - 1}}>
162
163
  <TriangleCorner
163
164
  color={height ? sideColor : 'transparent'}
164
165
  width={sideWidth}
@@ -166,7 +167,7 @@ const AnimatedThreeDBar = (props: animatedBarPropTypes) => {
166
167
  />
167
168
  <View
168
169
  style={{
169
- width: sideWidth / 2,
170
+ width: sideWidth / 2 + 1,
170
171
  height: height - sideWidth / 2, //animatedSideHeight
171
172
  backgroundColor: sideColor,
172
173
  opacity: opacity,
@@ -174,7 +175,7 @@ const AnimatedThreeDBar = (props: animatedBarPropTypes) => {
174
175
  />
175
176
  <TriangleCorner
176
177
  color={height ? sideColor : 'transparent'}
177
- width={sideWidth}
178
+ width={sideWidth + 1}
178
179
  style={{transform: [{rotate: '90deg'}], opacity: opacity}}
179
180
  />
180
181
  </View>
@@ -1,5 +1,5 @@
1
1
  import React, {Fragment, useEffect} from 'react';
2
- import {View, ScrollView, StyleSheet} from 'react-native';
2
+ import {View, ScrollView, StyleSheet, I18nManager} from 'react-native';
3
3
  import {renderHorizSections} from './renderHorizSections';
4
4
  import RenderLineInBarChart from './renderLineInBarChart';
5
5
  import RenderVerticalLines from './renderVerticalLines';
@@ -77,7 +77,7 @@ const BarAndLineChartsWrapper = (props: BarAndLineChartsWrapperTypes) => {
77
77
  verticalLinesProps,
78
78
  lineInBarChartProps,
79
79
  lineInBarChartProps2,
80
- } = useBarAndLineChartsWrapper(props);
80
+ } = useBarAndLineChartsWrapper({...props, isRTL:I18nManager.isRTL});
81
81
 
82
82
  useEffect(() => {
83
83
  if (pointerConfig && getPointerProps) {
@@ -0,0 +1,27 @@
1
+ import React from 'react';
2
+ import {ViewStyle} from "react-native";
3
+
4
+ type LinearGradientProps = {
5
+ style?: ViewStyle;
6
+ start?: { x: number, y: number };
7
+ end?: { x: number, y: number };
8
+ colors: string[];
9
+ }
10
+
11
+ let LinearGradient: React.FC<LinearGradientProps>;
12
+
13
+ try {
14
+ // for bare react-native projects
15
+ LinearGradient = require('react-native-linear-gradient').LinearGradient;
16
+ } catch (e) {
17
+ try {
18
+ // for expo-based projects
19
+ LinearGradient = require('expo-linear-gradient').LinearGradient;
20
+ } catch (e) {
21
+ throw new Error(
22
+ 'Gradient package was not found. Make sure "react-native-linear-gradient" or "expo-linear-gradient" is installed'
23
+ );
24
+ }
25
+ }
26
+
27
+ export default LinearGradient;
@@ -31,7 +31,7 @@ export const StripAndLabel = props => {
31
31
  <View
32
32
  style={{
33
33
  position: 'absolute',
34
- left: pointerX + (pointerItemLocal[0].pointerShiftX || 0),
34
+ left: pointerX + (pointerItemLocal[0]?.pointerShiftX || 0),
35
35
  top: pointerYLocal,
36
36
  }}>
37
37
  {(
@@ -18,8 +18,9 @@ import {
18
18
 
19
19
  export const LineChartBicolor = (props: LineChartBicolorPropsType) => {
20
20
  const scrollRef = useRef();
21
- const opacValue = useMemo(() => new Animated.Value(0), []);
21
+ // const heightValue = useMemo(() => new Animated.Value(0), []);
22
22
  const widthValue = useMemo(() => new Animated.Value(0), []);
23
+ const opacValue = useMemo(() => new Animated.Value(0), []);
23
24
 
24
25
  const {
25
26
  pointsArray,
@@ -10,6 +10,7 @@ import {
10
10
  I18nManager,
11
11
  } from 'react-native';
12
12
  import {styles} from './styles';
13
+ import {screenWidth} from '../utils';
13
14
  import Svg, {
14
15
  Path,
15
16
  LinearGradient,
@@ -31,23 +32,31 @@ import {
31
32
  lineDataItem,
32
33
  LineSvgProps,
33
34
  useLineChart,
35
+ adjustToOffset,
36
+ LineProperties,
34
37
  } from 'gifted-charts-core';
35
38
  import BarAndLineChartsWrapper from '../Components/BarAndLineChartsWrapper';
36
39
  import {StripAndLabel} from '../Components/common/StripAndLabel';
37
40
  import {Pointer} from '../Components/common/Pointer';
38
41
 
39
42
  let initialData: Array<lineDataItem> | null = null;
40
- let animations: Array<any> = [];
43
+ let animations: Array<Animated.Value> = [];
41
44
 
42
45
  export const LineChart = (props: LineChartPropsType) => {
43
46
  const scrollRef = props.scrollRef ?? useRef(null);
44
47
  const opacValue = useMemo(() => new Animated.Value(0), []);
48
+ const heightValue = useMemo(() => new Animated.Value(0), []);
45
49
  const widthValue = useMemo(() => new Animated.Value(0), []);
46
50
  const widthValue2 = useMemo(() => new Animated.Value(0), []);
47
51
  const widthValue3 = useMemo(() => new Animated.Value(0), []);
48
52
  const widthValue4 = useMemo(() => new Animated.Value(0), []);
49
53
  const widthValue5 = useMemo(() => new Animated.Value(0), []);
50
54
 
55
+ if (!initialData) {
56
+ initialData = props.dataSet?.[0]?.data ?? props.data ?? [];
57
+ animations = initialData.map(item => new Animated.Value(item.value));
58
+ }
59
+
51
60
  const {
52
61
  scrollX,
53
62
  setScrollX,
@@ -158,7 +167,7 @@ export const LineChart = (props: LineChartPropsType) => {
158
167
  dataPointsRadius5,
159
168
  dataPointsColor5,
160
169
  dataPointsShape5,
161
- atLeastOneAreaChart,
170
+ getIsNthAreaChart,
162
171
  textFontSize1,
163
172
  textFontSize2,
164
173
  textFontSize3,
@@ -293,12 +302,7 @@ export const LineChart = (props: LineChartPropsType) => {
293
302
  lineGradientStartColor,
294
303
  lineGradientEndColor,
295
304
  barAndLineChartsWrapperProps,
296
- } = useLineChart({...props, animations});
297
-
298
- if (!initialData) {
299
- initialData = data0 ?? [...data];
300
- animations = initialData?.map(item => new Animated.Value(item.value));
301
- }
305
+ } = useLineChart({...props, animations, screenWidth});
302
306
 
303
307
  const widthValuesFromSet = useMemo(
304
308
  () => dataSet?.map(set => new Animated.Value(0)),
@@ -889,7 +893,7 @@ export const LineChart = (props: LineChartPropsType) => {
889
893
 
890
894
  return Pointer({
891
895
  pointerX,
892
- pointerYLocal,
896
+ pointerYLocal: pointerYLocal + xAxisThickness,
893
897
  pointerComponent,
894
898
  pointerHeight,
895
899
  pointerRadius,
@@ -1013,17 +1017,19 @@ export const LineChart = (props: LineChartPropsType) => {
1013
1017
  arrowStrokeWidth,
1014
1018
  arrowStrokeColor,
1015
1019
  arrowFillColor,
1020
+ key,
1016
1021
  ) => {
1017
1022
  if (!points) return null;
1018
1023
  const isCurved = points.includes('C');
1019
- let ar: [any] = [{}];
1024
+ const isNthAreaChart = getIsNthAreaChart(key ?? 0);
1025
+ let ar: LineProperties[] = [{d: '', color: '', strokeWidth: 0}];
1020
1026
  if (points.includes(RANGE_ENTER)) {
1021
1027
  ar = getRegionPathObjects(
1022
1028
  points,
1023
1029
  color,
1024
- currentLineThickness,
1030
+ currentLineThickness ?? 0,
1025
1031
  thickness,
1026
- strokeDashArray,
1032
+ strokeDashArray ?? [],
1027
1033
  isCurved,
1028
1034
  RANGE_ENTER,
1029
1035
  STOP,
@@ -1033,9 +1039,9 @@ export const LineChart = (props: LineChartPropsType) => {
1033
1039
  ar = getSegmentedPathObjects(
1034
1040
  points,
1035
1041
  color,
1036
- currentLineThickness,
1042
+ currentLineThickness ?? 0,
1037
1043
  thickness,
1038
- strokeDashArray,
1044
+ strokeDashArray ?? [],
1039
1045
  isCurved,
1040
1046
  SEGMENT_START,
1041
1047
  SEGMENT_END,
@@ -1090,14 +1096,14 @@ export const LineChart = (props: LineChartPropsType) => {
1090
1096
 
1091
1097
  {/*********************** For Area Chart ************/}
1092
1098
 
1093
- {atLeastOneAreaChart &&
1099
+ {isNthAreaChart &&
1094
1100
  getAreaGradientComponent(
1095
1101
  startFillColor,
1096
1102
  endFillColor,
1097
1103
  startOpacity,
1098
1104
  endOpacity,
1099
1105
  )}
1100
- {atLeastOneAreaChart && (
1106
+ {isNthAreaChart && (
1101
1107
  <Path
1102
1108
  d={fillPoints}
1103
1109
  fill={
@@ -1120,14 +1126,10 @@ export const LineChart = (props: LineChartPropsType) => {
1120
1126
 
1121
1127
  {dataSet?.map(set => renderSpecificVerticalLines(set?.data)) ?? null}
1122
1128
  {dataSet?.map(set => {
1123
- const setData = set.data.map(item => {
1124
- item.value = item.value - (props.yAxisOffset ?? 0);
1125
- return item;
1126
- });
1127
1129
  return renderDataPoints(
1128
1130
  set.hideDataPoints ?? hideDataPoints1,
1129
- setData,
1130
1131
  set.data,
1132
+ adjustToOffset(set.data, -(props.yAxisOffset ?? 0)), // need the actual values passed by user
1131
1133
  set.dataPointsShape ?? dataPointsShape1,
1132
1134
  set.dataPointsWidth ?? dataPointsWidth1,
1133
1135
  set.dataPointsHeight ?? dataPointsHeight1,
@@ -1253,6 +1255,89 @@ export const LineChart = (props: LineChartPropsType) => {
1253
1255
  );
1254
1256
  };
1255
1257
 
1258
+ const activatePointers = x => {
1259
+ let factor = (x - initialSpacing) / spacing;
1260
+ factor = Math.round(factor);
1261
+ factor = Math.min(factor, (data0 ?? data).length - 1);
1262
+ factor = Math.max(factor, 0);
1263
+ let z =
1264
+ initialSpacing +
1265
+ spacing * factor -
1266
+ (pointerRadius || pointerWidth / 2) -
1267
+ 1;
1268
+ setPointerX(z);
1269
+ setPointerIndex(factor);
1270
+ let item, y;
1271
+ item = (data0 ?? data)[factor];
1272
+ y =
1273
+ containerHeight -
1274
+ (item.value * containerHeight) / maxValue -
1275
+ (pointerRadius || pointerHeight / 2) +
1276
+ 10;
1277
+ setPointerY(y);
1278
+ setPointerItem(item);
1279
+ if (data2 && data2.length) {
1280
+ item = data2[factor];
1281
+ if (item) {
1282
+ y =
1283
+ containerHeight -
1284
+ (item.value * containerHeight) / maxValue -
1285
+ (pointerRadius || pointerHeight / 2) +
1286
+ 10;
1287
+ setPointerY2(y);
1288
+ setPointerItem2(item);
1289
+ }
1290
+ }
1291
+ if (data3 && data3.length) {
1292
+ item = data3[factor];
1293
+ if (item) {
1294
+ y =
1295
+ containerHeight -
1296
+ (item.value * containerHeight) / maxValue -
1297
+ (pointerRadius || pointerHeight / 2) +
1298
+ 10;
1299
+ setPointerY3(y);
1300
+ setPointerItem3(item);
1301
+ }
1302
+ }
1303
+ if (data4 && data4.length) {
1304
+ item = data4[factor];
1305
+ if (item) {
1306
+ y =
1307
+ containerHeight -
1308
+ (item.value * containerHeight) / maxValue -
1309
+ (pointerRadius || pointerHeight / 2) +
1310
+ 10;
1311
+ setPointerY4(y);
1312
+ setPointerItem4(item);
1313
+ }
1314
+ }
1315
+ if (data5 && data5.length) {
1316
+ item = data5[factor];
1317
+ if (item) {
1318
+ y =
1319
+ containerHeight -
1320
+ (item.value * containerHeight) / maxValue -
1321
+ (pointerRadius || pointerHeight / 2) +
1322
+ 10;
1323
+ setPointerY5(y);
1324
+ setPointerItem5(item);
1325
+ }
1326
+ }
1327
+ if (secondaryData?.length) {
1328
+ item = secondaryData[factor];
1329
+ if (item) {
1330
+ y =
1331
+ containerHeight -
1332
+ (item.value * containerHeight) / maxValue -
1333
+ (pointerRadius || pointerHeight / 2) +
1334
+ 10;
1335
+ setSecondaryPointerY(y);
1336
+ setSecondaryPointerItem(item);
1337
+ }
1338
+ }
1339
+ };
1340
+
1256
1341
  const renderLine = (
1257
1342
  zIndex: number,
1258
1343
  points: any,
@@ -1274,7 +1359,6 @@ export const LineChart = (props: LineChartPropsType) => {
1274
1359
  return (
1275
1360
  <View
1276
1361
  key={key ?? 0}
1277
- onStartShouldSetResponder={evt => (pointerConfig ? true : false)}
1278
1362
  onMoveShouldSetResponder={evt => (pointerConfig ? true : false)}
1279
1363
  onResponderGrant={evt => {
1280
1364
  if (!pointerConfig) return;
@@ -1283,91 +1367,7 @@ export const LineChart = (props: LineChartPropsType) => {
1283
1367
  return;
1284
1368
  }
1285
1369
  let x = evt.nativeEvent.locationX;
1286
- if (
1287
- !activatePointersOnLongPress &&
1288
- x > (props.width || Dimensions.get('window').width)
1289
- )
1290
- return;
1291
- let factor = (x - initialSpacing) / spacing;
1292
- factor = Math.round(factor);
1293
- factor = Math.min(factor, (data0 ?? data).length - 1);
1294
- factor = Math.max(factor, 0);
1295
- let z =
1296
- initialSpacing +
1297
- spacing * factor -
1298
- (pointerRadius || pointerWidth / 2) -
1299
- 1;
1300
- setPointerX(z);
1301
- setPointerIndex(factor);
1302
- let item, y;
1303
- item = (data0 ?? data)[factor];
1304
- y =
1305
- containerHeight -
1306
- (item.value * containerHeight) / maxValue -
1307
- (pointerRadius || pointerHeight / 2) +
1308
- 10;
1309
- setPointerY(y);
1310
- setPointerItem(item);
1311
- if (data2 && data2.length) {
1312
- item = data2[factor];
1313
- if (item) {
1314
- y =
1315
- containerHeight -
1316
- (item.value * containerHeight) / maxValue -
1317
- (pointerRadius || pointerHeight / 2) +
1318
- 10;
1319
- setPointerY2(y);
1320
- setPointerItem2(item);
1321
- }
1322
- }
1323
- if (data3 && data3.length) {
1324
- item = data3[factor];
1325
- if (item) {
1326
- y =
1327
- containerHeight -
1328
- (item.value * containerHeight) / maxValue -
1329
- (pointerRadius || pointerHeight / 2) +
1330
- 10;
1331
- setPointerY3(y);
1332
- setPointerItem3(item);
1333
- }
1334
- }
1335
- if (data4 && data4.length) {
1336
- item = data4[factor];
1337
- if (item) {
1338
- y =
1339
- containerHeight -
1340
- (item.value * containerHeight) / maxValue -
1341
- (pointerRadius || pointerHeight / 2) +
1342
- 10;
1343
- setPointerY4(y);
1344
- setPointerItem4(item);
1345
- }
1346
- }
1347
- if (data5 && data5.length) {
1348
- item = data5[factor];
1349
- if (item) {
1350
- y =
1351
- containerHeight -
1352
- (item.value * containerHeight) / maxValue -
1353
- (pointerRadius || pointerHeight / 2) +
1354
- 10;
1355
- setPointerY5(y);
1356
- setPointerItem5(item);
1357
- }
1358
- }
1359
- if (secondaryData?.length) {
1360
- item = secondaryData[factor];
1361
- if (item) {
1362
- y =
1363
- containerHeight -
1364
- (item.value * containerHeight) / maxValue -
1365
- (pointerRadius || pointerHeight / 2) +
1366
- 10;
1367
- setSecondaryPointerY(y);
1368
- setSecondaryPointerItem(item);
1369
- }
1370
- }
1370
+ activatePointers(x);
1371
1371
  }}
1372
1372
  onResponderMove={evt => {
1373
1373
  if (!pointerConfig) return;
@@ -1495,6 +1495,7 @@ export const LineChart = (props: LineChartPropsType) => {
1495
1495
  60 +
1496
1496
  xAxisLabelsVerticalShift +
1497
1497
  labelsExtraHeight -
1498
+ xAxisThickness -
1498
1499
  (props.overflowBottom ?? dataPointsRadius1),
1499
1500
  zIndex: zIndex,
1500
1501
  transform: [{scaleX: I18nManager.isRTL ? -1 : 1}],
@@ -1515,6 +1516,7 @@ export const LineChart = (props: LineChartPropsType) => {
1515
1516
  arrowStrokeWidth,
1516
1517
  arrowStrokeColor,
1517
1518
  arrowFillColor,
1519
+ key,
1518
1520
  )}
1519
1521
  </View>
1520
1522
  );
@@ -1551,91 +1553,7 @@ export const LineChart = (props: LineChartPropsType) => {
1551
1553
  return;
1552
1554
  }
1553
1555
  let x = evt.nativeEvent.locationX;
1554
- if (
1555
- !activatePointersOnLongPress &&
1556
- x > (props.width || Dimensions.get('window').width)
1557
- )
1558
- return;
1559
- let factor = (x - initialSpacing) / spacing;
1560
- factor = Math.round(factor);
1561
- factor = Math.min(factor, (data0 ?? data).length - 1);
1562
- factor = Math.max(factor, 0);
1563
- let z =
1564
- initialSpacing +
1565
- spacing * factor -
1566
- (pointerRadius || pointerWidth / 2) -
1567
- 1;
1568
- setPointerX(z);
1569
- setPointerIndex(factor);
1570
- let item, y;
1571
- item = (data0 ?? data)[factor];
1572
- y =
1573
- containerHeight -
1574
- (item.value * containerHeight) / maxValue -
1575
- (pointerRadius || pointerHeight / 2) +
1576
- 10;
1577
- setPointerY(y);
1578
- setPointerItem(item);
1579
- if (data2 && data2.length) {
1580
- item = data2[factor];
1581
- if (item) {
1582
- y =
1583
- containerHeight -
1584
- (item.value * containerHeight) / maxValue -
1585
- (pointerRadius || pointerHeight / 2) +
1586
- 10;
1587
- setPointerY2(y);
1588
- setPointerItem2(item);
1589
- }
1590
- }
1591
- if (data3 && data3.length) {
1592
- item = data3[factor];
1593
- if (item) {
1594
- y =
1595
- containerHeight -
1596
- (item.value * containerHeight) / maxValue -
1597
- (pointerRadius || pointerHeight / 2) +
1598
- 10;
1599
- setPointerY3(y);
1600
- setPointerItem3(item);
1601
- }
1602
- }
1603
- if (data4 && data4.length) {
1604
- item = data4[factor];
1605
- if (item) {
1606
- y =
1607
- containerHeight -
1608
- (item.value * containerHeight) / maxValue -
1609
- (pointerRadius || pointerHeight / 2) +
1610
- 10;
1611
- setPointerY4(y);
1612
- setPointerItem4(item);
1613
- }
1614
- }
1615
- if (data5 && data5.length) {
1616
- item = data5[factor];
1617
- if (item) {
1618
- y =
1619
- containerHeight -
1620
- (item.value * containerHeight) / maxValue -
1621
- (pointerRadius || pointerHeight / 2) +
1622
- 10;
1623
- setPointerY5(y);
1624
- setPointerItem5(item);
1625
- }
1626
- }
1627
- if (secondaryData?.length) {
1628
- item = secondaryData[factor];
1629
- if (item) {
1630
- y =
1631
- containerHeight -
1632
- (item.value * containerHeight) / maxValue -
1633
- (pointerRadius || pointerHeight / 2) +
1634
- 10;
1635
- setSecondaryPointerY(y);
1636
- setSecondaryPointerItem(item);
1637
- }
1638
- }
1556
+ activatePointers(x);
1639
1557
  }}
1640
1558
  onResponderMove={evt => {
1641
1559
  if (!pointerConfig) return;
@@ -1763,6 +1681,7 @@ export const LineChart = (props: LineChartPropsType) => {
1763
1681
  60 +
1764
1682
  xAxisLabelsVerticalShift +
1765
1683
  labelsExtraHeight -
1684
+ xAxisThickness -
1766
1685
  (props.overflowBottom ?? dataPointsRadius1),
1767
1686
  zIndex: zIndex,
1768
1687
  transform: [{scaleX: I18nManager.isRTL ? -1 : 1}],
@@ -1783,6 +1702,7 @@ export const LineChart = (props: LineChartPropsType) => {
1783
1702
  arrowStrokeWidth,
1784
1703
  arrowStrokeColor,
1785
1704
  arrowFillColor,
1705
+ key,
1786
1706
  )}
1787
1707
  </Animated.View>
1788
1708
  );
@@ -1822,9 +1742,9 @@ export const LineChart = (props: LineChartPropsType) => {
1822
1742
  set.strokeDashArray ?? strokeDashArray1,
1823
1743
  set.showArrow || props.showArrows,
1824
1744
  arrowPointsFromSet[index],
1825
- arrowStrokeWidthsFromSet[index],
1826
- arrowStrokeColorsFromSet[index],
1827
- arrowFillColorsFromSet[index],
1745
+ arrowStrokeWidthsFromSet?.[index],
1746
+ arrowStrokeColorsFromSet?.[index],
1747
+ arrowFillColorsFromSet?.[index],
1828
1748
  index,
1829
1749
  );
1830
1750
  } else {
@@ -1841,9 +1761,9 @@ export const LineChart = (props: LineChartPropsType) => {
1841
1761
  set.strokeDashArray ?? strokeDashArray1,
1842
1762
  set.showArrow || props.showArrows,
1843
1763
  arrowPointsFromSet[index],
1844
- arrowStrokeWidthsFromSet[index],
1845
- arrowStrokeColorsFromSet[index],
1846
- arrowFillColorsFromSet[index],
1764
+ arrowStrokeWidthsFromSet?.[index],
1765
+ arrowStrokeColorsFromSet?.[index],
1766
+ arrowFillColorsFromSet?.[index],
1847
1767
  index,
1848
1768
  );
1849
1769
  }
@@ -156,7 +156,10 @@ export const PieChart = (props: PieChartPropsType) => {
156
156
  />
157
157
  </View>
158
158
  )}
159
- {renderInnerCircle(innerRadius - inwardExtraLengthForFocused, 0)}
159
+ {renderInnerCircle(
160
+ innerRadius - inwardExtraLengthForFocused,
161
+ inwardExtraLengthForFocused ? 0 : innerCircleBorderWidth,
162
+ )}
160
163
  </View>
161
164
  );
162
165
  };
@@ -13,8 +13,8 @@ import {
13
13
  getPieChartMainProps,
14
14
  PieChartMainProps,
15
15
  pieColors,
16
- rnVersion,
17
16
  } from 'gifted-charts-core';
17
+ import { rnVersion } from '../utils';
18
18
 
19
19
  export const PieChartMain = (props: PieChartMainProps) => {
20
20
  const {
@@ -0,0 +1,216 @@
1
+ import React, {useEffect} from 'react';
2
+ import {PieChartPropsType, pieColors, usePiePro} from 'gifted-charts-core';
3
+ import {
4
+ Defs,
5
+ Path,
6
+ Stop,
7
+ Svg,
8
+ Text as SvgText,
9
+ RadialGradient,
10
+ } from 'react-native-svg';
11
+ import {Animated} from 'react-native';
12
+
13
+ export const PieChartPro = (props: PieChartPropsType) => {
14
+ const {
15
+ radius,
16
+ total,
17
+ donut,
18
+ strokeWidth,
19
+ animationDuration,
20
+ initial,
21
+ dInitial,
22
+ dFinal,
23
+ getStartCaps,
24
+ getEndCaps,
25
+ getTextCoordinates,
26
+ } = usePiePro(props);
27
+
28
+ const {
29
+ data,
30
+ curvedStartEdges,
31
+ curvedEndEdges,
32
+ edgesRadius = 0,
33
+ showGradient,
34
+ } = props;
35
+
36
+ let {isAnimated} = props;
37
+
38
+ if (!props.semiCircle && data.some(dataItem => dataItem.value > total / 2)) {
39
+ // if we have an obtuse arc, we cant animate
40
+ isAnimated = false;
41
+ }
42
+
43
+ const AnimatedPath = Animated.createAnimatedComponent(Path);
44
+ const AnimatedText = Animated.createAnimatedComponent(SvgText);
45
+
46
+ const animatedValues = data.map(i => new Animated.Value(0));
47
+ const animatedOpacityValue = new Animated.Value(0);
48
+ const animatedPaths = data.map((item, index) =>
49
+ animatedValues[index]?.interpolate({
50
+ inputRange: [0, 1],
51
+ outputRange: [dInitial[index], dFinal[index]],
52
+ }),
53
+ );
54
+
55
+ const animatedOpacity = animatedOpacityValue.interpolate({
56
+ inputRange: [0, 1],
57
+ outputRange: [0, 1],
58
+ });
59
+
60
+ useEffect(() => {
61
+ Animated.timing(animatedOpacityValue, {
62
+ toValue: 1,
63
+ duration: 10,
64
+ useNativeDriver: true,
65
+ delay: animationDuration,
66
+ }).start();
67
+ animatedValues.forEach(animatedValue =>
68
+ Animated.timing(animatedValue, {
69
+ toValue: 1,
70
+ duration: animationDuration,
71
+ useNativeDriver: true,
72
+ }).start(),
73
+ );
74
+ }, [data]);
75
+
76
+ return (
77
+ <Svg height={radius * 2 + strokeWidth} width={radius * 2 + strokeWidth}>
78
+ {total ? (
79
+ <>
80
+ <Defs>
81
+ {data.map((item, index) => {
82
+ return (
83
+ <RadialGradient
84
+ key={index + ''}
85
+ id={'grad' + index}
86
+ cx="50%"
87
+ cy="50%"
88
+ rx="50%"
89
+ ry="50%"
90
+ fx="50%"
91
+ fy="50%"
92
+ gradientUnits="userSpaceOnUse">
93
+ <Stop
94
+ offset="0%"
95
+ stopColor={item.gradientCenterColor}
96
+ stopOpacity="1"
97
+ />
98
+ <Stop
99
+ offset="100%"
100
+ stopColor={item.color || pieColors[index % 9]}
101
+ stopOpacity="1"
102
+ />
103
+ </RadialGradient>
104
+ );
105
+ })}
106
+ </Defs>
107
+ {data.map((item, index) => {
108
+ const borderWidth = item.strokeWidth ?? strokeWidth;
109
+ const borderColor =
110
+ item.strokeColor ??
111
+ props.strokeColor ??
112
+ (borderWidth ? 'black' : 'transparent');
113
+ return (
114
+ <AnimatedPath
115
+ key={`path${index}`}
116
+ id="renderPath"
117
+ d={isAnimated ? animatedPaths[index] : dFinal[index]}
118
+ fill={
119
+ showGradient
120
+ ? `url(#grad${index})`
121
+ : data[index].color || pieColors[index % 9]
122
+ }
123
+ strokeWidth={borderWidth}
124
+ stroke={borderColor}
125
+ />
126
+ );
127
+ })}
128
+
129
+ {donut
130
+ ? data.map((item, index) => {
131
+ if (
132
+ curvedStartEdges ||
133
+ edgesRadius ||
134
+ item.isStartEdgeCurved ||
135
+ item.startEdgeRadius
136
+ )
137
+ return (
138
+ <AnimatedPath
139
+ key={`cap${index}`}
140
+ d={`${initial} ${getStartCaps(index, item)}`}
141
+ opacity={isAnimated ? animatedOpacity : 1}
142
+ fill={
143
+ showGradient
144
+ ? `url(#grad${index})`
145
+ : data[index].color || pieColors[index % 9]
146
+ }
147
+ />
148
+ );
149
+ return null;
150
+ })
151
+ : null}
152
+
153
+ {donut
154
+ ? data.map((item, index) => {
155
+ if (
156
+ curvedEndEdges ||
157
+ edgesRadius ||
158
+ item.isEndEdgeCurved ||
159
+ item.endEdgeRadius
160
+ )
161
+ return (
162
+ <Path
163
+ key={`cap${index}`}
164
+ d={`${initial} ${getEndCaps(index, item)}`}
165
+ fill={
166
+ showGradient
167
+ ? `url(#grad${index})`
168
+ : data[index].color || pieColors[index % 9]
169
+ }
170
+ />
171
+ );
172
+ return null;
173
+ })
174
+ : null}
175
+
176
+ {data.map((item, index) => {
177
+ const {x, y} = getTextCoordinates(index, item.labelPosition);
178
+
179
+ return (
180
+ <AnimatedText
181
+ key={`label${index}`}
182
+ // style={{ pointerEvents: 'all' }}
183
+ fill={
184
+ item.textColor ||
185
+ props.textColor ||
186
+ pieColors[(index + 2) % 9]
187
+ }
188
+ opacity={isAnimated ? animatedOpacity : 1}
189
+ fontSize={item.textSize || props.textSize}
190
+ fontFamily={item.font || props.font}
191
+ fontWeight={item.fontWeight || props.fontWeight}
192
+ fontStyle={item.fontStyle || props.fontStyle || 'normal'}
193
+ x={
194
+ x +
195
+ (item.shiftTextX || 0) -
196
+ (item.textSize ?? props.textSize ?? 0) / 1.8
197
+ }
198
+ y={y + (item.shiftTextY || 0)}
199
+ onPress={() => {
200
+ item.onLabelPress
201
+ ? item.onLabelPress()
202
+ : props.onLabelPress
203
+ ? props.onLabelPress(item, index)
204
+ : item.onPress
205
+ ? item.onPress()
206
+ : props.onPress?.(item, index);
207
+ }}>
208
+ {item.text || (props.showValuesAsLabels ? item.value + '' : '')}
209
+ </AnimatedText>
210
+ );
211
+ })}
212
+ </>
213
+ ) : null}
214
+ </Svg>
215
+ );
216
+ };
@@ -14,6 +14,7 @@ import {
14
14
  Text as SvgText,
15
15
  Use,
16
16
  } from 'react-native-svg';
17
+ import {screenWidth} from '../utils';
17
18
 
18
19
  export const PopulationPyramid = (props: PopulationPyramidPropsType) => {
19
20
  const {
@@ -105,7 +106,7 @@ export const PopulationPyramid = (props: PopulationPyramidPropsType) => {
105
106
  verticalLinesCommonProps,
106
107
  xAxisLabelsCommonProps,
107
108
  getXLabel,
108
- } = usePopulationPyramid(props);
109
+ } = usePopulationPyramid({...props, screenWidth});
109
110
 
110
111
  return (
111
112
  <View style={{height: containerHeightWithXaxisLabels, width}}>
package/src/index.tsx CHANGED
@@ -1,5 +1,6 @@
1
1
  export {BarChart} from './BarChart';
2
2
  export {PieChart} from './PieChart';
3
+ export {PieChartPro} from './PieChartPro';
3
4
  export {LineChart} from './LineChart';
4
5
  export {LineChartBicolor} from './LineChart/LineChartBicolor';
5
6
  export {PopulationPyramid} from './PopulationPyramid';
@@ -0,0 +1,16 @@
1
+ import {Dimensions} from 'react-native';
2
+
3
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
4
+ const versionString = require('react-native/package.json').version;
5
+
6
+ const versionAr = versionString?.split?.('.') ?? '';
7
+ const msb = Number(versionAr[0]);
8
+ const mid = Number(versionAr[1]);
9
+ const lsb = Number(versionAr[2]);
10
+
11
+ export const rnVersion =
12
+ (!isNaN(msb) ? msb : 0) * 1000000 +
13
+ (!isNaN(mid) ? mid : 0) * 10000 +
14
+ (!isNaN(lsb) ? lsb : 0);
15
+
16
+ export const screenWidth = Dimensions.get('window').width;