UNPKG

13.8 kBJavaScriptView Raw
1import _extends from 'babel-runtime/helpers/extends';
2import _objectWithoutProperties from 'babel-runtime/helpers/objectWithoutProperties';
3import _classCallCheck from 'babel-runtime/helpers/classCallCheck';
4import _possibleConstructorReturn from 'babel-runtime/helpers/possibleConstructorReturn';
5import _inherits from 'babel-runtime/helpers/inherits';
6
7var _class, _temp, _initialiseProps;
8
9import React, { isValidElement } from 'react';
10import PropTypes from 'prop-types';
11import classNames from 'classnames';
12import { polyfill } from 'react-lifecycles-compat';
13
14import Input from '../input';
15import Select from '../select';
16import Button from '../button';
17import Icon from '../icon';
18import { obj, func, KEYCODE } from '../util';
19import zhCN from '../locale/zh-cn';
20
21var Group = Input.Group;
22var AutoComplete = Select.AutoComplete;
23var noop = func.noop;
24
25/**
26 * Search
27 * @description 输入框部分继承 Select.AutoComplete 的能力,可以直接用AutoComplete 的 api
28 */
29
30var Search = (_temp = _class = function (_React$Component) {
31 _inherits(Search, _React$Component);
32
33 function Search(props) {
34 _classCallCheck(this, Search);
35
36 var _this = _possibleConstructorReturn(this, _React$Component.call(this, props));
37
38 _initialiseProps.call(_this);
39
40 var value = 'value' in props ? props.value : props.defaultValue;
41 var filterValue = 'filterValue' in props ? props.filterValue : props.defaultFilterValue;
42
43 _this.state = {
44 value: typeof value === 'undefined' ? '' : value,
45 filterValue: filterValue
46 };
47
48 _this.highlightKey = null;
49 return _this;
50 }
51
52 Search.getDerivedStateFromProps = function getDerivedStateFromProps(nextProps, prevState) {
53 var nextState = {};
54 if ('value' in nextProps && nextProps.value !== prevState.value) {
55 var value = nextProps.value;
56 nextState.value = value === undefined || value === null ? '' : nextProps.value;
57 }
58
59 if ('filterValue' in nextProps && nextProps.filterValue !== prevState.filterValue) {
60 var filterValue = nextProps.filterValue;
61 nextState.filterValue = filterValue === undefined ? '' : filterValue;
62 }
63
64 if (Object.keys(nextState).length > 0) {
65 return nextState;
66 }
67
68 return null;
69 };
70
71 Search.prototype.focus = function focus() {
72 var _inputRef;
73
74 (_inputRef = this.inputRef).focus.apply(_inputRef, arguments);
75 };
76
77 Search.prototype.render = function render() {
78 var _classNames;
79
80 var _props = this.props,
81 shape = _props.shape,
82 filter = _props.filter,
83 hasIcon = _props.hasIcon,
84 disabled = _props.disabled,
85 placeholder = _props.placeholder,
86 type = _props.type,
87 className = _props.className,
88 style = _props.style,
89 size = _props.size,
90 prefix = _props.prefix,
91 searchText = _props.searchText,
92 dataSource = _props.dataSource,
93 filterProps = _props.filterProps,
94 buttonProps = _props.buttonProps,
95 fillProps = _props.fillProps,
96 popupContent = _props.popupContent,
97 followTrigger = _props.followTrigger,
98 hasClear = _props.hasClear,
99 visible = _props.visible,
100 locale = _props.locale,
101 rtl = _props.rtl,
102 icons = _props.icons,
103 autoHighlightFirstItem = _props.autoHighlightFirstItem,
104 others = _objectWithoutProperties(_props, ['shape', 'filter', 'hasIcon', 'disabled', 'placeholder', 'type', 'className', 'style', 'size', 'prefix', 'searchText', 'dataSource', 'filterProps', 'buttonProps', 'fillProps', 'popupContent', 'followTrigger', 'hasClear', 'visible', 'locale', 'rtl', 'icons', 'autoHighlightFirstItem']);
105
106 var cls = classNames((_classNames = {}, _classNames[prefix + 'search'] = true, _classNames[prefix + 'search-' + shape] = true, _classNames['' + prefix + type] = type, _classNames['' + prefix + size] = size, _classNames[prefix + 'disabled'] = !!disabled, _classNames[className] = !!className, _classNames));
107
108 var searchIcon = null,
109 filterSelect = null,
110 searchBtn = null,
111 iconsSearch = icons.search;
112
113 if (!isValidElement(icons.search) && icons.search) {
114 iconsSearch = React.createElement(
115 'span',
116 null,
117 icons.search
118 );
119 }
120
121 if (shape === 'simple') {
122 var _classNames2;
123
124 var _cls = classNames((_classNames2 = {}, _classNames2[prefix + 'search-icon'] = true, _classNames2[buttonProps.className] = !!buttonProps.className, _classNames2[prefix + 'search-symbol-icon'] = !iconsSearch, _classNames2));
125 hasIcon && (searchIcon = React.cloneElement(iconsSearch || React.createElement(Icon, { type: 'search' }), _extends({
126 role: 'button',
127 'aria-disabled': disabled,
128 'aria-label': locale.buttonText
129 }, buttonProps, {
130 className: _cls,
131 onClick: this.onSearch,
132 onKeyDown: this.onKeyDown
133 })));
134 } else {
135 var _classNames3;
136
137 var _cls2 = classNames((_classNames3 = {}, _classNames3[prefix + 'search-btn'] = true, _classNames3[buttonProps.className] = !!buttonProps.className, _classNames3));
138 searchBtn = React.createElement(
139 Button,
140 _extends({
141 tabIndex: '0',
142 'aria-disabled': disabled,
143 'aria-label': locale.buttonText,
144 className: _cls2,
145 disabled: disabled
146 }, buttonProps, {
147 onClick: this.onSearch,
148 onKeyDown: this.onKeyDown
149 }),
150 hasIcon ? iconsSearch || React.createElement(Icon, { type: 'search', className: prefix + 'search-symbol-icon' }) : null,
151 searchText ? React.createElement(
152 'span',
153 { className: prefix + 'search-btn-text' },
154 searchText
155 ) : null
156 );
157 }
158
159 if (filter.length > 0) {
160 filterSelect = React.createElement(Select, _extends({}, filterProps, {
161 followTrigger: followTrigger,
162 hasBorder: false,
163 dataSource: filter,
164 size: size,
165 disabled: disabled,
166 value: this.state.filterValue,
167 onChange: this.onFilterChange
168 }));
169 }
170
171 var othersAttributes = obj.pickOthers(Search.propTypes, others);
172 if (visible !== undefined) {
173 // 受控属性 visible 不能直接写在组件上
174 othersAttributes.visible = Boolean(visible);
175 }
176 var dataAttr = obj.pickAttrsWith(others, 'data-');
177
178 var left = React.createElement(
179 Group,
180 {
181 addonBefore: filterSelect,
182 className: prefix + 'search-left',
183 addonBeforeClassName: prefix + 'search-left-addon'
184 },
185 React.createElement(AutoComplete, _extends({
186 'aria-label': locale.buttonText
187 }, othersAttributes, {
188 followTrigger: followTrigger,
189 role: 'searchbox',
190 hasClear: hasClear,
191 className: prefix + 'search-input',
192 size: size,
193 fillProps: fillProps,
194 placeholder: placeholder,
195 dataSource: dataSource,
196 innerAfter: searchIcon,
197 onPressEnter: this.onPressEnter,
198 value: this.state.value,
199 onChange: this.onChange,
200 onToggleHighlightItem: this.onToggleHighlightItem,
201 autoHighlightFirstItem: autoHighlightFirstItem,
202 popupContent: popupContent,
203 disabled: disabled,
204 ref: this.saveInputRef
205 }))
206 );
207
208 return React.createElement(
209 'span',
210 _extends({ className: cls, style: style }, dataAttr, { dir: rtl ? 'rtl' : undefined }),
211 searchBtn ? React.createElement(
212 Group,
213 { addonAfter: searchBtn },
214 left
215 ) : left
216 );
217 };
218
219 return Search;
220}(React.Component), _class.propTypes = {
221 /**
222 * 样式前缀
223 */
224 prefix: PropTypes.string,
225 /**
226 * 形状
227 */
228 shape: PropTypes.oneOf(['normal', 'simple']),
229 /**
230 * 类型 shape=normal: primary/secondary; shape=simple: normal/dark;
231 */
232 type: PropTypes.oneOf(['primary', 'secondary', 'normal', 'dark']),
233 /**
234 * 大小
235 * @enumdesc '大', '小'
236 */
237 size: PropTypes.oneOf(['large', 'medium']),
238 /**
239 * 搜索框默认值
240 */
241 defaultValue: PropTypes.string,
242 /**
243 * 搜索框数值
244 */
245 value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
246 /**
247 * 输入关键字时的回掉
248 * @param {Object} value 输入值
249 */
250 onChange: PropTypes.func,
251 /**
252 * 点击搜索按钮触发的回调
253 * @param {String} value 输入值
254 * @param {String} filterValue 选项值
255 */
256 onSearch: PropTypes.func,
257 /**
258 * 选择器默认值
259 */
260 defaultFilterValue: PropTypes.string,
261 /**
262 * 填充到输入框里的值的 key ,默认是value
263 */
264 fillProps: PropTypes.string,
265 /**
266 * 选择器
267 */
268 filter: PropTypes.array,
269 /**
270 * 选择器值
271 */
272 filterValue: PropTypes.string,
273 /**
274 * 选择器发生变化时回调
275 * @param {Object} filter value
276 */
277 onFilterChange: PropTypes.func,
278 /**
279 * 搜索框下拉联想列表
280 */
281 dataSource: PropTypes.array,
282 /**
283 * 默认提示
284 */
285 placeholder: PropTypes.string,
286 /**
287 * button 的内容
288 */
289 searchText: PropTypes.node,
290 /**
291 * 自定义样式
292 */
293 style: PropTypes.object,
294 /**
295 * 样式名称
296 */
297 className: PropTypes.string,
298 /**
299 * 选择器的props
300 */
301 filterProps: PropTypes.object,
302 /**
303 * 按钮的额外属性
304 */
305 buttonProps: PropTypes.object,
306 /**
307 * 自定义渲染的的下拉框
308 */
309 popupContent: PropTypes.node,
310 /**
311 * 是否跟随滚动
312 */
313 followTrigger: PropTypes.bool,
314 /**
315 * 自定义渲染的的下拉框
316 */
317 visible: PropTypes.bool,
318 /**
319 * 是否显示清除按钮
320 */
321 hasClear: PropTypes.bool,
322 /**
323 * 是否显示搜索按钮
324 */
325 hasIcon: PropTypes.bool,
326 /**
327 * 是否禁用
328 */
329 disabled: PropTypes.bool,
330 locale: PropTypes.object,
331 rtl: PropTypes.bool,
332 /**
333 * 可配置的icons,包括 search 等
334 */
335 icons: PropTypes.object,
336 /**
337 * 是否自动高亮第一个元素
338 */
339 autoHighlightFirstItem: PropTypes.bool,
340 /**
341 * 上下箭头切换选项的回调
342 */
343 onToggleHighlightItem: PropTypes.func
344}, _class.defaultProps = {
345 prefix: 'next-',
346 shape: 'normal',
347 type: 'normal',
348 size: 'medium',
349 hasIcon: true,
350 filter: [],
351 locale: zhCN.Search,
352 buttonProps: {},
353 onChange: noop,
354 onSearch: noop,
355 onFilterChange: noop,
356 onToggleHighlightItem: noop,
357 hasClear: false,
358 disabled: false,
359 icons: {},
360 autoHighlightFirstItem: true
361}, _initialiseProps = function _initialiseProps() {
362 var _this2 = this;
363
364 this.onChange = function (value, type) {
365 for (var _len = arguments.length, argv = Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {
366 argv[_key - 2] = arguments[_key];
367 }
368
369 var _props2;
370
371 if (_this2.props.disabled) {
372 return;
373 }
374
375 if (!('value' in _this2.props)) {
376 _this2.setState({ value: value });
377 }
378
379 (_props2 = _this2.props).onChange.apply(_props2, [value, type].concat(argv));
380 if (type === 'enter') {
381 _this2.highlightKey = '';
382 _this2.props.onSearch(value, _this2.state.filterValue);
383 }
384 };
385
386 this.onPressEnter = function () {
387 if (_this2.highlightKey) {
388 return;
389 }
390 _this2.onSearch();
391 };
392
393 this.onSearch = function () {
394 if (_this2.props.disabled) {
395 return;
396 }
397 _this2.props.onSearch(_this2.state.value, _this2.state.filterValue);
398 };
399
400 this.onFilterChange = function (filterValue) {
401 if (!('filterValue' in _this2.props)) {
402 _this2.setState({ filterValue: filterValue });
403 }
404
405 _this2.props.onFilterChange(filterValue);
406 };
407
408 this.onToggleHighlightItem = function (highlightKey) {
409 var _props3;
410
411 for (var _len2 = arguments.length, args = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
412 args[_key2 - 1] = arguments[_key2];
413 }
414
415 _this2.highlightKey = highlightKey;
416
417 (_props3 = _this2.props).onToggleHighlightItem.apply(_props3, [highlightKey].concat(args));
418 };
419
420 this.onKeyDown = function (e) {
421 if (_this2.props.disabled) {
422 return;
423 }
424 if (e.keyCode !== KEYCODE.ENTER) {
425 return;
426 }
427 _this2.onSearch();
428 };
429
430 this.saveInputRef = function (ref) {
431 if (ref && ref.getInstance()) {
432 _this2.inputRef = ref.getInstance();
433 }
434 };
435}, _temp);
436Search.displayName = 'Search';
437
438
439export default polyfill(Search);
\No newline at end of file