1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import { Input, Icon, AutoComplete } from 'antd';
import classNames from 'classnames';
import Debounce from 'lodash-decorators/debounce';
import Bind from 'lodash-decorators/bind';
import styles from './index.less';
export default class HeaderSearch extends PureComponent {
static propTypes = {
className: PropTypes.string,
placeholder: PropTypes.string,
onSearch: PropTypes.func,
onChange: PropTypes.func,
onPressEnter: PropTypes.func,
defaultActiveFirstOption: PropTypes.bool,
dataSource: PropTypes.array,
defaultOpen: PropTypes.bool,
onVisibleChange: PropTypes.func,
};
static defaultProps = {
defaultActiveFirstOption: false,
onPressEnter: () => {},
onSearch: () => {},
onChange: () => {},
className: '',
placeholder: '',
dataSource: [],
defaultOpen: false,
onVisibleChange: () => {},
};
static getDerivedStateFromProps(props) {
if ('open' in props) {
return {
searchMode: props.open,
};
}
return null;
}
constructor(props) {
super(props);
this.state = {
searchMode: props.defaultOpen,
value: '',
};
}
componentWillUnmount() {
clearTimeout(this.timeout);
}
onKeyDown = e => {
if (e.key === 'Enter') {
const { onPressEnter } = this.props;
const { value } = this.state;
this.timeout = setTimeout(() => {
onPressEnter(value); // Fix duplicate onPressEnter
}, 0);
}
};
onChange = value => {
const { onSearch, onChange } = this.props;
this.setState({ value });
if (onSearch) {
onSearch(value);
}
if (onChange) {
onChange(value);
}
};
enterSearchMode = () => {
const { onVisibleChange } = this.props;
onVisibleChange(true);
this.setState({ searchMode: true }, () => {
const { searchMode } = this.state;
if (searchMode) {
this.input.focus();
}
});
};
leaveSearchMode = () => {
this.setState({
searchMode: false,
value: '',
});
};
// NOTE: 不能小于500,如果长按某键,第一次触发auto repeat的间隔是500ms,小于500会导致触发2次
@Bind()
@Debounce(500, {
leading: true,
trailing: false,
})
debouncePressEnter() {
const { onPressEnter } = this.props;
const { value } = this.state;
onPressEnter(value);
}
render() {
const { className, placeholder, open, ...restProps } = this.props;
const { searchMode, value } = this.state;
delete restProps.defaultOpen; // for rc-select not affected
const inputClass = classNames(styles.input, {
[styles.show]: searchMode,
});
return (
<span
className={classNames(className, styles.headerSearch)}
onClick={this.enterSearchMode}
onTransitionEnd={({ propertyName }) => {
if (propertyName === 'width' && !searchMode) {
const { onVisibleChange } = this.props;
onVisibleChange(searchMode);
}
}}
>
<Icon type="search" key="Icon" />
<AutoComplete
key="AutoComplete"
{...restProps}
className={inputClass}
value={value}
onChange={this.onChange}
>
<Input
ref={node => {
this.input = node;
}}
aria-label={placeholder}
placeholder={placeholder}
onKeyDown={this.onKeyDown}
onBlur={this.leaveSearchMode}
/>
</AutoComplete>
</span>
);
}
}