UNPKG

8.74 kBJavaScriptView Raw
1var __rest = (this && this.__rest) || function (s, e) {
2 var t = {};
3 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4 t[p] = s[p];
5 if (s != null && typeof Object.getOwnPropertySymbols === "function")
6 for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7 if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
8 t[p[i]] = s[p[i]];
9 }
10 return t;
11};
12import React, { Component } from 'react';
13import { TouchableOpacity, LayoutAnimation, StyleSheet, View, ActivityIndicator, Text, } from 'react-native';
14import Input from '../input/Input';
15import Icon from '../icons/Icon';
16import { renderNode } from '../helpers';
17const defaultSearchIcon = (theme) => {
18 var _a, _b, _c;
19 return ({
20 type: 'ionicon',
21 size: 20,
22 name: 'ios-search',
23 color: (_c = (_b = (_a = theme === null || theme === void 0 ? void 0 : theme.colors) === null || _a === void 0 ? void 0 : _a.platform) === null || _b === void 0 ? void 0 : _b.ios) === null || _c === void 0 ? void 0 : _c.grey,
24 });
25};
26const defaultClearIcon = (theme) => {
27 var _a, _b, _c;
28 return ({
29 type: 'ionicon',
30 name: 'ios-close-circle',
31 size: 20,
32 color: (_c = (_b = (_a = theme === null || theme === void 0 ? void 0 : theme.colors) === null || _a === void 0 ? void 0 : _a.platform) === null || _b === void 0 ? void 0 : _b.ios) === null || _c === void 0 ? void 0 : _c.grey,
33 });
34};
35class SearchBar extends Component {
36 constructor(props) {
37 super(props);
38 this.focus = () => {
39 this.input.focus();
40 };
41 this.blur = () => {
42 this.input.blur();
43 };
44 this.clear = () => {
45 this.input.clear();
46 this.onChangeText('');
47 this.props.onClear();
48 };
49 this.cancel = () => {
50 this.onChangeText('');
51 if (this.props.showCancel) {
52 LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
53 this.setState({ hasFocus: false });
54 }
55 setTimeout(() => {
56 this.blur();
57 this.props.onCancel();
58 }, 0);
59 };
60 this.onFocus = (event) => {
61 this.props.onFocus(event);
62 LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
63 this.setState({
64 hasFocus: true,
65 isEmpty: this.props.value === '',
66 });
67 };
68 this.onBlur = (event) => {
69 this.props.onBlur(event);
70 if (!this.props.showCancel) {
71 LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
72 this.setState({
73 hasFocus: false,
74 });
75 }
76 };
77 this.onChangeText = (text) => {
78 this.props.onChangeText(text);
79 this.setState({ isEmpty: text === '' });
80 };
81 const { value } = props;
82 this.state = {
83 hasFocus: false,
84 isEmpty: value ? value === '' : true,
85 cancelButtonWidth: null,
86 };
87 }
88 render() {
89 var _a, _b, _c, _d, _e, _f, _g;
90 const _h = this.props, { theme, cancelButtonProps, cancelButtonTitle, clearIcon, containerStyle, leftIconContainerStyle, rightIconContainerStyle, inputContainerStyle, inputStyle, placeholderTextColor, showLoading, loadingProps, searchIcon, showCancel } = _h, attributes = __rest(_h, ["theme", "cancelButtonProps", "cancelButtonTitle", "clearIcon", "containerStyle", "leftIconContainerStyle", "rightIconContainerStyle", "inputContainerStyle", "inputStyle", "placeholderTextColor", "showLoading", "loadingProps", "searchIcon", "showCancel"]);
91 const { hasFocus, isEmpty } = this.state;
92 const { style: loadingStyle } = loadingProps, otherLoadingProps = __rest(loadingProps, ["style"]);
93 const { buttonStyle, buttonTextStyle, color: buttonColor, disabled: buttonDisabled, buttonDisabledStyle, buttonDisabledTextStyle } = cancelButtonProps, otherCancelButtonProps = __rest(cancelButtonProps, ["buttonStyle", "buttonTextStyle", "color", "disabled", "buttonDisabledStyle", "buttonDisabledTextStyle"]);
94 return (<View style={StyleSheet.flatten([
95 styles.container,
96 { backgroundColor: (_a = theme === null || theme === void 0 ? void 0 : theme.colors) === null || _a === void 0 ? void 0 : _a.white },
97 containerStyle,
98 ])}>
99 <Input testID="searchInput" renderErrorMessage={false} {...attributes} onFocus={this.onFocus} onBlur={this.onBlur} onChangeText={this.onChangeText} ref={(input) => {
100 this.input = input;
101 }} inputStyle={StyleSheet.flatten([styles.input, inputStyle])} containerStyle={{
102 paddingHorizontal: 0,
103 }} inputContainerStyle={StyleSheet.flatten([
104 styles.inputContainer,
105 { backgroundColor: (_d = (_c = (_b = theme === null || theme === void 0 ? void 0 : theme.colors) === null || _b === void 0 ? void 0 : _b.platform) === null || _c === void 0 ? void 0 : _c.ios) === null || _d === void 0 ? void 0 : _d.searchBg },
106 hasFocus && {
107 marginRight: this.state.cancelButtonWidth
108 ? this.state.cancelButtonWidth
109 : 0,
110 },
111 inputContainerStyle,
112 ])} leftIcon={renderNode(Icon, searchIcon, defaultSearchIcon(theme))} leftIconContainerStyle={StyleSheet.flatten([
113 styles.leftIconContainerStyle,
114 leftIconContainerStyle,
115 ])} placeholderTextColor={placeholderTextColor || ((_g = (_f = (_e = theme === null || theme === void 0 ? void 0 : theme.colors) === null || _e === void 0 ? void 0 : _e.platform) === null || _f === void 0 ? void 0 : _f.ios) === null || _g === void 0 ? void 0 : _g.grey)} rightIcon={<View style={{ flexDirection: 'row' }}>
116 {showLoading && (<ActivityIndicator key="loading" style={StyleSheet.flatten([{ marginRight: 5 }, loadingStyle])} {...otherLoadingProps}/>)}
117 {!isEmpty &&
118 renderNode(Icon, clearIcon, Object.assign(Object.assign({}, defaultClearIcon(theme)), { key: 'cancel', onPress: this.clear }))}
119 </View>} rightIconContainerStyle={StyleSheet.flatten([
120 styles.rightIconContainerStyle,
121 rightIconContainerStyle,
122 ])}/>
123
124 <View style={StyleSheet.flatten([
125 styles.cancelButtonContainer,
126 {
127 opacity: this.state.cancelButtonWidth === null ? 0 : 1,
128 right: hasFocus
129 ? 0
130 : this.state.cancelButtonWidth && -this.state.cancelButtonWidth,
131 },
132 ])} onLayout={(event) => this.setState({ cancelButtonWidth: event.nativeEvent.layout.width })}>
133 <TouchableOpacity accessibilityRole="button" onPress={this.cancel} disabled={buttonDisabled} {...otherCancelButtonProps}>
134 <View style={[buttonStyle, buttonDisabled && buttonDisabledStyle]}>
135 <Text style={[
136 styles.buttonTextStyle,
137 buttonColor && { color: buttonColor },
138 buttonTextStyle,
139 buttonDisabled &&
140 (buttonDisabledTextStyle || styles.buttonTextDisabled),
141 ]}>
142 {cancelButtonTitle}
143 </Text>
144 </View>
145 </TouchableOpacity>
146 </View>
147 </View>);
148 }
149}
150SearchBar.defaultProps = {
151 value: '',
152 cancelButtonTitle: 'Cancel',
153 loadingProps: {},
154 cancelButtonProps: {},
155 showLoading: false,
156 onClear: () => null,
157 onCancel: () => null,
158 onFocus: () => null,
159 onBlur: () => null,
160 onChangeText: () => null,
161 searchIcon: { name: 'ios-search' },
162 clearIcon: { name: 'ios-close-circle' },
163 showCancel: false,
164};
165const styles = StyleSheet.create({
166 container: {
167 paddingBottom: 13,
168 paddingTop: 13,
169 flexDirection: 'row',
170 overflow: 'hidden',
171 alignItems: 'center',
172 },
173 input: {
174 marginLeft: 6,
175 overflow: 'hidden',
176 },
177 inputContainer: {
178 borderBottomWidth: 0,
179 borderRadius: 9,
180 minHeight: 36,
181 marginLeft: 8,
182 marginRight: 8,
183 },
184 rightIconContainerStyle: {
185 marginRight: 8,
186 },
187 leftIconContainerStyle: {
188 marginLeft: 8,
189 },
190 buttonTextStyle: {
191 color: '#007aff',
192 textAlign: 'center',
193 padding: 8,
194 fontSize: 18,
195 },
196 buttonTextDisabled: {
197 color: '#cdcdcd',
198 },
199 cancelButtonContainer: {
200 position: 'absolute',
201 },
202});
203export default SearchBar;