react-native-gifted-charts 1.4.7 → 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.7",
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.21"
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,
@@ -32,6 +33,7 @@ import {
32
33
  LineSvgProps,
33
34
  useLineChart,
34
35
  adjustToOffset,
36
+ LineProperties,
35
37
  } from 'gifted-charts-core';
36
38
  import BarAndLineChartsWrapper from '../Components/BarAndLineChartsWrapper';
37
39
  import {StripAndLabel} from '../Components/common/StripAndLabel';
@@ -43,6 +45,7 @@ let animations: Array<Animated.Value> = [];
43
45
  export const LineChart = (props: LineChartPropsType) => {
44
46
  const scrollRef = props.scrollRef ?? useRef(null);
45
47
  const opacValue = useMemo(() => new Animated.Value(0), []);
48
+ const heightValue = useMemo(() => new Animated.Value(0), []);
46
49
  const widthValue = useMemo(() => new Animated.Value(0), []);
47
50
  const widthValue2 = useMemo(() => new Animated.Value(0), []);
48
51
  const widthValue3 = useMemo(() => new Animated.Value(0), []);
@@ -164,7 +167,7 @@ export const LineChart = (props: LineChartPropsType) => {
164
167
  dataPointsRadius5,
165
168
  dataPointsColor5,
166
169
  dataPointsShape5,
167
- atLeastOneAreaChart,
170
+ getIsNthAreaChart,
168
171
  textFontSize1,
169
172
  textFontSize2,
170
173
  textFontSize3,
@@ -299,7 +302,7 @@ export const LineChart = (props: LineChartPropsType) => {
299
302
  lineGradientStartColor,
300
303
  lineGradientEndColor,
301
304
  barAndLineChartsWrapperProps,
302
- } = useLineChart({...props, animations});
305
+ } = useLineChart({...props, animations, screenWidth});
303
306
 
304
307
  const widthValuesFromSet = useMemo(
305
308
  () => dataSet?.map(set => new Animated.Value(0)),
@@ -890,7 +893,7 @@ export const LineChart = (props: LineChartPropsType) => {
890
893
 
891
894
  return Pointer({
892
895
  pointerX,
893
- pointerYLocal,
896
+ pointerYLocal: pointerYLocal + xAxisThickness,
894
897
  pointerComponent,
895
898
  pointerHeight,
896
899
  pointerRadius,
@@ -1014,17 +1017,19 @@ export const LineChart = (props: LineChartPropsType) => {
1014
1017
  arrowStrokeWidth,
1015
1018
  arrowStrokeColor,
1016
1019
  arrowFillColor,
1020
+ key,
1017
1021
  ) => {
1018
1022
  if (!points) return null;
1019
1023
  const isCurved = points.includes('C');
1020
- let ar: [any] = [{}];
1024
+ const isNthAreaChart = getIsNthAreaChart(key ?? 0);
1025
+ let ar: LineProperties[] = [{d: '', color: '', strokeWidth: 0}];
1021
1026
  if (points.includes(RANGE_ENTER)) {
1022
1027
  ar = getRegionPathObjects(
1023
1028
  points,
1024
1029
  color,
1025
- currentLineThickness,
1030
+ currentLineThickness ?? 0,
1026
1031
  thickness,
1027
- strokeDashArray,
1032
+ strokeDashArray ?? [],
1028
1033
  isCurved,
1029
1034
  RANGE_ENTER,
1030
1035
  STOP,
@@ -1034,9 +1039,9 @@ export const LineChart = (props: LineChartPropsType) => {
1034
1039
  ar = getSegmentedPathObjects(
1035
1040
  points,
1036
1041
  color,
1037
- currentLineThickness,
1042
+ currentLineThickness ?? 0,
1038
1043
  thickness,
1039
- strokeDashArray,
1044
+ strokeDashArray ?? [],
1040
1045
  isCurved,
1041
1046
  SEGMENT_START,
1042
1047
  SEGMENT_END,
@@ -1091,14 +1096,14 @@ export const LineChart = (props: LineChartPropsType) => {
1091
1096
 
1092
1097
  {/*********************** For Area Chart ************/}
1093
1098
 
1094
- {atLeastOneAreaChart &&
1099
+ {isNthAreaChart &&
1095
1100
  getAreaGradientComponent(
1096
1101
  startFillColor,
1097
1102
  endFillColor,
1098
1103
  startOpacity,
1099
1104
  endOpacity,
1100
1105
  )}
1101
- {atLeastOneAreaChart && (
1106
+ {isNthAreaChart && (
1102
1107
  <Path
1103
1108
  d={fillPoints}
1104
1109
  fill={
@@ -1250,6 +1255,89 @@ export const LineChart = (props: LineChartPropsType) => {
1250
1255
  );
1251
1256
  };
1252
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
+
1253
1341
  const renderLine = (
1254
1342
  zIndex: number,
1255
1343
  points: any,
@@ -1271,7 +1359,6 @@ export const LineChart = (props: LineChartPropsType) => {
1271
1359
  return (
1272
1360
  <View
1273
1361
  key={key ?? 0}
1274
- onStartShouldSetResponder={evt => (pointerConfig ? true : false)}
1275
1362
  onMoveShouldSetResponder={evt => (pointerConfig ? true : false)}
1276
1363
  onResponderGrant={evt => {
1277
1364
  if (!pointerConfig) return;
@@ -1280,91 +1367,7 @@ export const LineChart = (props: LineChartPropsType) => {
1280
1367
  return;
1281
1368
  }
1282
1369
  let x = evt.nativeEvent.locationX;
1283
- if (
1284
- !activatePointersOnLongPress &&
1285
- x > (props.width || Dimensions.get('window').width)
1286
- )
1287
- return;
1288
- let factor = (x - initialSpacing) / spacing;
1289
- factor = Math.round(factor);
1290
- factor = Math.min(factor, (data0 ?? data).length - 1);
1291
- factor = Math.max(factor, 0);
1292
- let z =
1293
- initialSpacing +
1294
- spacing * factor -
1295
- (pointerRadius || pointerWidth / 2) -
1296
- 1;
1297
- setPointerX(z);
1298
- setPointerIndex(factor);
1299
- let item, y;
1300
- item = (data0 ?? data)[factor];
1301
- y =
1302
- containerHeight -
1303
- (item.value * containerHeight) / maxValue -
1304
- (pointerRadius || pointerHeight / 2) +
1305
- 10;
1306
- setPointerY(y);
1307
- setPointerItem(item);
1308
- if (data2 && data2.length) {
1309
- item = data2[factor];
1310
- if (item) {
1311
- y =
1312
- containerHeight -
1313
- (item.value * containerHeight) / maxValue -
1314
- (pointerRadius || pointerHeight / 2) +
1315
- 10;
1316
- setPointerY2(y);
1317
- setPointerItem2(item);
1318
- }
1319
- }
1320
- if (data3 && data3.length) {
1321
- item = data3[factor];
1322
- if (item) {
1323
- y =
1324
- containerHeight -
1325
- (item.value * containerHeight) / maxValue -
1326
- (pointerRadius || pointerHeight / 2) +
1327
- 10;
1328
- setPointerY3(y);
1329
- setPointerItem3(item);
1330
- }
1331
- }
1332
- if (data4 && data4.length) {
1333
- item = data4[factor];
1334
- if (item) {
1335
- y =
1336
- containerHeight -
1337
- (item.value * containerHeight) / maxValue -
1338
- (pointerRadius || pointerHeight / 2) +
1339
- 10;
1340
- setPointerY4(y);
1341
- setPointerItem4(item);
1342
- }
1343
- }
1344
- if (data5 && data5.length) {
1345
- item = data5[factor];
1346
- if (item) {
1347
- y =
1348
- containerHeight -
1349
- (item.value * containerHeight) / maxValue -
1350
- (pointerRadius || pointerHeight / 2) +
1351
- 10;
1352
- setPointerY5(y);
1353
- setPointerItem5(item);
1354
- }
1355
- }
1356
- if (secondaryData?.length) {
1357
- item = secondaryData[factor];
1358
- if (item) {
1359
- y =
1360
- containerHeight -
1361
- (item.value * containerHeight) / maxValue -
1362
- (pointerRadius || pointerHeight / 2) +
1363
- 10;
1364
- setSecondaryPointerY(y);
1365
- setSecondaryPointerItem(item);
1366
- }
1367
- }
1370
+ activatePointers(x);
1368
1371
  }}
1369
1372
  onResponderMove={evt => {
1370
1373
  if (!pointerConfig) return;
@@ -1492,6 +1495,7 @@ export const LineChart = (props: LineChartPropsType) => {
1492
1495
  60 +
1493
1496
  xAxisLabelsVerticalShift +
1494
1497
  labelsExtraHeight -
1498
+ xAxisThickness -
1495
1499
  (props.overflowBottom ?? dataPointsRadius1),
1496
1500
  zIndex: zIndex,
1497
1501
  transform: [{scaleX: I18nManager.isRTL ? -1 : 1}],
@@ -1512,6 +1516,7 @@ export const LineChart = (props: LineChartPropsType) => {
1512
1516
  arrowStrokeWidth,
1513
1517
  arrowStrokeColor,
1514
1518
  arrowFillColor,
1519
+ key,
1515
1520
  )}
1516
1521
  </View>
1517
1522
  );
@@ -1548,91 +1553,7 @@ export const LineChart = (props: LineChartPropsType) => {
1548
1553
  return;
1549
1554
  }
1550
1555
  let x = evt.nativeEvent.locationX;
1551
- if (
1552
- !activatePointersOnLongPress &&
1553
- x > (props.width || Dimensions.get('window').width)
1554
- )
1555
- return;
1556
- let factor = (x - initialSpacing) / spacing;
1557
- factor = Math.round(factor);
1558
- factor = Math.min(factor, (data0 ?? data).length - 1);
1559
- factor = Math.max(factor, 0);
1560
- let z =
1561
- initialSpacing +
1562
- spacing * factor -
1563
- (pointerRadius || pointerWidth / 2) -
1564
- 1;
1565
- setPointerX(z);
1566
- setPointerIndex(factor);
1567
- let item, y;
1568
- item = (data0 ?? data)[factor];
1569
- y =
1570
- containerHeight -
1571
- (item.value * containerHeight) / maxValue -
1572
- (pointerRadius || pointerHeight / 2) +
1573
- 10;
1574
- setPointerY(y);
1575
- setPointerItem(item);
1576
- if (data2 && data2.length) {
1577
- item = data2[factor];
1578
- if (item) {
1579
- y =
1580
- containerHeight -
1581
- (item.value * containerHeight) / maxValue -
1582
- (pointerRadius || pointerHeight / 2) +
1583
- 10;
1584
- setPointerY2(y);
1585
- setPointerItem2(item);
1586
- }
1587
- }
1588
- if (data3 && data3.length) {
1589
- item = data3[factor];
1590
- if (item) {
1591
- y =
1592
- containerHeight -
1593
- (item.value * containerHeight) / maxValue -
1594
- (pointerRadius || pointerHeight / 2) +
1595
- 10;
1596
- setPointerY3(y);
1597
- setPointerItem3(item);
1598
- }
1599
- }
1600
- if (data4 && data4.length) {
1601
- item = data4[factor];
1602
- if (item) {
1603
- y =
1604
- containerHeight -
1605
- (item.value * containerHeight) / maxValue -
1606
- (pointerRadius || pointerHeight / 2) +
1607
- 10;
1608
- setPointerY4(y);
1609
- setPointerItem4(item);
1610
- }
1611
- }
1612
- if (data5 && data5.length) {
1613
- item = data5[factor];
1614
- if (item) {
1615
- y =
1616
- containerHeight -
1617
- (item.value * containerHeight) / maxValue -
1618
- (pointerRadius || pointerHeight / 2) +
1619
- 10;
1620
- setPointerY5(y);
1621
- setPointerItem5(item);
1622
- }
1623
- }
1624
- if (secondaryData?.length) {
1625
- item = secondaryData[factor];
1626
- if (item) {
1627
- y =
1628
- containerHeight -
1629
- (item.value * containerHeight) / maxValue -
1630
- (pointerRadius || pointerHeight / 2) +
1631
- 10;
1632
- setSecondaryPointerY(y);
1633
- setSecondaryPointerItem(item);
1634
- }
1635
- }
1556
+ activatePointers(x);
1636
1557
  }}
1637
1558
  onResponderMove={evt => {
1638
1559
  if (!pointerConfig) return;
@@ -1760,6 +1681,7 @@ export const LineChart = (props: LineChartPropsType) => {
1760
1681
  60 +
1761
1682
  xAxisLabelsVerticalShift +
1762
1683
  labelsExtraHeight -
1684
+ xAxisThickness -
1763
1685
  (props.overflowBottom ?? dataPointsRadius1),
1764
1686
  zIndex: zIndex,
1765
1687
  transform: [{scaleX: I18nManager.isRTL ? -1 : 1}],
@@ -1780,6 +1702,7 @@ export const LineChart = (props: LineChartPropsType) => {
1780
1702
  arrowStrokeWidth,
1781
1703
  arrowStrokeColor,
1782
1704
  arrowFillColor,
1705
+ key,
1783
1706
  )}
1784
1707
  </Animated.View>
1785
1708
  );
@@ -1819,9 +1742,9 @@ export const LineChart = (props: LineChartPropsType) => {
1819
1742
  set.strokeDashArray ?? strokeDashArray1,
1820
1743
  set.showArrow || props.showArrows,
1821
1744
  arrowPointsFromSet[index],
1822
- arrowStrokeWidthsFromSet[index],
1823
- arrowStrokeColorsFromSet[index],
1824
- arrowFillColorsFromSet[index],
1745
+ arrowStrokeWidthsFromSet?.[index],
1746
+ arrowStrokeColorsFromSet?.[index],
1747
+ arrowFillColorsFromSet?.[index],
1825
1748
  index,
1826
1749
  );
1827
1750
  } else {
@@ -1838,9 +1761,9 @@ export const LineChart = (props: LineChartPropsType) => {
1838
1761
  set.strokeDashArray ?? strokeDashArray1,
1839
1762
  set.showArrow || props.showArrows,
1840
1763
  arrowPointsFromSet[index],
1841
- arrowStrokeWidthsFromSet[index],
1842
- arrowStrokeColorsFromSet[index],
1843
- arrowFillColorsFromSet[index],
1764
+ arrowStrokeWidthsFromSet?.[index],
1765
+ arrowStrokeColorsFromSet?.[index],
1766
+ arrowFillColorsFromSet?.[index],
1844
1767
  index,
1845
1768
  );
1846
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;