Skip to content

Commit d27d363

Browse files
committed
created Fumi
1 parent e2caf32 commit d27d363

File tree

3 files changed

+163
-0
lines changed

3 files changed

+163
-0
lines changed

Example/TextInputEffectsExample.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919
Kohana,
2020
Makiko,
2121
Sae,
22+
Fumi,
2223
} from 'react-native-textinput-effects';
2324

2425
export default class TextInputEffectsExample extends Component {
@@ -62,6 +63,13 @@ export default class TextInputEffectsExample extends Component {
6263
backgroundColor={'#F9F7F6'}
6364
borderColor={'#00ffaa'}
6465
/>
66+
<Fumi
67+
style={styles.input}
68+
label={'Degree'}
69+
iconClass={FontAwesomeIcon}
70+
iconName={'graduation-cap'}
71+
iconColor={'#00aeef'}
72+
/>
6573
<Jiro
6674
style={styles.input}
6775
label={'Cat\'s name'}

lib/Fumi.js

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
import React, { PropTypes, Component } from 'react';
2+
import {
3+
Animated,
4+
Text,
5+
TextInput,
6+
TouchableWithoutFeedback,
7+
View,
8+
StyleSheet,
9+
} from 'react-native';
10+
11+
import BaseInput from './BaseInput';
12+
13+
const PADDING = 16;
14+
const ICON_WIDTH = 40;
15+
16+
export default class Fumi extends BaseInput {
17+
18+
static propTypes = {
19+
/*
20+
* This is the icon component you are importing from react-native-vector-icons.
21+
* import FontAwesomeIcon from 'react-native-vector-icons/FontAwesome';
22+
* iconClass={FontAwesomeIcon}
23+
*/
24+
iconClass: PropTypes.func.isRequired,
25+
/*
26+
* Passed to react-native-vector-icons library as name prop
27+
*/
28+
iconName: PropTypes.string.isRequired,
29+
/*
30+
* Passed to react-native-vector-icons library as color prop.
31+
* Also used as textInput color.
32+
*/
33+
iconColor: PropTypes.string,
34+
height: PropTypes.number,
35+
};
36+
37+
static defaultProps = {
38+
height: 48,
39+
iconColor: '#00aeef',
40+
animationDuration: 300,
41+
};
42+
43+
render() {
44+
const {
45+
iconClass,
46+
iconColor,
47+
iconName,
48+
label,
49+
style: containerStyle,
50+
inputStyle,
51+
height: inputHeight,
52+
labelStyle,
53+
} = this.props;
54+
const { focusedAnim, value } = this.state;
55+
const AnimatedIcon = Animated.createAnimatedComponent(iconClass);
56+
const ANIM_PATH = PADDING + inputHeight;
57+
const NEGATIVE_ANIM_PATH = ANIM_PATH * -1;
58+
59+
return (
60+
<View style={[containerStyle, styles.container]} onLayout={this._onLayout}>
61+
<TouchableWithoutFeedback onPress={this._focus}>
62+
<AnimatedIcon
63+
name={iconName}
64+
color={iconColor}
65+
size={20}
66+
style={{
67+
position: 'absolute',
68+
left: PADDING,
69+
bottom: focusedAnim.interpolate({
70+
inputRange: [0, 0.5, 0.51, 0.7, 1],
71+
outputRange: [24, ANIM_PATH, NEGATIVE_ANIM_PATH, NEGATIVE_ANIM_PATH, 24],
72+
}),
73+
color: focusedAnim.interpolate({
74+
inputRange: [0, 0.5, 1],
75+
outputRange: ['#a3a3a3', iconColor, iconColor],
76+
}),
77+
}}
78+
/>
79+
</TouchableWithoutFeedback>
80+
<View
81+
style={[styles.separator, {
82+
height: inputHeight,
83+
left: ICON_WIDTH + 8,
84+
}]}
85+
/>
86+
<TouchableWithoutFeedback onPress={this._focus}>
87+
<Animated.View style={{
88+
position: 'absolute',
89+
left: ICON_WIDTH + PADDING,
90+
height: inputHeight,
91+
top: focusedAnim.interpolate({
92+
inputRange: [0, 0.5, 0.51, 0.7, 1],
93+
outputRange: [22, ANIM_PATH, NEGATIVE_ANIM_PATH, NEGATIVE_ANIM_PATH, 8],
94+
}),
95+
}}>
96+
<Animated.Text style={[styles.label, labelStyle, {
97+
fontSize: focusedAnim.interpolate({
98+
inputRange: [0, 0.7, 0.71, 1],
99+
outputRange: [16, 16, 12, 12],
100+
}),
101+
color: focusedAnim.interpolate({
102+
inputRange: [0, 0.7],
103+
outputRange: ['#696969', '#a3a3a3'],
104+
}),
105+
}]}>
106+
{label}
107+
</Animated.Text>
108+
</Animated.View>
109+
</TouchableWithoutFeedback>
110+
<TextInput
111+
ref="input"
112+
{...this.props}
113+
style={[styles.textInput, inputStyle, {
114+
marginLeft: ICON_WIDTH + PADDING,
115+
color: iconColor,
116+
marginBottom: PADDING * -1,
117+
}]}
118+
value={value}
119+
onBlur={this._onBlur}
120+
onFocus={this._onFocus}
121+
onChange={this._onChange}
122+
/>
123+
</View>
124+
);
125+
}
126+
}
127+
128+
const styles = StyleSheet.create({
129+
container: {
130+
flex: 1,
131+
flexDirection: 'row',
132+
backgroundColor: 'white',
133+
marginHorizontal: PADDING,
134+
overflow: 'hidden',
135+
paddingTop: 16,
136+
},
137+
label: {
138+
fontSize: 18,
139+
fontFamily: 'Arial',
140+
fontWeight: 'bold',
141+
},
142+
textInput: {
143+
flex: 1,
144+
color: 'black',
145+
fontSize: 18,
146+
},
147+
separator: {
148+
position: 'absolute',
149+
width: 1,
150+
backgroundColor: '#f0f0f0',
151+
marginTop: -8,
152+
},
153+
});

lib/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import Hideo from './Hideo';
88
import Kohana from './Kohana';
99
import Makiko from './Makiko';
1010
import Sae from './Sae';
11+
import Fumi from './Fumi';
1112

1213
export {
1314
Kaede,
@@ -20,4 +21,5 @@ export {
2021
Kohana,
2122
Makiko,
2223
Sae,
24+
Fumi,
2325
};

0 commit comments

Comments
 (0)