@rc-component/select 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (137) hide show
  1. package/LICENSE.md +9 -0
  2. package/README.md +191 -0
  3. package/assets/index.css +306 -0
  4. package/assets/index.less +397 -0
  5. package/es/BaseSelect/Polite.d.ts +7 -0
  6. package/es/BaseSelect/Polite.js +26 -0
  7. package/es/BaseSelect/index.d.ts +118 -0
  8. package/es/BaseSelect/index.js +569 -0
  9. package/es/OptGroup.d.ts +12 -0
  10. package/es/OptGroup.js +6 -0
  11. package/es/Option.d.ts +14 -0
  12. package/es/Option.js +6 -0
  13. package/es/OptionList.d.ts +10 -0
  14. package/es/OptionList.js +379 -0
  15. package/es/Select.d.ts +114 -0
  16. package/es/Select.js +480 -0
  17. package/es/SelectContext.d.ts +23 -0
  18. package/es/SelectContext.js +6 -0
  19. package/es/SelectTrigger.d.ts +30 -0
  20. package/es/SelectTrigger.js +138 -0
  21. package/es/Selector/Input.d.ts +27 -0
  22. package/es/Selector/Input.js +114 -0
  23. package/es/Selector/MultipleSelector.d.ts +16 -0
  24. package/es/Selector/MultipleSelector.js +185 -0
  25. package/es/Selector/SingleSelector.d.ts +8 -0
  26. package/es/Selector/SingleSelector.js +104 -0
  27. package/es/Selector/index.d.ts +85 -0
  28. package/es/Selector/index.js +184 -0
  29. package/es/TransBtn.d.ts +12 -0
  30. package/es/TransBtn.js +30 -0
  31. package/es/hooks/useAllowClear.d.ts +8 -0
  32. package/es/hooks/useAllowClear.js +26 -0
  33. package/es/hooks/useBaseProps.d.ts +13 -0
  34. package/es/hooks/useBaseProps.js +10 -0
  35. package/es/hooks/useCache.d.ts +7 -0
  36. package/es/hooks/useCache.js +40 -0
  37. package/es/hooks/useDelayReset.d.ts +5 -0
  38. package/es/hooks/useDelayReset.js +24 -0
  39. package/es/hooks/useFilterOptions.d.ts +3 -0
  40. package/es/hooks/useFilterOptions.js +57 -0
  41. package/es/hooks/useId.d.ts +5 -0
  42. package/es/hooks/useId.js +29 -0
  43. package/es/hooks/useLayoutEffect.d.ts +5 -0
  44. package/es/hooks/useLayoutEffect.js +17 -0
  45. package/es/hooks/useLock.d.ts +7 -0
  46. package/es/hooks/useLock.js +27 -0
  47. package/es/hooks/useOptions.d.ts +12 -0
  48. package/es/hooks/useOptions.js +45 -0
  49. package/es/hooks/useRefFunc.d.ts +5 -0
  50. package/es/hooks/useRefFunc.js +14 -0
  51. package/es/hooks/useSelectTriggerControl.d.ts +1 -0
  52. package/es/hooks/useSelectTriggerControl.js +27 -0
  53. package/es/index.d.ts +10 -0
  54. package/es/index.js +7 -0
  55. package/es/interface.d.ts +23 -0
  56. package/es/interface.js +1 -0
  57. package/es/utils/__mocks__/platformUtil.d.ts +1 -0
  58. package/es/utils/__mocks__/platformUtil.js +3 -0
  59. package/es/utils/commonUtil.d.ts +9 -0
  60. package/es/utils/commonUtil.js +32 -0
  61. package/es/utils/keyUtil.d.ts +2 -0
  62. package/es/utils/keyUtil.js +16 -0
  63. package/es/utils/legacyUtil.d.ts +3 -0
  64. package/es/utils/legacyUtil.js +44 -0
  65. package/es/utils/platformUtil.d.ts +1 -0
  66. package/es/utils/platformUtil.js +4 -0
  67. package/es/utils/valueUtil.d.ts +24 -0
  68. package/es/utils/valueUtil.js +128 -0
  69. package/es/utils/warningPropsUtil.d.ts +4 -0
  70. package/es/utils/warningPropsUtil.js +119 -0
  71. package/lib/BaseSelect/Polite.d.ts +7 -0
  72. package/lib/BaseSelect/Polite.js +34 -0
  73. package/lib/BaseSelect/index.d.ts +118 -0
  74. package/lib/BaseSelect/index.js +579 -0
  75. package/lib/OptGroup.d.ts +12 -0
  76. package/lib/OptGroup.js +12 -0
  77. package/lib/Option.d.ts +14 -0
  78. package/lib/Option.js +12 -0
  79. package/lib/OptionList.d.ts +10 -0
  80. package/lib/OptionList.js +387 -0
  81. package/lib/Select.d.ts +114 -0
  82. package/lib/Select.js +487 -0
  83. package/lib/SelectContext.d.ts +23 -0
  84. package/lib/SelectContext.js +13 -0
  85. package/lib/SelectTrigger.d.ts +30 -0
  86. package/lib/SelectTrigger.js +147 -0
  87. package/lib/Selector/Input.d.ts +27 -0
  88. package/lib/Selector/Input.js +123 -0
  89. package/lib/Selector/MultipleSelector.d.ts +16 -0
  90. package/lib/Selector/MultipleSelector.js +194 -0
  91. package/lib/Selector/SingleSelector.d.ts +8 -0
  92. package/lib/Selector/SingleSelector.js +113 -0
  93. package/lib/Selector/index.d.ts +85 -0
  94. package/lib/Selector/index.js +191 -0
  95. package/lib/TransBtn.d.ts +12 -0
  96. package/lib/TransBtn.js +39 -0
  97. package/lib/hooks/useAllowClear.d.ts +8 -0
  98. package/lib/hooks/useAllowClear.js +34 -0
  99. package/lib/hooks/useBaseProps.d.ts +13 -0
  100. package/lib/hooks/useBaseProps.js +19 -0
  101. package/lib/hooks/useCache.d.ts +7 -0
  102. package/lib/hooks/useCache.js +49 -0
  103. package/lib/hooks/useDelayReset.d.ts +5 -0
  104. package/lib/hooks/useDelayReset.js +31 -0
  105. package/lib/hooks/useFilterOptions.d.ts +3 -0
  106. package/lib/hooks/useFilterOptions.js +66 -0
  107. package/lib/hooks/useId.d.ts +5 -0
  108. package/lib/hooks/useId.js +40 -0
  109. package/lib/hooks/useLayoutEffect.d.ts +5 -0
  110. package/lib/hooks/useLayoutEffect.js +25 -0
  111. package/lib/hooks/useLock.d.ts +7 -0
  112. package/lib/hooks/useLock.js +34 -0
  113. package/lib/hooks/useOptions.d.ts +12 -0
  114. package/lib/hooks/useOptions.js +52 -0
  115. package/lib/hooks/useRefFunc.d.ts +5 -0
  116. package/lib/hooks/useRefFunc.js +21 -0
  117. package/lib/hooks/useSelectTriggerControl.d.ts +1 -0
  118. package/lib/hooks/useSelectTriggerControl.js +35 -0
  119. package/lib/index.d.ts +10 -0
  120. package/lib/index.js +37 -0
  121. package/lib/interface.d.ts +23 -0
  122. package/lib/interface.js +5 -0
  123. package/lib/utils/__mocks__/platformUtil.d.ts +1 -0
  124. package/lib/utils/__mocks__/platformUtil.js +9 -0
  125. package/lib/utils/commonUtil.d.ts +9 -0
  126. package/lib/utils/commonUtil.js +42 -0
  127. package/lib/utils/keyUtil.d.ts +2 -0
  128. package/lib/utils/keyUtil.js +22 -0
  129. package/lib/utils/legacyUtil.d.ts +3 -0
  130. package/lib/utils/legacyUtil.js +53 -0
  131. package/lib/utils/platformUtil.d.ts +1 -0
  132. package/lib/utils/platformUtil.js +10 -0
  133. package/lib/utils/valueUtil.d.ts +24 -0
  134. package/lib/utils/valueUtil.js +140 -0
  135. package/lib/utils/warningPropsUtil.d.ts +4 -0
  136. package/lib/utils/warningPropsUtil.js +129 -0
  137. package/package.json +86 -0
