@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.
- package/LICENSE.md +9 -0
- package/README.md +191 -0
- package/assets/index.css +306 -0
- package/assets/index.less +397 -0
- package/es/BaseSelect/Polite.d.ts +7 -0
- package/es/BaseSelect/Polite.js +26 -0
- package/es/BaseSelect/index.d.ts +118 -0
- package/es/BaseSelect/index.js +569 -0
- package/es/OptGroup.d.ts +12 -0
- package/es/OptGroup.js +6 -0
- package/es/Option.d.ts +14 -0
- package/es/Option.js +6 -0
- package/es/OptionList.d.ts +10 -0
- package/es/OptionList.js +379 -0
- package/es/Select.d.ts +114 -0
- package/es/Select.js +480 -0
- package/es/SelectContext.d.ts +23 -0
- package/es/SelectContext.js +6 -0
- package/es/SelectTrigger.d.ts +30 -0
- package/es/SelectTrigger.js +138 -0
- package/es/Selector/Input.d.ts +27 -0
- package/es/Selector/Input.js +114 -0
- package/es/Selector/MultipleSelector.d.ts +16 -0
- package/es/Selector/MultipleSelector.js +185 -0
- package/es/Selector/SingleSelector.d.ts +8 -0
- package/es/Selector/SingleSelector.js +104 -0
- package/es/Selector/index.d.ts +85 -0
- package/es/Selector/index.js +184 -0
- package/es/TransBtn.d.ts +12 -0
- package/es/TransBtn.js +30 -0
- package/es/hooks/useAllowClear.d.ts +8 -0
- package/es/hooks/useAllowClear.js +26 -0
- package/es/hooks/useBaseProps.d.ts +13 -0
- package/es/hooks/useBaseProps.js +10 -0
- package/es/hooks/useCache.d.ts +7 -0
- package/es/hooks/useCache.js +40 -0
- package/es/hooks/useDelayReset.d.ts +5 -0
- package/es/hooks/useDelayReset.js +24 -0
- package/es/hooks/useFilterOptions.d.ts +3 -0
- package/es/hooks/useFilterOptions.js +57 -0
- package/es/hooks/useId.d.ts +5 -0
- package/es/hooks/useId.js +29 -0
- package/es/hooks/useLayoutEffect.d.ts +5 -0
- package/es/hooks/useLayoutEffect.js +17 -0
- package/es/hooks/useLock.d.ts +7 -0
- package/es/hooks/useLock.js +27 -0
- package/es/hooks/useOptions.d.ts +12 -0
- package/es/hooks/useOptions.js +45 -0
- package/es/hooks/useRefFunc.d.ts +5 -0
- package/es/hooks/useRefFunc.js +14 -0
- package/es/hooks/useSelectTriggerControl.d.ts +1 -0
- package/es/hooks/useSelectTriggerControl.js +27 -0
- package/es/index.d.ts +10 -0
- package/es/index.js +7 -0
- package/es/interface.d.ts +23 -0
- package/es/interface.js +1 -0
- package/es/utils/__mocks__/platformUtil.d.ts +1 -0
- package/es/utils/__mocks__/platformUtil.js +3 -0
- package/es/utils/commonUtil.d.ts +9 -0
- package/es/utils/commonUtil.js +32 -0
- package/es/utils/keyUtil.d.ts +2 -0
- package/es/utils/keyUtil.js +16 -0
- package/es/utils/legacyUtil.d.ts +3 -0
- package/es/utils/legacyUtil.js +44 -0
- package/es/utils/platformUtil.d.ts +1 -0
- package/es/utils/platformUtil.js +4 -0
- package/es/utils/valueUtil.d.ts +24 -0
- package/es/utils/valueUtil.js +128 -0
- package/es/utils/warningPropsUtil.d.ts +4 -0
- package/es/utils/warningPropsUtil.js +119 -0
- package/lib/BaseSelect/Polite.d.ts +7 -0
- package/lib/BaseSelect/Polite.js +34 -0
- package/lib/BaseSelect/index.d.ts +118 -0
- package/lib/BaseSelect/index.js +579 -0
- package/lib/OptGroup.d.ts +12 -0
- package/lib/OptGroup.js +12 -0
- package/lib/Option.d.ts +14 -0
- package/lib/Option.js +12 -0
- package/lib/OptionList.d.ts +10 -0
- package/lib/OptionList.js +387 -0
- package/lib/Select.d.ts +114 -0
- package/lib/Select.js +487 -0
- package/lib/SelectContext.d.ts +23 -0
- package/lib/SelectContext.js +13 -0
- package/lib/SelectTrigger.d.ts +30 -0
- package/lib/SelectTrigger.js +147 -0
- package/lib/Selector/Input.d.ts +27 -0
- package/lib/Selector/Input.js +123 -0
- package/lib/Selector/MultipleSelector.d.ts +16 -0
- package/lib/Selector/MultipleSelector.js +194 -0
- package/lib/Selector/SingleSelector.d.ts +8 -0
- package/lib/Selector/SingleSelector.js +113 -0
- package/lib/Selector/index.d.ts +85 -0
- package/lib/Selector/index.js +191 -0
- package/lib/TransBtn.d.ts +12 -0
- package/lib/TransBtn.js +39 -0
- package/lib/hooks/useAllowClear.d.ts +8 -0
- package/lib/hooks/useAllowClear.js +34 -0
- package/lib/hooks/useBaseProps.d.ts +13 -0
- package/lib/hooks/useBaseProps.js +19 -0
- package/lib/hooks/useCache.d.ts +7 -0
- package/lib/hooks/useCache.js +49 -0
- package/lib/hooks/useDelayReset.d.ts +5 -0
- package/lib/hooks/useDelayReset.js +31 -0
- package/lib/hooks/useFilterOptions.d.ts +3 -0
- package/lib/hooks/useFilterOptions.js +66 -0
- package/lib/hooks/useId.d.ts +5 -0
- package/lib/hooks/useId.js +40 -0
- package/lib/hooks/useLayoutEffect.d.ts +5 -0
- package/lib/hooks/useLayoutEffect.js +25 -0
- package/lib/hooks/useLock.d.ts +7 -0
- package/lib/hooks/useLock.js +34 -0
- package/lib/hooks/useOptions.d.ts +12 -0
- package/lib/hooks/useOptions.js +52 -0
- package/lib/hooks/useRefFunc.d.ts +5 -0
- package/lib/hooks/useRefFunc.js +21 -0
- package/lib/hooks/useSelectTriggerControl.d.ts +1 -0
- package/lib/hooks/useSelectTriggerControl.js +35 -0
- package/lib/index.d.ts +10 -0
- package/lib/index.js +37 -0
- package/lib/interface.d.ts +23 -0
- package/lib/interface.js +5 -0
- package/lib/utils/__mocks__/platformUtil.d.ts +1 -0
- package/lib/utils/__mocks__/platformUtil.js +9 -0
- package/lib/utils/commonUtil.d.ts +9 -0
- package/lib/utils/commonUtil.js +42 -0
- package/lib/utils/keyUtil.d.ts +2 -0
- package/lib/utils/keyUtil.js +22 -0
- package/lib/utils/legacyUtil.d.ts +3 -0
- package/lib/utils/legacyUtil.js +53 -0
- package/lib/utils/platformUtil.d.ts +1 -0
- package/lib/utils/platformUtil.js +10 -0
- package/lib/utils/valueUtil.d.ts +24 -0
- package/lib/utils/valueUtil.js +140 -0
- package/lib/utils/warningPropsUtil.d.ts +4 -0
- package/lib/utils/warningPropsUtil.js +129 -0
- 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;
|