@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.
Files changed (99) hide show
  1. package/assets/index.css +63 -0
  2. package/assets/index.less +1 -0
  3. package/assets/patch.less +83 -0
  4. package/es/BaseSelect/index.d.ts +14 -3
  5. package/es/BaseSelect/index.js +137 -200
  6. package/es/OptionList.js +3 -3
  7. package/es/Select.d.ts +1 -1
  8. package/es/Select.js +5 -9
  9. package/es/SelectInput/Affix.d.ts +5 -0
  10. package/es/SelectInput/Affix.js +12 -0
  11. package/es/SelectInput/Content/MultipleContent.d.ts +4 -0
  12. package/es/SelectInput/Content/MultipleContent.js +152 -0
  13. package/es/SelectInput/Content/Placeholder.d.ts +5 -0
  14. package/es/SelectInput/Content/Placeholder.js +21 -0
  15. package/es/SelectInput/Content/SingleContent.d.ts +4 -0
  16. package/es/SelectInput/Content/SingleContent.js +98 -0
  17. package/es/SelectInput/Content/index.d.ts +6 -0
  18. package/es/SelectInput/Content/index.js +37 -0
  19. package/es/SelectInput/Input.d.ts +20 -0
  20. package/es/SelectInput/Input.js +214 -0
  21. package/es/SelectInput/context.d.ts +6 -0
  22. package/es/SelectInput/context.js +6 -0
  23. package/es/SelectInput/index.d.ts +39 -0
  24. package/es/SelectInput/index.js +189 -0
  25. package/es/SelectTrigger.d.ts +1 -0
  26. package/es/SelectTrigger.js +5 -3
  27. package/es/TransBtn.d.ts +10 -0
  28. package/es/TransBtn.js +12 -2
  29. package/es/hooks/useAllowClear.d.ts +8 -7
  30. package/es/hooks/useAllowClear.js +21 -23
  31. package/es/hooks/useBaseProps.d.ts +1 -0
  32. package/es/hooks/useComponents.d.ts +12 -0
  33. package/es/hooks/useComponents.js +23 -0
  34. package/es/hooks/useOpen.d.ts +15 -0
  35. package/es/hooks/useOpen.js +76 -0
  36. package/es/hooks/useSearchConfig.d.ts +2 -2
  37. package/es/hooks/useSearchConfig.js +3 -3
  38. package/es/hooks/useSelectTriggerControl.d.ts +1 -1
  39. package/es/hooks/useSelectTriggerControl.js +16 -21
  40. package/es/utils/keyUtil.js +4 -0
  41. package/lib/BaseSelect/index.d.ts +14 -3
  42. package/lib/BaseSelect/index.js +137 -201
  43. package/lib/OptionList.js +3 -3
  44. package/lib/Select.d.ts +1 -1
  45. package/lib/Select.js +5 -9
  46. package/lib/SelectInput/Affix.d.ts +5 -0
  47. package/lib/{hooks/useLayoutEffect.js → SelectInput/Affix.js} +11 -16
  48. package/lib/SelectInput/Content/MultipleContent.d.ts +4 -0
  49. package/lib/{Selector/MultipleSelector.js → SelectInput/Content/MultipleContent.js} +71 -104
  50. package/lib/SelectInput/Content/Placeholder.d.ts +5 -0
  51. package/lib/SelectInput/Content/Placeholder.js +29 -0
  52. package/lib/SelectInput/Content/SingleContent.d.ts +4 -0
  53. package/lib/SelectInput/Content/SingleContent.js +107 -0
  54. package/lib/SelectInput/Content/index.d.ts +6 -0
  55. package/lib/SelectInput/Content/index.js +46 -0
  56. package/lib/SelectInput/Input.d.ts +20 -0
  57. package/lib/SelectInput/Input.js +223 -0
  58. package/lib/SelectInput/context.d.ts +6 -0
  59. package/lib/SelectInput/context.js +15 -0
  60. package/lib/SelectInput/index.d.ts +39 -0
  61. package/lib/SelectInput/index.js +198 -0
  62. package/lib/SelectTrigger.d.ts +1 -0
  63. package/lib/SelectTrigger.js +5 -3
  64. package/lib/TransBtn.d.ts +10 -0
  65. package/lib/TransBtn.js +12 -3
  66. package/lib/hooks/useAllowClear.d.ts +8 -7
  67. package/lib/hooks/useAllowClear.js +21 -24
  68. package/lib/hooks/useBaseProps.d.ts +1 -0
  69. package/lib/hooks/useComponents.d.ts +12 -0
  70. package/lib/hooks/{useDelayReset.js → useComponents.js} +21 -30
  71. package/lib/hooks/useOpen.d.ts +15 -0
  72. package/lib/hooks/useOpen.js +82 -0
  73. package/lib/hooks/useSearchConfig.d.ts +2 -2
  74. package/lib/hooks/useSearchConfig.js +3 -3
  75. package/lib/hooks/useSelectTriggerControl.d.ts +1 -1
  76. package/lib/hooks/useSelectTriggerControl.js +16 -21
  77. package/lib/utils/keyUtil.js +4 -0
  78. package/package.json +5 -4
  79. package/es/Selector/Input.d.ts +0 -27
  80. package/es/Selector/Input.js +0 -61
  81. package/es/Selector/MultipleSelector.d.ts +0 -16
  82. package/es/Selector/MultipleSelector.js +0 -185
  83. package/es/Selector/SingleSelector.d.ts +0 -8
  84. package/es/Selector/SingleSelector.js +0 -104
  85. package/es/Selector/index.d.ts +0 -83
  86. package/es/Selector/index.js +0 -189
  87. package/es/hooks/useDelayReset.d.ts +0 -5
  88. package/es/hooks/useDelayReset.js +0 -33
  89. package/es/hooks/useLayoutEffect.d.ts +0 -5
  90. package/es/hooks/useLayoutEffect.js +0 -17
  91. package/lib/Selector/Input.d.ts +0 -27
  92. package/lib/Selector/Input.js +0 -70
  93. package/lib/Selector/MultipleSelector.d.ts +0 -16
  94. package/lib/Selector/SingleSelector.d.ts +0 -8
  95. package/lib/Selector/SingleSelector.js +0 -113
  96. package/lib/Selector/index.d.ts +0 -83
  97. package/lib/Selector/index.js +0 -196
  98. package/lib/hooks/useDelayReset.d.ts +0 -5
  99. package/lib/hooks/useLayoutEffect.d.ts +0 -5
