@chainplatform/charts 0.0.2 → 0.0.4

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chainplatform/charts",
3
- "version": "0.0.2",
3
+ "version": "0.0.4",
4
4
  "description": "Reusable React Native charts for Chain Platform.",
5
5
  "main": "src/index.js",
6
6
  "devDependencies": {
package/src/DonutChart.js CHANGED
@@ -13,6 +13,7 @@ class DonutChart extends PureComponent {
13
13
  label: PropTypes.string,
14
14
  value: PropTypes.number,
15
15
  color: PropTypes.string,
16
+ total: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
16
17
  })
17
18
  ).isRequired,
18
19
  size: PropTypes.number,
@@ -50,15 +51,11 @@ class DonutChart extends PureComponent {
50
51
 
51
52
  constructor(props) {
52
53
  super(props);
53
-
54
- this.state = {
55
- tooltip: null,
56
- };
54
+ this.state = { tooltip: null };
57
55
  }
58
56
 
59
57
  polarToCartesian = (cx, cy, radius, angle) => {
60
58
  const rad = ((angle - 90) * Math.PI) / 180;
61
-
62
59
  return {
63
60
  x: cx + radius * Math.cos(rad),
64
61
  y: cy + radius * Math.sin(rad),
@@ -68,7 +65,6 @@ class DonutChart extends PureComponent {
68
65
  describeArc = (cx, cy, radius, startAngle, endAngle) => {
69
66
  const start = this.polarToCartesian(cx, cy, radius, endAngle);
70
67
  const end = this.polarToCartesian(cx, cy, radius, startAngle);
71
-
72
68
  const largeArcFlag = endAngle - startAngle <= 180 ? '0' : '1';
73
69
 
74
70
  return [
@@ -92,8 +88,8 @@ class DonutChart extends PureComponent {
92
88
  x: point.x,
93
89
  y: point.y,
94
90
  label: item.label,
95
- value: item.total,
96
- percent: item.value,
91
+ value: item.total ?? item.value,
92
+ percent,
97
93
  color: item.color,
98
94
  },
99
95
  });
@@ -101,6 +97,45 @@ class DonutChart extends PureComponent {
101
97
 
102
98
  hideTooltip = () => { this.setState({ tooltip: null }); };
103
99
 
100
+ renderSegment = ({ item, index, center, radius, strokeWidth, segmentStartAngle, segmentEndAngle, sweepAngle, roundedPercent, percentPoint, arcPath }) => {
101
+ const eventProps = {
102
+ onPress: Platform.OS !== 'web' && this.props.enableTooltip ? () => this.showTooltip(item, roundedPercent, percentPoint) : undefined,
103
+ onPressOut: Platform.OS !== 'web' ? this.hideTooltip : undefined,
104
+ onMouseEnter: Platform.OS === 'web' && this.props.enableTooltip ? () => this.showTooltip(item, roundedPercent, percentPoint) : undefined,
105
+ onMouseLeave: Platform.OS === 'web' ? this.hideTooltip : undefined,
106
+ };
107
+
108
+ if (sweepAngle >= 359.99) {
109
+ return (
110
+ <Circle
111
+ key={`segment-full-${index}`}
112
+ cx={center}
113
+ cy={center}
114
+ r={radius}
115
+ stroke={item.color}
116
+ strokeWidth={strokeWidth}
117
+ fill="transparent"
118
+ strokeLinecap="butt"
119
+ {...eventProps}
120
+ />
121
+ );
122
+ }
123
+
124
+ if (segmentEndAngle <= segmentStartAngle) return null;
125
+
126
+ return (
127
+ <Path
128
+ key={`segment-path-${index}`}
129
+ d={arcPath}
130
+ stroke={item.color}
131
+ strokeWidth={strokeWidth}
132
+ fill="transparent"
133
+ strokeLinecap="butt"
134
+ {...eventProps}
135
+ />
136
+ );
137
+ };
138
+
104
139
  render() {
105
140
  const {
106
141
  data,
@@ -124,16 +159,11 @@ class DonutChart extends PureComponent {
124
159
 
125
160
  if (!data?.length) return null;
126
161
 
127
- const validData = data.filter(
128
- item => item?.value && item.value > 0
129
- );
162
+ const validData = data.filter(item => Number(item?.value) > 0);
130
163
 
131
164
  if (!validData.length) return null;
132
165
 
133
- const total = validData.reduce(
134
- (sum, item) => sum + item.value,
135
- 0
136
- );
166
+ const total = validData.reduce((sum, item) => sum + Number(item.value || 0), 0);
137
167
 
138
168
  if (total <= 0) return null;
139
169
 
@@ -148,108 +178,46 @@ class DonutChart extends PureComponent {
148
178
  <Circle cx={center} cy={center} r={radius} stroke={backgroundColor} strokeWidth={strokeWidth} fill="transparent" />
149
179
 
150
180
  {validData.map((item, index) => {
151
- const percent = item.value / total;
181
+ const value = Number(item.value || 0);
182
+ const percent = value / total;
152
183
  const sweepAngle = percent * 360;
153
-
154
- const segmentStartAngle = currentAngle + segmentGap / 2;
155
-
156
- const segmentEndAngle = currentAngle + sweepAngle - segmentGap / 2;
157
-
184
+ const isFullCircle = sweepAngle >= 359.99;
185
+ const gap = isFullCircle ? 0 : segmentGap;
186
+ const segmentStartAngle = currentAngle + gap / 2;
187
+ const segmentEndAngle = currentAngle + sweepAngle - gap / 2;
158
188
  const middleAngle = currentAngle + sweepAngle / 2;
159
189
 
160
190
  currentAngle += sweepAngle;
161
191
 
162
- if (segmentEndAngle <= segmentStartAngle) {
163
- return null;
164
- }
165
-
166
- const arcPath = this.describeArc(
167
- center,
168
- center,
169
- radius,
170
- segmentStartAngle,
171
- segmentEndAngle
172
- );
173
-
174
- const percentPoint = this.polarToCartesian(
175
- center,
176
- center,
177
- radius,
178
- middleAngle
179
- );
180
-
181
- const innerPoint = this.polarToCartesian(
182
- center,
183
- center,
184
- radius - strokeWidth / 2 - innerOffset,
185
- middleAngle
186
- );
187
-
192
+ const arcPath = this.describeArc(center, center, radius, segmentStartAngle, segmentEndAngle);
193
+ const percentPoint = this.polarToCartesian(center, center, radius, middleAngle);
194
+ const innerPoint = this.polarToCartesian(center, center, radius - strokeWidth / 2 - innerOffset, middleAngle);
188
195
  const roundedPercent = Math.round(percent * 100);
189
196
 
190
197
  return (
191
198
  <React.Fragment key={`segment-${index}`}>
192
- <Path
193
- d={arcPath}
194
- stroke={item.color}
195
- strokeWidth={strokeWidth}
196
- fill="transparent"
197
- strokeLinecap="butt"
198
- onPress={
199
- Platform.OS !== 'web' && enableTooltip
200
- ? () =>
201
- this.showTooltip(
202
- item,
203
- roundedPercent,
204
- percentPoint
205
- )
206
- : undefined
207
- }
208
- onPressOut={
209
- Platform.OS !== 'web'
210
- ? this.hideTooltip
211
- : undefined
212
- }
213
- onMouseEnter={
214
- Platform.OS === 'web' && enableTooltip
215
- ? () =>
216
- this.showTooltip(
217
- item,
218
- roundedPercent,
219
- percentPoint
220
- )
221
- : undefined
222
- }
223
- onMouseLeave={
224
- Platform.OS === 'web'
225
- ? this.hideTooltip
226
- : undefined
227
- }
228
- />
199
+ {this.renderSegment({
200
+ item,
201
+ index,
202
+ center,
203
+ radius,
204
+ strokeWidth,
205
+ segmentStartAngle,
206
+ segmentEndAngle,
207
+ sweepAngle,
208
+ roundedPercent,
209
+ percentPoint,
210
+ arcPath,
211
+ })}
229
212
 
230
213
  {showPercent && (
231
- <SvgText
232
- x={percentPoint.x}
233
- y={percentPoint.y}
234
- fill={percentColor}
235
- fontSize={percentFontSize}
236
- fontWeight="600"
237
- textAnchor="middle"
238
- alignmentBaseline="middle"
239
- >
214
+ <SvgText x={percentPoint.x} y={percentPoint.y} fill={percentColor} fontSize={percentFontSize} fontWeight="600" textAnchor="middle" alignmentBaseline="middle">
240
215
  {`${roundedPercent}%`}
241
216
  </SvgText>
242
217
  )}
243
218
 
244
- {showInnerLabels && (
245
- <SvgText
246
- x={innerPoint.x}
247
- y={innerPoint.y}
248
- fill={item.color}
249
- fontSize={labelFontSize}
250
- textAnchor="middle"
251
- alignmentBaseline="middle"
252
- >
219
+ {showInnerLabels && !!item.label && (
220
+ <SvgText x={innerPoint.x} y={innerPoint.y} fill={item.color} fontSize={labelFontSize} textAnchor="middle" alignmentBaseline="middle">
253
221
  {item.label}
254
222
  </SvgText>
255
223
  )}
@@ -258,15 +226,7 @@ class DonutChart extends PureComponent {
258
226
  })}
259
227
 
260
228
  {!!centerContent && (
261
- <SvgText
262
- x={center}
263
- y={center}
264
- fontSize={contentFontSize}
265
- fontWeight="600"
266
- fill="#333"
267
- textAnchor="middle"
268
- alignmentBaseline="middle"
269
- >
229
+ <SvgText x={center} y={center} fontSize={contentFontSize} fontWeight="600" fill="#333" textAnchor="middle" alignmentBaseline="middle">
270
230
  {centerContent}
271
231
  </SvgText>
272
232
  )}
package/src/LineChart.js CHANGED
@@ -31,7 +31,7 @@ class LineChart extends PureComponent {
31
31
  };
32
32
 
33
33
  render() {
34
- const { enableTooltip, data, width, height, strokeColor, strokeWidth, showDots, dotRadius, touchRadius, paddingHorizontal, paddingVertical, backgroundColor } = this.props;
34
+ const { enableTooltip, data, width, height, fillColor, strokeColor, strokeWidth, showDots, dotRadius, touchRadius, paddingHorizontal, paddingVertical, backgroundColor } = this.props;
35
35
  const { tooltip } = this.state;
36
36
 
37
37
  if (!data?.length) return null;
@@ -66,7 +66,7 @@ class LineChart extends PureComponent {
66
66
 
67
67
  {points.map((point, index) => (
68
68
  <React.Fragment key={`point-${index}`}>
69
- {showDots && <Circle cx={point.x} cy={point.y} r={dotRadius} fill="#fff" stroke={strokeColor} strokeWidth={setSize(2)} />}
69
+ {showDots && <Circle cx={point.x} cy={point.y} r={dotRadius} fill={fillColor} stroke={strokeColor} strokeWidth={setSize(2)} />}
70
70
  <Circle
71
71
  cx={point.x}
72
72
  cy={point.y}
@@ -93,6 +93,7 @@ LineChart.propTypes = {
93
93
  width: PropTypes.number,
94
94
  height: PropTypes.number,
95
95
  strokeColor: PropTypes.string,
96
+ fillColor: PropTypes.string,
96
97
  strokeWidth: PropTypes.number,
97
98
  showDots: PropTypes.bool,
98
99
  dotRadius: PropTypes.number,
@@ -108,6 +109,7 @@ LineChart.defaultProps = {
108
109
  width: setSize(160),
109
110
  height: setSize(60),
110
111
  strokeColor: '#5B7CFA',
112
+ fillColor: '#FFFFFF',
111
113
  strokeWidth: setSize(2),
112
114
  showDots: true,
113
115
  dotRadius: setSize(3),