Skip to content

Commit 8193aff

Browse files
committed
Initial commit
1 parent 8cb9ddb commit 8193aff

File tree

2 files changed

+223
-0
lines changed

2 files changed

+223
-0
lines changed

index.js

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
import React, {PropTypes, Component} from 'react'
2+
import {
3+
View,
4+
Text,
5+
TextInput,
6+
StyleSheet,
7+
TouchableOpacity,
8+
Dimensions,
9+
TouchableWithoutFeedback
10+
} from 'react-native'
11+
import Icon from 'react-native-vector-icons/Ionicons'
12+
import colors from "../../constants/colors"
13+
import _ from 'lodash'
14+
class EmailInput extends Component {
15+
constructor(props) {
16+
super(props);
17+
let {height, width} = Dimensions.get('window');
18+
19+
this.state = {
20+
text: "",
21+
inputWidth: 200
22+
};
23+
24+
this.wrapperWidth = width;
25+
this.parseEmails = this.parseEmails.bind(this);
26+
this.onChange = this.onChange.bind(this);
27+
this.pop = this.pop.bind(this);
28+
this.calculateWidth = this.calculateWidth.bind(this);
29+
this.focus = this.focus.bind(this);
30+
}
31+
measureWrapper() {
32+
if (!this.refs.wrapper)
33+
return;
34+
this.refs.wrapper.measure((ox, oy, w, h, px, py) => {
35+
this.wrapperWidth = w;
36+
});
37+
}
38+
calculateWidth() {
39+
40+
setTimeout(() => {
41+
if (!this.refs['tag' + (this.props.value.length - 1)])
42+
return;
43+
this.refs['tag' + (this.props.value.length - 1)].measure((ox, oy, w, h, px, py) => {
44+
45+
let endPosOfTag = w + ox;
46+
let margin = 3;
47+
let spaceLeft = this.wrapperWidth - endPosOfTag - margin;
48+
if (spaceLeft < 100) {
49+
this.setState({inputWidth: this.wrapperWidth});
50+
} else {
51+
this.setState({inputWidth: spaceLeft})
52+
}
53+
});
54+
}, 0);
55+
}
56+
componentDidMount() {
57+
this.calculateWidth();
58+
}
59+
componentWillReceiveProps() {
60+
this.calculateWidth();
61+
}
62+
componentDidUpdate(prevProps, prevState) {
63+
if (prevProps.value.length != this.props.value.length || !prevProps.value) {
64+
this.calculateWidth();
65+
}
66+
}
67+
onChange(event) {
68+
if (!event || !event.nativeEvent)
69+
return;
70+
let text = event.nativeEvent.text;
71+
this.setState({text: text});
72+
let lastTyped = text.charAt(text.length - 1);
73+
74+
let parseWhen = [",", " ", ";"];
75+
76+
if (parseWhen.indexOf(lastTyped) > -1)
77+
this.parseEmails();
78+
}
79+
80+
parseEmails() {
81+
let {text} = this.state;
82+
let {value} = this.props;
83+
let regex = this.props.regex || /([a-zA-Z0-9._-]+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9._-]+)/gi;
84+
let results = text.match(regex);
85+
86+
if (results && results.length > 0) {
87+
this.setState({text: ""});
88+
this.props.onChange(value.concat(results));
89+
}
90+
91+
}
92+
onKeyPress(event) {
93+
if (this.state.text == "" && event.nativeEvent && event.nativeEvent.key == "Backspace") {
94+
this.pop();
95+
}
96+
}
97+
focus() {
98+
if (this.refs.emailInput)
99+
this.refs.emailInput.focus();
100+
}
101+
pop() {
102+
let emails = _.clone(this.props.value);
103+
emails.pop();
104+
this.props.onChange(emails);
105+
this.focus();
106+
}
107+
removeIndex(index) {
108+
let emails = _.clone(this.props.value);
109+
emails.splice(index, 1);
110+
this.props.onChange(emails);
111+
this.focus();
112+
113+
}
114+
render() {
115+
let {text} = this.state;
116+
let {value} = this.props;
117+
118+
let width = text.length < 4
119+
? 100
120+
: null;
121+
122+
return <TouchableWithoutFeedback onPress={() => this.refs.emailInput.focus()} onLayout={this.measureWrapper.bind(this)} style={{
123+
flex: 1
124+
}}>
125+
<View style={styles.wrapper} ref="wrapper" onLayout={this.measureWrapper.bind(this)}>
126+
{value.map((email, index) => {
127+
return <TouchableOpacity ref={"tag" + index} style={styles.tag} onPress={this.removeIndex.bind(this, index)}>
128+
<Text style={styles.tagText}>{email}&nbsp;&nbsp;
129+
<Icon name="md-close"/></Text>
130+
</TouchableOpacity>
131+
})}
132+
133+
<View style={{
134+
width: this.state.inputWidth
135+
}}>
136+
<TextInput ref="emailInput" blurOnSubmit={false} onKeyPress={this.onKeyPress.bind(this)} value={this.state.text} style={[
137+
styles.textInput, {
138+
width: width
139+
}
140+
]} underlineColorAndroid="rgba(0,0,0,0)" onChange={this.onChange.bind(this)} onSubmitEditing={this.parseEmails}/>
141+
</View>
142+
</View>
143+
</TouchableWithoutFeedback>
144+
}
145+
}
146+
147+
EmailInput.PropTypes = {
148+
regex: React.PropTypes.object,
149+
onChange: React.PropTypes.func,
150+
value: React.PropTypes.array.isRequired
151+
}
152+
export default EmailInput;
153+
154+
const styles = StyleSheet.create({
155+
wrapper: {
156+
flex: 1,
157+
flexDirection: 'row',
158+
flexWrap: 'wrap',
159+
alignItems: 'flex-start',
160+
marginTop: 3,
161+
marginBottom: 8
162+
},
163+
spacer: {
164+
flexWrap: 'wrap',
165+
height: 24,
166+
width: 0,
167+
backgroundColor: "red"
168+
},
169+
textInput: {
170+
color: colors.defaultTextColor,
171+
height: 24,
172+
fontSize: 16,
173+
flex: .6,
174+
padding: 0,
175+
marginTop: 6,
176+
flexWrap: 'wrap'
177+
},
178+
tag: {
179+
padding: 0,
180+
justifyContent: 'center',
181+
backgroundColor: colors.lightGray,
182+
marginTop: 5,
183+
marginRight: 3,
184+
flexWrap: 'wrap',
185+
padding: 8,
186+
height: 24,
187+
borderRadius: 2
188+
},
189+
tagText: {
190+
color: "#777",
191+
padding: 0,
192+
margin: 0
193+
}
194+
})

package.json

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{
2+
"name": "react-native-tag-input",
3+
"version": "0.3.0",
4+
"description": "A tag input component for react-native",
5+
"main": "index.js",
6+
"author": "Jack Wohlfert (https://github.com/jwohlfert23)",
7+
"keywords": [
8+
"react-component",
9+
"react-native",
10+
"ios",
11+
"ui",
12+
"email input",
13+
"tag input",
14+
"emails"
15+
],
16+
"license": "MIT",
17+
"scripts": {
18+
"start": "node_modules/react-native/packager/packager.sh"
19+
},
20+
"repository": {
21+
"type": "git",
22+
"url": "git@github.com:jwohlfert23/react-native-tag-input.git"
23+
},
24+
"devDependencies": {
25+
"react": "^15.0.2",
26+
"react-native": "^0.26.2",
27+
"lodash": "^3.2.0"
28+
}
29+
}

0 commit comments

Comments
 (0)