1 | import React from 'react';
|
2 | import PropTypes from 'prop-types';
|
3 | import {
|
4 | Animated,
|
5 | TextInput,
|
6 | TouchableWithoutFeedback,
|
7 | View,
|
8 | StyleSheet,
|
9 | } from 'react-native';
|
10 |
|
11 | import BaseInput from './BaseInput';
|
12 |
|
13 | export default class Madoka extends BaseInput {
|
14 | static propTypes = {
|
15 | |
16 |
|
17 |
|
18 | borderColor: PropTypes.string,
|
19 | labelHeight: PropTypes.number,
|
20 | inputPadding: PropTypes.number,
|
21 | height: PropTypes.number,
|
22 | };
|
23 |
|
24 | static defaultProps = {
|
25 | borderColor: '#7A7593',
|
26 | animationDuration: 250,
|
27 | labelHeight: 24,
|
28 | inputPadding: 16,
|
29 | height: 48,
|
30 | };
|
31 |
|
32 | render() {
|
33 | const {
|
34 | label,
|
35 | style: containerStyle,
|
36 | height: inputHeight,
|
37 | inputPadding,
|
38 | labelHeight,
|
39 | inputStyle,
|
40 | labelStyle,
|
41 | borderColor,
|
42 | } = this.props;
|
43 | const {
|
44 | width,
|
45 | focusedAnim,
|
46 | value,
|
47 | } = this.state;
|
48 |
|
49 | return (
|
50 | <View
|
51 | style={[containerStyle, { height: inputHeight + labelHeight + 8 }]}
|
52 | onLayout={this._onLayout}
|
53 | >
|
54 | <View
|
55 | style={[styles.inputContainer, { borderBottomColor: borderColor }]}
|
56 | >
|
57 | <TextInput
|
58 | ref={this.input}
|
59 | {...this.props}
|
60 | style={[
|
61 | styles.textInput,
|
62 | inputStyle,
|
63 | {
|
64 | width,
|
65 | height: inputHeight,
|
66 | paddingHorizontal: inputPadding,
|
67 | },
|
68 | ]}
|
69 | value={value}
|
70 | onBlur={this._onBlur}
|
71 | onChange={this._onChange}
|
72 | onFocus={this._onFocus}
|
73 | underlineColorAndroid={'transparent'}
|
74 | />
|
75 | {}
|
76 | <Animated.View
|
77 | style={{
|
78 | position: 'absolute',
|
79 | right: 0,
|
80 | bottom: 0,
|
81 | width: 2,
|
82 | height: focusedAnim.interpolate({
|
83 | inputRange: [0, 0.2, 1],
|
84 | outputRange: [0, inputHeight, inputHeight],
|
85 | }),
|
86 | backgroundColor: borderColor,
|
87 | }}
|
88 | />
|
89 | {}
|
90 | <Animated.View
|
91 | style={{
|
92 | position: 'absolute',
|
93 | right: 0,
|
94 | top: 0,
|
95 | height: 2,
|
96 | width: focusedAnim.interpolate({
|
97 | inputRange: [0, 0.2, 0.8, 1],
|
98 | outputRange: [0, 0, width, width],
|
99 | }),
|
100 | backgroundColor: borderColor,
|
101 | }}
|
102 | />
|
103 | {}
|
104 | <Animated.View
|
105 | style={{
|
106 | position: 'absolute',
|
107 | left: 0,
|
108 | top: 0,
|
109 | width: 2,
|
110 | height: focusedAnim.interpolate({
|
111 | inputRange: [0, 0.8, 1],
|
112 | outputRange: [0, 0, inputHeight],
|
113 | }),
|
114 | backgroundColor: borderColor,
|
115 | }}
|
116 | />
|
117 | </View>
|
118 | <TouchableWithoutFeedback onPress={this.focus}>
|
119 | <Animated.View
|
120 | style={[
|
121 | styles.labelContainer,
|
122 | {
|
123 | width,
|
124 | height: labelHeight,
|
125 | bottom: focusedAnim.interpolate({
|
126 | inputRange: [0, 1],
|
127 | outputRange: [labelHeight + inputPadding, 0],
|
128 | }),
|
129 | left: inputPadding,
|
130 | },
|
131 | ]}
|
132 | >
|
133 | <Animated.Text
|
134 | style={[
|
135 | styles.label,
|
136 | labelStyle,
|
137 | {
|
138 | fontSize: focusedAnim.interpolate({
|
139 | inputRange: [0, 1],
|
140 | outputRange: [18, 14],
|
141 | }),
|
142 | },
|
143 | ]}
|
144 | >
|
145 | {label}
|
146 | </Animated.Text>
|
147 | </Animated.View>
|
148 | </TouchableWithoutFeedback>
|
149 | </View>
|
150 | );
|
151 | }
|
152 | }
|
153 |
|
154 | const styles = StyleSheet.create({
|
155 | inputContainer: {
|
156 | borderBottomWidth: 2,
|
157 | },
|
158 | labelContainer: {
|
159 | position: 'absolute',
|
160 | },
|
161 | label: {
|
162 | backgroundColor: 'transparent',
|
163 | fontWeight: 'bold',
|
164 | color: '#6a7989',
|
165 | },
|
166 | textInput: {
|
167 | paddingVertical: 0,
|
168 | color: 'black',
|
169 | fontSize: 18,
|
170 | fontWeight: 'bold',
|
171 | },
|
172 | });
|