UNPKG

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