UNPKG

4.03 kBJavaScriptView Raw
1import React, { PropTypes, Component } from 'react';
2import {
3 Animated,
4 Easing,
5 Text,
6 TextInput,
7 TouchableWithoutFeedback,
8 View,
9 StyleSheet,
10} from 'react-native';
11
12import BaseInput from './BaseInput';
13
14const PADDING = 16;
15
16export default class Jiro extends BaseInput {
17
18 static propTypes = {
19 borderColor: PropTypes.string,
20 height: PropTypes.number,
21 };
22
23 static defaultProps = {
24 borderColor: 'red',
25 height: 48,
26 };
27
28 constructor(props, context) {
29 super(props, context);
30
31 const animationValue = props.value ? 1 : 0;
32 this.state = {
33 value: props.value,
34 borderPositionAnim: new Animated.Value(animationValue),
35 borderHeightAnim: new Animated.Value(animationValue),
36 labelPositionAnim: new Animated.Value(animationValue),
37 };
38 }
39
40 _toggle(isActive) {
41 const animationValue = isActive ? 1 : 0;
42 const borderPositionAnimation = Animated.timing(this.state.borderPositionAnim, {
43 toValue: animationValue,
44 eaasing: Easing.bezier(0.2, 1, 0.3, 1),
45 duration: 200,
46 });
47 const borderHeightAnimation = Animated.timing(this.state.borderHeightAnim, {
48 toValue: animationValue,
49 eaasing: Easing.ease,
50 duration: 200,
51 });
52 const labelPositionAnimation = Animated.timing(this.state.labelPositionAnim, {
53 toValue: animationValue,
54 eaasing: Easing.ease,
55 duration: 200,
56 });
57
58 if (isActive) {
59 Animated.sequence([
60 borderPositionAnimation,
61 Animated.parallel([labelPositionAnimation, borderHeightAnimation]),
62 ]).start();
63 } else {
64 Animated.sequence([
65 borderHeightAnimation,
66 Animated.parallel([borderPositionAnimation, labelPositionAnimation]),
67 ]).start();
68 }
69 }
70
71 render() {
72 const {
73 label,
74 style: containerStyle,
75 inputStyle,
76 labelStyle,
77 borderColor,
78 height: inputHeight,
79 } = this.props;
80 const {
81 width,
82 borderPositionAnim,
83 borderHeightAnim,
84 labelPositionAnim,
85 value,
86 } = this.state;
87 const totalHeight = inputHeight + 2 * PADDING;
88
89 return (
90 <View
91 style={[containerStyle, {
92 height: totalHeight,
93 }]}
94 onLayout={this._onLayout}
95 >
96 <Animated.View
97 style={[styles.border, {
98 height: borderHeightAnim.interpolate({
99 inputRange: [0, 1],
100 outputRange: [3, inputHeight],
101 }),
102 top: borderPositionAnim.interpolate({
103 inputRange: [0, 1],
104 outputRange: [totalHeight - 3, 2 * PADDING],
105 }),
106 backgroundColor: borderColor,
107 }]}
108 />
109 <TextInput
110 ref="input"
111 {...this.props}
112 style={[styles.textInput, inputStyle, {
113 width,
114 height: inputHeight,
115 }]}
116 value={value}
117 onBlur={this._onBlur}
118 onChange={this._onChange}
119 onFocus={this._onFocus}
120 underlineColorAndroid={'transparent'}
121 />
122 <TouchableWithoutFeedback onPress={this._focus}>
123 <Animated.View style={[styles.labelContainer, {
124 bottom: labelPositionAnim.interpolate({
125 inputRange: [0, 1],
126 outputRange: [PADDING / 2, inputHeight + PADDING / 4],
127 }),
128 }]}>
129 <Text style={[styles.label, labelStyle]}>
130 {label}
131 </Text>
132 </Animated.View>
133 </TouchableWithoutFeedback>
134 </View>
135 );
136 }
137}
138
139const styles = StyleSheet.create({
140 labelContainer: {
141 position: 'absolute',
142 left: PADDING,
143 backgroundColor: 'transparent',
144 },
145 label: {
146 fontFamily: 'Arial',
147 fontSize: 13,
148 fontWeight: 'bold',
149 color: '#6a7989',
150 },
151 textInput: {
152 position: 'absolute',
153 bottom: 0,
154 padding: 0,
155 left: PADDING,
156 color: 'black',
157 fontSize: 18,
158 fontWeight: 'bold',
159 },
160 border: {
161 position: 'absolute',
162 bottom: 0,
163 left: 0,
164 right: 0,
165 },
166});