瀏覽代碼

fix: select onSearch add event param to detech operation origin (#1485)

* fix: select onSearch add event param to detech operation origin

* docs: update onSearch version

* docs: update onSearch
pointhalo 2 年之前
父節點
當前提交
0a12ce9f81

+ 1 - 1
content/input/select/index-en-US.md

@@ -1379,7 +1379,7 @@ import { Select, Checkbox } from '@douyinfe/semi-ui';
 | onDropdownVisibleChange | A callback when the drop-down menu expands / collapsed | function(visible: boolean) |  |
 | onExceed | Callback invoked when the number of attempts to select exceeds the max limit, effective only at multi-selection | function |  |
 | onFocus | Callback when focus select | function(event) |  |
-| onSearch | The callback function when the content of the input box changes. | function(sugInput: string) |  |
+| onSearch | The callback function when the content of the input box changes. The second parameter is available after v2.31 | function(sugInput: string, e: ReactEvent) |  |
 | onSelect | Callback when selected | function (value, option) |  |
 
 ### Option Props

+ 13 - 13
content/input/select/index.md

@@ -1411,18 +1411,6 @@ import { Select, Checkbox } from '@douyinfe/semi-ui';
 | multiple | 是否多选 | boolean | false |
 | outerTopSlot | 渲染在弹出层顶部,与 optionList 平级的自定义 slot | ReactNode |  |
 | outerBottomSlot | 渲染在弹出层底部,与 optionList 平级的自定义 slot | ReactNode |  |
-| onBlur | 失去焦点时的回调 | function(event) |  |
-| onChange | 变化时回调函数 | function(value:string\|number\|array) |  |
-| onCreate | allowCreate 为 true,创建备选项时的回调 | function(option) |  |
-| onClear | 清除按钮的回调 | function |  |
-| onChangeWithObject | 是否将选中项 option 的其他属性作为回调。设为 true 时,onChange 的入参类型会从 string 变为 object: { value, label, ...rest } | boolean | false |
-| onDropdownVisibleChange | 下拉菜单展开/收起时的回调 | function(visible:boolean) |  |
-| onListScroll | 候选项列表滚动时的回调 | function(e) |  |
-| onSearch | input 输入框内容发生改变时回调函数 | function(sugInput:string) |  |
-| onSelect | 被选中时的回调 | function(value, option) |  |
-| onDeselect | 取消选中时的回调,仅在多选时有效 | function(value, option) |  |
-| onExceed | 当试图选择数超出 max 限制时的回调,仅在多选时生效 <br/> 入参在 v1.16.0 后提供 | function(option) |  |
-| onFocus | 获得焦点时的回调 | function(event) |  |
 | optionList | 可以通过该属性传入 Option,请确保数组内每个元素都具备 label、value 属性 | array(\[{value, label}\]) |  |
 | placeholder | 选择框默认文字 | ReactNode |  |
 | position | 菜单展开的位置,可选项同 Tooltip position | string | 'bottomLeft' |
@@ -1446,6 +1434,18 @@ import { Select, Checkbox } from '@douyinfe/semi-ui';
 | validateStatus | 校验结果,可选`warning`、`error`、 `default`(只影响样式背景色) | string | 'default' |
 | virtualize | 列表虚拟化,用于大量节点的情况优化性能表现,由 height, width, itemSize 组成 | object |  |
 | zIndex | 弹层的 zIndex | number | 1030 |
+| onBlur | 失去焦点时的回调 | function(event) |  |
+| onChange | 变化时回调函数 | function(value:string\|number\|array) |  |
+| onCreate | allowCreate 为 true,创建备选项时的回调 | function(option) |  |
+| onClear | 清除按钮的回调 | function |  |
+| onChangeWithObject | 是否将选中项 option 的其他属性作为回调。设为 true 时,onChange 的入参类型会从 string 变为 object: { value, label, ...rest } | boolean | false |
+| onDropdownVisibleChange | 下拉菜单展开/收起时的回调 | function(visible:boolean) |  |
+| onListScroll | 候选项列表滚动时的回调 | function(e) |  |
+| onSearch | input 输入框内容发生改变时回调函数,第二个参数于 v2.31 后提供 | function(sugInput:string, e: ReactEvent) |  |
+| onSelect | 被选中时的回调 | function(value, option) |  |
+| onDeselect | 取消选中时的回调,仅在多选时有效 | function(value, option) |  |
+| onExceed | 当试图选择数超出 max 限制时的回调,仅在多选时生效 <br/> 入参在 v1.16.0 后提供 | function(option) |  |
+| onFocus | 获得焦点时的回调 | function(event) |  |
 
 ### Option Props
 
@@ -1593,4 +1593,4 @@ import { Select, Checkbox } from '@douyinfe/semi-ui';
 3,4,44,54,58,62,72
 ``` -->
 ## 相关物料
-<semi-material-list code="3, 4, 58, 62"></semi-material-list>
+<semi-material-list code="3, 4, 58, 62"></semi-material-list>

+ 15 - 13
packages/semi-foundation/select/foundation.ts

@@ -32,7 +32,7 @@ export interface SelectAdapter<P = Record<string, any>, S = Record<string, any>>
     notifyClear(): void;
     updateInputValue(inputValue: string): void;
     focusInput(): void;
-    notifySearch(inputValue: string): void;
+    notifySearch(inputValue: string, event?: any): void;
     registerKeyDown(handler: () => void): void;
     unregisterKeyDown(): void;
     notifyChange(value: string | BasicOptionProps | (string | BasicOptionProps)[]): void;
@@ -396,7 +396,7 @@ export default class SelectFoundation extends BaseFoundation<SelectAdapter> {
 
         this._adapter.once('popoverClose', () => {
             if (isFilterable) {
-                this.clearInput();
+                this.clearInput(e);
             }
             if (closeCb) {
                 closeCb();
@@ -467,7 +467,7 @@ export default class SelectFoundation extends BaseFoundation<SelectAdapter> {
             this._notifyChange(selections);
             if (this._isFilterable()) {
                 if (autoClearSearchValue) {
-                    this.clearInput();
+                    this.clearInput(event);
                 }
                 this.focusInput();
             }
@@ -482,7 +482,7 @@ export default class SelectFoundation extends BaseFoundation<SelectAdapter> {
             if (this._isFilterable()) {
                 // When filter active,if autoClearSearchValue is true,reset input after select
                 if (autoClearSearchValue) {
-                    this.clearInput();
+                    this.clearInput(event);
                     // At the same time, the filtering of options is also cleared, in order to show all candidates
                     const sugInput = '';
                     options = this._filterOption(options, sugInput);
@@ -550,12 +550,14 @@ export default class SelectFoundation extends BaseFoundation<SelectAdapter> {
         }
     }
 
-    clearInput() {
+
+    // The reason why event input is optional is that clearInput may be manually called by the user through ref
+    clearInput(event?: any) {
         const { inputValue } = this.getStates();
         // only when input is not null, select should notifySearch and updateOptions
         if (inputValue !== ''){
             this._adapter.updateInputValue('');
-            this._adapter.notifySearch('');
+            this._adapter.notifySearch('', event);
             // reset options filter
             const { options } = this.getStates();
             const { remote } = this.getProps();
@@ -573,7 +575,7 @@ export default class SelectFoundation extends BaseFoundation<SelectAdapter> {
         this._adapter.setIsFocusInContainer(false);
     }
 
-    handleInputChange(sugInput: string) {
+    handleInputChange(sugInput: string, event: any) {
         // Input is a controlled component, so the value needs to be updated
         this._adapter.updateInputValue(sugInput);
         const { options, isOpen } = this.getStates();
@@ -589,7 +591,7 @@ export default class SelectFoundation extends BaseFoundation<SelectAdapter> {
         optionsAfterFilter = this._createOptionByInput(allowCreate, optionsAfterFilter, sugInput);
 
         this._adapter.updateOptions(optionsAfterFilter);
-        this._adapter.notifySearch(sugInput);
+        this._adapter.notifySearch(sugInput, event);
         // In multi-select mode, the drop-down box is repositioned each time you enter, because it may cause a line break as the input changes
         if (this._isMultiple()) {
             this._adapter.rePositionDropdown();
@@ -809,7 +811,7 @@ export default class SelectFoundation extends BaseFoundation<SelectAdapter> {
                 }
             } else {
                 // there are no focusable elements inside the container, tab to next element and trigger blur
-                this.close();
+                this.close(event);
                 this._notifyBlur(event);
             }
         } else {
@@ -829,7 +831,7 @@ export default class SelectFoundation extends BaseFoundation<SelectAdapter> {
         } else if (activeElement === focusableElements[focusableElements.length - 1]) {
             // focus in the last element in container, focus back to trigger and close panel
             this._focusTrigger(); 
-            this.close();
+            this.close(event);
             handlePrevent(event);
         }
     }
@@ -840,7 +842,7 @@ export default class SelectFoundation extends BaseFoundation<SelectAdapter> {
 
         if (!isFocusInContainer) {
             // focus in trigger, close the panel, shift tab to previe element and trigger blur
-            this.close();
+            this.close(event);
             this._notifyBlur(event);
         } else if (activeElement === focusableElements[0]) {
             // focus in the first element in container, focus back to trigger
@@ -870,7 +872,7 @@ export default class SelectFoundation extends BaseFoundation<SelectAdapter> {
                     this.onSelect(selectedOption, focusIndex, event);
                 }
             } else {
-                this.close();
+                this.close(event);
             }
         }
     }
@@ -1018,7 +1020,7 @@ export default class SelectFoundation extends BaseFoundation<SelectAdapter> {
     handleClearClick(e: MouseEvent) {
         const { filter } = this.getProps();
         if (filter) {
-            this.clearInput();
+            this.clearInput(e);
         }
         this.clearSelected();
         // prevent this click open dropdown

+ 4 - 14
packages/semi-ui/select/index.tsx

@@ -118,7 +118,7 @@ export type SelectProps = {
     onDropdownVisibleChange?: (visible: boolean) => void;
     zIndex?: number;
     position?: Position;
-    onSearch?: (value: string) => void;
+    onSearch?: (value: string, event: React.KeyboardEvent | React.MouseEvent) => void;
     dropdownClassName?: string;
     dropdownStyle?: React.CSSProperties;
     dropdownMargin?: PopoverProps['margin'];
@@ -388,16 +388,6 @@ class Select extends BaseComponent<SelectProps, SelectState> {
         this.eventManager = new Event();
 
         this.foundation = new SelectFoundation(this.adapter);
-
-        warning(
-            'optionLabelProp' in this.props,
-            '[Semi Select] \'optionLabelProp\' has already been deprecated, please use \'renderSelectedItem\' instead.'
-        );
-
-        warning(
-            'labelInValue' in this.props,
-            '[Semi Select] \'labelInValue\' has already been deprecated, please use \'onChangeWithObject\' instead.'
-        );
     }
 
     setOptionContainerEl = (node: HTMLDivElement) => (this.optionContainerEl = { current: node });
@@ -533,8 +523,8 @@ class Select extends BaseComponent<SelectProps, SelectState> {
             notifyDropdownVisibleChange: (visible: boolean) => {
                 this.props.onDropdownVisibleChange(visible);
             },
-            notifySearch: (input: string) => {
-                this.props.onSearch(input);
+            notifySearch: (input: string, event: React.MouseEvent | React.KeyboardEvent) => {
+                this.props.onSearch(input, event);
             },
             notifyCreate: (input: OptionProps) => {
                 this.props.onCreate(input);
@@ -647,7 +637,7 @@ class Select extends BaseComponent<SelectProps, SelectState> {
         }
     }
 
-    handleInputChange = (value: string) => this.foundation.handleInputChange(value);
+    handleInputChange = (value: string, event: React.KeyboardEvent) => this.foundation.handleInputChange(value, event);
 
     renderInput() {
         const { size, multiple, disabled, inputProps, filter } = this.props;