Skip to content

Commit 008f3b1

Browse files
author
Peter Piekarczyk
committed
add better prop support, small animation effect to fade in, better readme
1 parent d65c531 commit 008f3b1

File tree

1 file changed

+128
-69
lines changed

1 file changed

+128
-69
lines changed

src/index.js

Lines changed: 128 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
1-
// @flow
2-
3-
import React, { PureComponent } from 'react';
4-
import PropTypes from 'prop-types';
5-
import type { StyleObj } from 'react-native/Libraries/StyleSheet/StyleSheetTypes';
6-
import { View, Text, Image, StyleSheet } from 'react-native';
1+
import React, { PureComponent } from 'react'
2+
import PropTypes from 'prop-types'
3+
import { View, Text, Image, StyleSheet, Animated } from 'react-native'
74

85
const styles = StyleSheet.create({
96
container: {
@@ -14,61 +11,94 @@ const styles = StyleSheet.create({
1411
alignSelf: 'center'
1512
},
1613
circle: {
17-
width: 20,
18-
height: 20,
19-
borderRadius: 10,
2014
marginBottom: 20
2115
},
22-
avatarContainer: {
23-
width: 40,
24-
height: 40,
25-
borderRadius: 20,
26-
borderColor: 'white',
27-
borderWidth: 1.5,
28-
borderStyle: 'solid'
29-
},
30-
avatar: {
31-
width: 40,
32-
height: 40,
33-
borderRadius: 20
16+
circleImage: {
17+
borderWidth: 2,
18+
borderColor: 'white'
3419
},
35-
extra: {
20+
overflow: {
3621
backgroundColor: '#b6c0ca',
3722
justifyContent: 'center',
3823
alignItems: 'center',
39-
marginLeft: 9
24+
marginLeft: 5
4025
},
41-
extraLabel: {
42-
color: '#333',
43-
fontSize: 12
26+
overflowLabel: {
27+
color: '#fff',
28+
fontSize: 14,
29+
letterSpacing: -1,
30+
marginLeft: 3,
31+
fontWeight: 'bold'
4432
}
45-
});
33+
})
4634

47-
type Face = {
48-
imageUrl: string,
49-
id?: string
50-
};
35+
class Circle extends PureComponent {
36+
state = {
37+
fadeAnim: new Animated.Value(0)
38+
}
39+
40+
componentDidMount () {
41+
const { delay } = this.props
42+
Animated.timing(this.state.fadeAnim, {
43+
toValue: 1,
44+
duration: 1000,
45+
delay
46+
}).start()
47+
}
5148

52-
type FacePileType = {
53-
faces: Array<Face>,
54-
overflow: number,
55-
containerStyle?: StyleObj
56-
};
49+
render () {
50+
const { fadeAnim } = this.state
51+
const { circleStyle, imageStyle, circleSize, face } = this.props
52+
53+
const borderRadius = circleSize / 2
54+
const innerCircleSize = circleSize * 2
55+
return (
56+
<Animated.View
57+
style={[
58+
styles.circle,
59+
{
60+
width: circleSize,
61+
height: circleSize,
62+
borderRadius: borderRadius,
63+
opacity: fadeAnim
64+
},
65+
circleStyle
66+
]}
67+
>
68+
<Image
69+
style={[
70+
styles.circleImage,
71+
{
72+
width: innerCircleSize,
73+
height: innerCircleSize,
74+
borderRadius: circleSize
75+
},
76+
imageStyle
77+
]}
78+
source={{ uri: face.imageUrl }}
79+
resizeMode='contain'
80+
/>
81+
</Animated.View>
82+
)
83+
}
84+
}
5785

58-
class FacePile extends PureComponent {
86+
export default class FacePile extends PureComponent {
5987
static propTypes = {
6088
faces: PropTypes.shape({
6189
imageUrl: PropTypes.string
6290
}),
91+
circleSize: PropTypes.number,
6392
overflow: PropTypes.number,
64-
circleHeight: PropTypes.number,
65-
circleWidth: PropTypes.number,
66-
containerStyle: PropTypes.style,
67-
circleStyle: PropTypes.style,
68-
overflowStyle: PropTypes.styles
69-
};
93+
containerStyle: PropTypes.instanceOf(StyleSheet),
94+
circleStyle: PropTypes.instanceOf(StyleSheet),
95+
imageStyle: PropTypes.instanceOf(StyleSheet),
96+
overflowStyle: PropTypes.instanceOf(StyleSheet),
97+
overflowLabelStyle: PropTypes.instanceOf(StyleSheet)
98+
}
7099

71100
static defaultProps = {
101+
circleSize: 20,
72102
faces: [
73103
{
74104
imageUrl: 'https://lorempixel.com/200/200/people'
@@ -84,46 +114,75 @@ class FacePile extends PureComponent {
84114
}
85115
],
86116
overflow: 8
87-
};
117+
}
88118

89119
_renderOverflowCircle = overflow => {
90-
const { overflowStyle } = this.props;
120+
const {
121+
circleStyle,
122+
overflowStyle,
123+
overflowLabelStyle,
124+
circleSize
125+
} = this.props
126+
const innerCircleSize = circleSize * 2
127+
91128
return (
92-
<View style={styles.circle}>
93-
<View style={[styles.avatar, styles.extra, overflowStyle]}>
94-
<Text style={styles.extraLabel}>
129+
<View
130+
style={[
131+
styles.circle,
132+
{ width: circleSize, height: circleSize },
133+
circleStyle
134+
]}
135+
>
136+
<View
137+
style={[
138+
styles.overflow,
139+
{
140+
width: innerCircleSize,
141+
height: innerCircleSize,
142+
borderRadius: circleSize
143+
},
144+
overflowStyle
145+
]}
146+
>
147+
<Text
148+
style={[
149+
styles.overflowLabel,
150+
{
151+
fontSize: circleSize * 0.7
152+
},
153+
overflowLabelStyle
154+
]}
155+
>
95156
+{overflow}
96157
</Text>
97158
</View>
98159
</View>
99-
);
100-
};
160+
)
161+
}
162+
163+
_renderFace = (face, index, arr) => {
164+
const { circleStyle, imageStyle, circleSize } = this.props
165+
if (!face.imageUrl) return null
101166

102-
_renderFace = face => {
103-
const { circleStyle, circleHeight, circleWidth } = this.props
104-
if (!face.imageUrl) return null;
105167
return (
106-
<View key={face.id || index} style={styles.circle}>
107-
<View style={[styles.avatarContainer, circleStyle, { width: circleWidth, height: circleHeight }]}>
108-
<Image
109-
style={[styles.avatar, { width: circleWidth / 2, height: circleHeight / 2}]}
110-
source={{ uri: face.imageUrl }}
111-
resizeMode="contain"
112-
/>
113-
</View>
114-
</View>
115-
);
116-
};
168+
<Circle
169+
key={face.id || index}
170+
delay={(arr.length - index) * 2}
171+
face={face}
172+
circleStyle={circleStyle}
173+
imageStyle={imageStyle}
174+
circleSize={circleSize}
175+
/>
176+
)
177+
}
117178

118-
render() {
119-
const { faces, overflow, containerStyle } = this.props;
179+
render () {
180+
const { faces, overflow, containerStyle } = this.props
120181
return (
121182
<View style={[styles.container, containerStyle]}>
122183
{this._renderOverflowCircle(overflow)}
123184
{faces.map(this._renderFace)}
124185
</View>
125-
);
186+
)
126187
}
127188
}
128-
129-
export default FacePile;

0 commit comments

Comments
 (0)