UNPKG

15.3 kBJavaScriptView Raw
1'use strict';
2
3exports.__esModule = true;
4
5var _extends2 = require('babel-runtime/helpers/extends');
6
7var _extends3 = _interopRequireDefault(_extends2);
8
9var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
10
11var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
12
13var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');
14
15var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
16
17var _inherits2 = require('babel-runtime/helpers/inherits');
18
19var _inherits3 = _interopRequireDefault(_inherits2);
20
21var _class, _temp;
22
23var _react = require('react');
24
25var _react2 = _interopRequireDefault(_react);
26
27var _propTypes = require('prop-types');
28
29var _propTypes2 = _interopRequireDefault(_propTypes);
30
31var _classnames = require('classnames');
32
33var _classnames2 = _interopRequireDefault(_classnames);
34
35var _reactLifecyclesCompat = require('react-lifecycles-compat');
36
37var _util = require('../util');
38
39var _input = require('../input');
40
41var _input2 = _interopRequireDefault(_input);
42
43var _base = require('./base');
44
45var _base2 = _interopRequireDefault(_base);
46
47function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
48
49var bindCtx = _util.func.bindCtx,
50 noop = _util.func.noop;
51
52/**
53 * Select.AutoComplete
54 */
55
56var AutoComplete = (_temp = _class = function (_Base) {
57 (0, _inherits3.default)(AutoComplete, _Base);
58
59 function AutoComplete(props) {
60 (0, _classCallCheck3.default)(this, AutoComplete);
61
62 var _this = (0, _possibleConstructorReturn3.default)(this, _Base.call(this, props));
63
64 _this.handleChange = function (value, proxy, item) {
65 var _this$props = _this.props,
66 disabled = _this$props.disabled,
67 readOnly = _this$props.readOnly,
68 filterLocal = _this$props.filterLocal;
69
70
71 if (disabled || readOnly) {
72 return false;
73 }
74
75 var actionType = typeof proxy === 'string' ? proxy : 'change';
76
77 _this.isInputing = actionType === 'change';
78
79 if (filterLocal) {
80 _this.setState({
81 dataSource: _this.dataStore.updateByKey(value)
82 });
83
84 _this.shouldControlPopup(_this.props, actionType);
85 _this.setFirstHightLightKeyForMenu(value);
86 }
87
88 // 非受控模式清空内部数据
89 if (!('value' in _this.props)) {
90 _this.setState({
91 value: value
92 });
93 }
94
95 // 不自动高亮的情况下, highlightKey 根据value精确值走,也就是被选中元素自动高亮,这样也不会影响不在选项内的用户搜索操作
96 if (!_this.props.autoHighlightFirstItem) {
97 _this.setState({
98 highlightKey: value
99 });
100 }
101
102 _this.props.onChange(value, actionType, item);
103
104 if (actionType === 'itemClick' || actionType === 'enter') {
105 // 点击 item 的时候不会触发关闭,需要手动关闭,其它类型比如 keyDown 等都会有其它事件句柄处理
106 _this.setVisible(false, actionType);
107 }
108 };
109
110 _this.isAutoComplete = true;
111 _this.isInputing = false;
112
113 _this.dataStore.setOptions({ key: _this.state.value });
114 (0, _extends3.default)(_this.state, {
115 dataSource: _this.setDataSource(props)
116 });
117
118 bindCtx(_this, ['handleTriggerKeyDown', 'handleMenuSelect', 'handleItemClick']);
119 return _this;
120 }
121
122 AutoComplete.getDerivedStateFromProps = function getDerivedStateFromProps(nextProps, prevState) {
123 var state = {};
124
125 if ('value' in nextProps && nextProps.value !== prevState.value) {
126 (0, _extends3.default)(state, {
127 value: nextProps.value
128 });
129 }
130
131 if ('visible' in nextProps && nextProps.visible !== prevState.visible) {
132 (0, _extends3.default)(state, {
133 visible: nextProps.visible
134 });
135 }
136
137 if (Object.keys(state).length) {
138 return state;
139 }
140
141 return null;
142 };
143
144 AutoComplete.prototype.componentDidUpdate = function componentDidUpdate(prevProps, prevState) {
145 var props = this.props;
146
147 if ('value' in props) {
148 this.dataStore.setOptions({ key: props.value });
149 }
150
151 if (props.filter !== prevProps.filter) {
152 this.dataStore.setOptions({
153 filter: props.filter
154 });
155 }
156 if (props.filterLocal !== prevProps.filterLocal) {
157 this.dataStore.setOptions({
158 filterLocal: props.filterLocal
159 });
160 }
161
162 if (prevProps.children !== props.children || prevProps.dataSource !== props.dataSource) {
163 /* eslint-disable react/no-did-update-set-state */
164 this.setState({
165 dataSource: this.setDataSource(props)
166 });
167
168 // remote dataSource and focused
169 // 因为autoComplete没有下拉数据不展示,搜索并且有数据了需要自动展示下拉
170 if (!props.filterLocal && this.isInputing) {
171 this.shouldControlPopup(props, 'update');
172 }
173 if (!props.filterLocal && !props.popupContent) {
174 this.setFirstHightLightKeyForMenu();
175 }
176 }
177 };
178
179 AutoComplete.prototype.shouldControlPopup = function shouldControlPopup() {
180 var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.props;
181 var type = arguments[1];
182
183 var hasPopup = props.popupContent || this.dataStore.getMenuDS().length;
184 if (hasPopup) {
185 this.setVisible(true, type);
186 } else {
187 this.setVisible(false, type);
188 }
189 };
190
191 AutoComplete.prototype.handleMenuSelect = function handleMenuSelect(keys) {
192 var key = keys[0];
193
194 var mapDS = this.dataStore.getMapDS();
195
196 if (key in mapDS) {
197 var item = mapDS[key];
198 this.handleSelectEvent(key, item, 'itemClick');
199 }
200 };
201
202 AutoComplete.prototype.handleItemClick = function handleItemClick() {
203 this.setVisible(false, 'itemClick');
204 };
205
206 AutoComplete.prototype.handleSelectEvent = function handleSelectEvent(key, item, triggerType) {
207 var value = item && item[this.props.fillProps] || key;
208
209 if (triggerType === 'itemClick' || triggerType === 'enter') {
210 // 点击 item 的时候不会触发关闭,需要手动关闭,其它类型比如 keyDown 等都会有其它事件句柄处理
211 this.setVisible(false, triggerType);
212 }
213
214 this.handleChange(value, triggerType, item);
215 };
216
217 AutoComplete.prototype.handleVisibleChange = function handleVisibleChange(visible, type) {
218 if (!('visible' in this.props) && visible && !this.props.popupContent && !this.dataStore.getMenuDS().length) {
219 return;
220 }
221
222 this.setVisible(visible, type);
223 };
224
225 AutoComplete.prototype.beforeClose = function beforeClose() {
226 this.isInputing = false;
227 };
228
229 /**
230 * Handle trigger keydown event
231 * @param {Event} e
232 */
233
234
235 AutoComplete.prototype.handleTriggerKeyDown = function handleTriggerKeyDown(e) {
236 var _props = this.props,
237 popupContent = _props.popupContent,
238 onToggleHighlightItem = _props.onToggleHighlightItem,
239 onKeyDown = _props.onKeyDown;
240
241 if (popupContent) {
242 e.stopPropagation(); //stopPropagation can make use onChange triggerd while typing space('') in Input
243 return onKeyDown(e);
244 }
245
246 switch (e.keyCode) {
247 case _util.KEYCODE.UP:
248 e.preventDefault();
249 onToggleHighlightItem(this.toggleHighlightItem(-1, e), 'up');
250 break;
251 case _util.KEYCODE.DOWN:
252 e.preventDefault();
253 onToggleHighlightItem(this.toggleHighlightItem(1, e), 'down');
254 break;
255 case _util.KEYCODE.ENTER:
256 e.preventDefault();
257 this.chooseHighlightItem(e);
258 break;
259 case _util.KEYCODE.SPACE:
260 // stopPropagation can make use onChange triggerd while typing space('') in Input
261 e.stopPropagation();
262 break;
263 case _util.KEYCODE.ESC:
264 e.preventDefault();
265 this.state.visible && this.setVisible(false, 'esc');
266 break;
267 default:
268 break;
269 }
270
271 onKeyDown(e);
272 };
273
274 // 回车 选择高亮的 item
275
276
277 AutoComplete.prototype.chooseHighlightItem = function chooseHighlightItem() {
278 if (!this.state.visible) {
279 return false;
280 }
281
282 var highlightKey = this.state.highlightKey;
283
284 var highlightItem = this.dataStore.getEnableDS().find(function (item) {
285 return highlightKey === '' + item.value;
286 });
287
288 if (highlightItem) {
289 this.handleSelectEvent(highlightKey, highlightItem, 'enter');
290 }
291 };
292
293 AutoComplete.prototype.hasClear = function hasClear() {
294 var _props2 = this.props,
295 hasClear = _props2.hasClear,
296 readOnly = _props2.readOnly,
297 disabled = _props2.disabled;
298 var value = this.state.value;
299
300
301 return value && hasClear && !readOnly && !disabled;
302 };
303
304 /**
305 * 选择器
306 * @override
307 * @param {object} props
308 */
309
310
311 AutoComplete.prototype.renderSelect = function renderSelect() {
312 var _classNames;
313
314 var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.props;
315 var placeholder = props.placeholder,
316 size = props.size,
317 prefix = props.prefix,
318 className = props.className,
319 style = props.style,
320 label = props.label,
321 readOnly = props.readOnly,
322 disabled = props.disabled,
323 highlightHolder = props.highlightHolder,
324 locale = props.locale,
325 hasClear = props.hasClear,
326 state = props.state,
327 rtl = props.rtl;
328
329 var others = _util.obj.pickOthers(AutoComplete.propTypes, props);
330 var othersData = _util.obj.pickAttrsWith(others, 'data-');
331
332 var value = this.state.value;
333 var visible = this.state.visible;
334
335 // // 下拉箭头
336 // const arrowNode = this.renderArrowNode(props, () => {
337 // this.focusInput();
338 // this.setVisible(!this.state.visible);
339 // });
340
341 // trigger className
342 var triggerClazz = (0, _classnames2.default)([prefix + 'select', prefix + 'select-auto-complete', prefix + 'size-' + size, className], (_classNames = {}, _classNames[prefix + 'active'] = visible, _classNames[prefix + 'disabled'] = disabled, _classNames));
343
344 // highlightKey into placeholder
345 // compatible with selectPlaceHolder. TODO: removed in 2.0 version
346 var _placeholder = placeholder || locale.autoCompletePlaceholder || locale.autoCompletePlaceHolder;
347 if (highlightHolder && visible) {
348 _placeholder = this.state.highlightKey || _placeholder;
349 }
350
351 // Input props
352 var _inputProps = (0, _extends3.default)({}, _util.obj.pickOthers(othersData, others), {
353 state: state,
354 ref: this.saveInputRef,
355 hasClear: hasClear,
356 value: value,
357 size: size,
358 disabled: disabled,
359 readOnly: readOnly,
360 placeholder: _placeholder,
361 label: label,
362 // extra: arrowNode,
363 onChange: this.handleChange,
364 onKeyDown: this.handleTriggerKeyDown
365 });
366
367 return _react2.default.createElement(
368 'span',
369 (0, _extends3.default)({}, othersData, {
370 className: triggerClazz,
371 style: style,
372 dir: rtl ? 'rtl' : undefined,
373 ref: this.saveSelectRef,
374 onClick: this.focusInput
375 }),
376 _react2.default.createElement(_input2.default, (0, _extends3.default)({
377 role: 'combobox',
378 'aria-autocomplete': 'list',
379 'aria-disabled': disabled,
380 'aria-expanded': this.state.visible
381 }, _inputProps)),
382 _react2.default.createElement(
383 'span',
384 { className: prefix + 'sr-only', 'aria-live': 'polite' },
385 this.state.srReader
386 )
387 );
388 };
389
390 AutoComplete.prototype.render = function render() {
391 var _this2 = this;
392
393 if (this.hasClear()) {
394 // clear 按钮点击后,会在 dom 结构中被删除掉,需要将其额外设置为安全节点,防止触发弹层的显示或隐藏
395 var safeNode = this.props.popupProps.safeNode || [];
396 var safeNodes = Array.isArray(safeNode) ? safeNode : [safeNode];
397 safeNodes.push(function () {
398 return _this2.clearNode;
399 });
400 this.props.popupProps.safeNode = safeNodes;
401 }
402
403 return _Base.prototype.render.call(this, (0, _extends3.default)({}, this.props, { canCloseByTrigger: false }));
404 };
405
406 return AutoComplete;
407}(_base2.default), _class.propTypes = (0, _extends3.default)({}, _base2.default.propTypes, {
408 /**
409 * 当前值,用于受控模式
410 */
411 value: _propTypes2.default.oneOfType([_propTypes2.default.string, _propTypes2.default.number]),
412 /**
413 * 初始化的默认值
414 */
415 defaultValue: _propTypes2.default.oneOfType([_propTypes2.default.string, _propTypes2.default.number]),
416 /**
417 * Select发生改变时触发的回调
418 * @param {*} value 选中的值
419 * @param {String} actionType 触发的方式, 'itemClick', 'enter', 'change'
420 * @param {*} item 选中的值的对象数据
421 */
422 onChange: _propTypes2.default.func,
423 /**
424 * 传入的数据源,可以动态渲染子项
425 */
426 dataSource: _propTypes2.default.arrayOf(_propTypes2.default.oneOfType([_propTypes2.default.shape({
427 value: _propTypes2.default.string,
428 label: _propTypes2.default.any,
429 disabled: _propTypes2.default.bool,
430 children: _propTypes2.default.array
431 }), _propTypes2.default.string])),
432 /**
433 * 填充到选择框里的值的 key,默认是 value
434 */
435 fillProps: _propTypes2.default.string,
436 /**
437 * 渲染 MenuItem 内容的方法
438 * @param {Object} item 渲染节点的 item
439 * @return {ReactNode} item node
440 */
441 itemRender: _propTypes2.default.func,
442 // input keydown
443 onKeyDown: _propTypes2.default.func,
444 // 是否将当前高亮的选项作为 placeholder
445 highlightHolder: _propTypes2.default.bool,
446 style: _propTypes2.default.object
447}), _class.defaultProps = (0, _extends3.default)({}, _base2.default.defaultProps, {
448 onKeyDown: noop,
449 fillProps: 'value'
450}), _temp);
451exports.default = (0, _reactLifecyclesCompat.polyfill)(AutoComplete);
452module.exports = exports['default'];
\No newline at end of file