Created
September 22, 2015 07:19
-
-
Save mattiamanzati/3dda55ae4b59cf6b9a5e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var React = require('react-native'); | |
var EventEmitter = require('eventemitter3'); | |
var MyTextInput = require('./TextInput'); | |
var {View, Text, TextInput, TouchableOpacity, StyleSheet} = React; | |
var styles = StyleSheet.create({ | |
wrapper: { | |
position: 'absolute', | |
top: 0, | |
left: 0, | |
bottom: 0, | |
right: 0 | |
}, | |
overlay: { | |
padding: 15, | |
backgroundColor: 'rgba(0, 0, 0, 0.75)' | |
}, | |
inputContainer: { | |
flexDirection: 'row', | |
backgroundColor: '#FFFFFF', | |
marginBottom: 10, | |
alignItems: 'center' | |
}, | |
input: { | |
flex: 1, | |
borderRadius: 2, | |
padding: 10, | |
height: 40 | |
}, | |
dismiss: { | |
fontSize: 20, | |
lineHeight: 20, | |
fontWeight: 'bold' | |
}, | |
dismissButton: { | |
padding: 10 | |
}, | |
hint: { | |
textAlign: 'center', | |
color: '#FFFFFF', | |
marginBottom: 10 | |
}, | |
results: { | |
borderRadius: 4, | |
flex: 1, | |
backgroundColor: '#FFFFFF' | |
} | |
}); | |
class AutoCompleteMediator extends EventEmitter{ | |
constructor(props){ | |
super(props); | |
} | |
focus(autoComplete, value){ | |
this.emit('focus', autoComplete, value); | |
} | |
attach(overlay){ | |
this.on('focus', overlay.onAutoCompleteFocus); | |
} | |
detach(overlay){ | |
this.off('focus', overlay.onAutoCompleteFocus); | |
} | |
} | |
var mediator = new AutoCompleteMediator(); | |
class AutoCompleteOverlay extends React.Component{ | |
constructor(props){ | |
super(props); | |
// initialize state | |
this.state = { | |
value: '', | |
shown: false, | |
autoComplete: null | |
}; | |
// autobinding | |
this.onChange = this.onChange.bind(this); | |
this.dismissOverlay = this.dismissOverlay.bind(this); | |
this.onAutoCompleteFocus = this.onAutoCompleteFocus.bind(this); | |
} | |
componentDidMount(){ | |
mediator.attach(this); | |
} | |
componentWillUnmount(){ | |
mediator.detach(this); | |
} | |
// an autocomplete focused, open the overlay mama! | |
onAutoCompleteFocus(autoComplete, value){ | |
this.setState({shown: true, autoComplete, value}); | |
} | |
// handle suggestions | |
onChange(e){ | |
if(this.state.autoComplete) this.state.autoComplete.onChange(e); | |
this.setState({value: e.nativeEvent.text}); | |
} | |
// dismiss the overlay | |
dismissOverlay(){ | |
if(this.state.autoComplete) this.state.autoComplete.onBlur(); | |
this.setState({shown: false, autoComplete: null}); | |
} | |
render(){ | |
// deconstruct | |
var {children, style, ...props} = this.props; | |
// if not shown, return only the children | |
// | |
var overlay = null; | |
if(this.state.shown){ | |
overlay = <View {...props} style={[styles.wrapper, styles.overlay].concat(Array.isArray(style) ? style : [style])}> | |
<View style={styles.inputContainer}> | |
<TextInput underlineColorAndroid="transparent" value={this.state.value} onChange={this.onChange} autoFocus={true} onSubmitEditing={this.dismissOverlay} onEndEditing={this.dismissOverlay} style={styles.input} /> | |
<TouchableOpacity onPress={this.dismissOverlay} style={styles.dismissButton}> | |
<Text style={styles.dismiss}>×</Text> | |
</TouchableOpacity> | |
</View> | |
{this.state.value ? null : <Text style={styles.hint}>Start typing to see suggestions...</Text>} | |
{this.state.value && !this.state.pending && !this.state.items ? <Text style={styles.hint}>No suggestion found.</Text> : null} | |
{this.state.value && !this.state.pending && this.state.items ? <View style={styles.results}></View> : null} | |
</View>; | |
} | |
// render | |
return <View style={styles.wrapper}> | |
{children} | |
{overlay} | |
</View>; | |
} | |
} | |
class AutoComplete extends React.Component{ | |
constructor(props, ctx){ | |
super(props, ctx); | |
// handles internally the value | |
this.state = {}; | |
// autobind | |
this.onFocus = this.onFocus.bind(this); | |
this.onChange = this.onChange.bind(this); | |
this.onBlur = this.onBlur.bind(this); | |
} | |
onFocus(e){ | |
// deconstruct | |
var {onFocus, onChange, onBlur, ...props} = this.props; | |
// call and focus the overlay | |
if(onFocus) onFocus(e); | |
mediator.focus(this, this.state.value); | |
} | |
onChange(e){ | |
// deconstruct | |
var {onFocus, onChange, onBlur, ...props} = this.props; | |
// handle on change | |
if(onChange) onChange(e); | |
// set value | |
this.setState({value: e.nativeEvent.text}); | |
} | |
onBlur(e){ | |
// deconstruct | |
var {onFocus, onChange, onBlur, ...props} = this.props; | |
// handle on change | |
if(onBlur) onBlur(e); | |
} | |
render(){ | |
// deconstruct | |
var {onFocus, onChange, onBlur, ...props} = this.props; | |
// render | |
return <MyTextInput {...props} onChange={this.onChange} onFocus={this.onFocus} />; | |
} | |
} | |
AutoComplete.Overlay = AutoCompleteOverlay; | |
module.exports = AutoComplete; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Sample React Native App | |
* https://github.com/facebook/react-native | |
*/ | |
'use strict'; | |
var React = require('react-native'); | |
var { | |
AppRegistry, | |
StyleSheet, | |
Text, | |
View, | |
} = React; | |
var AutoComplete = require('./AutoComplete'); | |
var demoerror = React.createClass({ | |
render: function() { | |
return ( | |
<View style={styles.container}> | |
<AutoComplete.Overlay> | |
<Text style={styles.welcome}> | |
Welcome to React Native! | |
</Text> | |
<Text style={styles.instructions}> | |
To get started, edit index.android.js | |
</Text> | |
<Text style={styles.instructions}> | |
Shake or press menu button for dev menu | |
</Text> | |
<AutoComplete /> | |
</AutoComplete.Overlay> | |
</View> | |
); | |
} | |
}); | |
var styles = StyleSheet.create({ | |
container: { | |
flex: 1, | |
justifyContent: 'center', | |
backgroundColor: '#F5FCFF', | |
}, | |
welcome: { | |
fontSize: 20, | |
textAlign: 'center', | |
margin: 10, | |
}, | |
instructions: { | |
textAlign: 'center', | |
color: '#333333', | |
marginBottom: 5, | |
}, | |
}); | |
AppRegistry.registerComponent('demoerror', () => demoerror); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var React = require('react-native'); | |
var {View, Text, StyleSheet} = React; | |
var ReactNativeTextInput = React.TextInput; | |
module.exports = class TextInput extends React.Component{ | |
render(){ | |
// deconstruct | |
var {style, ...props} = this.props; | |
// render | |
return <View style={[styles.main].concat(Array.isArray(style) ? style : [style])}> | |
<ReactNativeTextInput underlineColorAndroid="transparent" {...props} style={styles.input}/> | |
</View>; | |
} | |
} | |
let styles = StyleSheet.create({ | |
main: { | |
borderBottomColor: '#2980b9', | |
borderBottomWidth: 3, | |
marginBottom: 3 | |
}, | |
input: { | |
padding: 5, | |
height: 30, | |
} | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment