UNPKG

@deboxsoft/react-native-elements

Version:
209 lines (188 loc) 4.82 kB
import PropTypes from 'prop-types'; import React, { Component } from 'react'; import { Dimensions, StyleSheet, View, ActivityIndicator, Text, } from 'react-native'; import { ViewPropTypes } from '../config'; import { nodeType, renderNode } from '../helpers'; import Input from '../input/Input'; import Icon from '../icons/Icon'; const SCREEN_WIDTH = Dimensions.get('window').width; const ANDROID_GRAY = 'rgba(0, 0, 0, 0.54)'; const defaultSearchIcon = { type: 'material-community', size: 25, color: ANDROID_GRAY, name: 'magnify', }; const defaultCancelIcon = { type: 'material-community', size: 25, color: ANDROID_GRAY, name: 'arrow-left', }; const defaultClearIcon = { type: 'material-community', name: 'close', size: 25, color: ANDROID_GRAY, }; class SearchBar extends Component { focus = () => { this.input.focus(); }; blur = () => { this.input.blur(); }; clear = () => { this.input.clear(); this.onChangeText(''); this.props.onClear(); }; cancel = () => { this.blur(); this.props.onCancel(); }; onFocus = () => { this.props.onFocus(); this.setState({ hasFocus: true }); }; onBlur = () => { this.props.onBlur(); this.setState({ hasFocus: false }); }; onChangeText = text => { this.props.onChangeText(text); this.setState({ isEmpty: text === '' }); }; constructor(props) { super(props); this.state = { hasFocus: false, isEmpty: true, }; } render() { const { clearIcon, containerStyle, leftIconContainerStyle, rightIconContainerStyle, inputContainerStyle, inputStyle, searchIcon, cancelIcon, showLoading, loadingProps, ...attributes } = this.props; const { hasFocus, isEmpty } = this.state; const { style: loadingStyle, ...otherLoadingProps } = loadingProps; return ( <View style={StyleSheet.flatten([styles.container, containerStyle])}> <Input {...attributes} testID="searchInput" onFocus={this.onFocus} onBlur={this.onBlur} onChangeText={this.onChangeText} ref={input => (this.input = input)} inputStyle={StyleSheet.flatten([styles.input, inputStyle])} inputContainerStyle={StyleSheet.flatten([ styles.inputContainer, inputContainerStyle, ])} leftIcon={ hasFocus ? renderNode(Icon, cancelIcon, { ...defaultCancelIcon, onPress: this.cancel, }) : renderNode(Icon, searchIcon, defaultSearchIcon) } leftIconContainerStyle={StyleSheet.flatten([ styles.leftIconContainerStyle, leftIconContainerStyle, ])} rightIcon={ <View style={{ flexDirection: 'row' }}> {showLoading && ( <ActivityIndicator key="loading" style={StyleSheet.flatten([{ marginRight: 5 }, loadingStyle])} {...otherLoadingProps} /> )} {!isEmpty && renderNode(Icon, clearIcon, { ...defaultClearIcon, key: 'cancel', onPress: this.clear, })} </View> } rightIconContainerStyle={StyleSheet.flatten([ styles.rightIconContainerStyle, rightIconContainerStyle, ])} /> </View> ); } } SearchBar.propTypes = { clearIcon: nodeType, searchIcon: nodeType, cancelIcon: nodeType, loadingProps: PropTypes.object, showLoading: PropTypes.bool, containerStyle: ViewPropTypes.style, leftIconContainerStyle: ViewPropTypes.style, rightIconContainerStyle: ViewPropTypes.style, inputContainerStyle: ViewPropTypes.style, inputStyle: Text.propTypes.style, onClear: PropTypes.func, onCancel: PropTypes.func, onFocus: PropTypes.func, onBlur: PropTypes.func, onChangeText: PropTypes.func, }; SearchBar.defaultProps = { loadingProps: {}, showLoading: false, onClear: () => null, onCancel: () => null, onFocus: () => null, onBlur: () => null, onChangeText: () => null, searchIcon: defaultSearchIcon, clearIcon: defaultCancelIcon, cancelIcon: defaultCancelIcon, }; const styles = StyleSheet.create({ container: { backgroundColor: 'white', width: SCREEN_WIDTH, paddingTop: 8, paddingBottom: 8, }, input: { marginLeft: 24, marginRight: 8, }, inputContainer: { borderBottomWidth: 0, width: SCREEN_WIDTH, }, rightIconContainerStyle: { marginRight: 8, }, leftIconContainerStyle: { marginLeft: 8, }, }); export default SearchBar;