1 | var __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 | };
|
12 | import React, { Component } from 'react';
|
13 | import { TouchableOpacity, LayoutAnimation, StyleSheet, View, ActivityIndicator, Text, } from 'react-native';
|
14 | import Input from '../input/Input';
|
15 | import Icon from '../icons/Icon';
|
16 | import { renderNode } from '../helpers';
|
17 | const 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 | };
|
26 | const 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 | };
|
35 | class 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 | }
|
150 | SearchBar.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 | };
|
165 | const 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 | });
|
203 | export default SearchBar;
|