Skip to content

Commit 1e15a7d

Browse files
Adds LabeledTextInput
1 parent 08ec68a commit 1e15a7d

File tree

2 files changed

+162
-1
lines changed

2 files changed

+162
-1
lines changed

components/LabeledTextInput.js

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
import React, { Component, PropTypes } from 'react'
2+
import { View, Text, TextInput, StyleSheet } from 'react-native'
3+
4+
export default class LabeledTextInput extends Component {
5+
componentDidMount() {
6+
this.scrollTo = 0
7+
}
8+
9+
handleLayout(event) {
10+
this.scrollTo = event.nativeEvent.layout.y
11+
}
12+
13+
handleFocus() {
14+
const { onFocus } = this.props
15+
onFocus && onFocus(this.scrollTo)
16+
}
17+
18+
focus() {
19+
this.refs.input.focus()
20+
}
21+
22+
blur() {
23+
this.refs.input.blur()
24+
}
25+
26+
shouldDisplayMessage() {
27+
const { value, valid, message } = this.props
28+
return (value && value.length > 0 && !valid && message)
29+
}
30+
31+
handleSubmitEditing() {
32+
const { nextInput, onNextInputFocus } = this.props
33+
onNextInputFocus && onNextInputFocus(nextInput, this)
34+
}
35+
36+
renderIcon() {
37+
const { icon, validIcon, invalidIcon, valid, value, iconStyle } = this.props
38+
if (!icon)
39+
return
40+
let renderedIcon = null
41+
if (value && value.length > 0) {
42+
renderedIcon = (valid ? (validIcon ? validIcon : icon) : (invalidIcon ? invalidIcon : icon))
43+
} else {
44+
renderedIcon = icon
45+
}
46+
return (
47+
<View
48+
style={iconStyle}
49+
>
50+
{renderedIcon}
51+
</View>
52+
)
53+
}
54+
55+
renderMessage() {
56+
const { message, messageStyle } = this.props
57+
const style = StyleSheet.flatten(this.props.style)
58+
if (this.shouldDisplayMessage()) {
59+
return(
60+
<View style={{
61+
backgroundColor: (style && style.backgroundColor ? style.backgroundColor : 'white')
62+
}}>
63+
<Text style={[{
64+
color: 'red',
65+
margin: 10,
66+
fontSize: 12,
67+
}, messageStyle]}>
68+
{ message }
69+
</Text>
70+
</View>
71+
)
72+
}
73+
}
74+
75+
render() {
76+
const { label, value, labelStyle, inputStyle, nextInput, onBlur, multiline } = this.props
77+
const style = StyleSheet.flatten(this.props.style)
78+
return (
79+
<View
80+
onLayout={this.handleLayout.bind(this)}
81+
style={[{
82+
backgroundColor: (style && style.backgroundColor ? style.backgroundColor : 'white'),
83+
borderTopWidth: StyleSheet.hairlineWidth,
84+
borderBottomWidth: (nextInput ? 0 : StyleSheet.hairlineWidth),
85+
borderColor: 'lightgray',
86+
paddingTop: 10,
87+
paddingBottom: (this.shouldDisplayMessage() ? 0 : 10),
88+
paddingHorizontal: 10,
89+
}, style]}
90+
>
91+
{ this.renderIcon() }
92+
<Text
93+
style={[{
94+
fontSize: 12,
95+
fontWeight: 'bold',
96+
marginBottom: 4,
97+
}, labelStyle]}
98+
>
99+
{label}
100+
</Text>
101+
<TextInput
102+
clearButtonMode='while-editing'
103+
underlineColorAndroid='transparent'
104+
returnKeyType={ multiline ? 'default' : (nextInput ? 'next' : 'done') }
105+
onSubmitEditing={this.handleSubmitEditing.bind(this)}
106+
{ ...this.props }
107+
onFocus={this.handleFocus.bind(this)}
108+
onBlur={onBlur}
109+
ref='input'
110+
value={value}
111+
style={[{
112+
height: 24,
113+
paddingHorizontal: 10,
114+
fontSize: 12,
115+
lineHeight: 24,
116+
borderWidth: StyleSheet.hairlineWidth,
117+
borderColor: 'lightgray',
118+
backgroundColor: 'white',
119+
}, inputStyle]}
120+
/>
121+
{ this.renderMessage() }
122+
</View>
123+
)
124+
}
125+
}
126+
127+
const stylePropType = PropTypes.oneOfType([
128+
React.PropTypes.object,
129+
React.PropTypes.arrayOf(React.PropTypes.object),
130+
])
131+
132+
LabeledTextInput.propTypes = {
133+
label: PropTypes.string,
134+
value: PropTypes.string,
135+
valid: PropTypes.bool,
136+
message: PropTypes.string,
137+
style: stylePropType,
138+
iconStyle: stylePropType,
139+
labelStyle: stylePropType,
140+
inputStyle: stylePropType,
141+
messageStyle: stylePropType,
142+
icon: PropTypes.element,
143+
validIcon: PropTypes.element,
144+
invalidIcon: PropTypes.element,
145+
}
146+
147+
LabeledTextInput.defaultProps = {
148+
label: 'Use label prop',
149+
value: null,
150+
valid: false,
151+
message: null,
152+
style: {},
153+
iconStyle: {},
154+
labelStyle: {},
155+
inputStyle: {},
156+
messageStyle: {},
157+
icon: null,
158+
validIcon: null,
159+
invalidIcon: null,
160+
}

index.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import StatelessForm from './StatelessForm'
2+
import LabeledTextInput from './components/LabeledTextInput'
23
import InlineTextInput from './components/InlineTextInput'
34

4-
module.exports = { StatelessForm, InlineTextInput }
5+
module.exports = { StatelessForm, LabeledTextInput, InlineTextInput }

0 commit comments

Comments
 (0)