@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
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
var _classnames = _interopRequireDefault(require("classnames"));
|
|
8
|
+
var _KeyCode = _interopRequireDefault(require("@rc-component/util/lib/KeyCode"));
|
|
9
|
+
var _useMemo = _interopRequireDefault(require("@rc-component/util/lib/hooks/useMemo"));
|
|
10
|
+
var _omit = _interopRequireDefault(require("@rc-component/util/lib/omit"));
|
|
11
|
+
var _pickAttrs = _interopRequireDefault(require("@rc-component/util/lib/pickAttrs"));
|
|
12
|
+
var _rcVirtualList = _interopRequireDefault(require("rc-virtual-list"));
|
|
13
|
+
var _react = _interopRequireWildcard(require("react"));
|
|
14
|
+
var React = _react;
|
|
15
|
+
var _SelectContext = _interopRequireDefault(require("./SelectContext"));
|
|
16
|
+
var _TransBtn = _interopRequireDefault(require("./TransBtn"));
|
|
17
|
+
var _useBaseProps = _interopRequireDefault(require("./hooks/useBaseProps"));
|
|
18
|
+
var _platformUtil = require("./utils/platformUtil");
|
|
19
|
+
var _valueUtil = require("./utils/valueUtil");
|
|
20
|
+
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); }
|
|
21
|
+
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; }
|
|
22
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
23
|
+
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); }
|
|
24
|
+
// export interface OptionListProps<OptionsType extends object[]> {
|
|
25
|
+
|
|
26
|
+
function isTitleType(content) {
|
|
27
|
+
return typeof content === 'string' || typeof content === 'number';
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Using virtual list of option display.
|
|
32
|
+
* Will fallback to dom if use customize render.
|
|
33
|
+
*/
|
|
34
|
+
const OptionList = (_, ref) => {
|
|
35
|
+
const {
|
|
36
|
+
prefixCls,
|
|
37
|
+
id,
|
|
38
|
+
open,
|
|
39
|
+
multiple,
|
|
40
|
+
mode,
|
|
41
|
+
searchValue,
|
|
42
|
+
toggleOpen,
|
|
43
|
+
notFoundContent,
|
|
44
|
+
onPopupScroll,
|
|
45
|
+
showScrollBar
|
|
46
|
+
} = (0, _useBaseProps.default)();
|
|
47
|
+
const {
|
|
48
|
+
maxCount,
|
|
49
|
+
flattenOptions,
|
|
50
|
+
onActiveValue,
|
|
51
|
+
defaultActiveFirstOption,
|
|
52
|
+
onSelect,
|
|
53
|
+
menuItemSelectedIcon,
|
|
54
|
+
rawValues,
|
|
55
|
+
fieldNames,
|
|
56
|
+
virtual,
|
|
57
|
+
direction,
|
|
58
|
+
listHeight,
|
|
59
|
+
listItemHeight,
|
|
60
|
+
optionRender
|
|
61
|
+
} = React.useContext(_SelectContext.default);
|
|
62
|
+
const itemPrefixCls = `${prefixCls}-item`;
|
|
63
|
+
const memoFlattenOptions = (0, _useMemo.default)(() => flattenOptions, [open, flattenOptions], (prev, next) => next[0] && prev[1] !== next[1]);
|
|
64
|
+
|
|
65
|
+
// =========================== List ===========================
|
|
66
|
+
const listRef = React.useRef(null);
|
|
67
|
+
const overMaxCount = React.useMemo(() => multiple && (0, _valueUtil.isValidCount)(maxCount) && rawValues?.size >= maxCount, [multiple, maxCount, rawValues?.size]);
|
|
68
|
+
const onListMouseDown = event => {
|
|
69
|
+
event.preventDefault();
|
|
70
|
+
};
|
|
71
|
+
const scrollIntoView = args => {
|
|
72
|
+
listRef.current?.scrollTo(typeof args === 'number' ? {
|
|
73
|
+
index: args
|
|
74
|
+
} : args);
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
// https://github.com/ant-design/ant-design/issues/34975
|
|
78
|
+
const isSelected = React.useCallback(value => {
|
|
79
|
+
if (mode === 'combobox') {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
return rawValues.has(value);
|
|
83
|
+
}, [mode, [...rawValues].toString(), rawValues.size]);
|
|
84
|
+
|
|
85
|
+
// ========================== Active ==========================
|
|
86
|
+
const getEnabledActiveIndex = (index, offset = 1) => {
|
|
87
|
+
const len = memoFlattenOptions.length;
|
|
88
|
+
for (let i = 0; i < len; i += 1) {
|
|
89
|
+
const current = (index + i * offset + len) % len;
|
|
90
|
+
const {
|
|
91
|
+
group,
|
|
92
|
+
data
|
|
93
|
+
} = memoFlattenOptions[current] || {};
|
|
94
|
+
if (!group && !data?.disabled && (isSelected(data.value) || !overMaxCount)) {
|
|
95
|
+
return current;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return -1;
|
|
99
|
+
};
|
|
100
|
+
const [activeIndex, setActiveIndex] = React.useState(() => getEnabledActiveIndex(0));
|
|
101
|
+
const setActive = (index, fromKeyboard = false) => {
|
|
102
|
+
setActiveIndex(index);
|
|
103
|
+
const info = {
|
|
104
|
+
source: fromKeyboard ? 'keyboard' : 'mouse'
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
// Trigger active event
|
|
108
|
+
const flattenItem = memoFlattenOptions[index];
|
|
109
|
+
if (!flattenItem) {
|
|
110
|
+
onActiveValue(null, -1, info);
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
onActiveValue(flattenItem.value, index, info);
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
// Auto active first item when list length or searchValue changed
|
|
117
|
+
(0, _react.useEffect)(() => {
|
|
118
|
+
setActive(defaultActiveFirstOption !== false ? getEnabledActiveIndex(0) : -1);
|
|
119
|
+
}, [memoFlattenOptions.length, searchValue]);
|
|
120
|
+
|
|
121
|
+
// https://github.com/ant-design/ant-design/issues/48036
|
|
122
|
+
const isAriaSelected = React.useCallback(value => {
|
|
123
|
+
if (mode === 'combobox') {
|
|
124
|
+
return String(value).toLowerCase() === searchValue.toLowerCase();
|
|
125
|
+
}
|
|
126
|
+
return rawValues.has(value);
|
|
127
|
+
}, [mode, searchValue, [...rawValues].toString(), rawValues.size]);
|
|
128
|
+
|
|
129
|
+
// Auto scroll to item position in single mode
|
|
130
|
+
(0, _react.useEffect)(() => {
|
|
131
|
+
/**
|
|
132
|
+
* React will skip `onChange` when component update.
|
|
133
|
+
* `setActive` function will call root accessibility state update which makes re-render.
|
|
134
|
+
* So we need to delay to let Input component trigger onChange first.
|
|
135
|
+
*/
|
|
136
|
+
const timeoutId = setTimeout(() => {
|
|
137
|
+
if (!multiple && open && rawValues.size === 1) {
|
|
138
|
+
const value = Array.from(rawValues)[0];
|
|
139
|
+
const index = memoFlattenOptions.findIndex(({
|
|
140
|
+
data
|
|
141
|
+
}) => data.value === value);
|
|
142
|
+
if (index !== -1) {
|
|
143
|
+
setActive(index);
|
|
144
|
+
scrollIntoView(index);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
// Force trigger scrollbar visible when open
|
|
150
|
+
if (open) {
|
|
151
|
+
listRef.current?.scrollTo(undefined);
|
|
152
|
+
}
|
|
153
|
+
return () => clearTimeout(timeoutId);
|
|
154
|
+
}, [open, searchValue]);
|
|
155
|
+
|
|
156
|
+
// ========================== Values ==========================
|
|
157
|
+
const onSelectValue = value => {
|
|
158
|
+
if (value !== undefined) {
|
|
159
|
+
onSelect(value, {
|
|
160
|
+
selected: !rawValues.has(value)
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Single mode should always close by select
|
|
165
|
+
if (!multiple) {
|
|
166
|
+
toggleOpen(false);
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
// ========================= Keyboard =========================
|
|
171
|
+
React.useImperativeHandle(ref, () => ({
|
|
172
|
+
onKeyDown: event => {
|
|
173
|
+
const {
|
|
174
|
+
which,
|
|
175
|
+
ctrlKey
|
|
176
|
+
} = event;
|
|
177
|
+
switch (which) {
|
|
178
|
+
// >>> Arrow keys & ctrl + n/p on Mac
|
|
179
|
+
case _KeyCode.default.N:
|
|
180
|
+
case _KeyCode.default.P:
|
|
181
|
+
case _KeyCode.default.UP:
|
|
182
|
+
case _KeyCode.default.DOWN:
|
|
183
|
+
{
|
|
184
|
+
let offset = 0;
|
|
185
|
+
if (which === _KeyCode.default.UP) {
|
|
186
|
+
offset = -1;
|
|
187
|
+
} else if (which === _KeyCode.default.DOWN) {
|
|
188
|
+
offset = 1;
|
|
189
|
+
} else if ((0, _platformUtil.isPlatformMac)() && ctrlKey) {
|
|
190
|
+
if (which === _KeyCode.default.N) {
|
|
191
|
+
offset = 1;
|
|
192
|
+
} else if (which === _KeyCode.default.P) {
|
|
193
|
+
offset = -1;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
if (offset !== 0) {
|
|
197
|
+
const nextActiveIndex = getEnabledActiveIndex(activeIndex + offset, offset);
|
|
198
|
+
scrollIntoView(nextActiveIndex);
|
|
199
|
+
setActive(nextActiveIndex, true);
|
|
200
|
+
}
|
|
201
|
+
break;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// >>> Select (Tab / Enter)
|
|
205
|
+
case _KeyCode.default.TAB:
|
|
206
|
+
case _KeyCode.default.ENTER:
|
|
207
|
+
{
|
|
208
|
+
// value
|
|
209
|
+
const item = memoFlattenOptions[activeIndex];
|
|
210
|
+
if (item && !item?.data?.disabled && !overMaxCount) {
|
|
211
|
+
onSelectValue(item.value);
|
|
212
|
+
} else {
|
|
213
|
+
onSelectValue(undefined);
|
|
214
|
+
}
|
|
215
|
+
if (open) {
|
|
216
|
+
event.preventDefault();
|
|
217
|
+
}
|
|
218
|
+
break;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// >>> Close
|
|
222
|
+
case _KeyCode.default.ESC:
|
|
223
|
+
{
|
|
224
|
+
toggleOpen(false);
|
|
225
|
+
if (open) {
|
|
226
|
+
event.stopPropagation();
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
},
|
|
231
|
+
onKeyUp: () => {},
|
|
232
|
+
scrollTo: index => {
|
|
233
|
+
scrollIntoView(index);
|
|
234
|
+
}
|
|
235
|
+
}));
|
|
236
|
+
|
|
237
|
+
// ========================== Render ==========================
|
|
238
|
+
if (memoFlattenOptions.length === 0) {
|
|
239
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
240
|
+
role: "listbox",
|
|
241
|
+
id: `${id}_list`,
|
|
242
|
+
className: `${itemPrefixCls}-empty`,
|
|
243
|
+
onMouseDown: onListMouseDown
|
|
244
|
+
}, notFoundContent);
|
|
245
|
+
}
|
|
246
|
+
const omitFieldNameList = Object.keys(fieldNames).map(key => fieldNames[key]);
|
|
247
|
+
const getLabel = item => item.label;
|
|
248
|
+
function getItemAriaProps(item, index) {
|
|
249
|
+
const {
|
|
250
|
+
group
|
|
251
|
+
} = item;
|
|
252
|
+
return {
|
|
253
|
+
role: group ? 'presentation' : 'option',
|
|
254
|
+
id: `${id}_list_${index}`
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
const renderItem = index => {
|
|
258
|
+
const item = memoFlattenOptions[index];
|
|
259
|
+
if (!item) {
|
|
260
|
+
return null;
|
|
261
|
+
}
|
|
262
|
+
const itemData = item.data || {};
|
|
263
|
+
const {
|
|
264
|
+
value
|
|
265
|
+
} = itemData;
|
|
266
|
+
const {
|
|
267
|
+
group
|
|
268
|
+
} = item;
|
|
269
|
+
const attrs = (0, _pickAttrs.default)(itemData, true);
|
|
270
|
+
const mergedLabel = getLabel(item);
|
|
271
|
+
return item ? /*#__PURE__*/React.createElement("div", _extends({
|
|
272
|
+
"aria-label": typeof mergedLabel === 'string' && !group ? mergedLabel : null
|
|
273
|
+
}, attrs, {
|
|
274
|
+
key: index
|
|
275
|
+
}, getItemAriaProps(item, index), {
|
|
276
|
+
"aria-selected": isAriaSelected(value)
|
|
277
|
+
}), value) : null;
|
|
278
|
+
};
|
|
279
|
+
const a11yProps = {
|
|
280
|
+
role: 'listbox',
|
|
281
|
+
id: `${id}_list`
|
|
282
|
+
};
|
|
283
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, virtual && /*#__PURE__*/React.createElement("div", _extends({}, a11yProps, {
|
|
284
|
+
style: {
|
|
285
|
+
height: 0,
|
|
286
|
+
width: 0,
|
|
287
|
+
overflow: 'hidden'
|
|
288
|
+
}
|
|
289
|
+
}), renderItem(activeIndex - 1), renderItem(activeIndex), renderItem(activeIndex + 1)), /*#__PURE__*/React.createElement(_rcVirtualList.default, {
|
|
290
|
+
itemKey: "key",
|
|
291
|
+
ref: listRef,
|
|
292
|
+
data: memoFlattenOptions,
|
|
293
|
+
height: listHeight,
|
|
294
|
+
itemHeight: listItemHeight,
|
|
295
|
+
fullHeight: false,
|
|
296
|
+
onMouseDown: onListMouseDown,
|
|
297
|
+
onScroll: onPopupScroll,
|
|
298
|
+
virtual: virtual,
|
|
299
|
+
direction: direction,
|
|
300
|
+
innerProps: virtual ? null : a11yProps,
|
|
301
|
+
showScrollBar: showScrollBar
|
|
302
|
+
}, (item, itemIndex) => {
|
|
303
|
+
const {
|
|
304
|
+
group,
|
|
305
|
+
groupOption,
|
|
306
|
+
data,
|
|
307
|
+
label,
|
|
308
|
+
value
|
|
309
|
+
} = item;
|
|
310
|
+
const {
|
|
311
|
+
key
|
|
312
|
+
} = data;
|
|
313
|
+
|
|
314
|
+
// Group
|
|
315
|
+
if (group) {
|
|
316
|
+
const groupTitle = data.title ?? (isTitleType(label) ? label.toString() : undefined);
|
|
317
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
318
|
+
className: (0, _classnames.default)(itemPrefixCls, `${itemPrefixCls}-group`, data.className),
|
|
319
|
+
title: groupTitle
|
|
320
|
+
}, label !== undefined ? label : key);
|
|
321
|
+
}
|
|
322
|
+
const {
|
|
323
|
+
disabled,
|
|
324
|
+
title,
|
|
325
|
+
children,
|
|
326
|
+
style,
|
|
327
|
+
className,
|
|
328
|
+
...otherProps
|
|
329
|
+
} = data;
|
|
330
|
+
const passedProps = (0, _omit.default)(otherProps, omitFieldNameList);
|
|
331
|
+
|
|
332
|
+
// Option
|
|
333
|
+
const selected = isSelected(value);
|
|
334
|
+
const mergedDisabled = disabled || !selected && overMaxCount;
|
|
335
|
+
const optionPrefixCls = `${itemPrefixCls}-option`;
|
|
336
|
+
const optionClassName = (0, _classnames.default)(itemPrefixCls, optionPrefixCls, className, {
|
|
337
|
+
[`${optionPrefixCls}-grouped`]: groupOption,
|
|
338
|
+
[`${optionPrefixCls}-active`]: activeIndex === itemIndex && !mergedDisabled,
|
|
339
|
+
[`${optionPrefixCls}-disabled`]: mergedDisabled,
|
|
340
|
+
[`${optionPrefixCls}-selected`]: selected
|
|
341
|
+
});
|
|
342
|
+
const mergedLabel = getLabel(item);
|
|
343
|
+
const iconVisible = !menuItemSelectedIcon || typeof menuItemSelectedIcon === 'function' || selected;
|
|
344
|
+
|
|
345
|
+
// https://github.com/ant-design/ant-design/issues/34145
|
|
346
|
+
const content = typeof mergedLabel === 'number' ? mergedLabel : mergedLabel || value;
|
|
347
|
+
// https://github.com/ant-design/ant-design/issues/26717
|
|
348
|
+
let optionTitle = isTitleType(content) ? content.toString() : undefined;
|
|
349
|
+
if (title !== undefined) {
|
|
350
|
+
optionTitle = title;
|
|
351
|
+
}
|
|
352
|
+
return /*#__PURE__*/React.createElement("div", _extends({}, (0, _pickAttrs.default)(passedProps), !virtual ? getItemAriaProps(item, itemIndex) : {}, {
|
|
353
|
+
"aria-selected": isAriaSelected(value),
|
|
354
|
+
className: optionClassName,
|
|
355
|
+
title: optionTitle,
|
|
356
|
+
onMouseMove: () => {
|
|
357
|
+
if (activeIndex === itemIndex || mergedDisabled) {
|
|
358
|
+
return;
|
|
359
|
+
}
|
|
360
|
+
setActive(itemIndex);
|
|
361
|
+
},
|
|
362
|
+
onClick: () => {
|
|
363
|
+
if (!mergedDisabled) {
|
|
364
|
+
onSelectValue(value);
|
|
365
|
+
}
|
|
366
|
+
},
|
|
367
|
+
style: style
|
|
368
|
+
}), /*#__PURE__*/React.createElement("div", {
|
|
369
|
+
className: `${optionPrefixCls}-content`
|
|
370
|
+
}, typeof optionRender === 'function' ? optionRender(item, {
|
|
371
|
+
index: itemIndex
|
|
372
|
+
}) : content), /*#__PURE__*/React.isValidElement(menuItemSelectedIcon) || selected, iconVisible && /*#__PURE__*/React.createElement(_TransBtn.default, {
|
|
373
|
+
className: `${itemPrefixCls}-option-state`,
|
|
374
|
+
customizeIcon: menuItemSelectedIcon,
|
|
375
|
+
customizeIconProps: {
|
|
376
|
+
value,
|
|
377
|
+
disabled: mergedDisabled,
|
|
378
|
+
isSelected: selected
|
|
379
|
+
}
|
|
380
|
+
}, selected ? '✓' : null));
|
|
381
|
+
}));
|
|
382
|
+
};
|
|
383
|
+
const RefOptionList = /*#__PURE__*/React.forwardRef(OptionList);
|
|
384
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
385
|
+
RefOptionList.displayName = 'OptionList';
|
|
386
|
+
}
|
|
387
|
+
var _default = exports.default = RefOptionList;
|
package/lib/Select.d.ts
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* To match accessibility requirement, we always provide an input in the component.
|
|
3
|
+
* Other element will not set `tabIndex` to avoid `onBlur` sequence problem.
|
|
4
|
+
* For focused select, we set `aria-live="polite"` to update the accessibility content.
|
|
5
|
+
*
|
|
6
|
+
* ref:
|
|
7
|
+
* - keyboard: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/listbox_role#Keyboard_interactions
|
|
8
|
+
*
|
|
9
|
+
* New api:
|
|
10
|
+
* - listHeight
|
|
11
|
+
* - listItemHeight
|
|
12
|
+
* - component
|
|
13
|
+
*
|
|
14
|
+
* Remove deprecated api:
|
|
15
|
+
* - multiple
|
|
16
|
+
* - tags
|
|
17
|
+
* - combobox
|
|
18
|
+
* - firstActiveValue
|
|
19
|
+
* - dropdownMenuStyle
|
|
20
|
+
* - openClassName (Not list in api)
|
|
21
|
+
*
|
|
22
|
+
* Update:
|
|
23
|
+
* - `backfill` only support `combobox` mode
|
|
24
|
+
* - `combobox` mode not support `labelInValue` since it's meaningless
|
|
25
|
+
* - `getInputElement` only support `combobox` mode
|
|
26
|
+
* - `onChange` return OptionData instead of ReactNode
|
|
27
|
+
* - `filterOption` `onChange` `onSelect` accept OptionData instead of ReactNode
|
|
28
|
+
* - `combobox` mode trigger `onChange` will get `undefined` if no `value` match in Option
|
|
29
|
+
* - `combobox` mode not support `optionLabelProp`
|
|
30
|
+
*/
|
|
31
|
+
import * as React from 'react';
|
|
32
|
+
import type { BaseSelectPropsWithoutPrivate, BaseSelectRef, DisplayValueType, RenderNode } from './BaseSelect';
|
|
33
|
+
import OptGroup from './OptGroup';
|
|
34
|
+
import Option from './Option';
|
|
35
|
+
import type { FlattenOptionData } from './interface';
|
|
36
|
+
export type OnActiveValue = (active: RawValueType, index: number, info?: {
|
|
37
|
+
source?: 'keyboard' | 'mouse';
|
|
38
|
+
}) => void;
|
|
39
|
+
export type OnInternalSelect = (value: RawValueType, info: {
|
|
40
|
+
selected: boolean;
|
|
41
|
+
}) => void;
|
|
42
|
+
export type RawValueType = string | number;
|
|
43
|
+
export interface LabelInValueType {
|
|
44
|
+
label: React.ReactNode;
|
|
45
|
+
value: RawValueType;
|
|
46
|
+
}
|
|
47
|
+
export type DraftValueType = RawValueType | LabelInValueType | DisplayValueType | (RawValueType | LabelInValueType | DisplayValueType)[];
|
|
48
|
+
export type FilterFunc<OptionType> = (inputValue: string, option?: OptionType) => boolean;
|
|
49
|
+
export interface FieldNames {
|
|
50
|
+
value?: string;
|
|
51
|
+
label?: string;
|
|
52
|
+
groupLabel?: string;
|
|
53
|
+
options?: string;
|
|
54
|
+
}
|
|
55
|
+
export interface BaseOptionType {
|
|
56
|
+
disabled?: boolean;
|
|
57
|
+
className?: string;
|
|
58
|
+
title?: string;
|
|
59
|
+
[name: string]: any;
|
|
60
|
+
}
|
|
61
|
+
export interface DefaultOptionType extends BaseOptionType {
|
|
62
|
+
label?: React.ReactNode;
|
|
63
|
+
value?: string | number | null;
|
|
64
|
+
children?: Omit<DefaultOptionType, 'children'>[];
|
|
65
|
+
}
|
|
66
|
+
export type SelectHandler<ValueType, OptionType extends BaseOptionType = DefaultOptionType> = (value: ValueType, option: OptionType) => void;
|
|
67
|
+
type ArrayElementType<T> = T extends (infer E)[] ? E : T;
|
|
68
|
+
export interface SelectProps<ValueType = any, OptionType extends BaseOptionType = DefaultOptionType> extends BaseSelectPropsWithoutPrivate {
|
|
69
|
+
prefixCls?: string;
|
|
70
|
+
id?: string;
|
|
71
|
+
backfill?: boolean;
|
|
72
|
+
fieldNames?: FieldNames;
|
|
73
|
+
searchValue?: string;
|
|
74
|
+
onSearch?: (value: string) => void;
|
|
75
|
+
autoClearSearchValue?: boolean;
|
|
76
|
+
onSelect?: SelectHandler<ArrayElementType<ValueType>, OptionType>;
|
|
77
|
+
onDeselect?: SelectHandler<ArrayElementType<ValueType>, OptionType>;
|
|
78
|
+
/**
|
|
79
|
+
* In Select, `false` means do nothing.
|
|
80
|
+
* In TreeSelect, `false` will highlight match item.
|
|
81
|
+
* It's by design.
|
|
82
|
+
*/
|
|
83
|
+
filterOption?: boolean | FilterFunc<OptionType>;
|
|
84
|
+
filterSort?: (optionA: OptionType, optionB: OptionType, info: {
|
|
85
|
+
searchValue: string;
|
|
86
|
+
}) => number;
|
|
87
|
+
optionFilterProp?: string;
|
|
88
|
+
optionLabelProp?: string;
|
|
89
|
+
children?: React.ReactNode;
|
|
90
|
+
options?: OptionType[];
|
|
91
|
+
optionRender?: (oriOption: FlattenOptionData<OptionType>, info: {
|
|
92
|
+
index: number;
|
|
93
|
+
}) => React.ReactNode;
|
|
94
|
+
defaultActiveFirstOption?: boolean;
|
|
95
|
+
virtual?: boolean;
|
|
96
|
+
direction?: 'ltr' | 'rtl';
|
|
97
|
+
listHeight?: number;
|
|
98
|
+
listItemHeight?: number;
|
|
99
|
+
labelRender?: (props: LabelInValueType) => React.ReactNode;
|
|
100
|
+
menuItemSelectedIcon?: RenderNode;
|
|
101
|
+
mode?: 'combobox' | 'multiple' | 'tags';
|
|
102
|
+
labelInValue?: boolean;
|
|
103
|
+
value?: ValueType | null;
|
|
104
|
+
defaultValue?: ValueType | null;
|
|
105
|
+
maxCount?: number;
|
|
106
|
+
onChange?: (value: ValueType, option?: OptionType | OptionType[]) => void;
|
|
107
|
+
}
|
|
108
|
+
declare const TypedSelect: (<ValueType = any, OptionType extends BaseOptionType | DefaultOptionType = DefaultOptionType>(props: SelectProps<ValueType, OptionType> & {
|
|
109
|
+
children?: React.ReactNode;
|
|
110
|
+
} & React.RefAttributes<BaseSelectRef>) => React.ReactElement) & {
|
|
111
|
+
Option: typeof Option;
|
|
112
|
+
OptGroup: typeof OptGroup;
|
|
113
|
+
};
|
|
114
|
+
export default TypedSelect;
|