package/lib/Select.js ADDED
@@ -0,0 +1,487 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _useMergedState = _interopRequireDefault(require("@rc-component/util/lib/hooks/useMergedState"));
8
+ var _warning = _interopRequireDefault(require("@rc-component/util/lib/warning"));
9
+ var React = _interopRequireWildcard(require("react"));
10
+ var _BaseSelect = _interopRequireWildcard(require("./BaseSelect"));
11
+ var _OptGroup = _interopRequireDefault(require("./OptGroup"));
12
+ var _Option = _interopRequireDefault(require("./Option"));
13
+ var _OptionList = _interopRequireDefault(require("./OptionList"));
14
+ var _SelectContext = _interopRequireDefault(require("./SelectContext"));
15
+ var _useCache = _interopRequireDefault(require("./hooks/useCache"));
16
+ var _useFilterOptions = _interopRequireDefault(require("./hooks/useFilterOptions"));
17
+ var _useId = _interopRequireDefault(require("./hooks/useId"));
18
+ var _useOptions = _interopRequireDefault(require("./hooks/useOptions"));
19
+ var _useRefFunc = _interopRequireDefault(require("./hooks/useRefFunc"));
20
+ var _commonUtil = require("./utils/commonUtil");
21
+ var _valueUtil = require("./utils/valueUtil");
22
+ var _warningPropsUtil = _interopRequireWildcard(require("./utils/warningPropsUtil"));
23
+ function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
24
+ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
25
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
26
+ function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } /**
27
+ * To match accessibility requirement, we always provide an input in the component.
28
+ * Other element will not set `tabIndex` to avoid `onBlur` sequence problem.
29
+ * For focused select, we set `aria-live="polite"` to update the accessibility content.
30
+ *
31
+ * ref:
32
+ * - keyboard: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/listbox_role#Keyboard_interactions
33
+ *
34
+ * New api:
35
+ * - listHeight
36
+ * - listItemHeight
37
+ * - component
38
+ *
39
+ * Remove deprecated api:
40
+ * - multiple
41
+ * - tags
42
+ * - combobox
43
+ * - firstActiveValue
44
+ * - dropdownMenuStyle
45
+ * - openClassName (Not list in api)
46
+ *
47
+ * Update:
48
+ * - `backfill` only support `combobox` mode
49
+ * - `combobox` mode not support `labelInValue` since it's meaningless
50
+ * - `getInputElement` only support `combobox` mode
51
+ * - `onChange` return OptionData instead of ReactNode
52
+ * - `filterOption` `onChange` `onSelect` accept OptionData instead of ReactNode
53
+ * - `combobox` mode trigger `onChange` will get `undefined` if no `value` match in Option
54
+ * - `combobox` mode not support `optionLabelProp`
55
+ */
56
+ const OMIT_DOM_PROPS = ['inputValue'];
57
+ function isRawValue(value) {
58
+ return !value || typeof value !== 'object';
59
+ }
60
+ const Select = /*#__PURE__*/React.forwardRef((props, ref) => {
61
+ const {
62
+ id,
63
+ mode,
64
+ prefixCls = 'rc-select',
65
+ backfill,
66
+ fieldNames,
67
+ // Search
68
+ searchValue,
69
+ onSearch,
70
+ autoClearSearchValue = true,
71
+ // Select
72
+ onSelect,
73
+ onDeselect,
74
+ popupMatchSelectWidth = true,
75
+ // Options
76
+ filterOption,
77
+ filterSort,
78
+ optionFilterProp,
79
+ optionLabelProp,
80
+ options,
81
+ optionRender,
82
+ children,
83
+ defaultActiveFirstOption,
84
+ menuItemSelectedIcon,
85
+ virtual,
86
+ direction,
87
+ listHeight = 200,
88
+ listItemHeight = 20,
89
+ labelRender,
90
+ // Value
91
+ value,
92
+ defaultValue,
93
+ labelInValue,
94
+ onChange,
95
+ maxCount,
96
+ ...restProps
97
+ } = props;
98
+ const mergedId = (0, _useId.default)(id);
99
+ const multiple = (0, _BaseSelect.isMultiple)(mode);
100
+ const childrenAsData = !!(!options && children);
101
+ const mergedFilterOption = React.useMemo(() => {
102
+ if (filterOption === undefined && mode === 'combobox') {
103
+ return false;
104
+ }
105
+ return filterOption;
106
+ }, [filterOption, mode]);
107
+
108
+ // ========================= FieldNames =========================
109
+ const mergedFieldNames = React.useMemo(() => (0, _valueUtil.fillFieldNames)(fieldNames, childrenAsData), /* eslint-disable react-hooks/exhaustive-deps */
110
+ [
111
+ // We stringify fieldNames to avoid unnecessary re-renders.
112
+ JSON.stringify(fieldNames), childrenAsData]
113
+ /* eslint-enable react-hooks/exhaustive-deps */);
114
+
115
+ // =========================== Search ===========================
116
+ const [mergedSearchValue, setSearchValue] = (0, _useMergedState.default)('', {
117
+ value: searchValue,
118
+ postState: search => search || ''
119
+ });
120
+
121
+ // =========================== Option ===========================
122
+ const parsedOptions = (0, _useOptions.default)(options, children, mergedFieldNames, optionFilterProp, optionLabelProp);
123
+ const {
124
+ valueOptions,
125
+ labelOptions,
126
+ options: mergedOptions
127
+ } = parsedOptions;
128
+
129
+ // ========================= Wrap Value =========================
130
+ const convert2LabelValues = React.useCallback(draftValues => {
131
+ // Convert to array
132
+ const valueList = (0, _commonUtil.toArray)(draftValues);
133
+
134
+ // Convert to labelInValue type
135
+ return valueList.map(val => {
136
+ let rawValue;
137
+ let rawLabel;
138
+ let rawDisabled;
139
+ let rawTitle;
140
+
141
+ // Fill label & value
142
+ if (isRawValue(val)) {
143
+ rawValue = val;
144
+ } else {
145
+ rawLabel = val.label;
146
+ rawValue = val.value;
147
+ }
148
+ const option = valueOptions.get(rawValue);
149
+ if (option) {
150
+ // Fill missing props
151
+ if (rawLabel === undefined) rawLabel = option?.[optionLabelProp || mergedFieldNames.label];
152
+ rawDisabled = option?.disabled;
153
+ rawTitle = option?.title;
154
+
155
+ // Warning if label not same as provided
156
+ if (process.env.NODE_ENV !== 'production' && !optionLabelProp) {
157
+ const optionLabel = option?.[mergedFieldNames.label];
158
+ if (optionLabel !== undefined && ! /*#__PURE__*/React.isValidElement(optionLabel) && ! /*#__PURE__*/React.isValidElement(rawLabel) && optionLabel !== rawLabel) {
159
+ (0, _warning.default)(false, '`label` of `value` is not same as `label` in Select options.');
160
+ }
161
+ }
162
+ }
163
+ return {
164
+ label: rawLabel,
165
+ value: rawValue,
166
+ key: rawValue,
167
+ disabled: rawDisabled,
168
+ title: rawTitle
169
+ };
170
+ });
171
+ }, [mergedFieldNames, optionLabelProp, valueOptions]);
172
+
173
+ // =========================== Values ===========================
174
+ const [internalValue, setInternalValue] = (0, _useMergedState.default)(defaultValue, {
175
+ value
176
+ });
177
+
178
+ // Merged value with LabelValueType
179
+ const rawLabeledValues = React.useMemo(() => {
180
+ const newInternalValue = multiple && internalValue === null ? [] : internalValue;
181
+ const values = convert2LabelValues(newInternalValue);
182
+
183
+ // combobox no need save value when it's no value (exclude value equal 0)
184
+ if (mode === 'combobox' && (0, _commonUtil.isComboNoValue)(values[0]?.value)) {
185
+ return [];
186
+ }
187
+ return values;
188
+ }, [internalValue, convert2LabelValues, mode, multiple]);
189
+
190
+ // Fill label with cache to avoid option remove
191
+ const [mergedValues, getMixedOption] = (0, _useCache.default)(rawLabeledValues, valueOptions);
192
+ const displayValues = React.useMemo(() => {
193
+ // `null` need show as placeholder instead
194
+ // https://github.com/ant-design/ant-design/issues/25057
195
+ if (!mode && mergedValues.length === 1) {
196
+ const firstValue = mergedValues[0];
197
+ if (firstValue.value === null && (firstValue.label === null || firstValue.label === undefined)) {
198
+ return [];
199
+ }
200
+ }
201
+ return mergedValues.map(item => ({
202
+ ...item,
203
+ label: (typeof labelRender === 'function' ? labelRender(item) : item.label) ?? item.value
204
+ }));
205
+ }, [mode, mergedValues, labelRender]);
206
+
207
+ /** Convert `displayValues` to raw value type set */
208
+ const rawValues = React.useMemo(() => new Set(mergedValues.map(val => val.value)), [mergedValues]);
209
+ React.useEffect(() => {
210
+ if (mode === 'combobox') {
211
+ const strValue = mergedValues[0]?.value;
212
+ setSearchValue((0, _commonUtil.hasValue)(strValue) ? String(strValue) : '');
213
+ }
214
+ }, [mergedValues]);
215
+
216
+ // ======================= Display Option =======================
217
+ // Create a placeholder item if not exist in `options`
218
+ const createTagOption = (0, _useRefFunc.default)((val, label) => {
219
+ const mergedLabel = label ?? val;
220
+ return {
221
+ [mergedFieldNames.value]: val,
222
+ [mergedFieldNames.label]: mergedLabel
223
+ };
224
+ });
225
+
226
+ // Fill tag as option if mode is `tags`
227
+ const filledTagOptions = React.useMemo(() => {
228
+ if (mode !== 'tags') {
229
+ return mergedOptions;
230
+ }
231
+
232
+ // >>> Tag mode
233
+ const cloneOptions = [...mergedOptions];
234
+
235
+ // Check if value exist in options (include new patch item)
236
+ const existOptions = val => valueOptions.has(val);
237
+
238
+ // Fill current value as option
239
+ [...mergedValues].sort((a, b) => a.value < b.value ? -1 : 1).forEach(item => {
240
+ const val = item.value;
241
+ if (!existOptions(val)) {
242
+ cloneOptions.push(createTagOption(val, item.label));
243
+ }
244
+ });
245
+ return cloneOptions;
246
+ }, [createTagOption, mergedOptions, valueOptions, mergedValues, mode]);
247
+ const filteredOptions = (0, _useFilterOptions.default)(filledTagOptions, mergedFieldNames, mergedSearchValue, mergedFilterOption, optionFilterProp);
248
+
249
+ // Fill options with search value if needed
250
+ const filledSearchOptions = React.useMemo(() => {
251
+ if (mode !== 'tags' || !mergedSearchValue || filteredOptions.some(item => item[optionFilterProp || 'value'] === mergedSearchValue)) {
252
+ return filteredOptions;
253
+ }
254
+ // ignore when search value equal select input value
255
+ if (filteredOptions.some(item => item[mergedFieldNames.value] === mergedSearchValue)) {
256
+ return filteredOptions;
257
+ }
258
+ // Fill search value as option
259
+ return [createTagOption(mergedSearchValue), ...filteredOptions];
260
+ }, [createTagOption, optionFilterProp, mode, filteredOptions, mergedSearchValue, mergedFieldNames]);
261
+ const sorter = inputOptions => {
262
+ const sortedOptions = [...inputOptions].sort((a, b) => filterSort(a, b, {
263
+ searchValue: mergedSearchValue
264
+ }));
265
+ return sortedOptions.map(item => {
266
+ if (Array.isArray(item.options)) {
267
+ return {
268
+ ...item,
269
+ options: item.options.length > 0 ? sorter(item.options) : item.options
270
+ };
271
+ }
272
+ return item;
273
+ });
274
+ };
275
+ const orderedFilteredOptions = React.useMemo(() => {
276
+ if (!filterSort) {
277
+ return filledSearchOptions;
278
+ }
279
+ return sorter(filledSearchOptions);
280
+ }, [filledSearchOptions, filterSort, mergedSearchValue]);
281
+ const displayOptions = React.useMemo(() => (0, _valueUtil.flattenOptions)(orderedFilteredOptions, {
282
+ fieldNames: mergedFieldNames,
283
+ childrenAsData
284
+ }), [orderedFilteredOptions, mergedFieldNames, childrenAsData]);
285
+
286
+ // =========================== Change ===========================
287
+ const triggerChange = values => {
288
+ const labeledValues = convert2LabelValues(values);
289
+ setInternalValue(labeledValues);
290
+ if (onChange && (
291
+ // Trigger event only when value changed
292
+ labeledValues.length !== mergedValues.length || labeledValues.some((newVal, index) => mergedValues[index]?.value !== newVal?.value))) {
293
+ const returnValues = labelInValue ? labeledValues.map(({
294
+ label: l,
295
+ value: v
296
+ }) => ({
297
+ label: l,
298
+ value: v
299
+ })) : labeledValues.map(v => v.value);
300
+ const returnOptions = labeledValues.map(v => (0, _valueUtil.injectPropsWithOption)(getMixedOption(v.value)));
301
+ onChange(
302
+ // Value
303
+ multiple ? returnValues : returnValues[0],
304
+ // Option
305
+ multiple ? returnOptions : returnOptions[0]);
306
+ }
307
+ };
308
+
309
+ // ======================= Accessibility ========================
310
+ const [activeValue, setActiveValue] = React.useState(null);
311
+ const [accessibilityIndex, setAccessibilityIndex] = React.useState(0);
312
+ const mergedDefaultActiveFirstOption = defaultActiveFirstOption !== undefined ? defaultActiveFirstOption : mode !== 'combobox';
313
+ const onActiveValue = React.useCallback((active, index, {
314
+ source = 'keyboard'
315
+ } = {}) => {
316
+ setAccessibilityIndex(index);
317
+ if (backfill && mode === 'combobox' && active !== null && source === 'keyboard') {
318
+ setActiveValue(String(active));
319
+ }
320
+ }, [backfill, mode]);
321
+
322
+ // ========================= OptionList =========================
323
+ const triggerSelect = (val, selected, type) => {
324
+ const getSelectEnt = () => {
325
+ const option = getMixedOption(val);
326
+ return [labelInValue ? {
327
+ label: option?.[mergedFieldNames.label],
328
+ value: val
329
+ } : val, (0, _valueUtil.injectPropsWithOption)(option)];
330
+ };
331
+ if (selected && onSelect) {
332
+ const [wrappedValue, option] = getSelectEnt();
333
+ onSelect(wrappedValue, option);
334
+ } else if (!selected && onDeselect && type !== 'clear') {
335
+ const [wrappedValue, option] = getSelectEnt();
336
+ onDeselect(wrappedValue, option);
337
+ }
338
+ };
339
+
340
+ // Used for OptionList selection
341
+ const onInternalSelect = (0, _useRefFunc.default)((val, info) => {
342
+ let cloneValues;
343
+
344
+ // Single mode always trigger select only with option list
345
+ const mergedSelect = multiple ? info.selected : true;
346
+ if (mergedSelect) {
347
+ cloneValues = multiple ? [...mergedValues, val] : [val];
348
+ } else {
349
+ cloneValues = mergedValues.filter(v => v.value !== val);
350
+ }
351
+ triggerChange(cloneValues);
352
+ triggerSelect(val, mergedSelect);
353
+
354
+ // Clean search value if single or configured
355
+ if (mode === 'combobox') {
356
+ setActiveValue('');
357
+ } else if (!_BaseSelect.isMultiple || autoClearSearchValue) {
358
+ setSearchValue('');
359
+ setActiveValue('');
360
+ }
361
+ });
362
+
363
+ // ======================= Display Change =======================
364
+ // BaseSelect display values change
365
+ const onDisplayValuesChange = (nextValues, info) => {
366
+ triggerChange(nextValues);
367
+ const {
368
+ type,
369
+ values
370
+ } = info;
371
+ if (type === 'remove' || type === 'clear') {
372
+ values.forEach(item => {
373
+ triggerSelect(item.value, false, type);
374
+ });
375
+ }
376
+ };
377
+
378
+ // =========================== Search ===========================
379
+ const onInternalSearch = (searchText, info) => {
380
+ setSearchValue(searchText);
381
+ setActiveValue(null);
382
+
383
+ // [Submit] Tag mode should flush input
384
+ if (info.source === 'submit') {
385
+ const formatted = (searchText || '').trim();
386
+ // prevent empty tags from appearing when you click the Enter button
387
+ if (formatted) {
388
+ const newRawValues = Array.from(new Set([...rawValues, formatted]));
389
+ triggerChange(newRawValues);
390
+ triggerSelect(formatted, true);
391
+ setSearchValue('');
392
+ }
393
+ return;
394
+ }
395
+ if (info.source !== 'blur') {
396
+ if (mode === 'combobox') {
397
+ triggerChange(searchText);
398
+ }
399
+ onSearch?.(searchText);
400
+ }
401
+ };
402
+ const onInternalSearchSplit = words => {
403
+ let patchValues = words;
404
+ if (mode !== 'tags') {
405
+ patchValues = words.map(word => {
406
+ const opt = labelOptions.get(word);
407
+ return opt?.value;
408
+ }).filter(val => val !== undefined);
409
+ }
410
+ const newRawValues = Array.from(new Set([...rawValues, ...patchValues]));
411
+ triggerChange(newRawValues);
412
+ newRawValues.forEach(newRawValue => {
413
+ triggerSelect(newRawValue, true);
414
+ });
415
+ };
416
+
417
+ // ========================== Context ===========================
418
+ const selectContext = React.useMemo(() => {
419
+ const realVirtual = virtual !== false && popupMatchSelectWidth !== false;
420
+ return {
421
+ ...parsedOptions,
422
+ flattenOptions: displayOptions,
423
+ onActiveValue,
424
+ defaultActiveFirstOption: mergedDefaultActiveFirstOption,
425
+ onSelect: onInternalSelect,
426
+ menuItemSelectedIcon,
427
+ rawValues,
428
+ fieldNames: mergedFieldNames,
429
+ virtual: realVirtual,
430
+ direction,
431
+ listHeight,
432
+ listItemHeight,
433
+ childrenAsData,
434
+ maxCount,
435
+ optionRender
436
+ };
437
+ }, [maxCount, parsedOptions, displayOptions, onActiveValue, mergedDefaultActiveFirstOption, onInternalSelect, menuItemSelectedIcon, rawValues, mergedFieldNames, virtual, popupMatchSelectWidth, direction, listHeight, listItemHeight, childrenAsData, optionRender]);
438
+
439
+ // ========================== Warning ===========================
440
+ if (process.env.NODE_ENV !== 'production') {
441
+ (0, _warningPropsUtil.default)(props);
442
+ (0, _warningPropsUtil.warningNullOptions)(mergedOptions, mergedFieldNames);
443
+ }
444
+
445
+ // ==============================================================
446
+ // == Render ==
447
+ // ==============================================================
448
+ return /*#__PURE__*/React.createElement(_SelectContext.default.Provider, {
449
+ value: selectContext
450
+ }, /*#__PURE__*/React.createElement(_BaseSelect.default, _extends({}, restProps, {
451
+ // >>> MISC
452
+ id: mergedId,
453
+ prefixCls: prefixCls,
454
+ ref: ref,
455
+ omitDomProps: OMIT_DOM_PROPS,
456
+ mode: mode
457
+ // >>> Values
458
+ ,
459
+ displayValues: displayValues,
460
+ onDisplayValuesChange: onDisplayValuesChange
461
+ // >>> Trigger
462
+ ,
463
+ direction: direction
464
+ // >>> Search
465
+ ,
466
+ searchValue: mergedSearchValue,
467
+ onSearch: onInternalSearch,
468
+ autoClearSearchValue: autoClearSearchValue,
469
+ onSearchSplit: onInternalSearchSplit,
470
+ popupMatchSelectWidth: popupMatchSelectWidth
471
+ // >>> OptionList
472
+ ,
473
+ OptionList: _OptionList.default,
474
+ emptyOptions: !displayOptions.length
475
+ // >>> Accessibility
476
+ ,
477
+ activeValue: activeValue,
478
+ activeDescendantId: `${mergedId}_list_${accessibilityIndex}`
479
+ })));
480
+ });
481
+ if (process.env.NODE_ENV !== 'production') {
482
+ Select.displayName = 'Select';
483
+ }
484
+ const TypedSelect = Select;
485
+ TypedSelect.Option = _Option.default;
486
+ TypedSelect.OptGroup = _OptGroup.default;
487
+ var _default = exports.default = TypedSelect;
@@ -0,0 +1,23 @@
1
+ import * as React from 'react';
2
+ import type { RawValueType, RenderNode } from './BaseSelect';
3
+ import type { BaseOptionType, FieldNames, OnActiveValue, OnInternalSelect, SelectProps } from './Select';
4
+ import type { FlattenOptionData } from './interface';
5
+ export interface SelectContextProps {
6
+ options: BaseOptionType[];
7
+ optionRender?: SelectProps['optionRender'];
8
+ flattenOptions: FlattenOptionData<BaseOptionType>[];
9
+ onActiveValue: OnActiveValue;
10
+ defaultActiveFirstOption?: boolean;
11
+ onSelect: OnInternalSelect;
12
+ menuItemSelectedIcon?: RenderNode;
13
+ rawValues: Set<RawValueType>;
14
+ fieldNames?: FieldNames;
15
+ virtual?: boolean;
16
+ direction?: 'ltr' | 'rtl';
17
+ listHeight?: number;
18
+ listItemHeight?: number;
19
+ childrenAsData?: boolean;
20
+ maxCount?: number;
21
+ }
22
+ declare const SelectContext: React.Context<SelectContextProps>;
23
+ export default SelectContext;
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var React = _interopRequireWildcard(require("react"));
8
+ function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
9
+ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
10
+ // Use any here since we do not get the type during compilation
11
+
12
+ const SelectContext = /*#__PURE__*/React.createContext(null);
13
+ var _default = exports.default = SelectContext;
@@ -0,0 +1,30 @@
1
+ import type { AlignType, BuildInPlacements } from '@rc-component/trigger/lib/interface';
2
+ import * as React from 'react';
3
+ import type { Placement, RenderDOMFunc } from './BaseSelect';
4
+ export interface RefTriggerProps {
5
+ getPopupElement: () => HTMLDivElement;
6
+ }
7
+ export interface SelectTriggerProps {
8
+ prefixCls: string;
9
+ children: React.ReactElement;
10
+ disabled: boolean;
11
+ visible: boolean;
12
+ popupElement: React.ReactElement;
13
+ animation?: string;
14
+ transitionName?: string;
15
+ placement?: Placement;
16
+ builtinPlacements?: BuildInPlacements;
17
+ popupStyle: React.CSSProperties;
18
+ popupClassName: string;
19
+ direction: string;
20
+ popupMatchSelectWidth?: boolean | number;
21
+ popupRender?: (menu: React.ReactElement) => React.ReactElement;
22
+ getPopupContainer?: RenderDOMFunc;
23
+ popupAlign: AlignType;
24
+ empty: boolean;
25
+ getTriggerDOMNode: (node: HTMLElement) => HTMLElement;
26
+ onPopupVisibleChange?: (visible: boolean) => void;
27
+ onPopupMouseEnter: () => void;
28
+ }
29
+ declare const RefSelectTrigger: React.ForwardRefExoticComponent<SelectTriggerProps & React.RefAttributes<RefTriggerProps>>;
30
+ export default RefSelectTrigger;