1 | import React from 'react';
|
2 | import PropTypes from 'prop-types';
|
3 | import {
|
4 | Animated,
|
5 | Easing,
|
6 | Text,
|
7 | TextInput,
|
8 | TouchableWithoutFeedback,
|
9 | View,
|
10 | StyleSheet,
|
11 | } from 'react-native';
|
12 |
|
13 | import BaseInput from './BaseInput';
|
14 |
|
15 | export default class Makiko extends BaseInput {
|
16 | static propTypes = {
|
17 | |
18 |
|
19 |
|
20 |
|
21 |
|
22 | iconClass: PropTypes.func.isRequired,
|
23 |
|
24 | |
25 |
|
26 |
|
27 |
|
28 |
|
29 |
|
30 | iconName: PropTypes.string.isRequired,
|
31 |
|
32 | |
33 |
|
34 |
|
35 | iconColor: PropTypes.string,
|
36 |
|
37 | |
38 |
|
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 |
|
165 | const 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 | });
|