1
0
Эх сурвалжийг харах

feat: cascader ref method add search (#2105)

* feat: Cascader support search method

* test: add test for Casader ref method

* feat: Cascader support SearchPostion API
YyumeiZhang 1 жил өмнө
parent
commit
26457b6e36

+ 2 - 0
content/input/cascader/index-en-US.md

@@ -1855,6 +1855,7 @@ function Demo() {
 | preventScroll | Indicates whether the browser should scroll the document to display the newly focused element, acting on the focus method inside the component, excluding the component passed in by the user                                                 | boolean | - | 2.15.0 |
 |restTagsPopoverProps | The configuration properties of the [Popover](/en-US/show/popover#API%20Reference)                                                                                                                                                            |PopoverProps   | {}  |1.28.0|
 | searchPlaceholder  | Placeholder for search input                                                                                                                                                                                                                  | string | - | -  |
+| searchPosition | Set the position of the search box,  `trigger` or `custom` | string| `trigger` | 2.54.0 |
 | separator  | Custom separator, including: the separator of the content displayed in the dropdown during search and displayed in the Trigger during single selection                                                                                        | string| ` / ` | 2.2.0 |
 | showClear | Toggle whether to show clear button                                                                                                                                                                                                           | boolean  | false | 0.35.0 |
 | showNext| Set the way to expand the Dropdown submenu, one of: `click`、`hover`                                                                                                                                                                           | string |`click`|1.29.0|
@@ -1905,6 +1906,7 @@ Some internal methods provided by Select can be accessed through ref:
 | open        | Manually open dropdown list     | v2.30.0 |
 | focus       | Manually focus                  | v2.34.0 |
 | blur        | Manually blur                   | v2.34.0 |
+| search(value: string) | To manually trigger the search, you need to set filterTreeNode to enable search, and searchPosition to `custom` to customize the display search box.  | v2.54.0 |
 
 ## Accessibility
 

+ 2 - 0
content/input/cascader/index.md

@@ -1838,6 +1838,7 @@ function Demo() {
 | preventScroll        | 指示浏览器是否应滚动文档以显示新聚焦的元素,作用于组件内的 focus 方法                                                                                                              | boolean                                                                                   | -                              | 2.15.0 |
 | restTagsPopoverProps | Popover 的配置属性,可以控制 position、zIndex、trigger 等,具体参考[Popover](/zh-CN/show/popover#API%20%E5%8F%82%E8%80%83)                                            | PopoverProps                                                                              | {}                             | 1.28.0 |
 | searchPlaceholder    | 搜索框默认文字                                                                                                                                             | string                                                                                    | -                              | -      |
+| searchPosition | 设置搜索框的位置,可选: `trigger`、`custom` | string| `trigger` | 2.54.0 |
 | separator            | 自定义分隔符,包括:搜索时显示在下拉框的内容以及单选时回显到 Trigger 的内容的分隔符                                                                                                      | string                                                                                    | `/`                            | 2.2.0  |
 | showClear            | 是否展示清除按钮                                                                                                                                            | boolean                                                                                   | false                          | 0.35.0 |
 | showNext             | 设置展开 Dropdown 子菜单的方式,可选: `click`、`hover`                                                                                                            | string                                                                                    | `click`                        | 1.29.0 |
@@ -1889,6 +1890,7 @@ function Demo() {
 | open        | 调用时可以手动展开下拉列表          | v2.30.0 |
 | focus       | 调用时可以手动聚焦                 | v2.34.0 |
 | blur        | 调用时可以手动失焦                 | v2.34.0 |
+| search(value: string) | 手动触发搜索,需同时设置 filterTreeNode 开启搜索,searchPosition 为 `custom` 自定义展示搜素框  | v2.54.0 |
 
 ## Accessibility
 

+ 2 - 0
packages/semi-foundation/cascader/constants.ts

@@ -16,6 +16,8 @@ const strings = {
     LEAF_ONLY_MERGE_TYPE: 'leafOnly',
     AUTO_MERGE_VALUE_MERGE_TYPE: 'autoMergeValue',
     NONE_MERGE_TYPE: 'none',
+    SEARCH_POSITION_TRIGGER: 'trigger',
+    SEARCH_POSITION_CUSTOM: 'custom',
 } as const;
 
 const numbers = {};

+ 17 - 0
packages/semi-ui/cascader/__test__/cascader.test.js

@@ -1245,6 +1245,23 @@ describe('Cascader', () => {
         cascader.unmount();
     });
 
+    it('search ref method', () => {
+        let r;
+        const cascader = render({
+            ref: (ref) => { r = ref },
+            filterTreeNode: true,
+            searchPosition: 'custom',
+            defaultOpen: true,
+        });
+        r.search('北京');
+        expect(cascader.state().inputValue).toEqual('北京');
+        expect(
+            document.querySelectorAll(`.${BASE_CLASS_PREFIX}-cascader-option-label-highlight`)[0]
+            .textContent
+        ).toEqual('北京');
+        cascader.unmount();
+    });
+
     it('triggerRender', () => {
         const spyTriggerRender = sinon.spy(() => <span>123</span>);
         const cascaderAutoMerge = render({

+ 25 - 1
packages/semi-ui/cascader/_story/cascader.stories.jsx

@@ -2372,4 +2372,28 @@ export const NumberValue = () => {
           placeholder="请选择所在地区"
       />
   );
-};
+};
+
+export const SearchInTopSlot = () => {
+  const cascaderRef = useRef();
+
+  const handleInputChange = useCallback((value) => {
+    cascaderRef.current.search(value);
+  }, [cascaderRef]);
+
+  const topSlot = useMemo(() => {
+    return <Input prefix="搜索" onChange={handleInputChange} style={{width: '100%'}}/>
+  }, [handleInputChange]);
+
+  return (
+      <Cascader
+          filterTreeNode
+          searchPosition={"custom"}
+          ref={cascaderRef}
+          style={{ width: 300 }}
+          treeData={treeData2}
+          topSlot={topSlot}
+          placeholder="请选择所在地区"
+      />
+  );
+}

+ 12 - 4
packages/semi-ui/cascader/index.tsx

@@ -87,7 +87,8 @@ export interface CascaderProps extends BasicCascaderProps {
     onBlur?: (e: MouseEvent) => void;
     onFocus?: (e: MouseEvent) => void;
     validateStatus?: ValidateStatus;
-    position?: Position
+    position?: Position;
+    searchPosition?: string
 }
 
 export interface CascaderState extends BasicCascaderInnerData {
@@ -182,7 +183,8 @@ class Cascader extends BaseComponent<CascaderProps, CascaderState> {
         leafOnly: PropTypes.bool,
         enableLeafClick: PropTypes.bool,
         preventScroll: PropTypes.bool,
-        position: PropTypes.string
+        position: PropTypes.string,
+        searchPosition: PropTypes.string,
     };
 
     static defaultProps = getDefaultPropsFromGlobalConfig(Cascader.__SemiComponentName__, {
@@ -215,6 +217,7 @@ class Cascader extends BaseComponent<CascaderProps, CascaderState> {
         onListScroll: noop,
         enableLeafClick: false,
         'aria-label': 'Cascader',
+        searchPosition: strings.SEARCH_POSITION_TRIGGER,
     })
 
     options: any;
@@ -514,6 +517,11 @@ class Cascader extends BaseComponent<CascaderProps, CascaderState> {
         }
     }
 
+    // ref method
+    search = (value: string) => {
+        this.handleInputChange(value);
+    };
+
     handleInputChange = (value: string) => {
         this.foundation.handleInputChange(value);
     };
@@ -783,9 +791,9 @@ class Cascader extends BaseComponent<CascaderProps, CascaderState> {
     };
 
     renderSelectContent = () => {
-        const { placeholder, filterTreeNode, multiple } = this.props;
+        const { placeholder, filterTreeNode, multiple, searchPosition } = this.props;
         const { checkedKeys } = this.state;
-        const searchable = Boolean(filterTreeNode);
+        const searchable = Boolean(filterTreeNode) && searchPosition === strings.SEARCH_POSITION_TRIGGER;
 
         if (!searchable) {
             if (multiple) {