1 | import _extends from "@babel/runtime/helpers/esm/extends";
|
2 | import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray";
|
3 | import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
|
4 | import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
|
5 | import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
|
6 | import _objectWithoutProperties from "@babel/runtime/helpers/esm/objectWithoutProperties";
|
7 | import _typeof from "@babel/runtime/helpers/esm/typeof";
|
8 | var _excluded = ["id", "mode", "prefixCls", "backfill", "fieldNames", "inputValue", "searchValue", "onSearch", "autoClearSearchValue", "onSelect", "onDeselect", "dropdownMatchSelectWidth", "filterOption", "filterSort", "optionFilterProp", "optionLabelProp", "options", "children", "defaultActiveFirstOption", "menuItemSelectedIcon", "virtual", "direction", "listHeight", "listItemHeight", "value", "defaultValue", "labelInValue", "onChange"];
|
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 | import useMergedState from "rc-util/es/hooks/useMergedState";
|
41 | import warning from "rc-util/es/warning";
|
42 | import * as React from 'react';
|
43 | import BaseSelect, { isMultiple } from "./BaseSelect";
|
44 | import useCache from "./hooks/useCache";
|
45 | import useFilterOptions from "./hooks/useFilterOptions";
|
46 | import useId from "./hooks/useId";
|
47 | import useOptions from "./hooks/useOptions";
|
48 | import useRefFunc from "./hooks/useRefFunc";
|
49 | import OptGroup from "./OptGroup";
|
50 | import Option from "./Option";
|
51 | import OptionList from "./OptionList";
|
52 | import SelectContext from "./SelectContext";
|
53 | import { hasValue, isComboNoValue, toArray } from "./utils/commonUtil";
|
54 | import { fillFieldNames, flattenOptions, injectPropsWithOption } from "./utils/valueUtil";
|
55 | import warningProps, { warningNullOptions } from "./utils/warningPropsUtil";
|
56 | var OMIT_DOM_PROPS = ['inputValue'];
|
57 | function isRawValue(value) {
|
58 | return !value || _typeof(value) !== 'object';
|
59 | }
|
60 | var Select = React.forwardRef(function (props, ref) {
|
61 | var id = props.id,
|
62 | mode = props.mode,
|
63 | _props$prefixCls = props.prefixCls,
|
64 | prefixCls = _props$prefixCls === void 0 ? 'rc-select' : _props$prefixCls,
|
65 | backfill = props.backfill,
|
66 | fieldNames = props.fieldNames,
|
67 | inputValue = props.inputValue,
|
68 | searchValue = props.searchValue,
|
69 | onSearch = props.onSearch,
|
70 | _props$autoClearSearc = props.autoClearSearchValue,
|
71 | autoClearSearchValue = _props$autoClearSearc === void 0 ? true : _props$autoClearSearc,
|
72 | onSelect = props.onSelect,
|
73 | onDeselect = props.onDeselect,
|
74 | _props$dropdownMatchS = props.dropdownMatchSelectWidth,
|
75 | dropdownMatchSelectWidth = _props$dropdownMatchS === void 0 ? true : _props$dropdownMatchS,
|
76 | filterOption = props.filterOption,
|
77 | filterSort = props.filterSort,
|
78 | optionFilterProp = props.optionFilterProp,
|
79 | optionLabelProp = props.optionLabelProp,
|
80 | options = props.options,
|
81 | children = props.children,
|
82 | defaultActiveFirstOption = props.defaultActiveFirstOption,
|
83 | menuItemSelectedIcon = props.menuItemSelectedIcon,
|
84 | virtual = props.virtual,
|
85 | direction = props.direction,
|
86 | _props$listHeight = props.listHeight,
|
87 | listHeight = _props$listHeight === void 0 ? 200 : _props$listHeight,
|
88 | _props$listItemHeight = props.listItemHeight,
|
89 | listItemHeight = _props$listItemHeight === void 0 ? 20 : _props$listItemHeight,
|
90 | value = props.value,
|
91 | defaultValue = props.defaultValue,
|
92 | labelInValue = props.labelInValue,
|
93 | onChange = props.onChange,
|
94 | restProps = _objectWithoutProperties(props, _excluded);
|
95 | var mergedId = useId(id);
|
96 | var multiple = isMultiple(mode);
|
97 | var childrenAsData = !!(!options && children);
|
98 | var mergedFilterOption = React.useMemo(function () {
|
99 | if (filterOption === undefined && mode === 'combobox') {
|
100 | return false;
|
101 | }
|
102 | return filterOption;
|
103 | }, [filterOption, mode]);
|
104 |
|
105 |
|
106 | var mergedFieldNames = React.useMemo(function () {
|
107 | return fillFieldNames(fieldNames, childrenAsData);
|
108 | },
|
109 | [
|
110 |
|
111 | JSON.stringify(fieldNames), childrenAsData]
|
112 | );
|
113 |
|
114 |
|
115 | var _useMergedState = useMergedState('', {
|
116 | value: searchValue !== undefined ? searchValue : inputValue,
|
117 | postState: function postState(search) {
|
118 | return search || '';
|
119 | }
|
120 | }),
|
121 | _useMergedState2 = _slicedToArray(_useMergedState, 2),
|
122 | mergedSearchValue = _useMergedState2[0],
|
123 | setSearchValue = _useMergedState2[1];
|
124 |
|
125 |
|
126 | var parsedOptions = useOptions(options, children, mergedFieldNames, optionFilterProp, optionLabelProp);
|
127 | var valueOptions = parsedOptions.valueOptions,
|
128 | labelOptions = parsedOptions.labelOptions,
|
129 | mergedOptions = parsedOptions.options;
|
130 |
|
131 |
|
132 | var convert2LabelValues = React.useCallback(function (draftValues) {
|
133 |
|
134 | var valueList = toArray(draftValues);
|
135 |
|
136 |
|
137 | return valueList.map(function (val) {
|
138 | var rawValue;
|
139 | var rawLabel;
|
140 | var rawKey;
|
141 | var rawDisabled;
|
142 | var rawTitle;
|
143 |
|
144 |
|
145 | if (isRawValue(val)) {
|
146 | rawValue = val;
|
147 | } else {
|
148 | var _val$value;
|
149 | rawKey = val.key;
|
150 | rawLabel = val.label;
|
151 | rawValue = (_val$value = val.value) !== null && _val$value !== void 0 ? _val$value : rawKey;
|
152 | }
|
153 | var option = valueOptions.get(rawValue);
|
154 | if (option) {
|
155 | var _option$key;
|
156 |
|
157 | if (rawLabel === undefined) rawLabel = option === null || option === void 0 ? void 0 : option[optionLabelProp || mergedFieldNames.label];
|
158 | if (rawKey === undefined) rawKey = (_option$key = option === null || option === void 0 ? void 0 : option.key) !== null && _option$key !== void 0 ? _option$key : rawValue;
|
159 | rawDisabled = option === null || option === void 0 ? void 0 : option.disabled;
|
160 | rawTitle = option === null || option === void 0 ? void 0 : option.title;
|
161 |
|
162 |
|
163 | if (process.env.NODE_ENV !== 'production' && !optionLabelProp) {
|
164 | var optionLabel = option === null || option === void 0 ? void 0 : option[mergedFieldNames.label];
|
165 | if (optionLabel !== undefined && ! React.isValidElement(optionLabel) && ! React.isValidElement(rawLabel) && optionLabel !== rawLabel) {
|
166 | warning(false, '`label` of `value` is not same as `label` in Select options.');
|
167 | }
|
168 | }
|
169 | }
|
170 | return {
|
171 | label: rawLabel,
|
172 | value: rawValue,
|
173 | key: rawKey,
|
174 | disabled: rawDisabled,
|
175 | title: rawTitle
|
176 | };
|
177 | });
|
178 | }, [mergedFieldNames, optionLabelProp, valueOptions]);
|
179 |
|
180 |
|
181 | var _useMergedState3 = useMergedState(defaultValue, {
|
182 | value: value
|
183 | }),
|
184 | _useMergedState4 = _slicedToArray(_useMergedState3, 2),
|
185 | internalValue = _useMergedState4[0],
|
186 | setInternalValue = _useMergedState4[1];
|
187 |
|
188 |
|
189 | var rawLabeledValues = React.useMemo(function () {
|
190 | var _values$;
|
191 | var values = convert2LabelValues(internalValue);
|
192 |
|
193 |
|
194 | if (mode === 'combobox' && isComboNoValue((_values$ = values[0]) === null || _values$ === void 0 ? void 0 : _values$.value)) {
|
195 | return [];
|
196 | }
|
197 | return values;
|
198 | }, [internalValue, convert2LabelValues, mode]);
|
199 |
|
200 |
|
201 | var _useCache = useCache(rawLabeledValues, valueOptions),
|
202 | _useCache2 = _slicedToArray(_useCache, 2),
|
203 | mergedValues = _useCache2[0],
|
204 | getMixedOption = _useCache2[1];
|
205 | var displayValues = React.useMemo(function () {
|
206 |
|
207 |
|
208 | if (!mode && mergedValues.length === 1) {
|
209 | var firstValue = mergedValues[0];
|
210 | if (firstValue.value === null && (firstValue.label === null || firstValue.label === undefined)) {
|
211 | return [];
|
212 | }
|
213 | }
|
214 | return mergedValues.map(function (item) {
|
215 | var _item$label;
|
216 | return _objectSpread(_objectSpread({}, item), {}, {
|
217 | label: (_item$label = item.label) !== null && _item$label !== void 0 ? _item$label : item.value
|
218 | });
|
219 | });
|
220 | }, [mode, mergedValues]);
|
221 |
|
222 |
|
223 | var rawValues = React.useMemo(function () {
|
224 | return new Set(mergedValues.map(function (val) {
|
225 | return val.value;
|
226 | }));
|
227 | }, [mergedValues]);
|
228 | React.useEffect(function () {
|
229 | if (mode === 'combobox') {
|
230 | var _mergedValues$;
|
231 | var strValue = (_mergedValues$ = mergedValues[0]) === null || _mergedValues$ === void 0 ? void 0 : _mergedValues$.value;
|
232 | setSearchValue(hasValue(strValue) ? String(strValue) : '');
|
233 | }
|
234 | }, [mergedValues]);
|
235 |
|
236 |
|
237 |
|
238 | var createTagOption = useRefFunc(function (val, label) {
|
239 | var _ref;
|
240 | var mergedLabel = label !== null && label !== void 0 ? label : val;
|
241 | return _ref = {}, _defineProperty(_ref, mergedFieldNames.value, val), _defineProperty(_ref, mergedFieldNames.label, mergedLabel), _ref;
|
242 | });
|
243 |
|
244 |
|
245 | var filledTagOptions = React.useMemo(function () {
|
246 | if (mode !== 'tags') {
|
247 | return mergedOptions;
|
248 | }
|
249 |
|
250 |
|
251 | var cloneOptions = _toConsumableArray(mergedOptions);
|
252 |
|
253 |
|
254 | var existOptions = function existOptions(val) {
|
255 | return valueOptions.has(val);
|
256 | };
|
257 |
|
258 |
|
259 | _toConsumableArray(mergedValues).sort(function (a, b) {
|
260 | return a.value < b.value ? -1 : 1;
|
261 | }).forEach(function (item) {
|
262 | var val = item.value;
|
263 | if (!existOptions(val)) {
|
264 | cloneOptions.push(createTagOption(val, item.label));
|
265 | }
|
266 | });
|
267 | return cloneOptions;
|
268 | }, [createTagOption, mergedOptions, valueOptions, mergedValues, mode]);
|
269 | var filteredOptions = useFilterOptions(filledTagOptions, mergedFieldNames, mergedSearchValue, mergedFilterOption, optionFilterProp);
|
270 |
|
271 |
|
272 | var filledSearchOptions = React.useMemo(function () {
|
273 | if (mode !== 'tags' || !mergedSearchValue || filteredOptions.some(function (item) {
|
274 | return item[optionFilterProp || 'value'] === mergedSearchValue;
|
275 | })) {
|
276 | return filteredOptions;
|
277 | }
|
278 |
|
279 |
|
280 | return [createTagOption(mergedSearchValue)].concat(_toConsumableArray(filteredOptions));
|
281 | }, [createTagOption, optionFilterProp, mode, filteredOptions, mergedSearchValue]);
|
282 | var orderedFilteredOptions = React.useMemo(function () {
|
283 | if (!filterSort) {
|
284 | return filledSearchOptions;
|
285 | }
|
286 | return _toConsumableArray(filledSearchOptions).sort(function (a, b) {
|
287 | return filterSort(a, b);
|
288 | });
|
289 | }, [filledSearchOptions, filterSort]);
|
290 | var displayOptions = React.useMemo(function () {
|
291 | return flattenOptions(orderedFilteredOptions, {
|
292 | fieldNames: mergedFieldNames,
|
293 | childrenAsData: childrenAsData
|
294 | });
|
295 | }, [orderedFilteredOptions, mergedFieldNames, childrenAsData]);
|
296 |
|
297 |
|
298 | var triggerChange = function triggerChange(values) {
|
299 | var labeledValues = convert2LabelValues(values);
|
300 | setInternalValue(labeledValues);
|
301 | if (onChange && (
|
302 |
|
303 | labeledValues.length !== mergedValues.length || labeledValues.some(function (newVal, index) {
|
304 | var _mergedValues$index;
|
305 | return ((_mergedValues$index = mergedValues[index]) === null || _mergedValues$index === void 0 ? void 0 : _mergedValues$index.value) !== (newVal === null || newVal === void 0 ? void 0 : newVal.value);
|
306 | }))) {
|
307 | var returnValues = labelInValue ? labeledValues : labeledValues.map(function (v) {
|
308 | return v.value;
|
309 | });
|
310 | var returnOptions = labeledValues.map(function (v) {
|
311 | return injectPropsWithOption(getMixedOption(v.value));
|
312 | });
|
313 | onChange(
|
314 |
|
315 | multiple ? returnValues : returnValues[0],
|
316 |
|
317 | multiple ? returnOptions : returnOptions[0]);
|
318 | }
|
319 | };
|
320 |
|
321 |
|
322 | var _React$useState = React.useState(null),
|
323 | _React$useState2 = _slicedToArray(_React$useState, 2),
|
324 | activeValue = _React$useState2[0],
|
325 | setActiveValue = _React$useState2[1];
|
326 | var _React$useState3 = React.useState(0),
|
327 | _React$useState4 = _slicedToArray(_React$useState3, 2),
|
328 | accessibilityIndex = _React$useState4[0],
|
329 | setAccessibilityIndex = _React$useState4[1];
|
330 | var mergedDefaultActiveFirstOption = defaultActiveFirstOption !== undefined ? defaultActiveFirstOption : mode !== 'combobox';
|
331 | var onActiveValue = React.useCallback(function (active, index) {
|
332 | var _ref2 = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {},
|
333 | _ref2$source = _ref2.source,
|
334 | source = _ref2$source === void 0 ? 'keyboard' : _ref2$source;
|
335 | setAccessibilityIndex(index);
|
336 | if (backfill && mode === 'combobox' && active !== null && source === 'keyboard') {
|
337 | setActiveValue(String(active));
|
338 | }
|
339 | }, [backfill, mode]);
|
340 |
|
341 |
|
342 | var triggerSelect = function triggerSelect(val, selected, type) {
|
343 | var getSelectEnt = function getSelectEnt() {
|
344 | var _option$key2;
|
345 | var option = getMixedOption(val);
|
346 | return [labelInValue ? {
|
347 | label: option === null || option === void 0 ? void 0 : option[mergedFieldNames.label],
|
348 | value: val,
|
349 | key: (_option$key2 = option === null || option === void 0 ? void 0 : option.key) !== null && _option$key2 !== void 0 ? _option$key2 : val
|
350 | } : val, injectPropsWithOption(option)];
|
351 | };
|
352 | if (selected && onSelect) {
|
353 | var _getSelectEnt = getSelectEnt(),
|
354 | _getSelectEnt2 = _slicedToArray(_getSelectEnt, 2),
|
355 | wrappedValue = _getSelectEnt2[0],
|
356 | _option = _getSelectEnt2[1];
|
357 | onSelect(wrappedValue, _option);
|
358 | } else if (!selected && onDeselect && type !== 'clear') {
|
359 | var _getSelectEnt3 = getSelectEnt(),
|
360 | _getSelectEnt4 = _slicedToArray(_getSelectEnt3, 2),
|
361 | _wrappedValue = _getSelectEnt4[0],
|
362 | _option2 = _getSelectEnt4[1];
|
363 | onDeselect(_wrappedValue, _option2);
|
364 | }
|
365 | };
|
366 |
|
367 |
|
368 | var onInternalSelect = useRefFunc(function (val, info) {
|
369 | var cloneValues;
|
370 |
|
371 |
|
372 | var mergedSelect = multiple ? info.selected : true;
|
373 | if (mergedSelect) {
|
374 | cloneValues = multiple ? [].concat(_toConsumableArray(mergedValues), [val]) : [val];
|
375 | } else {
|
376 | cloneValues = mergedValues.filter(function (v) {
|
377 | return v.value !== val;
|
378 | });
|
379 | }
|
380 | triggerChange(cloneValues);
|
381 | triggerSelect(val, mergedSelect);
|
382 |
|
383 |
|
384 | if (mode === 'combobox') {
|
385 |
|
386 | setActiveValue('');
|
387 | } else if (!isMultiple || autoClearSearchValue) {
|
388 | setSearchValue('');
|
389 | setActiveValue('');
|
390 | }
|
391 | });
|
392 |
|
393 |
|
394 |
|
395 | var onDisplayValuesChange = function onDisplayValuesChange(nextValues, info) {
|
396 | triggerChange(nextValues);
|
397 | var type = info.type,
|
398 | values = info.values;
|
399 | if (type === 'remove' || type === 'clear') {
|
400 | values.forEach(function (item) {
|
401 | triggerSelect(item.value, false, type);
|
402 | });
|
403 | }
|
404 | };
|
405 |
|
406 |
|
407 | var onInternalSearch = function onInternalSearch(searchText, info) {
|
408 | setSearchValue(searchText);
|
409 | setActiveValue(null);
|
410 |
|
411 |
|
412 | if (info.source === 'submit') {
|
413 | var formatted = (searchText || '').trim();
|
414 |
|
415 | if (formatted) {
|
416 | var newRawValues = Array.from(new Set([].concat(_toConsumableArray(rawValues), [formatted])));
|
417 | triggerChange(newRawValues);
|
418 | triggerSelect(formatted, true);
|
419 | setSearchValue('');
|
420 | }
|
421 | return;
|
422 | }
|
423 | if (info.source !== 'blur') {
|
424 | if (mode === 'combobox') {
|
425 | triggerChange(searchText);
|
426 | }
|
427 | onSearch === null || onSearch === void 0 ? void 0 : onSearch(searchText);
|
428 | }
|
429 | };
|
430 | var onInternalSearchSplit = function onInternalSearchSplit(words) {
|
431 | var patchValues = words;
|
432 | if (mode !== 'tags') {
|
433 | patchValues = words.map(function (word) {
|
434 | var opt = labelOptions.get(word);
|
435 | return opt === null || opt === void 0 ? void 0 : opt.value;
|
436 | }).filter(function (val) {
|
437 | return val !== undefined;
|
438 | });
|
439 | }
|
440 | var newRawValues = Array.from(new Set([].concat(_toConsumableArray(rawValues), _toConsumableArray(patchValues))));
|
441 | triggerChange(newRawValues);
|
442 | newRawValues.forEach(function (newRawValue) {
|
443 | triggerSelect(newRawValue, true);
|
444 | });
|
445 | };
|
446 |
|
447 |
|
448 | var selectContext = React.useMemo(function () {
|
449 | var realVirtual = virtual !== false && dropdownMatchSelectWidth !== false;
|
450 | return _objectSpread(_objectSpread({}, parsedOptions), {}, {
|
451 | flattenOptions: displayOptions,
|
452 | onActiveValue: onActiveValue,
|
453 | defaultActiveFirstOption: mergedDefaultActiveFirstOption,
|
454 | onSelect: onInternalSelect,
|
455 | menuItemSelectedIcon: menuItemSelectedIcon,
|
456 | rawValues: rawValues,
|
457 | fieldNames: mergedFieldNames,
|
458 | virtual: realVirtual,
|
459 | direction: direction,
|
460 | listHeight: listHeight,
|
461 | listItemHeight: listItemHeight,
|
462 | childrenAsData: childrenAsData
|
463 | });
|
464 | }, [parsedOptions, displayOptions, onActiveValue, mergedDefaultActiveFirstOption, onInternalSelect, menuItemSelectedIcon, rawValues, mergedFieldNames, virtual, dropdownMatchSelectWidth, listHeight, listItemHeight, childrenAsData]);
|
465 |
|
466 |
|
467 | if (process.env.NODE_ENV !== 'production') {
|
468 | warningProps(props);
|
469 | warningNullOptions(mergedOptions, mergedFieldNames);
|
470 | }
|
471 |
|
472 |
|
473 |
|
474 |
|
475 | return React.createElement(SelectContext.Provider, {
|
476 | value: selectContext
|
477 | }, React.createElement(BaseSelect, _extends({}, restProps, {
|
478 |
|
479 | id: mergedId,
|
480 | prefixCls: prefixCls,
|
481 | ref: ref,
|
482 | omitDomProps: OMIT_DOM_PROPS,
|
483 | mode: mode
|
484 |
|
485 | ,
|
486 | displayValues: displayValues,
|
487 | onDisplayValuesChange: onDisplayValuesChange
|
488 |
|
489 | ,
|
490 | direction: direction
|
491 |
|
492 | ,
|
493 | searchValue: mergedSearchValue,
|
494 | onSearch: onInternalSearch,
|
495 | autoClearSearchValue: autoClearSearchValue,
|
496 | onSearchSplit: onInternalSearchSplit,
|
497 | dropdownMatchSelectWidth: dropdownMatchSelectWidth
|
498 |
|
499 | ,
|
500 | OptionList: OptionList,
|
501 | emptyOptions: !displayOptions.length
|
502 |
|
503 | ,
|
504 | activeValue: activeValue,
|
505 | activeDescendantId: "".concat(mergedId, "_list_").concat(accessibilityIndex)
|
506 | })));
|
507 | });
|
508 | if (process.env.NODE_ENV !== 'production') {
|
509 | Select.displayName = 'Select';
|
510 | }
|
511 | var TypedSelect = Select;
|
512 | TypedSelect.Option = Option;
|
513 | TypedSelect.OptGroup = OptGroup;
|
514 | export default TypedSelect; |
\ | No newline at end of file |