@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,27 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
type InputRef = HTMLInputElement | HTMLTextAreaElement;
|
|
3
|
+
interface InputProps {
|
|
4
|
+
prefixCls: string;
|
|
5
|
+
id: string;
|
|
6
|
+
inputElement: React.ReactElement;
|
|
7
|
+
disabled: boolean;
|
|
8
|
+
autoFocus: boolean;
|
|
9
|
+
autoComplete: string;
|
|
10
|
+
editable: boolean;
|
|
11
|
+
activeDescendantId?: string;
|
|
12
|
+
value: string;
|
|
13
|
+
maxLength?: number;
|
|
14
|
+
open: boolean;
|
|
15
|
+
tabIndex: number;
|
|
16
|
+
/** Pass accessibility props to input */
|
|
17
|
+
attrs: Record<string, unknown>;
|
|
18
|
+
onKeyDown: React.KeyboardEventHandler<HTMLInputElement | HTMLTextAreaElement | HTMLElement>;
|
|
19
|
+
onMouseDown: React.MouseEventHandler<HTMLInputElement | HTMLTextAreaElement | HTMLElement>;
|
|
20
|
+
onChange: React.ChangeEventHandler<HTMLInputElement | HTMLTextAreaElement | HTMLElement>;
|
|
21
|
+
onPaste: React.ClipboardEventHandler<HTMLInputElement | HTMLTextAreaElement | HTMLElement>;
|
|
22
|
+
onBlur: React.FocusEventHandler<HTMLInputElement | HTMLTextAreaElement | HTMLElement>;
|
|
23
|
+
onCompositionStart: React.CompositionEventHandler<HTMLInputElement | HTMLTextAreaElement | HTMLElement>;
|
|
24
|
+
onCompositionEnd: React.CompositionEventHandler<HTMLInputElement | HTMLTextAreaElement | HTMLElement>;
|
|
25
|
+
}
|
|
26
|
+
declare const RefInput: React.ForwardRefExoticComponent<InputProps & React.RefAttributes<InputRef>>;
|
|
27
|
+
export default RefInput;
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import classNames from 'classnames';
|
|
3
|
+
import { composeRef } from "@rc-component/util/es/ref";
|
|
4
|
+
import { warning } from "@rc-component/util/es/warning";
|
|
5
|
+
const Input = (props, ref) => {
|
|
6
|
+
const {
|
|
7
|
+
prefixCls,
|
|
8
|
+
id,
|
|
9
|
+
inputElement,
|
|
10
|
+
disabled,
|
|
11
|
+
tabIndex,
|
|
12
|
+
autoFocus,
|
|
13
|
+
autoComplete,
|
|
14
|
+
editable,
|
|
15
|
+
activeDescendantId,
|
|
16
|
+
value,
|
|
17
|
+
maxLength,
|
|
18
|
+
onKeyDown,
|
|
19
|
+
onMouseDown,
|
|
20
|
+
onChange,
|
|
21
|
+
onPaste,
|
|
22
|
+
onCompositionStart,
|
|
23
|
+
onCompositionEnd,
|
|
24
|
+
onBlur,
|
|
25
|
+
open,
|
|
26
|
+
attrs
|
|
27
|
+
} = props;
|
|
28
|
+
let inputNode = inputElement || /*#__PURE__*/React.createElement("input", null);
|
|
29
|
+
const {
|
|
30
|
+
ref: originRef,
|
|
31
|
+
props: originProps
|
|
32
|
+
} = inputNode;
|
|
33
|
+
const {
|
|
34
|
+
onKeyDown: onOriginKeyDown,
|
|
35
|
+
onChange: onOriginChange,
|
|
36
|
+
onMouseDown: onOriginMouseDown,
|
|
37
|
+
onCompositionStart: onOriginCompositionStart,
|
|
38
|
+
onCompositionEnd: onOriginCompositionEnd,
|
|
39
|
+
onBlur: onOriginBlur,
|
|
40
|
+
style
|
|
41
|
+
} = originProps;
|
|
42
|
+
warning(!('maxLength' in inputNode.props), `Passing 'maxLength' to input element directly may not work because input in BaseSelect is controlled.`);
|
|
43
|
+
inputNode = /*#__PURE__*/React.cloneElement(inputNode, {
|
|
44
|
+
type: 'search',
|
|
45
|
+
...originProps,
|
|
46
|
+
// Override over origin props
|
|
47
|
+
id,
|
|
48
|
+
ref: composeRef(ref, originRef),
|
|
49
|
+
disabled,
|
|
50
|
+
tabIndex,
|
|
51
|
+
autoComplete: autoComplete || 'off',
|
|
52
|
+
autoFocus,
|
|
53
|
+
className: classNames(`${prefixCls}-selection-search-input`, inputNode?.props?.className),
|
|
54
|
+
role: 'combobox',
|
|
55
|
+
'aria-expanded': open || false,
|
|
56
|
+
'aria-haspopup': 'listbox',
|
|
57
|
+
'aria-owns': `${id}_list`,
|
|
58
|
+
'aria-autocomplete': 'list',
|
|
59
|
+
'aria-controls': `${id}_list`,
|
|
60
|
+
'aria-activedescendant': open ? activeDescendantId : undefined,
|
|
61
|
+
...attrs,
|
|
62
|
+
value: editable ? value : '',
|
|
63
|
+
maxLength,
|
|
64
|
+
readOnly: !editable,
|
|
65
|
+
unselectable: !editable ? 'on' : null,
|
|
66
|
+
style: {
|
|
67
|
+
...style,
|
|
68
|
+
opacity: editable ? null : 0
|
|
69
|
+
},
|
|
70
|
+
onKeyDown: event => {
|
|
71
|
+
onKeyDown(event);
|
|
72
|
+
if (onOriginKeyDown) {
|
|
73
|
+
onOriginKeyDown(event);
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
onMouseDown: event => {
|
|
77
|
+
onMouseDown(event);
|
|
78
|
+
if (onOriginMouseDown) {
|
|
79
|
+
onOriginMouseDown(event);
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
onChange: event => {
|
|
83
|
+
onChange(event);
|
|
84
|
+
if (onOriginChange) {
|
|
85
|
+
onOriginChange(event);
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
onCompositionStart(event) {
|
|
89
|
+
onCompositionStart(event);
|
|
90
|
+
if (onOriginCompositionStart) {
|
|
91
|
+
onOriginCompositionStart(event);
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
onCompositionEnd(event) {
|
|
95
|
+
onCompositionEnd(event);
|
|
96
|
+
if (onOriginCompositionEnd) {
|
|
97
|
+
onOriginCompositionEnd(event);
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
onPaste,
|
|
101
|
+
onBlur(event) {
|
|
102
|
+
onBlur(event);
|
|
103
|
+
if (onOriginBlur) {
|
|
104
|
+
onOriginBlur(event);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
return inputNode;
|
|
109
|
+
};
|
|
110
|
+
const RefInput = /*#__PURE__*/React.forwardRef(Input);
|
|
111
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
112
|
+
RefInput.displayName = 'Input';
|
|
113
|
+
}
|
|
114
|
+
export default RefInput;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { InnerSelectorProps } from '.';
|
|
3
|
+
import type { DisplayValueType, RenderNode, CustomTagProps } from '../BaseSelect';
|
|
4
|
+
interface SelectorProps extends InnerSelectorProps {
|
|
5
|
+
removeIcon?: RenderNode;
|
|
6
|
+
maxTagCount?: number | 'responsive';
|
|
7
|
+
maxTagTextLength?: number;
|
|
8
|
+
maxTagPlaceholder?: React.ReactNode | ((omittedValues: DisplayValueType[]) => React.ReactNode);
|
|
9
|
+
tokenSeparators?: string[];
|
|
10
|
+
tagRender?: (props: CustomTagProps) => React.ReactElement;
|
|
11
|
+
onToggleOpen: (open?: boolean) => void;
|
|
12
|
+
choiceTransitionName?: string;
|
|
13
|
+
onRemove: (value: DisplayValueType) => void;
|
|
14
|
+
}
|
|
15
|
+
declare const SelectSelector: React.FC<SelectorProps>;
|
|
16
|
+
export default SelectSelector;
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import classNames from 'classnames';
|
|
4
|
+
import pickAttrs from "@rc-component/util/es/pickAttrs";
|
|
5
|
+
import Overflow from 'rc-overflow';
|
|
6
|
+
import TransBtn from "../TransBtn";
|
|
7
|
+
import Input from "./Input";
|
|
8
|
+
import useLayoutEffect from "../hooks/useLayoutEffect";
|
|
9
|
+
import { getTitle } from "../utils/commonUtil";
|
|
10
|
+
function itemKey(value) {
|
|
11
|
+
return value.key ?? value.value;
|
|
12
|
+
}
|
|
13
|
+
const onPreventMouseDown = event => {
|
|
14
|
+
event.preventDefault();
|
|
15
|
+
event.stopPropagation();
|
|
16
|
+
};
|
|
17
|
+
const SelectSelector = props => {
|
|
18
|
+
const {
|
|
19
|
+
id,
|
|
20
|
+
prefixCls,
|
|
21
|
+
values,
|
|
22
|
+
open,
|
|
23
|
+
searchValue,
|
|
24
|
+
autoClearSearchValue,
|
|
25
|
+
inputRef,
|
|
26
|
+
placeholder,
|
|
27
|
+
disabled,
|
|
28
|
+
mode,
|
|
29
|
+
showSearch,
|
|
30
|
+
autoFocus,
|
|
31
|
+
autoComplete,
|
|
32
|
+
activeDescendantId,
|
|
33
|
+
tabIndex,
|
|
34
|
+
removeIcon,
|
|
35
|
+
maxTagCount,
|
|
36
|
+
maxTagTextLength,
|
|
37
|
+
maxTagPlaceholder = omittedValues => `+ ${omittedValues.length} ...`,
|
|
38
|
+
tagRender,
|
|
39
|
+
onToggleOpen,
|
|
40
|
+
onRemove,
|
|
41
|
+
onInputChange,
|
|
42
|
+
onInputPaste,
|
|
43
|
+
onInputKeyDown,
|
|
44
|
+
onInputMouseDown,
|
|
45
|
+
onInputCompositionStart,
|
|
46
|
+
onInputCompositionEnd,
|
|
47
|
+
onInputBlur
|
|
48
|
+
} = props;
|
|
49
|
+
const measureRef = React.useRef(null);
|
|
50
|
+
const [inputWidth, setInputWidth] = useState(0);
|
|
51
|
+
const [focused, setFocused] = useState(false);
|
|
52
|
+
const selectionPrefixCls = `${prefixCls}-selection`;
|
|
53
|
+
|
|
54
|
+
// ===================== Search ======================
|
|
55
|
+
const inputValue = open || mode === 'multiple' && autoClearSearchValue === false || mode === 'tags' ? searchValue : '';
|
|
56
|
+
const inputEditable = mode === 'tags' || mode === 'multiple' && autoClearSearchValue === false || showSearch && (open || focused);
|
|
57
|
+
|
|
58
|
+
// We measure width and set to the input immediately
|
|
59
|
+
useLayoutEffect(() => {
|
|
60
|
+
setInputWidth(measureRef.current.scrollWidth);
|
|
61
|
+
}, [inputValue]);
|
|
62
|
+
|
|
63
|
+
// ===================== Render ======================
|
|
64
|
+
// >>> Render Selector Node. Includes Item & Rest
|
|
65
|
+
const defaultRenderSelector = (item, content, itemDisabled, closable, onClose) => /*#__PURE__*/React.createElement("span", {
|
|
66
|
+
title: getTitle(item),
|
|
67
|
+
className: classNames(`${selectionPrefixCls}-item`, {
|
|
68
|
+
[`${selectionPrefixCls}-item-disabled`]: itemDisabled
|
|
69
|
+
})
|
|
70
|
+
}, /*#__PURE__*/React.createElement("span", {
|
|
71
|
+
className: `${selectionPrefixCls}-item-content`
|
|
72
|
+
}, content), closable && /*#__PURE__*/React.createElement(TransBtn, {
|
|
73
|
+
className: `${selectionPrefixCls}-item-remove`,
|
|
74
|
+
onMouseDown: onPreventMouseDown,
|
|
75
|
+
onClick: onClose,
|
|
76
|
+
customizeIcon: removeIcon
|
|
77
|
+
}, "\xD7"));
|
|
78
|
+
const customizeRenderSelector = (value, content, itemDisabled, closable, onClose, isMaxTag, info) => {
|
|
79
|
+
const onMouseDown = e => {
|
|
80
|
+
onPreventMouseDown(e);
|
|
81
|
+
onToggleOpen(!open);
|
|
82
|
+
};
|
|
83
|
+
return /*#__PURE__*/React.createElement("span", {
|
|
84
|
+
onMouseDown: onMouseDown
|
|
85
|
+
}, tagRender({
|
|
86
|
+
label: content,
|
|
87
|
+
value,
|
|
88
|
+
index: info?.index,
|
|
89
|
+
disabled: itemDisabled,
|
|
90
|
+
closable,
|
|
91
|
+
onClose,
|
|
92
|
+
isMaxTag: !!isMaxTag
|
|
93
|
+
}));
|
|
94
|
+
};
|
|
95
|
+
const renderItem = (valueItem, info) => {
|
|
96
|
+
const {
|
|
97
|
+
disabled: itemDisabled,
|
|
98
|
+
label,
|
|
99
|
+
value
|
|
100
|
+
} = valueItem;
|
|
101
|
+
const closable = !disabled && !itemDisabled;
|
|
102
|
+
let displayLabel = label;
|
|
103
|
+
if (typeof maxTagTextLength === 'number') {
|
|
104
|
+
if (typeof label === 'string' || typeof label === 'number') {
|
|
105
|
+
const strLabel = String(displayLabel);
|
|
106
|
+
if (strLabel.length > maxTagTextLength) {
|
|
107
|
+
displayLabel = `${strLabel.slice(0, maxTagTextLength)}...`;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
const onClose = event => {
|
|
112
|
+
if (event) {
|
|
113
|
+
event.stopPropagation();
|
|
114
|
+
}
|
|
115
|
+
onRemove(valueItem);
|
|
116
|
+
};
|
|
117
|
+
return typeof tagRender === 'function' ? customizeRenderSelector(value, displayLabel, itemDisabled, closable, onClose, undefined, info) : defaultRenderSelector(valueItem, displayLabel, itemDisabled, closable, onClose);
|
|
118
|
+
};
|
|
119
|
+
const renderRest = omittedValues => {
|
|
120
|
+
// https://github.com/ant-design/ant-design/issues/48930
|
|
121
|
+
if (!values.length) {
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
const content = typeof maxTagPlaceholder === 'function' ? maxTagPlaceholder(omittedValues) : maxTagPlaceholder;
|
|
125
|
+
return typeof tagRender === 'function' ? customizeRenderSelector(undefined, content, false, false, undefined, true) : defaultRenderSelector({
|
|
126
|
+
title: content
|
|
127
|
+
}, content, false);
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
// >>> Input Node
|
|
131
|
+
const inputNode = /*#__PURE__*/React.createElement("div", {
|
|
132
|
+
className: `${selectionPrefixCls}-search`,
|
|
133
|
+
style: {
|
|
134
|
+
width: inputWidth
|
|
135
|
+
},
|
|
136
|
+
onFocus: () => {
|
|
137
|
+
setFocused(true);
|
|
138
|
+
},
|
|
139
|
+
onBlur: () => {
|
|
140
|
+
setFocused(false);
|
|
141
|
+
}
|
|
142
|
+
}, /*#__PURE__*/React.createElement(Input, {
|
|
143
|
+
ref: inputRef,
|
|
144
|
+
open: open,
|
|
145
|
+
prefixCls: prefixCls,
|
|
146
|
+
id: id,
|
|
147
|
+
inputElement: null,
|
|
148
|
+
disabled: disabled,
|
|
149
|
+
autoFocus: autoFocus,
|
|
150
|
+
autoComplete: autoComplete,
|
|
151
|
+
editable: inputEditable,
|
|
152
|
+
activeDescendantId: activeDescendantId,
|
|
153
|
+
value: inputValue,
|
|
154
|
+
onKeyDown: onInputKeyDown,
|
|
155
|
+
onMouseDown: onInputMouseDown,
|
|
156
|
+
onChange: onInputChange,
|
|
157
|
+
onPaste: onInputPaste,
|
|
158
|
+
onCompositionStart: onInputCompositionStart,
|
|
159
|
+
onCompositionEnd: onInputCompositionEnd,
|
|
160
|
+
onBlur: onInputBlur,
|
|
161
|
+
tabIndex: tabIndex,
|
|
162
|
+
attrs: pickAttrs(props, true)
|
|
163
|
+
}), /*#__PURE__*/React.createElement("span", {
|
|
164
|
+
ref: measureRef,
|
|
165
|
+
className: `${selectionPrefixCls}-search-mirror`,
|
|
166
|
+
"aria-hidden": true
|
|
167
|
+
}, inputValue, "\xA0"));
|
|
168
|
+
|
|
169
|
+
// >>> Selections
|
|
170
|
+
const selectionNode = /*#__PURE__*/React.createElement(Overflow, {
|
|
171
|
+
prefixCls: `${selectionPrefixCls}-overflow`,
|
|
172
|
+
data: values,
|
|
173
|
+
renderItem: renderItem,
|
|
174
|
+
renderRest: renderRest,
|
|
175
|
+
suffix: inputNode,
|
|
176
|
+
itemKey: itemKey,
|
|
177
|
+
maxCount: maxTagCount
|
|
178
|
+
});
|
|
179
|
+
return /*#__PURE__*/React.createElement("span", {
|
|
180
|
+
className: `${selectionPrefixCls}-wrap`
|
|
181
|
+
}, selectionNode, !values.length && !inputValue && /*#__PURE__*/React.createElement("span", {
|
|
182
|
+
className: `${selectionPrefixCls}-placeholder`
|
|
183
|
+
}, placeholder));
|
|
184
|
+
};
|
|
185
|
+
export default SelectSelector;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { InnerSelectorProps } from '.';
|
|
3
|
+
interface SelectorProps extends InnerSelectorProps {
|
|
4
|
+
inputElement: React.ReactElement;
|
|
5
|
+
activeValue: string;
|
|
6
|
+
}
|
|
7
|
+
declare const SingleSelector: React.FC<SelectorProps>;
|
|
8
|
+
export default SingleSelector;
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import pickAttrs from "@rc-component/util/es/pickAttrs";
|
|
3
|
+
import Input from "./Input";
|
|
4
|
+
import { getTitle } from "../utils/commonUtil";
|
|
5
|
+
const SingleSelector = props => {
|
|
6
|
+
const {
|
|
7
|
+
inputElement,
|
|
8
|
+
prefixCls,
|
|
9
|
+
id,
|
|
10
|
+
inputRef,
|
|
11
|
+
disabled,
|
|
12
|
+
autoFocus,
|
|
13
|
+
autoComplete,
|
|
14
|
+
activeDescendantId,
|
|
15
|
+
mode,
|
|
16
|
+
open,
|
|
17
|
+
values,
|
|
18
|
+
placeholder,
|
|
19
|
+
tabIndex,
|
|
20
|
+
showSearch,
|
|
21
|
+
searchValue,
|
|
22
|
+
activeValue,
|
|
23
|
+
maxLength,
|
|
24
|
+
onInputKeyDown,
|
|
25
|
+
onInputMouseDown,
|
|
26
|
+
onInputChange,
|
|
27
|
+
onInputPaste,
|
|
28
|
+
onInputCompositionStart,
|
|
29
|
+
onInputCompositionEnd,
|
|
30
|
+
onInputBlur,
|
|
31
|
+
title
|
|
32
|
+
} = props;
|
|
33
|
+
const [inputChanged, setInputChanged] = React.useState(false);
|
|
34
|
+
const combobox = mode === 'combobox';
|
|
35
|
+
const inputEditable = combobox || showSearch;
|
|
36
|
+
const item = values[0];
|
|
37
|
+
let inputValue = searchValue || '';
|
|
38
|
+
if (combobox && activeValue && !inputChanged) {
|
|
39
|
+
inputValue = activeValue;
|
|
40
|
+
}
|
|
41
|
+
React.useEffect(() => {
|
|
42
|
+
if (combobox) {
|
|
43
|
+
setInputChanged(false);
|
|
44
|
+
}
|
|
45
|
+
}, [combobox, activeValue]);
|
|
46
|
+
|
|
47
|
+
// Not show text when closed expect combobox mode
|
|
48
|
+
const hasTextInput = mode !== 'combobox' && !open && !showSearch ? false : !!inputValue;
|
|
49
|
+
|
|
50
|
+
// Get title of selection item
|
|
51
|
+
const selectionTitle = title === undefined ? getTitle(item) : title;
|
|
52
|
+
const placeholderNode = React.useMemo(() => {
|
|
53
|
+
if (item) {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
return /*#__PURE__*/React.createElement("span", {
|
|
57
|
+
className: `${prefixCls}-selection-placeholder`,
|
|
58
|
+
style: hasTextInput ? {
|
|
59
|
+
visibility: 'hidden'
|
|
60
|
+
} : undefined
|
|
61
|
+
}, placeholder);
|
|
62
|
+
}, [item, hasTextInput, placeholder, prefixCls]);
|
|
63
|
+
return /*#__PURE__*/React.createElement("span", {
|
|
64
|
+
className: `${prefixCls}-selection-wrap`
|
|
65
|
+
}, /*#__PURE__*/React.createElement("span", {
|
|
66
|
+
className: `${prefixCls}-selection-search`
|
|
67
|
+
}, /*#__PURE__*/React.createElement(Input, {
|
|
68
|
+
ref: inputRef,
|
|
69
|
+
prefixCls: prefixCls,
|
|
70
|
+
id: id,
|
|
71
|
+
open: open,
|
|
72
|
+
inputElement: inputElement,
|
|
73
|
+
disabled: disabled,
|
|
74
|
+
autoFocus: autoFocus,
|
|
75
|
+
autoComplete: autoComplete,
|
|
76
|
+
editable: inputEditable,
|
|
77
|
+
activeDescendantId: activeDescendantId,
|
|
78
|
+
value: inputValue,
|
|
79
|
+
onKeyDown: onInputKeyDown,
|
|
80
|
+
onMouseDown: onInputMouseDown,
|
|
81
|
+
onChange: e => {
|
|
82
|
+
setInputChanged(true);
|
|
83
|
+
onInputChange(e);
|
|
84
|
+
},
|
|
85
|
+
onPaste: onInputPaste,
|
|
86
|
+
onCompositionStart: onInputCompositionStart,
|
|
87
|
+
onCompositionEnd: onInputCompositionEnd,
|
|
88
|
+
onBlur: onInputBlur,
|
|
89
|
+
tabIndex: tabIndex,
|
|
90
|
+
attrs: pickAttrs(props, true),
|
|
91
|
+
maxLength: combobox ? maxLength : undefined
|
|
92
|
+
})), !combobox && item ? /*#__PURE__*/React.createElement("span", {
|
|
93
|
+
className: `${prefixCls}-selection-item`,
|
|
94
|
+
title: selectionTitle
|
|
95
|
+
// 当 Select 已经选中选项时,还需 selection 隐藏但留在原地占位
|
|
96
|
+
// https://github.com/ant-design/ant-design/issues/27688
|
|
97
|
+
// https://github.com/ant-design/ant-design/issues/41530
|
|
98
|
+
,
|
|
99
|
+
style: hasTextInput ? {
|
|
100
|
+
visibility: 'hidden'
|
|
101
|
+
} : undefined
|
|
102
|
+
}, item.label) : null, placeholderNode);
|
|
103
|
+
};
|
|
104
|
+
export default SingleSelector;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cursor rule:
|
|
3
|
+
* 1. Only `showSearch` enabled
|
|
4
|
+
* 2. Only `open` is `true`
|
|
5
|
+
* 3. When typing, set `open` to `true` which hit rule of 2
|
|
6
|
+
*
|
|
7
|
+
* Accessibility:
|
|
8
|
+
* - https://www.w3.org/TR/wai-aria-practices/examples/combobox/aria1.1pattern/listbox-combo.html
|
|
9
|
+
*/
|
|
10
|
+
import type { ScrollTo } from 'rc-virtual-list/lib/List';
|
|
11
|
+
import * as React from 'react';
|
|
12
|
+
import type { CustomTagProps, DisplayValueType, Mode, RenderNode } from '../BaseSelect';
|
|
13
|
+
export interface InnerSelectorProps {
|
|
14
|
+
prefixCls: string;
|
|
15
|
+
id: string;
|
|
16
|
+
mode: Mode;
|
|
17
|
+
title?: string;
|
|
18
|
+
inputRef: React.Ref<HTMLInputElement | HTMLTextAreaElement>;
|
|
19
|
+
placeholder?: React.ReactNode;
|
|
20
|
+
disabled?: boolean;
|
|
21
|
+
autoFocus?: boolean;
|
|
22
|
+
autoComplete?: string;
|
|
23
|
+
values: DisplayValueType[];
|
|
24
|
+
showSearch?: boolean;
|
|
25
|
+
searchValue: string;
|
|
26
|
+
autoClearSearchValue?: boolean;
|
|
27
|
+
activeDescendantId?: string;
|
|
28
|
+
open: boolean;
|
|
29
|
+
tabIndex?: number;
|
|
30
|
+
maxLength?: number;
|
|
31
|
+
onInputKeyDown: React.KeyboardEventHandler<HTMLInputElement | HTMLTextAreaElement>;
|
|
32
|
+
onInputMouseDown: React.MouseEventHandler<HTMLInputElement | HTMLTextAreaElement>;
|
|
33
|
+
onInputChange: React.ChangeEventHandler<HTMLInputElement | HTMLTextAreaElement>;
|
|
34
|
+
onInputPaste: React.ClipboardEventHandler<HTMLInputElement | HTMLTextAreaElement>;
|
|
35
|
+
onInputCompositionStart: React.CompositionEventHandler<HTMLInputElement | HTMLTextAreaElement>;
|
|
36
|
+
onInputCompositionEnd: React.CompositionEventHandler<HTMLInputElement | HTMLTextAreaElement>;
|
|
37
|
+
onInputBlur: React.FocusEventHandler<HTMLInputElement | HTMLTextAreaElement>;
|
|
38
|
+
}
|
|
39
|
+
export interface RefSelectorProps {
|
|
40
|
+
focus: (options?: FocusOptions) => void;
|
|
41
|
+
blur: () => void;
|
|
42
|
+
scrollTo?: ScrollTo;
|
|
43
|
+
}
|
|
44
|
+
export interface SelectorProps {
|
|
45
|
+
id: string;
|
|
46
|
+
prefixCls: string;
|
|
47
|
+
showSearch?: boolean;
|
|
48
|
+
open: boolean;
|
|
49
|
+
/** Display in the Selector value, it's not same as `value` prop */
|
|
50
|
+
values: DisplayValueType[];
|
|
51
|
+
mode: Mode;
|
|
52
|
+
searchValue: string;
|
|
53
|
+
activeValue: string;
|
|
54
|
+
autoClearSearchValue: boolean;
|
|
55
|
+
inputElement: JSX.Element;
|
|
56
|
+
maxLength?: number;
|
|
57
|
+
autoFocus?: boolean;
|
|
58
|
+
activeDescendantId?: string;
|
|
59
|
+
tabIndex?: number;
|
|
60
|
+
disabled?: boolean;
|
|
61
|
+
placeholder?: React.ReactNode;
|
|
62
|
+
removeIcon?: RenderNode;
|
|
63
|
+
prefix?: React.ReactNode;
|
|
64
|
+
maxTagCount?: number | 'responsive';
|
|
65
|
+
maxTagTextLength?: number;
|
|
66
|
+
maxTagPlaceholder?: React.ReactNode | ((omittedValues: DisplayValueType[]) => React.ReactNode);
|
|
67
|
+
tagRender?: (props: CustomTagProps) => React.ReactElement;
|
|
68
|
+
/** Check if `tokenSeparators` contains `\n` or `\r\n` */
|
|
69
|
+
tokenWithEnter?: boolean;
|
|
70
|
+
choiceTransitionName?: string;
|
|
71
|
+
onToggleOpen: (open?: boolean) => void;
|
|
72
|
+
/** `onSearch` returns go next step boolean to check if need do toggle open */
|
|
73
|
+
onSearch: (searchText: string, fromTyping: boolean, isCompositing: boolean) => boolean;
|
|
74
|
+
onSearchSubmit?: (searchText: string) => void;
|
|
75
|
+
onRemove: (value: DisplayValueType) => void;
|
|
76
|
+
onInputKeyDown?: React.KeyboardEventHandler<HTMLInputElement | HTMLTextAreaElement>;
|
|
77
|
+
onInputBlur?: () => void;
|
|
78
|
+
/**
|
|
79
|
+
* @private get real dom for trigger align.
|
|
80
|
+
* This may be removed after React provides replacement of `findDOMNode`
|
|
81
|
+
*/
|
|
82
|
+
domRef: React.Ref<HTMLDivElement>;
|
|
83
|
+
}
|
|
84
|
+
declare const ForwardSelector: React.ForwardRefExoticComponent<SelectorProps & React.RefAttributes<RefSelectorProps>>;
|
|
85
|
+
export default ForwardSelector;
|