UNPKG

4.94 kBJavaScriptView Raw
1import React from 'react';
2import PropTypes from 'prop-types';
3import {
4 Animated,
5 TextInput,
6 TouchableWithoutFeedback,
7 View,
8 StyleSheet,
9} from 'react-native';
10
11import BaseInput from './BaseInput';
12
13export default class Fumi extends BaseInput {
14 static propTypes = {
15 /*
16 * This is the icon component you are importing from react-native-vector-icons.
17 * import FontAwesomeIcon from 'react-native-vector-icons/FontAwesome';
18 * iconClass={FontAwesomeIcon}
19 */
20 iconClass: PropTypes.func.isRequired,
21 /*
22 * Passed to react-native-vector-icons library as name prop
23 */
24 iconName: PropTypes.string.isRequired,
25 /*
26 * Passed to react-native-vector-icons library as color prop.
27 * Also used as textInput color.
28 */
29 iconColor: PropTypes.string,
30 /*
31 * Passed to react-native-vector-icons library as size prop.
32 */
33 iconSize: PropTypes.number,
34
35 passiveIconColor: PropTypes.string,
36 height: PropTypes.number,
37 };
38
39 static defaultProps = {
40 height: 48,
41 iconColor: '#00aeef',
42 iconSize: 20,
43 iconWidth: 40,
44 inputPadding: 16,
45 passiveIconColor: '#a3a3a3',
46 animationDuration: 300,
47 };
48
49 render() {
50 const {
51 iconClass,
52 iconColor,
53 iconSize,
54 passiveIconColor,
55 iconName,
56 label,
57 style: containerStyle,
58 inputStyle,
59 height: inputHeight,
60 inputPadding,
61 iconWidth,
62 labelStyle,
63 } = this.props;
64 const { focusedAnim, value } = this.state;
65 const AnimatedIcon = Animated.createAnimatedComponent(iconClass);
66 const ANIM_PATH = inputPadding + inputHeight;
67 const NEGATIVE_ANIM_PATH = ANIM_PATH * -1;
68
69 return (
70 <View
71 style={[styles.container, containerStyle, {
72 height: ANIM_PATH,
73 }]}
74 onLayout={this._onLayout}
75 >
76 <TouchableWithoutFeedback onPress={this.focus}>
77 <AnimatedIcon
78 name={iconName}
79 color={iconColor}
80 size={iconSize}
81 style={{
82 position: 'absolute',
83 left: inputPadding,
84 bottom: focusedAnim.interpolate({
85 inputRange: [0, 0.5, 0.51, 0.7, 1],
86 outputRange: [
87 24,
88 ANIM_PATH,
89 NEGATIVE_ANIM_PATH,
90 NEGATIVE_ANIM_PATH,
91 24,
92 ],
93 }),
94 color: focusedAnim.interpolate({
95 inputRange: [0, 0.5, 1],
96 outputRange: [passiveIconColor, iconColor, iconColor],
97 }),
98 }}
99 />
100 </TouchableWithoutFeedback>
101 <View
102 style={[
103 styles.separator,
104 {
105 height: inputHeight,
106 left: iconWidth + 8,
107 },
108 ]}
109 />
110 <TouchableWithoutFeedback onPress={this.focus}>
111 <Animated.View
112 style={{
113 position: 'absolute',
114 left: iconWidth + inputPadding,
115 height: inputHeight,
116 top: focusedAnim.interpolate({
117 inputRange: [0, 0.5, 0.51, 0.7, 1],
118 outputRange: [
119 24,
120 ANIM_PATH,
121 NEGATIVE_ANIM_PATH,
122 NEGATIVE_ANIM_PATH,
123 inputPadding / 2,
124 ],
125 }),
126 }}
127 >
128 <Animated.Text
129 style={[
130 styles.label,
131 {
132 fontSize: focusedAnim.interpolate({
133 inputRange: [0, 0.7, 0.71, 1],
134 outputRange: [16, 16, 12, 12],
135 }),
136 color: focusedAnim.interpolate({
137 inputRange: [0, 0.7],
138 outputRange: ['#696969', '#a3a3a3'],
139 }),
140 },
141 labelStyle,
142 ]}
143 >
144 {label}
145 </Animated.Text>
146 </Animated.View>
147 </TouchableWithoutFeedback>
148 <TextInput
149 ref={this.input}
150 {...this.props}
151 style={[
152 styles.textInput,
153 {
154 marginLeft: iconWidth + inputPadding,
155 color: iconColor,
156 },
157 inputStyle,
158 ]}
159 value={value}
160 onBlur={this._onBlur}
161 onFocus={this._onFocus}
162 onChange={this._onChange}
163 underlineColorAndroid={'transparent'}
164 />
165 </View>
166 );
167 }
168}
169
170const styles = StyleSheet.create({
171 container: {
172 overflow: 'hidden',
173 paddingTop: 16,
174 backgroundColor: 'white',
175 },
176 label: {
177 fontSize: 18,
178 fontWeight: 'bold',
179 },
180 textInput: {
181 flex: 1,
182 color: 'black',
183 fontSize: 18,
184 padding: 7,
185 paddingLeft: 0,
186 },
187 separator: {
188 position: 'absolute',
189 width: 1,
190 backgroundColor: '#f0f0f0',
191 top: 8,
192 },
193});