react-native-elements
Version:
React Native Elements & UI Toolkit
196 lines (194 loc) • 7.85 kB
JavaScript
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
import React, { Component } from 'react';
import { TouchableOpacity, LayoutAnimation, UIManager, StyleSheet, View, ActivityIndicator, Text, } from 'react-native';
import Input from '../input/Input';
import Icon from '../icons/Icon';
import { renderNode } from '../helpers';
const defaultSearchIcon = (theme) => ({
type: 'ionicon',
size: 20,
name: 'ios-search',
color: theme.colors.platform.ios.grey,
});
const defaultClearIcon = (theme) => ({
type: 'ionicon',
name: 'ios-close-circle',
size: 20,
color: theme.colors.platform.ios.grey,
});
class SearchBar extends Component {
constructor(props) {
super(props);
this.focus = () => {
this.input.focus();
};
this.blur = () => {
this.input.blur();
};
this.clear = () => {
this.input.clear();
this.onChangeText('');
this.props.onClear();
};
this.cancel = () => {
this.onChangeText('');
if (this.props.showCancel) {
// @ts-ignore
UIManager.configureNextLayoutAnimation && LayoutAnimation.easeInEaseOut();
this.setState({ hasFocus: false });
}
setTimeout(() => {
this.blur();
this.props.onCancel();
}, 0);
};
this.onFocus = (event) => {
this.props.onFocus(event);
// @ts-ignore
UIManager.configureNextLayoutAnimation && LayoutAnimation.easeInEaseOut();
this.setState({
hasFocus: true,
isEmpty: this.props.value === '',
});
};
this.onBlur = (event) => {
this.props.onBlur(event);
if (!this.props.showCancel) {
// @ts-ignore
UIManager.configureNextLayoutAnimation && LayoutAnimation.easeInEaseOut();
this.setState({
hasFocus: false,
});
}
};
this.onChangeText = (text) => {
this.props.onChangeText(text);
this.setState({ isEmpty: text === '' });
};
const { value } = props;
this.state = {
hasFocus: false,
isEmpty: value ? value === '' : true,
cancelButtonWidth: null,
};
}
render() {
const _a = this.props, { theme, cancelButtonProps, cancelButtonTitle, clearIcon, containerStyle, leftIconContainerStyle, rightIconContainerStyle, inputContainerStyle, inputStyle, placeholderTextColor, showLoading, loadingProps, searchIcon, showCancel } = _a, attributes = __rest(_a, ["theme", "cancelButtonProps", "cancelButtonTitle", "clearIcon", "containerStyle", "leftIconContainerStyle", "rightIconContainerStyle", "inputContainerStyle", "inputStyle", "placeholderTextColor", "showLoading", "loadingProps", "searchIcon", "showCancel"]);
const { hasFocus, isEmpty } = this.state;
const { style: loadingStyle } = loadingProps, otherLoadingProps = __rest(loadingProps, ["style"]);
const { buttonStyle, buttonTextStyle, color: buttonColor, disabled: buttonDisabled, buttonDisabledStyle, buttonDisabledTextStyle } = cancelButtonProps, otherCancelButtonProps = __rest(cancelButtonProps, ["buttonStyle", "buttonTextStyle", "color", "disabled", "buttonDisabledStyle", "buttonDisabledTextStyle"]);
return (<View style={StyleSheet.flatten([
styles.container,
{ backgroundColor: theme.colors.white },
containerStyle,
])}>
<Input testID="searchInput" renderErrorMessage={false} {...attributes} onFocus={this.onFocus} onBlur={this.onBlur} onChangeText={this.onChangeText}
//@ts-ignore
ref={(input) => {
this.input = input;
}} inputStyle={StyleSheet.flatten([styles.input, inputStyle])} containerStyle={{
paddingHorizontal: 0,
}} inputContainerStyle={StyleSheet.flatten([
styles.inputContainer,
{ backgroundColor: theme.colors.platform.ios.searchBg },
hasFocus && { marginRight: this.state.cancelButtonWidth },
inputContainerStyle,
])} leftIcon={renderNode(Icon, searchIcon, defaultSearchIcon(theme))} leftIconContainerStyle={StyleSheet.flatten([
styles.leftIconContainerStyle,
leftIconContainerStyle,
])} placeholderTextColor={placeholderTextColor || theme.colors.platform.ios.grey} rightIcon={<View style={{ flexDirection: 'row' }}>
{showLoading && (<ActivityIndicator key="loading" style={StyleSheet.flatten([{ marginRight: 5 }, loadingStyle])} {...otherLoadingProps}/>)}
{!isEmpty &&
renderNode(Icon, clearIcon, Object.assign(Object.assign({}, defaultClearIcon(theme)), { key: 'cancel', onPress: this.clear }))}
</View>} rightIconContainerStyle={StyleSheet.flatten([
styles.rightIconContainerStyle,
rightIconContainerStyle,
])}/>
<View style={StyleSheet.flatten([
styles.cancelButtonContainer,
{
opacity: this.state.cancelButtonWidth === null ? 0 : 1,
right: hasFocus ? 0 : -this.state.cancelButtonWidth,
},
])} onLayout={(event) => this.setState({ cancelButtonWidth: event.nativeEvent.layout.width })}>
<TouchableOpacity accessibilityRole="button" onPress={this.cancel} disabled={buttonDisabled} {...otherCancelButtonProps}>
<View style={[buttonStyle, buttonDisabled && buttonDisabledStyle]}>
<Text style={[
styles.buttonTextStyle,
buttonColor && { color: buttonColor },
buttonTextStyle,
buttonDisabled &&
(buttonDisabledTextStyle || styles.buttonTextDisabled),
]}>
{cancelButtonTitle}
</Text>
</View>
</TouchableOpacity>
</View>
</View>);
}
}
SearchBar.defaultProps = {
value: '',
cancelButtonTitle: 'Cancel',
loadingProps: {},
cancelButtonProps: {},
showLoading: false,
onClear: () => null,
onCancel: () => null,
onFocus: () => null,
onBlur: () => null,
onChangeText: () => null,
searchIcon: { name: 'ios-search' },
clearIcon: { name: 'ios-close-circle' },
showCancel: false,
};
const styles = StyleSheet.create({
container: {
paddingBottom: 13,
paddingTop: 13,
flexDirection: 'row',
overflow: 'hidden',
alignItems: 'center',
},
input: {
marginLeft: 6,
overflow: 'hidden',
},
inputContainer: {
borderBottomWidth: 0,
borderRadius: 9,
minHeight: 36,
marginLeft: 8,
marginRight: 8,
},
rightIconContainerStyle: {
marginRight: 8,
},
leftIconContainerStyle: {
marginLeft: 8,
},
buttonTextStyle: {
color: '#007aff',
textAlign: 'center',
padding: 8,
fontSize: 18,
},
buttonTextDisabled: {
color: '#cdcdcd',
},
cancelButtonContainer: {
position: 'absolute',
},
});
export default SearchBar;