Skip to content

Commit 1c747f3

Browse files
committed
Initial commit of components and README.
0 parents  commit 1c747f3

File tree

5 files changed

+274
-0
lines changed

5 files changed

+274
-0
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# React Native Material Design TextInput
2+
3+
React Native TextInput styled with Material Design.

index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
import TextField from './lib/TextField';

lib/FloatingLabel.js

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
'use strict';
2+
/* @flow */
3+
4+
import React, {
5+
Component,
6+
StyleSheet,
7+
Animated,
8+
PropTypes
9+
} from 'react-native';
10+
11+
export default class FloatingLabel extends Component {
12+
constructor(props: Object) {
13+
super(props);
14+
this.state = {
15+
top: new Animated.Value(34),
16+
fontSize: new Animated.Value(16)
17+
};
18+
}
19+
floatLabel() {
20+
Animated.parallel([
21+
Animated.timing(this.state.top, {
22+
toValue: 16,
23+
duration: this.props.duration
24+
}),
25+
Animated.timing(this.state.fontSize, {
26+
toValue: 10,
27+
duration: this.props.duration
28+
})
29+
]).start();
30+
}
31+
sinkLabel() {
32+
Animated.parallel([
33+
Animated.timing(this.state.top, {
34+
toValue: 34,
35+
duration: this.props.duration
36+
}),
37+
Animated.timing(this.state.fontSize, {
38+
toValue: 16,
39+
duration: this.props.duration
40+
})
41+
]).start();
42+
}
43+
render() {
44+
let {
45+
label,
46+
labelColor,
47+
highlightColor
48+
} = this.props;
49+
return (
50+
<Animated.Text
51+
style={[{
52+
fontSize: this.state.fontSize,
53+
top: this.state.top,
54+
color: labelColor
55+
}, styles.labelText, this.props.isFocused && {
56+
color: highlightColor
57+
}]}
58+
onPress={()=> {
59+
this.props.focusHandler();
60+
}}
61+
>
62+
{label}
63+
</Animated.Text>
64+
);
65+
}
66+
}
67+
68+
FloatingLabel.propTypes = {
69+
duration: PropTypes.number,
70+
label: PropTypes.string,
71+
labelColor: PropTypes.string,
72+
highlightColor: PropTypes.string
73+
};
74+
75+
const styles = StyleSheet.create({
76+
labelText: {
77+
position: 'absolute',
78+
left: 1,
79+
backgroundColor: 'rgba(0,0,0,0)'
80+
}
81+
});

lib/TextField.js

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
'use strict';
2+
/* @flow */
3+
4+
import React, {
5+
Component,
6+
View,
7+
TextInput,
8+
StyleSheet,
9+
PropTypes
10+
} from 'react-native';
11+
12+
import Underline from './Underline';
13+
import FloatingLabel from './FloatingLabel';
14+
15+
export default class TextField extends Component {
16+
constructor(props: Object, context: Object) {
17+
super(props, context);
18+
this.state = {
19+
isFocused: false,
20+
text: ''
21+
}
22+
this.input = null;
23+
}
24+
focusInput() {
25+
// this.input.focus();
26+
this.refs.input.focus();
27+
}
28+
render() {
29+
let {
30+
label,
31+
highlightColor,
32+
duration,
33+
labelColor,
34+
borderColor,
35+
...props
36+
} = this.props;
37+
return (
38+
<View style={styles.wrapper} ref="wrapper">
39+
<View style={[styles.inputWrapper, this.state.isFocused && styles.inputWrapperActive]}>
40+
<TextInput
41+
style={styles.textInput}
42+
onFocus={() => {
43+
this.setState({isFocused: true});
44+
this.refs.floatingLabel.floatLabel();
45+
this.refs.underline.expandLine();
46+
}}
47+
onBlur={() => {
48+
this.setState({isFocused: false});
49+
if(!this.state.text.length) {
50+
this.refs.floatingLabel.sinkLabel();
51+
}
52+
this.refs.underline.shrinkLine();
53+
}}
54+
onChangeText={(text) => {
55+
this.setState({text: text});
56+
}}
57+
ref="input"
58+
{...props}
59+
/>
60+
<Underline
61+
ref="underline"
62+
highlightColor={highlightColor}
63+
duration={duration}
64+
borderColor={borderColor}
65+
/>
66+
</View>
67+
<FloatingLabel
68+
isFocused={this.state.isFocused}
69+
ref="floatingLabel"
70+
focusHandler={this.focusInput.bind(this)}
71+
label={label}
72+
labelColor={labelColor}
73+
highlightColor={highlightColor}
74+
duration={duration}
75+
/>
76+
</View>
77+
);
78+
}
79+
}
80+
81+
TextField.propTypes = {
82+
duration: PropTypes.number,
83+
label: PropTypes.string,
84+
highlightColor: PropTypes.string
85+
};
86+
87+
TextField.defaultProps = {
88+
duration: 200,
89+
labelColor: '#9E9E9E',
90+
borderColor: '#E0E0E0'
91+
};
92+
93+
const styles = StyleSheet.create({
94+
wrapper: {
95+
height: 72,
96+
flex: 1,
97+
paddingTop: 28,
98+
paddingBottom: 8,
99+
position: 'relative'
100+
},
101+
textInput: {
102+
flex: 1,
103+
fontSize: 16,
104+
lineHeight: 16
105+
},
106+
inputWrapper: {
107+
borderWidth: 0,
108+
height: 32,
109+
flex: 1
110+
}
111+
});

lib/Underline.js

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
'use strict';
2+
/* @flow */
3+
4+
import React, {
5+
Component,
6+
View,
7+
StyleSheet,
8+
Animated,
9+
PropTypes
10+
} from 'react-native';
11+
12+
export default class Underline extends Component {
13+
constructor(props: Object) {
14+
super(props);
15+
this.state = {
16+
lineLength: new Animated.Value(0),
17+
};
18+
this.wrapperWidth = 0;
19+
}
20+
componentDidMount() {
21+
requestAnimationFrame(() => {
22+
if (this.refs.wrapper == null) {
23+
return;
24+
}
25+
const container = this.refs.wrapper; // un-box animated view
26+
container.measure((left, top, width, height) => {
27+
this.wrapperWidth = width;
28+
});
29+
});
30+
}
31+
expandLine() {
32+
Animated.timing(this.state.lineLength, {
33+
toValue: this.wrapperWidth,
34+
duration: this.props.duration
35+
}).start();
36+
}
37+
shrinkLine() {
38+
Animated.timing(this.state.lineLength, {
39+
toValue: 0,
40+
duration: this.props.duration
41+
}).start();
42+
}
43+
render() {
44+
let {
45+
borderColor,
46+
highlightColor
47+
} = this.props;
48+
return (
49+
<View
50+
style={[styles.underlineWrapper, {
51+
backgroundColor: borderColor
52+
}]}
53+
ref="wrapper"
54+
>
55+
<Animated.View
56+
style={[{
57+
width: this.state.lineLength,
58+
height: 1,
59+
backgroundColor: highlightColor
60+
}]}>
61+
</Animated.View>
62+
</View>
63+
);
64+
}
65+
}
66+
67+
Underline.propTypes = {
68+
duration: PropTypes.number,
69+
highlightColor: PropTypes.string,
70+
borderColor: PropTypes.string
71+
};
72+
73+
const styles = StyleSheet.create({
74+
underlineWrapper: {
75+
height: 1,
76+
alignItems: 'center'
77+
}
78+
});

0 commit comments

Comments
 (0)