@@ -0,0 +1,152 @@
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 * as React from 'react';
3
+ import { clsx } from 'clsx';
4
+ import Overflow from 'rc-overflow';
5
+ import Input from "../Input";
6
+ import { useSelectInputContext } from "../context";
7
+ import TransBtn from "../../TransBtn";
8
+ import { getTitle } from "../../utils/commonUtil";
9
+ import useBaseProps from "../../hooks/useBaseProps";
10
+ import Placeholder from "./Placeholder";
11
+ function itemKey(value) {
12
+ return value.key ?? value.value;
13
+ }
14
+ const onPreventMouseDown = event => {
15
+ event.preventDefault();
16
+ event.stopPropagation();
17
+ };
18
+ export default /*#__PURE__*/React.forwardRef(function MultipleContent({
19
+ inputProps
20
+ }, ref) {
21
+ const {
22
+ prefixCls,
23
+ displayValues,
24
+ searchValue,
25
+ mode,
26
+ onSelectorRemove,
27
+ removeIcon: removeIconFromContext
28
+ } = useSelectInputContext();
29
+ const {
30
+ disabled,
31
+ showSearch,
32
+ triggerOpen,
33
+ toggleOpen,
34
+ autoClearSearchValue,
35
+ tagRender: tagRenderFromContext,
36
+ maxTagPlaceholder: maxTagPlaceholderFromContext,
37
+ maxTagTextLength,
38
+ maxTagCount
39
+ } = useBaseProps();
40
+ const selectionItemPrefixCls = `${prefixCls}-selection-item`;
41
+
42
+ // ===================== Search ======================
43
+ // Apply autoClearSearchValue logic: when dropdown is closed and autoClearSearchValue is not false (default true), clear search value
44
+ let computedSearchValue = searchValue;
45
+ if (!triggerOpen && mode === 'multiple' && autoClearSearchValue !== false) {
46
+ computedSearchValue = '';
47
+ }
48
+ const inputValue = showSearch ? computedSearchValue || '' : '';
49
+ const inputEditable = showSearch && !disabled;
50
+
51
+ // Props from context with safe defaults
52
+ const removeIcon = removeIconFromContext ?? '×';
53
+ const maxTagPlaceholder = maxTagPlaceholderFromContext ?? (omittedValues => `+ ${omittedValues.length} ...`);
54
+ const tagRender = tagRenderFromContext;
55
+ const onToggleOpen = newOpen => {
56
+ toggleOpen(newOpen);
57
+ };
58
+ const onRemove = value => {
59
+ onSelectorRemove?.(value);
60
+ };
61
+
62
+ // ======================== Item ========================
63
+ // >>> Render Selector Node. Includes Item & Rest
64
+ const defaultRenderSelector = (item, content, itemDisabled, closable, onClose) => /*#__PURE__*/React.createElement("span", {
65
+ title: getTitle(item),
66
+ className: clsx(selectionItemPrefixCls, {
67
+ [`${selectionItemPrefixCls}-disabled`]: itemDisabled
68
+ })
69
+ }, /*#__PURE__*/React.createElement("span", {
70
+ className: `${selectionItemPrefixCls}-content`
71
+ }, content), closable && /*#__PURE__*/React.createElement(TransBtn, {
72
+ className: `${selectionItemPrefixCls}-remove`,
73
+ onMouseDown: onPreventMouseDown,
74
+ onClick: onClose,
75
+ customizeIcon: removeIcon
76
+ }, "\xD7"));
77
+ const customizeRenderSelector = (value, content, itemDisabled, closable, onClose, isMaxTag, info) => {
78
+ const onMouseDown = e => {
79
+ onPreventMouseDown(e);
80
+ onToggleOpen(!triggerOpen);
81
+ };
82
+ return /*#__PURE__*/React.createElement("span", {
83
+ onMouseDown: onMouseDown
84
+ }, tagRender({
85
+ label: content,
86
+ value,
87
+ index: info?.index,
88
+ disabled: itemDisabled,
89
+ closable,
90
+ onClose,
91
+ isMaxTag: !!isMaxTag
92
+ }));
93
+ };
94
+
95
+ // ====================== Overflow ======================
96
+ const renderItem = (valueItem, info) => {
97
+ const {
98
+ disabled: itemDisabled,
99
+ label,
100
+ value
101
+ } = valueItem;
102
+ const closable = !disabled && !itemDisabled;
103
+ let displayLabel = label;
104
+ if (typeof maxTagTextLength === 'number') {
105
+ if (typeof label === 'string' || typeof label === 'number') {
106
+ const strLabel = String(displayLabel);
107
+ if (strLabel.length > maxTagTextLength) {
108
+ displayLabel = `${strLabel.slice(0, maxTagTextLength)}...`;
109
+ }
110
+ }
111
+ }
112
+ const onClose = event => {
113
+ if (event) {
114
+ event.stopPropagation();
115
+ }
116
+ onRemove(valueItem);
117
+ };
118
+ return typeof tagRender === 'function' ? customizeRenderSelector(value, displayLabel, itemDisabled, closable, onClose, undefined, info) : defaultRenderSelector(valueItem, displayLabel, itemDisabled, closable, onClose);
119
+ };
120
+ const renderRest = omittedValues => {
121
+ // https://github.com/ant-design/ant-design/issues/48930
122
+ if (!displayValues.length) {
123
+ return null;
124
+ }
125
+ const content = typeof maxTagPlaceholder === 'function' ? maxTagPlaceholder(omittedValues) : maxTagPlaceholder;
126
+ return typeof tagRender === 'function' ? customizeRenderSelector(undefined, content, false, false, undefined, true) : defaultRenderSelector({
127
+ title: content
128
+ }, content, false);
129
+ };
130
+
131
+ // ======================= Render =======================
132
+ return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Placeholder, {
133
+ show: !searchValue || !triggerOpen
134
+ }), /*#__PURE__*/React.createElement(Overflow, {
135
+ prefixCls: `${prefixCls}-content`,
136
+ data: displayValues,
137
+ renderItem: renderItem,
138
+ renderRest: renderRest
139
+ // suffix={inputNode}
140
+ ,
141
+ suffix: /*#__PURE__*/React.createElement(Input, _extends({
142
+ ref: ref,
143
+ disabled: disabled,
144
+ readOnly: !inputEditable
145
+ }, inputProps, {
146
+ value: inputValue || '',
147
+ syncWidth: true
148
+ })),
149
+ itemKey: itemKey,
150
+ maxCount: maxTagCount
151
+ }));
152
+ });
@@ -0,0 +1,5 @@
1
+ import * as React from 'react';
2
+ export interface PlaceholderProps {
3
+ show: boolean;
4
+ }
5
+ export default function Placeholder(props: PlaceholderProps): React.JSX.Element;
@@ -0,0 +1,21 @@
1
+ import * as React from 'react';
2
+ import { useSelectInputContext } from "../context";
3
+ export default function Placeholder(props) {
4
+ const {
5
+ prefixCls,
6
+ placeholder,
7
+ displayValues
8
+ } = useSelectInputContext();
9
+ const {
10
+ show
11
+ } = props;
12
+ if (displayValues.length) {
13
+ return null;
14
+ }
15
+ return /*#__PURE__*/React.createElement("div", {
16
+ className: `${prefixCls}-placeholder`,
17
+ style: {
18
+ visibility: show ? 'visible' : 'hidden'
19
+ }
20
+ }, placeholder);
21
+ }
@@ -0,0 +1,4 @@
1
+ import * as React from 'react';
2
+ import type { SharedContentProps } from '.';
3
+ declare const SingleContent: React.ForwardRefExoticComponent<SharedContentProps & React.RefAttributes<HTMLInputElement>>;
4
+ export default SingleContent;
@@ -0,0 +1,98 @@
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 * as React from 'react';
3
+ import { clsx } from 'clsx';
4
+ import Input from "../Input";
5
+ import { useSelectInputContext } from "../context";
6
+ import useBaseProps from "../../hooks/useBaseProps";
7
+ import Placeholder from "./Placeholder";
8
+ import SelectContext from "../../SelectContext";
9
+ import { getTitle } from "../../utils/commonUtil";
10
+ const SingleContent = /*#__PURE__*/React.forwardRef(({
11
+ inputProps
12
+ }, ref) => {
13
+ const {
14
+ prefixCls,
15
+ searchValue,
16
+ activeValue,
17
+ displayValues,
18
+ maxLength,
19
+ mode
20
+ } = useSelectInputContext();
21
+ const {
22
+ triggerOpen,
23
+ title: rootTitle,
24
+ showSearch
25
+ } = useBaseProps();
26
+ const selectContext = React.useContext(SelectContext);
27
+ const [inputChanged, setInputChanged] = React.useState(false);
28
+ const combobox = mode === 'combobox';
29
+ const displayValue = displayValues[0];
30
+
31
+ // Implement the same logic as the old SingleSelector
32
+ const mergedSearchValue = React.useMemo(() => {
33
+ if (combobox && activeValue && !inputChanged && triggerOpen) {
34
+ return activeValue;
35
+ }
36
+ return showSearch ? searchValue : '';
37
+ }, [combobox, activeValue, inputChanged, triggerOpen, searchValue, showSearch]);
38
+
39
+ // Extract option props, excluding label and value, and handle className/style merging
40
+ const optionProps = React.useMemo(() => {
41
+ let restProps = {
42
+ className: `${prefixCls}-content-value`,
43
+ style: {
44
+ visibility: mergedSearchValue ? 'hidden' : 'visible'
45
+ }
46
+ };
47
+ if (displayValue && selectContext?.flattenOptions) {
48
+ const option = selectContext.flattenOptions.find(opt => opt.value === displayValue.value);
49
+ if (option?.data) {
50
+ const {
51
+ label,
52
+ value,
53
+ className,
54
+ style,
55
+ key,
56
+ ...rest
57
+ } = option.data;
58
+ restProps = {
59
+ ...restProps,
60
+ ...rest,
61
+ title: getTitle(option.data),
62
+ className: clsx(restProps.className, className),
63
+ style: {
64
+ ...restProps.style,
65
+ ...style
66
+ }
67
+ };
68
+ }
69
+ }
70
+ if (displayValue && !restProps.title) {
71
+ restProps.title = getTitle(displayValue);
72
+ }
73
+ if (rootTitle !== undefined) {
74
+ restProps.title = rootTitle;
75
+ }
76
+ return restProps;
77
+ }, [displayValue, selectContext?.flattenOptions, prefixCls, mergedSearchValue, rootTitle]);
78
+ React.useEffect(() => {
79
+ if (combobox) {
80
+ setInputChanged(false);
81
+ }
82
+ }, [combobox, activeValue]);
83
+ return /*#__PURE__*/React.createElement("div", {
84
+ className: `${prefixCls}-content`
85
+ }, displayValue ? /*#__PURE__*/React.createElement("div", optionProps, displayValue.label) : /*#__PURE__*/React.createElement(Placeholder, {
86
+ show: !mergedSearchValue
87
+ }), /*#__PURE__*/React.createElement(Input, _extends({
88
+ ref: ref
89
+ }, inputProps, {
90
+ value: mergedSearchValue,
91
+ maxLength: mode === 'combobox' ? maxLength : undefined,
92
+ onChange: e => {
93
+ setInputChanged(true);
94
+ inputProps.onChange?.(e);
95
+ }
96
+ })));
97
+ });
98
+ export default SingleContent;
@@ -0,0 +1,6 @@
1
+ import * as React from 'react';
2
+ export interface SharedContentProps {
3
+ inputProps: React.InputHTMLAttributes<HTMLInputElement>;
4
+ }
5
+ declare const SelectContent: React.ForwardRefExoticComponent<React.RefAttributes<HTMLInputElement>>;
6
+ export default SelectContent;
@@ -0,0 +1,37 @@
1
+ import * as React from 'react';
2
+ import pickAttrs from "@rc-component/util/es/pickAttrs";
3
+ import SingleContent from "./SingleContent";
4
+ import MultipleContent from "./MultipleContent";
5
+ import { useSelectInputContext } from "../context";
6
+ import useBaseProps from "../../hooks/useBaseProps";
7
+ const SelectContent = /*#__PURE__*/React.forwardRef(function SelectContent(_, ref) {
8
+ const {
9
+ multiple,
10
+ onInputKeyDown,
11
+ tabIndex
12
+ } = useSelectInputContext();
13
+ const baseProps = useBaseProps();
14
+ const {
15
+ showSearch
16
+ } = baseProps;
17
+ const ariaProps = pickAttrs(baseProps, {
18
+ aria: true
19
+ });
20
+ const sharedInputProps = {
21
+ ...ariaProps,
22
+ onKeyDown: onInputKeyDown,
23
+ readOnly: !showSearch,
24
+ tabIndex
25
+ };
26
+ if (multiple) {
27
+ return /*#__PURE__*/React.createElement(MultipleContent, {
28
+ ref: ref,
29
+ inputProps: sharedInputProps
30
+ });
31
+ }
32
+ return /*#__PURE__*/React.createElement(SingleContent, {
33
+ ref: ref,
34
+ inputProps: sharedInputProps
35
+ });
36
+ });
37
+ export default SelectContent;
@@ -0,0 +1,20 @@
1
+ import * as React from 'react';
2
+ export interface InputProps {
3
+ id?: string;
4
+ readOnly?: boolean;
5
+ value?: string;
6
+ onChange?: React.ChangeEventHandler<HTMLInputElement>;
7
+ onKeyDown?: React.KeyboardEventHandler<HTMLInputElement>;
8
+ onFocus?: React.FocusEventHandler<HTMLInputElement>;
9
+ onBlur?: React.FocusEventHandler<HTMLInputElement>;
10
+ placeholder?: string;
11
+ className?: string;
12
+ style?: React.CSSProperties;
13
+ maxLength?: number;
14
+ /** width always match content width */
15
+ syncWidth?: boolean;
16
+ /** autoComplete for input */
17
+ autoComplete?: string;
18
+ }
19
+ declare const Input: React.ForwardRefExoticComponent<InputProps & React.RefAttributes<HTMLInputElement>>;
20
+ export default Input;
@@ -0,0 +1,214 @@
1
+ import * as React from 'react';
2
+ import { clsx } from 'clsx';
3
+ import { useSelectInputContext } from "./context";
4
+ import useLayoutEffect from "@rc-component/util/es/hooks/useLayoutEffect";
5
+ import useBaseProps from "../hooks/useBaseProps";
6
+ import { composeRef } from "@rc-component/util/es/ref";
7
+ const Input = /*#__PURE__*/React.forwardRef((props, ref) => {
8
+ const {
9
+ onChange,
10
+ onKeyDown,
11
+ onBlur,
12
+ style,
13
+ syncWidth,
14
+ value,
15
+ className,
16
+ autoComplete,
17
+ ...restProps
18
+ } = props;
19
+ const {
20
+ prefixCls,
21
+ mode,
22
+ onSearch,
23
+ onSearchSubmit,
24
+ onInputBlur,
25
+ autoFocus,
26
+ tokenWithEnter,
27
+ components: {
28
+ input: InputComponent = 'input'
29
+ }
30
+ } = useSelectInputContext();
31
+ const {
32
+ id,
33
+ classNames,
34
+ styles,
35
+ open,
36
+ activeDescendantId,
37
+ role,
38
+ disabled
39
+ } = useBaseProps() || {};
40
+ const inputCls = clsx(`${prefixCls}-input`, classNames?.input, className);
41
+
42
+ // Used to handle input method composition status
43
+ const compositionStatusRef = React.useRef(false);
44
+
45
+ // Used to handle paste content, similar to original Selector implementation
46
+ const pastedTextRef = React.useRef(null);
47
+
48
+ // ============================== Refs ==============================
49
+ const inputRef = React.useRef(null);
50
+ React.useImperativeHandle(ref, () => inputRef.current);
51
+
52
+ // ============================== Data ==============================
53
+ // Handle input changes
54
+ const handleChange = event => {
55
+ let {
56
+ value: nextVal
57
+ } = event.target;
58
+
59
+ // Handle pasted text with tokenWithEnter, similar to original Selector implementation
60
+ if (tokenWithEnter && pastedTextRef.current && /[\r\n]/.test(pastedTextRef.current)) {
61
+ // CRLF will be treated as a single space for input element
62
+ const replacedText = pastedTextRef.current.replace(/[\r\n]+$/, '').replace(/\r\n/g, ' ').replace(/[\r\n]/g, ' ');
63
+ nextVal = nextVal.replace(replacedText, pastedTextRef.current);
64
+ }
65
+
66
+ // Reset pasted text reference
67
+ pastedTextRef.current = null;
68
+
69
+ // Call onSearch callback
70
+ if (onSearch) {
71
+ onSearch(nextVal, true, compositionStatusRef.current);
72
+ }
73
+
74
+ // Call original onChange callback
75
+ onChange?.(event);
76
+ };
77
+
78
+ // ============================ Keyboard ============================
79
+ // Handle keyboard events
80
+ const handleKeyDown = event => {
81
+ const {
82
+ key
83
+ } = event;
84
+ const {
85
+ value: nextVal
86
+ } = event.currentTarget;
87
+
88
+ // Handle Enter key submission - referencing Selector implementation
89
+ if (key === 'Enter' && mode === 'tags' && !compositionStatusRef.current && onSearchSubmit) {
90
+ onSearchSubmit(nextVal);
91
+ }
92
+
93
+ // Call original onKeyDown callback
94
+ onKeyDown?.(event);
95
+ };
96
+
97
+ // Handle blur events
98
+ const handleBlur = event => {
99
+ // Call onInputBlur callback
100
+ onInputBlur?.();
101
+
102
+ // Call original onBlur callback
103
+ onBlur?.(event);
104
+ };
105
+
106
+ // Handle input method composition start
107
+ const handleCompositionStart = () => {
108
+ compositionStatusRef.current = true;
109
+ };
110
+
111
+ // Handle input method composition end
112
+ const handleCompositionEnd = event => {
113
+ compositionStatusRef.current = false;
114
+
115
+ // Trigger search when input method composition ends, similar to original Selector
116
+ if (mode !== 'combobox') {
117
+ const {
118
+ value: nextVal
119
+ } = event.currentTarget;
120
+ onSearch?.(nextVal, true, false);
121
+ }
122
+ };
123
+
124
+ // Handle paste events to track pasted content
125
+ const handlePaste = event => {
126
+ const {
127
+ clipboardData
128
+ } = event;
129
+ const pastedValue = clipboardData?.getData('text');
130
+ pastedTextRef.current = pastedValue || '';
131
+ };
132
+
133
+ // ============================= Width ==============================
134
+ const [widthCssVar, setWidthCssVar] = React.useState(undefined);
135
+
136
+ // When syncWidth is enabled, adjust input width based on content
137
+ useLayoutEffect(() => {
138
+ const input = inputRef.current;
139
+ if (syncWidth && input) {
140
+ input.style.width = '0px';
141
+ const scrollWidth = input.scrollWidth;
142
+ setWidthCssVar(scrollWidth);
143
+
144
+ // Reset input style
145
+ input.style.width = '';
146
+ }
147
+ }, [syncWidth, value]);
148
+
149
+ // ============================= Render =============================
150
+ // Extract shared input props
151
+ const sharedInputProps = {
152
+ id,
153
+ type: mode === 'combobox' ? 'text' : 'search',
154
+ ...restProps,
155
+ ref: inputRef,
156
+ style: {
157
+ ...styles?.input,
158
+ ...style,
159
+ '--select-input-width': widthCssVar
160
+ },
161
+ autoFocus,
162
+ autoComplete: autoComplete || 'off',
163
+ className: inputCls,
164
+ disabled,
165
+ value: value || '',
166
+ onChange: handleChange,
167
+ onKeyDown: handleKeyDown,
168
+ onBlur: handleBlur,
169
+ onPaste: handlePaste,
170
+ onCompositionStart: handleCompositionStart,
171
+ onCompositionEnd: handleCompositionEnd,
172
+ // Accessibility attributes
173
+ role: role || 'combobox',
174
+ 'aria-expanded': open || false,
175
+ 'aria-haspopup': 'listbox',
176
+ 'aria-owns': `${id}_list`,
177
+ 'aria-autocomplete': 'list',
178
+ 'aria-controls': `${id}_list`,
179
+ 'aria-activedescendant': open ? activeDescendantId : undefined
180
+ };
181
+
182
+ // Handle different InputComponent types
183
+ if ( /*#__PURE__*/React.isValidElement(InputComponent)) {
184
+ // If InputComponent is a ReactElement, use cloneElement with merged props
185
+ const existingProps = InputComponent.props || {};
186
+
187
+ // Start with shared props as base
188
+ const mergedProps = {
189
+ ...sharedInputProps,
190
+ ...existingProps
191
+ };
192
+
193
+ // Batch update function calls
194
+ Object.keys(existingProps).forEach(key => {
195
+ const existingValue = existingProps[key];
196
+ if (typeof existingValue === 'function') {
197
+ // Merge event handlers
198
+ mergedProps[key] = (...args) => {
199
+ existingValue(...args);
200
+ sharedInputProps[key]?.(...args);
201
+ };
202
+ }
203
+ });
204
+
205
+ // Update ref
206
+ mergedProps.ref = composeRef(InputComponent.ref, sharedInputProps.ref);
207
+ return /*#__PURE__*/React.cloneElement(InputComponent, mergedProps);
208
+ }
209
+
210
+ // If InputComponent is a component type, render normally
211
+ const Component = InputComponent;
212
+ return /*#__PURE__*/React.createElement(Component, sharedInputProps);
213
+ });
214
+ export default Input;
@@ -0,0 +1,6 @@
1
+ import * as React from 'react';
2
+ import type { SelectInputProps } from '.';
3
+ export type ContentContextProps = SelectInputProps;
4
+ declare const SelectInputContext: React.Context<SelectInputProps>;
5
+ export declare function useSelectInputContext(): SelectInputProps;
6
+ export default SelectInputContext;
@@ -0,0 +1,6 @@
1
+ import * as React from 'react';
2
+ const SelectInputContext = /*#__PURE__*/React.createContext(null);
3
+ export function useSelectInputContext() {
4
+ return React.useContext(SelectInputContext);
5
+ }
6
+ export default SelectInputContext;
@@ -0,0 +1,39 @@
1
+ import * as React from 'react';
2
+ import type { DisplayValueType, Mode, RenderNode } from '../interface';
3
+ import type { ComponentsConfig } from '../hooks/useComponents';
4
+ export interface SelectInputRef {
5
+ focus: (options?: FocusOptions) => void;
6
+ blur: () => void;
7
+ nativeElement: HTMLDivElement;
8
+ }
9
+ export interface SelectInputProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'prefix'> {
10
+ prefixCls: string;
11
+ prefix?: React.ReactNode;
12
+ suffix?: React.ReactNode;
13
+ clearIcon?: React.ReactNode;
14
+ removeIcon?: RenderNode;
15
+ multiple?: boolean;
16
+ displayValues: DisplayValueType[];
17
+ placeholder?: React.ReactNode;
18
+ searchValue?: string;
19
+ activeValue?: string;
20
+ mode?: Mode;
21
+ autoClearSearchValue?: boolean;
22
+ onSearch?: (searchText: string, fromTyping: boolean, isCompositing: boolean) => void;
23
+ onSearchSubmit?: (searchText: string) => void;
24
+ onInputBlur?: () => void;
25
+ onClearMouseDown?: React.MouseEventHandler<HTMLElement>;
26
+ onInputKeyDown?: React.KeyboardEventHandler<HTMLInputElement | HTMLTextAreaElement>;
27
+ onSelectorRemove?: (value: DisplayValueType) => void;
28
+ maxLength?: number;
29
+ autoFocus?: boolean;
30
+ /** Check if `tokenSeparators` contains `\n` or `\r\n` */
31
+ tokenWithEnter?: boolean;
32
+ className?: string;
33
+ style?: React.CSSProperties;
34
+ focused?: boolean;
35
+ components: ComponentsConfig;
36
+ children?: React.ReactElement;
37
+ }
38
+ declare const _default: React.ForwardRefExoticComponent<SelectInputProps & React.RefAttributes<SelectInputRef>>;
39
+ export default _default;