@rc-component/select 1.1.4 → 1.2.0-alpha.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/assets/index.css +63 -0
- package/assets/index.less +1 -0
- package/assets/patch.less +83 -0
- package/es/BaseSelect/index.d.ts +14 -3
- package/es/BaseSelect/index.js +137 -200
- package/es/OptionList.js +3 -3
- package/es/Select.d.ts +1 -1
- package/es/Select.js +5 -9
- package/es/SelectInput/Affix.d.ts +5 -0
- package/es/SelectInput/Affix.js +12 -0
- package/es/SelectInput/Content/MultipleContent.d.ts +4 -0
- package/es/SelectInput/Content/MultipleContent.js +152 -0
- package/es/SelectInput/Content/Placeholder.d.ts +5 -0
- package/es/SelectInput/Content/Placeholder.js +21 -0
- package/es/SelectInput/Content/SingleContent.d.ts +4 -0
- package/es/SelectInput/Content/SingleContent.js +98 -0
- package/es/SelectInput/Content/index.d.ts +6 -0
- package/es/SelectInput/Content/index.js +37 -0
- package/es/SelectInput/Input.d.ts +20 -0
- package/es/SelectInput/Input.js +214 -0
- package/es/SelectInput/context.d.ts +6 -0
- package/es/SelectInput/context.js +6 -0
- package/es/SelectInput/index.d.ts +39 -0
- package/es/SelectInput/index.js +189 -0
- package/es/SelectTrigger.d.ts +1 -0
- package/es/SelectTrigger.js +5 -3
- package/es/TransBtn.d.ts +10 -0
- package/es/TransBtn.js +12 -2
- package/es/hooks/useAllowClear.d.ts +8 -7
- package/es/hooks/useAllowClear.js +21 -23
- package/es/hooks/useBaseProps.d.ts +1 -0
- package/es/hooks/useComponents.d.ts +12 -0
- package/es/hooks/useComponents.js +23 -0
- package/es/hooks/useOpen.d.ts +15 -0
- package/es/hooks/useOpen.js +76 -0
- package/es/hooks/useSearchConfig.d.ts +2 -2
- package/es/hooks/useSearchConfig.js +3 -3
- package/es/hooks/useSelectTriggerControl.d.ts +1 -1
- package/es/hooks/useSelectTriggerControl.js +16 -21
- package/es/utils/keyUtil.js +4 -0
- package/lib/BaseSelect/index.d.ts +14 -3
- package/lib/BaseSelect/index.js +137 -201
- package/lib/OptionList.js +3 -3
- package/lib/Select.d.ts +1 -1
- package/lib/Select.js +5 -9
- package/lib/SelectInput/Affix.d.ts +5 -0
- package/lib/{hooks/useLayoutEffect.js → SelectInput/Affix.js} +11 -16
- package/lib/SelectInput/Content/MultipleContent.d.ts +4 -0
- package/lib/{Selector/MultipleSelector.js → SelectInput/Content/MultipleContent.js} +71 -104
- package/lib/SelectInput/Content/Placeholder.d.ts +5 -0
- package/lib/SelectInput/Content/Placeholder.js +29 -0
- package/lib/SelectInput/Content/SingleContent.d.ts +4 -0
- package/lib/SelectInput/Content/SingleContent.js +107 -0
- package/lib/SelectInput/Content/index.d.ts +6 -0
- package/lib/SelectInput/Content/index.js +46 -0
- package/lib/SelectInput/Input.d.ts +20 -0
- package/lib/SelectInput/Input.js +223 -0
- package/lib/SelectInput/context.d.ts +6 -0
- package/lib/SelectInput/context.js +15 -0
- package/lib/SelectInput/index.d.ts +39 -0
- package/lib/SelectInput/index.js +198 -0
- package/lib/SelectTrigger.d.ts +1 -0
- package/lib/SelectTrigger.js +5 -3
- package/lib/TransBtn.d.ts +10 -0
- package/lib/TransBtn.js +12 -3
- package/lib/hooks/useAllowClear.d.ts +8 -7
- package/lib/hooks/useAllowClear.js +21 -24
- package/lib/hooks/useBaseProps.d.ts +1 -0
- package/lib/hooks/useComponents.d.ts +12 -0
- package/lib/hooks/{useDelayReset.js → useComponents.js} +21 -30
- package/lib/hooks/useOpen.d.ts +15 -0
- package/lib/hooks/useOpen.js +82 -0
- package/lib/hooks/useSearchConfig.d.ts +2 -2
- package/lib/hooks/useSearchConfig.js +3 -3
- package/lib/hooks/useSelectTriggerControl.d.ts +1 -1
- package/lib/hooks/useSelectTriggerControl.js +16 -21
- package/lib/utils/keyUtil.js +4 -0
- package/package.json +5 -4
- package/es/Selector/Input.d.ts +0 -27
- package/es/Selector/Input.js +0 -61
- package/es/Selector/MultipleSelector.d.ts +0 -16
- package/es/Selector/MultipleSelector.js +0 -185
- package/es/Selector/SingleSelector.d.ts +0 -8
- package/es/Selector/SingleSelector.js +0 -104
- package/es/Selector/index.d.ts +0 -83
- package/es/Selector/index.js +0 -189
- package/es/hooks/useDelayReset.d.ts +0 -5
- package/es/hooks/useDelayReset.js +0 -33
- package/es/hooks/useLayoutEffect.d.ts +0 -5
- package/es/hooks/useLayoutEffect.js +0 -17
- package/lib/Selector/Input.d.ts +0 -27
- package/lib/Selector/Input.js +0 -70
- package/lib/Selector/MultipleSelector.d.ts +0 -16
- package/lib/Selector/SingleSelector.d.ts +0 -8
- package/lib/Selector/SingleSelector.js +0 -113
- package/lib/Selector/index.d.ts +0 -83
- package/lib/Selector/index.js +0 -196
- package/lib/hooks/useDelayReset.d.ts +0 -5
- package/lib/hooks/useLayoutEffect.d.ts +0 -5
package/es/BaseSelect/index.js
CHANGED
|
@@ -1,22 +1,27 @@
|
|
|
1
1
|
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); }
|
|
2
|
-
import
|
|
3
|
-
import useLayoutEffect from "@rc-component/util/es/hooks/useLayoutEffect";
|
|
4
|
-
import useMergedState from "@rc-component/util/es/hooks/useMergedState";
|
|
5
|
-
import isMobile from "@rc-component/util/es/isMobile";
|
|
6
|
-
import { useComposeRef } from "@rc-component/util/es/ref";
|
|
2
|
+
import { clsx } from 'clsx';
|
|
7
3
|
import { getDOM } from "@rc-component/util/es/Dom/findDOMNode";
|
|
8
4
|
import * as React from 'react';
|
|
9
5
|
import { useAllowClear } from "../hooks/useAllowClear";
|
|
10
6
|
import { BaseSelectContext } from "../hooks/useBaseProps";
|
|
11
|
-
import useDelayReset from "../hooks/useDelayReset";
|
|
12
7
|
import useLock from "../hooks/useLock";
|
|
13
8
|
import useSelectTriggerControl from "../hooks/useSelectTriggerControl";
|
|
14
|
-
import Selector from "../Selector";
|
|
15
9
|
import SelectTrigger from "../SelectTrigger";
|
|
16
|
-
import TransBtn from "../TransBtn";
|
|
17
10
|
import { getSeparatedContent, isValidCount } from "../utils/valueUtil";
|
|
18
11
|
import Polite from "./Polite";
|
|
19
|
-
|
|
12
|
+
import useOpen from "../hooks/useOpen";
|
|
13
|
+
import { useEvent } from '@rc-component/util';
|
|
14
|
+
import SelectInput from "../SelectInput";
|
|
15
|
+
import useComponents from "../hooks/useComponents";
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* ZombieJ:
|
|
19
|
+
* We are currently refactoring the semantic structure of the component. Changelog:
|
|
20
|
+
* - Remove `suffixIcon` and change to `suffix`.
|
|
21
|
+
* - Add `components.root` for replacing response element.
|
|
22
|
+
* - Remove `getInputElement` and `getRawInputElement` since we can use `components.input` instead.
|
|
23
|
+
*/
|
|
24
|
+
|
|
20
25
|
export const isMultiple = mode => mode === 'tags' || mode === 'multiple';
|
|
21
26
|
const BaseSelect = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
22
27
|
const {
|
|
@@ -37,6 +42,7 @@ const BaseSelect = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
|
37
42
|
notFoundContent = 'Not Found',
|
|
38
43
|
onClear,
|
|
39
44
|
maxCount,
|
|
45
|
+
placeholder,
|
|
40
46
|
// Mode
|
|
41
47
|
mode,
|
|
42
48
|
// Status
|
|
@@ -62,6 +68,7 @@ const BaseSelect = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
|
62
68
|
// Icons
|
|
63
69
|
allowClear,
|
|
64
70
|
prefix,
|
|
71
|
+
suffix,
|
|
65
72
|
suffixIcon,
|
|
66
73
|
clearIcon,
|
|
67
74
|
// Dropdown
|
|
@@ -84,49 +91,34 @@ const BaseSelect = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
|
84
91
|
onKeyUp,
|
|
85
92
|
onKeyDown,
|
|
86
93
|
onMouseDown,
|
|
94
|
+
// Components
|
|
95
|
+
components,
|
|
87
96
|
// Rest Props
|
|
88
97
|
...restProps
|
|
89
98
|
} = props;
|
|
90
99
|
|
|
91
100
|
// ============================== MISC ==============================
|
|
92
101
|
const multiple = isMultiple(mode);
|
|
93
|
-
const mergedShowSearch = (showSearch !== undefined ? showSearch : multiple) || mode === 'combobox';
|
|
94
|
-
const domProps = {
|
|
95
|
-
...restProps
|
|
96
|
-
};
|
|
97
|
-
DEFAULT_OMIT_PROPS.forEach(propName => {
|
|
98
|
-
delete domProps[propName];
|
|
99
|
-
});
|
|
100
|
-
omitDomProps?.forEach(propName => {
|
|
101
|
-
delete domProps[propName];
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
// ============================= Mobile =============================
|
|
105
|
-
const [mobile, setMobile] = React.useState(false);
|
|
106
|
-
React.useEffect(() => {
|
|
107
|
-
// Only update on the client side
|
|
108
|
-
setMobile(isMobile());
|
|
109
|
-
}, []);
|
|
110
102
|
|
|
111
103
|
// ============================== Refs ==============================
|
|
112
104
|
const containerRef = React.useRef(null);
|
|
113
105
|
const triggerRef = React.useRef(null);
|
|
114
|
-
const selectorRef = React.useRef(null);
|
|
115
106
|
const listRef = React.useRef(null);
|
|
116
|
-
const blurRef = React.useRef(false);
|
|
117
|
-
const customDomRef = React.useRef(null);
|
|
118
107
|
|
|
119
108
|
/** Used for component focused management */
|
|
120
|
-
const [
|
|
109
|
+
const [focused, setFocused] = React.useState(false);
|
|
121
110
|
|
|
122
111
|
// =========================== Imperative ===========================
|
|
123
112
|
React.useImperativeHandle(ref, () => ({
|
|
124
|
-
focus:
|
|
125
|
-
blur:
|
|
113
|
+
focus: containerRef.current?.focus,
|
|
114
|
+
blur: containerRef.current?.blur,
|
|
126
115
|
scrollTo: arg => listRef.current?.scrollTo(arg),
|
|
127
|
-
nativeElement:
|
|
116
|
+
nativeElement: getDOM(containerRef.current)
|
|
128
117
|
}));
|
|
129
118
|
|
|
119
|
+
// =========================== Components ===========================
|
|
120
|
+
const mergedComponents = useComponents(components, getInputElement, getRawInputElement);
|
|
121
|
+
|
|
130
122
|
// ========================== Search Value ==========================
|
|
131
123
|
const mergedSearchValue = React.useMemo(() => {
|
|
132
124
|
if (mode !== 'combobox') {
|
|
@@ -140,37 +132,10 @@ const BaseSelect = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
|
140
132
|
// Only works in `combobox`
|
|
141
133
|
const customizeInputElement = mode === 'combobox' && typeof getInputElement === 'function' && getInputElement() || null;
|
|
142
134
|
|
|
143
|
-
// Used for customize replacement for `rc-cascader`
|
|
144
|
-
const customizeRawInputElement = typeof getRawInputElement === 'function' && getRawInputElement();
|
|
145
|
-
const customizeRawInputRef = useComposeRef(customDomRef, customizeRawInputElement?.props?.ref);
|
|
146
|
-
|
|
147
135
|
// ============================== Open ==============================
|
|
148
|
-
//
|
|
149
|
-
const [rendered, setRendered] = React.useState(false);
|
|
150
|
-
useLayoutEffect(() => {
|
|
151
|
-
setRendered(true);
|
|
152
|
-
}, []);
|
|
153
|
-
const [innerOpen, setInnerOpen] = useMergedState(false, {
|
|
154
|
-
defaultValue: defaultOpen,
|
|
155
|
-
value: open
|
|
156
|
-
});
|
|
157
|
-
let mergedOpen = rendered ? innerOpen : false;
|
|
158
|
-
|
|
159
|
-
// Not trigger `open` in `combobox` when `notFoundContent` is empty
|
|
136
|
+
// Not trigger `open` when `notFoundContent` is empty
|
|
160
137
|
const emptyListContent = !notFoundContent && emptyOptions;
|
|
161
|
-
|
|
162
|
-
mergedOpen = false;
|
|
163
|
-
}
|
|
164
|
-
const triggerOpen = emptyListContent ? false : mergedOpen;
|
|
165
|
-
const onToggleOpen = React.useCallback(newOpen => {
|
|
166
|
-
const nextOpen = newOpen !== undefined ? newOpen : !mergedOpen;
|
|
167
|
-
if (!disabled) {
|
|
168
|
-
setInnerOpen(nextOpen);
|
|
169
|
-
if (mergedOpen !== nextOpen) {
|
|
170
|
-
onPopupVisibleChange?.(nextOpen);
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
}, [disabled, mergedOpen, setInnerOpen, onPopupVisibleChange]);
|
|
138
|
+
const [mergedOpen, triggerOpen] = useOpen(open, onPopupVisibleChange, nextOpen => disabled || emptyListContent ? false : nextOpen);
|
|
174
139
|
|
|
175
140
|
// ============================= Search =============================
|
|
176
141
|
const tokenWithEnter = React.useMemo(() => (tokenSeparators || []).some(tokenSeparator => ['\n', '\r\n'].includes(tokenSeparator)), [tokenSeparators]);
|
|
@@ -192,7 +157,7 @@ const BaseSelect = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
|
192
157
|
onSearchSplit?.(patchLabels);
|
|
193
158
|
|
|
194
159
|
// Should close when paste finish
|
|
195
|
-
|
|
160
|
+
triggerOpen(false);
|
|
196
161
|
|
|
197
162
|
// Tell Selector that break next actions
|
|
198
163
|
ret = false;
|
|
@@ -202,6 +167,11 @@ const BaseSelect = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
|
202
167
|
source: fromTyping ? 'typing' : 'effect'
|
|
203
168
|
});
|
|
204
169
|
}
|
|
170
|
+
|
|
171
|
+
// Open if from typing
|
|
172
|
+
if (searchText && fromTyping && ret) {
|
|
173
|
+
triggerOpen(true);
|
|
174
|
+
}
|
|
205
175
|
return ret;
|
|
206
176
|
};
|
|
207
177
|
|
|
@@ -228,15 +198,12 @@ const BaseSelect = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
|
228
198
|
// ============================ Disabled ============================
|
|
229
199
|
// Close dropdown & remove focus state when disabled change
|
|
230
200
|
React.useEffect(() => {
|
|
231
|
-
if (innerOpen && disabled) {
|
|
232
|
-
setInnerOpen(false);
|
|
233
|
-
}
|
|
234
|
-
|
|
235
201
|
// After onBlur is triggered, the focused does not need to be reset
|
|
236
|
-
if (disabled
|
|
237
|
-
|
|
202
|
+
if (disabled) {
|
|
203
|
+
triggerOpen(false);
|
|
204
|
+
setFocused(false);
|
|
238
205
|
}
|
|
239
|
-
}, [disabled]);
|
|
206
|
+
}, [disabled, mergedOpen]);
|
|
240
207
|
|
|
241
208
|
// ============================ Keyboard ============================
|
|
242
209
|
/**
|
|
@@ -249,7 +216,7 @@ const BaseSelect = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
|
249
216
|
const keyLockRef = React.useRef(false);
|
|
250
217
|
|
|
251
218
|
// KeyDown
|
|
252
|
-
const onInternalKeyDown =
|
|
219
|
+
const onInternalKeyDown = event => {
|
|
253
220
|
const clearLock = getClearLock();
|
|
254
221
|
const {
|
|
255
222
|
key
|
|
@@ -263,7 +230,7 @@ const BaseSelect = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
|
263
230
|
|
|
264
231
|
// We only manage open state here, close logic should handle by list component
|
|
265
232
|
if (!mergedOpen) {
|
|
266
|
-
|
|
233
|
+
triggerOpen(true);
|
|
267
234
|
}
|
|
268
235
|
}
|
|
269
236
|
setClearLock(!!mergedSearchValue);
|
|
@@ -292,9 +259,9 @@ const BaseSelect = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
|
292
259
|
if (isEnterKey) {
|
|
293
260
|
keyLockRef.current = true;
|
|
294
261
|
}
|
|
295
|
-
listRef.current?.onKeyDown(event
|
|
262
|
+
listRef.current?.onKeyDown(event);
|
|
296
263
|
}
|
|
297
|
-
onKeyDown?.(event
|
|
264
|
+
onKeyDown?.(event);
|
|
298
265
|
};
|
|
299
266
|
|
|
300
267
|
// KeyUp
|
|
@@ -309,13 +276,13 @@ const BaseSelect = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
|
309
276
|
};
|
|
310
277
|
|
|
311
278
|
// ============================ Selector ============================
|
|
312
|
-
const onSelectorRemove = val => {
|
|
279
|
+
const onSelectorRemove = useEvent(val => {
|
|
313
280
|
const newValues = displayValues.filter(i => i !== val);
|
|
314
281
|
onDisplayValuesChange(newValues, {
|
|
315
282
|
type: 'remove',
|
|
316
283
|
values: [val]
|
|
317
284
|
});
|
|
318
|
-
};
|
|
285
|
+
});
|
|
319
286
|
const onInputBlur = () => {
|
|
320
287
|
// Unlock the Enter key after the input blur; otherwise, the Enter key needs to be pressed twice to trigger the correct effect.
|
|
321
288
|
keyLockRef.current = false;
|
|
@@ -323,31 +290,20 @@ const BaseSelect = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
|
323
290
|
|
|
324
291
|
// ========================== Focus / Blur ==========================
|
|
325
292
|
/** Record real focus status */
|
|
326
|
-
const focusRef = React.useRef(false);
|
|
327
|
-
const onContainerFocus = (...args) => {
|
|
328
|
-
setMockFocused(true);
|
|
329
|
-
if (!disabled) {
|
|
330
|
-
if (onFocus && !focusRef.current) {
|
|
331
|
-
onFocus(...args);
|
|
332
|
-
}
|
|
293
|
+
// const focusRef = React.useRef<boolean>(false);
|
|
333
294
|
|
|
295
|
+
const onInternalFocus = event => {
|
|
296
|
+
setFocused(true);
|
|
297
|
+
if (!disabled) {
|
|
334
298
|
// `showAction` should handle `focus` if set
|
|
335
299
|
if (showAction.includes('focus')) {
|
|
336
|
-
|
|
300
|
+
triggerOpen(true);
|
|
337
301
|
}
|
|
302
|
+
onFocus?.(event);
|
|
338
303
|
}
|
|
339
|
-
focusRef.current = true;
|
|
340
304
|
};
|
|
341
|
-
const
|
|
342
|
-
|
|
343
|
-
setMockFocused(false, () => {
|
|
344
|
-
focusRef.current = false;
|
|
345
|
-
blurRef.current = false;
|
|
346
|
-
onToggleOpen(false);
|
|
347
|
-
});
|
|
348
|
-
if (disabled) {
|
|
349
|
-
return;
|
|
350
|
-
}
|
|
305
|
+
const onInternalBlur = event => {
|
|
306
|
+
setFocused(false);
|
|
351
307
|
if (mergedSearchValue) {
|
|
352
308
|
// `tags` mode should move `searchValue` into values
|
|
353
309
|
if (mode === 'tags') {
|
|
@@ -361,17 +317,11 @@ const BaseSelect = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
|
361
317
|
});
|
|
362
318
|
}
|
|
363
319
|
}
|
|
364
|
-
if (
|
|
365
|
-
|
|
320
|
+
if (!disabled) {
|
|
321
|
+
triggerOpen(false);
|
|
322
|
+
onBlur?.(event);
|
|
366
323
|
}
|
|
367
324
|
};
|
|
368
|
-
|
|
369
|
-
// Give focus back of Select
|
|
370
|
-
const activeTimeoutIds = [];
|
|
371
|
-
React.useEffect(() => () => {
|
|
372
|
-
activeTimeoutIds.forEach(timeoutId => clearTimeout(timeoutId));
|
|
373
|
-
activeTimeoutIds.splice(0, activeTimeoutIds.length);
|
|
374
|
-
}, []);
|
|
375
325
|
const onInternalMouseDown = (event, ...restArgs) => {
|
|
376
326
|
const {
|
|
377
327
|
target
|
|
@@ -379,18 +329,9 @@ const BaseSelect = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
|
379
329
|
const popupElement = triggerRef.current?.getPopupElement();
|
|
380
330
|
|
|
381
331
|
// We should give focus back to selector if clicked item is not focusable
|
|
382
|
-
if (popupElement
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
if (index !== -1) {
|
|
386
|
-
activeTimeoutIds.splice(index, 1);
|
|
387
|
-
}
|
|
388
|
-
cancelSetMockFocused();
|
|
389
|
-
if (!mobile && !popupElement.contains(document.activeElement)) {
|
|
390
|
-
selectorRef.current?.focus();
|
|
391
|
-
}
|
|
392
|
-
});
|
|
393
|
-
activeTimeoutIds.push(timeoutId);
|
|
332
|
+
if (popupElement?.contains(target) && triggerOpen) {
|
|
333
|
+
// Tell `open` not to close since it's safe in the popup
|
|
334
|
+
triggerOpen(true, true);
|
|
394
335
|
}
|
|
395
336
|
onMouseDown?.(event, ...restArgs);
|
|
396
337
|
};
|
|
@@ -404,58 +345,53 @@ const BaseSelect = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
|
404
345
|
|
|
405
346
|
// Used for raw custom input trigger
|
|
406
347
|
let onTriggerVisibleChange;
|
|
407
|
-
if (
|
|
348
|
+
if (!!mergedComponents.root) {
|
|
408
349
|
onTriggerVisibleChange = newOpen => {
|
|
409
|
-
|
|
350
|
+
triggerOpen(newOpen);
|
|
410
351
|
};
|
|
411
352
|
}
|
|
412
353
|
|
|
413
354
|
// Close when click on non-select element
|
|
414
|
-
useSelectTriggerControl(() => [containerRef.current, triggerRef.current?.getPopupElement()],
|
|
355
|
+
useSelectTriggerControl(() => [getDOM(containerRef.current), triggerRef.current?.getPopupElement()], mergedOpen, triggerOpen, !!mergedComponents.root);
|
|
415
356
|
|
|
416
357
|
// ============================ Context =============================
|
|
417
358
|
const baseSelectContext = React.useMemo(() => ({
|
|
418
359
|
...props,
|
|
419
360
|
notFoundContent,
|
|
420
361
|
open: mergedOpen,
|
|
421
|
-
triggerOpen,
|
|
362
|
+
triggerOpen: mergedOpen,
|
|
422
363
|
id,
|
|
423
|
-
showSearch
|
|
364
|
+
showSearch,
|
|
424
365
|
multiple,
|
|
425
|
-
toggleOpen:
|
|
366
|
+
toggleOpen: triggerOpen,
|
|
426
367
|
showScrollBar,
|
|
427
368
|
styles,
|
|
428
369
|
classNames
|
|
429
|
-
}), [props, notFoundContent, triggerOpen,
|
|
370
|
+
}), [props, notFoundContent, triggerOpen, id, showSearch, multiple, mergedOpen, showScrollBar, styles, classNames]);
|
|
430
371
|
|
|
431
372
|
// ==================================================================
|
|
432
373
|
// == Render ==
|
|
433
374
|
// ==================================================================
|
|
434
375
|
|
|
435
|
-
// =============================
|
|
436
|
-
const
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
className: cls(`${prefixCls}-arrow`, classNames?.suffix, {
|
|
441
|
-
[`${prefixCls}-arrow-loading`]: loading
|
|
442
|
-
}),
|
|
443
|
-
style: styles?.suffix,
|
|
444
|
-
customizeIcon: suffixIcon,
|
|
445
|
-
customizeIconProps: {
|
|
446
|
-
loading,
|
|
376
|
+
// ============================= Suffix =============================
|
|
377
|
+
const mergedSuffixIcon = React.useMemo(() => {
|
|
378
|
+
const nextSuffix = suffix ?? suffixIcon;
|
|
379
|
+
if (typeof nextSuffix === 'function') {
|
|
380
|
+
return nextSuffix({
|
|
447
381
|
searchValue: mergedSearchValue,
|
|
448
382
|
open: mergedOpen,
|
|
449
|
-
focused
|
|
450
|
-
showSearch
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
383
|
+
focused,
|
|
384
|
+
showSearch,
|
|
385
|
+
loading
|
|
386
|
+
});
|
|
387
|
+
}
|
|
388
|
+
return nextSuffix;
|
|
389
|
+
}, [suffix, suffixIcon, mergedSearchValue, mergedOpen, focused, showSearch, loading]);
|
|
454
390
|
|
|
455
391
|
// ============================= Clear ==============================
|
|
456
392
|
const onClearMouseDown = () => {
|
|
457
393
|
onClear?.();
|
|
458
|
-
|
|
394
|
+
containerRef.current?.focus();
|
|
459
395
|
onDisplayValuesChange([], {
|
|
460
396
|
type: 'clear',
|
|
461
397
|
values: displayValues
|
|
@@ -465,7 +401,7 @@ const BaseSelect = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
|
465
401
|
const {
|
|
466
402
|
allowClear: mergedAllowClear,
|
|
467
403
|
clearIcon: clearNode
|
|
468
|
-
} = useAllowClear(prefixCls,
|
|
404
|
+
} = useAllowClear(prefixCls, displayValues, allowClear, clearIcon, disabled, mergedSearchValue, mode);
|
|
469
405
|
|
|
470
406
|
// =========================== OptionList ===========================
|
|
471
407
|
const optionList = /*#__PURE__*/React.createElement(OptionList, {
|
|
@@ -473,25 +409,69 @@ const BaseSelect = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
|
473
409
|
});
|
|
474
410
|
|
|
475
411
|
// ============================= Select =============================
|
|
476
|
-
const mergedClassName =
|
|
477
|
-
[`${prefixCls}-focused`]:
|
|
412
|
+
const mergedClassName = clsx(prefixCls, className, {
|
|
413
|
+
[`${prefixCls}-focused`]: focused,
|
|
478
414
|
[`${prefixCls}-multiple`]: multiple,
|
|
479
415
|
[`${prefixCls}-single`]: !multiple,
|
|
480
|
-
[`${prefixCls}-allow-clear`]:
|
|
481
|
-
[`${prefixCls}-show-arrow`]:
|
|
416
|
+
[`${prefixCls}-allow-clear`]: mergedAllowClear,
|
|
417
|
+
[`${prefixCls}-show-arrow`]: mergedSuffixIcon !== undefined && mergedSuffixIcon !== null,
|
|
482
418
|
[`${prefixCls}-disabled`]: disabled,
|
|
483
419
|
[`${prefixCls}-loading`]: loading,
|
|
484
420
|
[`${prefixCls}-open`]: mergedOpen,
|
|
485
421
|
[`${prefixCls}-customize-input`]: customizeInputElement,
|
|
486
|
-
[`${prefixCls}-show-search`]:
|
|
422
|
+
[`${prefixCls}-show-search`]: showSearch
|
|
487
423
|
});
|
|
488
424
|
|
|
489
|
-
// >>>
|
|
490
|
-
|
|
425
|
+
// >>> Render
|
|
426
|
+
let renderNode = /*#__PURE__*/React.createElement(SelectInput, _extends({}, restProps, {
|
|
427
|
+
// Ref
|
|
428
|
+
ref: containerRef
|
|
429
|
+
// Style
|
|
430
|
+
,
|
|
431
|
+
prefixCls: prefixCls,
|
|
432
|
+
className: mergedClassName
|
|
433
|
+
// Focus state
|
|
434
|
+
,
|
|
435
|
+
focused: focused
|
|
436
|
+
// UI
|
|
437
|
+
,
|
|
438
|
+
prefix: prefix,
|
|
439
|
+
suffix: mergedSuffixIcon,
|
|
440
|
+
clearIcon: clearNode
|
|
441
|
+
// Type or mode
|
|
442
|
+
,
|
|
443
|
+
multiple: multiple,
|
|
444
|
+
mode: mode
|
|
445
|
+
// Values
|
|
446
|
+
,
|
|
447
|
+
displayValues: displayValues,
|
|
448
|
+
placeholder: placeholder,
|
|
449
|
+
searchValue: mergedSearchValue,
|
|
450
|
+
activeValue: activeValue,
|
|
451
|
+
onSearch: onInternalSearch,
|
|
452
|
+
onSearchSubmit: onInternalSearchSubmit,
|
|
453
|
+
onInputBlur: onInputBlur,
|
|
454
|
+
onFocus: onInternalFocus,
|
|
455
|
+
onBlur: onInternalBlur,
|
|
456
|
+
onClearMouseDown: onClearMouseDown,
|
|
457
|
+
onKeyDown: onInternalKeyDown,
|
|
458
|
+
onKeyUp: onInternalKeyUp,
|
|
459
|
+
onSelectorRemove: onSelectorRemove
|
|
460
|
+
// Token handling
|
|
461
|
+
,
|
|
462
|
+
tokenWithEnter: tokenWithEnter
|
|
463
|
+
// Open
|
|
464
|
+
,
|
|
465
|
+
onMouseDown: onInternalMouseDown
|
|
466
|
+
// Components
|
|
467
|
+
,
|
|
468
|
+
components: mergedComponents
|
|
469
|
+
}));
|
|
470
|
+
renderNode = /*#__PURE__*/React.createElement(SelectTrigger, {
|
|
491
471
|
ref: triggerRef,
|
|
492
472
|
disabled: disabled,
|
|
493
473
|
prefixCls: prefixCls,
|
|
494
|
-
visible:
|
|
474
|
+
visible: mergedOpen,
|
|
495
475
|
popupElement: optionList,
|
|
496
476
|
animation: animation,
|
|
497
477
|
transitionName: transitionName,
|
|
@@ -506,58 +486,15 @@ const BaseSelect = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
|
506
486
|
getPopupContainer: getPopupContainer,
|
|
507
487
|
empty: emptyOptions,
|
|
508
488
|
onPopupVisibleChange: onTriggerVisibleChange,
|
|
509
|
-
onPopupMouseEnter: onPopupMouseEnter
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
})) : /*#__PURE__*/React.createElement(Selector, _extends({}, props, {
|
|
513
|
-
prefixClassName: classNames?.prefix,
|
|
514
|
-
prefixStyle: styles?.prefix,
|
|
515
|
-
prefixCls: prefixCls,
|
|
516
|
-
inputElement: customizeInputElement,
|
|
517
|
-
ref: selectorRef,
|
|
518
|
-
id: id,
|
|
519
|
-
prefix: prefix,
|
|
520
|
-
showSearch: mergedShowSearch,
|
|
521
|
-
autoClearSearchValue: autoClearSearchValue,
|
|
522
|
-
mode: mode,
|
|
523
|
-
activeDescendantId: activeDescendantId,
|
|
524
|
-
tagRender: tagRender,
|
|
525
|
-
values: displayValues,
|
|
526
|
-
open: mergedOpen,
|
|
527
|
-
onToggleOpen: onToggleOpen,
|
|
528
|
-
activeValue: activeValue,
|
|
529
|
-
searchValue: mergedSearchValue,
|
|
530
|
-
onSearch: onInternalSearch,
|
|
531
|
-
onSearchSubmit: onInternalSearchSubmit,
|
|
532
|
-
onRemove: onSelectorRemove,
|
|
533
|
-
tokenWithEnter: tokenWithEnter,
|
|
534
|
-
onInputBlur: onInputBlur
|
|
535
|
-
})));
|
|
536
|
-
|
|
537
|
-
// >>> Render
|
|
538
|
-
let renderNode;
|
|
539
|
-
|
|
540
|
-
// Render raw
|
|
541
|
-
if (customizeRawInputElement) {
|
|
542
|
-
renderNode = selectorNode;
|
|
543
|
-
} else {
|
|
544
|
-
renderNode = /*#__PURE__*/React.createElement("div", _extends({
|
|
545
|
-
className: mergedClassName
|
|
546
|
-
}, domProps, {
|
|
547
|
-
ref: containerRef,
|
|
548
|
-
onMouseDown: onInternalMouseDown,
|
|
549
|
-
onKeyDown: onInternalKeyDown,
|
|
550
|
-
onKeyUp: onInternalKeyUp,
|
|
551
|
-
onFocus: onContainerFocus,
|
|
552
|
-
onBlur: onContainerBlur
|
|
553
|
-
}), /*#__PURE__*/React.createElement(Polite, {
|
|
554
|
-
visible: mockFocused && !mergedOpen,
|
|
555
|
-
values: displayValues
|
|
556
|
-
}), selectorNode, arrowNode, mergedAllowClear && clearNode);
|
|
557
|
-
}
|
|
489
|
+
onPopupMouseEnter: onPopupMouseEnter,
|
|
490
|
+
onPopupMouseDown: onInternalMouseDown
|
|
491
|
+
}, renderNode);
|
|
558
492
|
return /*#__PURE__*/React.createElement(BaseSelectContext.Provider, {
|
|
559
493
|
value: baseSelectContext
|
|
560
|
-
},
|
|
494
|
+
}, /*#__PURE__*/React.createElement(Polite, {
|
|
495
|
+
visible: focused && !mergedOpen,
|
|
496
|
+
values: displayValues
|
|
497
|
+
}), renderNode);
|
|
561
498
|
});
|
|
562
499
|
|
|
563
500
|
// Set display name for dev
|
package/es/OptionList.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
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); }
|
|
2
|
-
import
|
|
2
|
+
import { clsx } from 'clsx';
|
|
3
3
|
import KeyCode from "@rc-component/util/es/KeyCode";
|
|
4
4
|
import useMemo from "@rc-component/util/es/hooks/useMemo";
|
|
5
5
|
import omit from "@rc-component/util/es/omit";
|
|
@@ -316,7 +316,7 @@ const OptionList = (_, ref) => {
|
|
|
316
316
|
if (group) {
|
|
317
317
|
const groupTitle = data.title ?? (isTitleType(label) ? label.toString() : undefined);
|
|
318
318
|
return /*#__PURE__*/React.createElement("div", {
|
|
319
|
-
className:
|
|
319
|
+
className: clsx(itemPrefixCls, `${itemPrefixCls}-group`, data.className),
|
|
320
320
|
title: groupTitle
|
|
321
321
|
}, label !== undefined ? label : key);
|
|
322
322
|
}
|
|
@@ -334,7 +334,7 @@ const OptionList = (_, ref) => {
|
|
|
334
334
|
const selected = isSelected(value);
|
|
335
335
|
const mergedDisabled = disabled || !selected && overMaxCount;
|
|
336
336
|
const optionPrefixCls = `${itemPrefixCls}-option`;
|
|
337
|
-
const optionClassName =
|
|
337
|
+
const optionClassName = clsx(itemPrefixCls, optionPrefixCls, className, contextClassNames?.popup?.listItem, {
|
|
338
338
|
[`${optionPrefixCls}-grouped`]: groupOption,
|
|
339
339
|
[`${optionPrefixCls}-active`]: activeIndex === itemIndex && !mergedDisabled,
|
|
340
340
|
[`${optionPrefixCls}-disabled`]: mergedDisabled,
|
package/es/Select.d.ts
CHANGED
|
@@ -125,7 +125,7 @@ export interface SelectProps<ValueType = any, OptionType extends BaseOptionType
|
|
|
125
125
|
classNames?: Partial<Record<SemanticName, string>>;
|
|
126
126
|
styles?: Partial<Record<SemanticName, React.CSSProperties>>;
|
|
127
127
|
}
|
|
128
|
-
declare const TypedSelect: (<ValueType = any, OptionType extends
|
|
128
|
+
declare const TypedSelect: (<ValueType = any, OptionType extends DefaultOptionType | BaseOptionType = DefaultOptionType>(props: React.PropsWithChildren<SelectProps<ValueType, OptionType>> & React.RefAttributes<BaseSelectRef>) => React.ReactElement) & {
|
|
129
129
|
Option: typeof Option;
|
|
130
130
|
OptGroup: typeof OptGroup;
|
|
131
131
|
};
|
package/es/Select.js
CHANGED
|
@@ -30,7 +30,7 @@ function _extends() { _extends = Object.assign ? Object.assign.bind() : function
|
|
|
30
30
|
* - `combobox` mode not support `optionLabelProp`
|
|
31
31
|
*/
|
|
32
32
|
|
|
33
|
-
import
|
|
33
|
+
import useControlledState from "@rc-component/util/es/hooks/useControlledState";
|
|
34
34
|
import warning from "@rc-component/util/es/warning";
|
|
35
35
|
import * as React from 'react';
|
|
36
36
|
import BaseSelect, { isMultiple } from "./BaseSelect";
|
|
@@ -100,7 +100,7 @@ const Select = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
|
100
100
|
optionFilterProp: legacyOptionFilterProp,
|
|
101
101
|
filterSort: legacyFilterSort
|
|
102
102
|
};
|
|
103
|
-
const [mergedShowSearch, searchConfig] = useSearchConfig(showSearch, searchProps);
|
|
103
|
+
const [mergedShowSearch, searchConfig] = useSearchConfig(showSearch, searchProps, mode);
|
|
104
104
|
const {
|
|
105
105
|
filterOption,
|
|
106
106
|
searchValue,
|
|
@@ -127,10 +127,8 @@ const Select = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
|
127
127
|
/* eslint-enable react-hooks/exhaustive-deps */);
|
|
128
128
|
|
|
129
129
|
// =========================== Search ===========================
|
|
130
|
-
const [
|
|
131
|
-
|
|
132
|
-
postState: search => search || ''
|
|
133
|
-
});
|
|
130
|
+
const [internalSearchValue, setSearchValue] = useControlledState('', searchValue);
|
|
131
|
+
const mergedSearchValue = internalSearchValue || '';
|
|
134
132
|
|
|
135
133
|
// =========================== Option ===========================
|
|
136
134
|
const parsedOptions = useOptions(options, children, mergedFieldNames, optionFilterProp, optionLabelProp);
|
|
@@ -185,9 +183,7 @@ const Select = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
|
185
183
|
}, [mergedFieldNames, optionLabelProp, valueOptions]);
|
|
186
184
|
|
|
187
185
|
// =========================== Values ===========================
|
|
188
|
-
const [internalValue, setInternalValue] =
|
|
189
|
-
value
|
|
190
|
-
});
|
|
186
|
+
const [internalValue, setInternalValue] = useControlledState(defaultValue, value);
|
|
191
187
|
|
|
192
188
|
// Merged value with LabelValueType
|
|
193
189
|
const rawLabeledValues = React.useMemo(() => {
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
// Affix is a simple wrapper which should not read context or logical props
|
|
3
|
+
export default function Affix(props) {
|
|
4
|
+
const {
|
|
5
|
+
children,
|
|
6
|
+
...restProps
|
|
7
|
+
} = props;
|
|
8
|
+
if (!children) {
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
return /*#__PURE__*/React.createElement("div", restProps, children);
|
|
12
|
+
}
|