Browse Source

Merge branch 'release' of github.com:DouyinFE/semi-design into release

pointhalo 3 years ago
parent
commit
b5457d902c

+ 4 - 3
content/navigation/tree/index-en-US.md

@@ -2192,9 +2192,10 @@ import { IconFixedStroked, IconSectionStroked, IconAbsoluteStroked, IconInnerSec
 | width | Width | number\|string | '100%' |
 
 ### Methods
-|Name | Description | Type 
-|----|----|----|
-| search | Trigger search manually | (value: string) => void |
+|Name | Description | Type | Version |
+|----|----|----|----|
+| search | Trigger search manually | (value: string) => void |-|
+| scrollTo | In a virtualized Tree, make the specified node(Which is an expanded node in the tree) scroll to view | ({key: string; align?: 'center' \| 'start' \| 'end' \| 'smart' \| 'auto';}) => void | 2.18.0|
 
 
 ## Accessibility

+ 4 - 4
content/navigation/tree/index.md

@@ -2187,10 +2187,10 @@ import { IconFixedStroked, IconSectionStroked, IconAbsoluteStroked, IconInnerSec
 
 ### Methods
 
-|名称 | 描述 | 类型
-|----|----|----|
-| search | 手动触发搜索 | (value: string) => void |
-
+|名称 | 描述 | 类型 | 版本  |
+|----|----|----|----|
+| search | 手动触发搜索 | (value: string) => void |-|
+| scrollTo | 在虚拟化 Tree 中,使得指定节点(该节点为当前树的已展开节点)滚动到视图 | ({key: string; align?: 'center' \| 'start' \| 'end' \| 'smart' \| 'auto';}) => void | 2.18.0 |
 ## Accessibility
 
 ### ARIA

+ 60 - 1
content/show/tag/index-en-US.md

@@ -243,6 +243,64 @@ import { TagGroup } from '@douyinfe/semi-ui';
 };
 ```
 
+If the tags in the TagGroup can be deleted, the user needs to process the `tagList` passed to the TagGroup in `onTagClose`
+
+```jsx live=true
+import React from 'react';
+import { TagGroup } from '@douyinfe/semi-ui';
+
+class TagGroupCloseableDemo extends React.Component {
+    constructor(props){
+        super(props);
+        this.state = {
+            tagList: [
+                { tagKey: '1', color: 'white', children: '抖音', closable: true, },
+                { tagKey: '2', color: 'white', children: '火山小视频', closable: true, },
+                { tagKey: '3', color: 'white', children: '剪映', closable: true, },
+                { tagKey: '4', color: 'white', children: '皮皮虾', closable: true, },
+                { tagKey: '5', color: 'white', children: '懂车帝', closable: true, },
+            ]
+        };
+        this.tagListClick = this.tagListClick.bind(this);
+    }
+
+    tagListClick(value, e, tagKey){
+        const newTagList = [...this.state.tagList];
+        const closeTagIndex = newTagList.findIndex(t => t.tagKey === tagKey);
+        newTagList.splice(closeTagIndex, 1);
+        this.setState({
+          tagList: newTagList,
+        });
+    }
+
+    render() {
+        return (
+            <div style={ {
+                backgroundColor: 'var(--semi-color-fill-0)',
+                height: 35,
+                width: 300,
+                display: 'flex',
+                alignItems: 'center',
+                padding: '0 10px',
+                marginBottom: 30,
+            }}>
+                <TagGroup
+                    maxTagCount={3}
+                    style={ {
+                        display: 'flex',
+                        alignItems: 'center',
+                        width: 350,
+                    }}
+                    tagList={this.state.tagList}
+                    size='large'
+                    onTagClose={this.tagListClick}
+                />
+            </div>
+        );
+    }
+}
+```
+
 ## API Reference
 
 ### Tag
@@ -260,7 +318,7 @@ import { TagGroup } from '@douyinfe/semi-ui';
 | visible | Toggle the visibility of the tag | boolean | true |  |
 | tagKey  | The key required by React, as the unique identifier of each tag, does not allow repetition | string | number | |
 | onClick | Callback function when clicking the tag | (e: MouseEvent) => void | - |  |
-| onClose | Callback function when the tag is closed | (tagChildren: ReactNode, e: MouseEvent) => void | - |  |
+| onClose | Callback function when the tag is closed | (tagChildren: ReactNode, e: MouseEvent, tagKey: string \| number ) => void | - | e is available in v1.18, tagKey is available in v2.18.0 |
 
 ### TagGroup
 
@@ -274,6 +332,7 @@ import { TagGroup } from '@douyinfe/semi-ui';
 | size | Size, one of `small`, `large` | string | `small` |  |
 | style | Inline style | CSSProperties |  |  |
 | tagList | Label Group data | (TagProps)[] |  |  |
+| onTagClose | The callback function when deleting the Tag in the TagGroup | (tagChildren: ReactNode, e: MouseEvent, tagKey: string \| number ) => void | - |  2.18.0 |
 
 ## Accessibility
 

+ 60 - 1
content/show/tag/index.md

@@ -204,6 +204,64 @@ import { TagGroup } from '@douyinfe/semi-ui';
 
 ```
 
+如果 TagGroup 中的标签可删除,用户需要在 `onTagClose` 中处理传递给 TagGroup 的 `tagList`。
+
+```jsx live=true
+import React from 'react';
+import { TagGroup } from '@douyinfe/semi-ui';
+
+class TagGroupCloseableDemo extends React.Component {
+    constructor(props){
+        super(props);
+        this.state = {
+            tagList: [
+                { tagKey: '1', color: 'white', children: '抖音', closable: true, },
+                { tagKey: '2', color: 'white', children: '火山小视频', closable: true, },
+                { tagKey: '3', color: 'white', children: '剪映', closable: true, },
+                { tagKey: '4', color: 'white', children: '皮皮虾', closable: true, },
+                { tagKey: '5', color: 'white', children: '懂车帝', closable: true, },
+            ]
+        };
+        this.tagListClick = this.tagListClick.bind(this);
+    }
+
+    tagListClick(value, e, tagKey){
+        const newTagList = [...this.state.tagList];
+        const closeTagIndex = newTagList.findIndex(t => t.tagKey === tagKey);
+        newTagList.splice(closeTagIndex, 1);
+        this.setState({
+          tagList: newTagList,
+        });
+    }
+
+    render() {
+        return (
+            <div style={ {
+                backgroundColor: 'var(--semi-color-fill-0)',
+                height: 35,
+                width: 300,
+                display: 'flex',
+                alignItems: 'center',
+                padding: '0 10px',
+                marginBottom: 30,
+            }}>
+                <TagGroup
+                    maxTagCount={3}
+                    style={ {
+                        display: 'flex',
+                        alignItems: 'center',
+                        width: 350,
+                    }}
+                    tagList={this.state.tagList}
+                    size='large'
+                    onTagClose={this.tagListClick}
+                />
+            </div>
+        );
+    }
+}
+```
+
 ## API参考
 
 ### Tag
@@ -221,7 +279,7 @@ import { TagGroup } from '@douyinfe/semi-ui';
 | visible | 标签是否可见 | boolean | true    | |
 | tagKey  | React 需要的 key,作为每个标签的唯一标识,不允许重复 | string | number | |
 | onClick | 单击标签时的回调函数 | (e: MouseEvent) => void | 无   | |
-| onClose | 关闭标签时的回调函数 | (tagChildren: ReactNode, e: MouseEvent) => void | 无    | e于v1.18版本提供 |
+| onClose | 关闭标签时的回调函数 | (tagChildren: ReactNode, e: MouseEvent, tagKey: string \| number ) => void | 无    | e  v1.18 版本提供, tagKey 于 v2.18.0 提供 |
 
 ### TagGroup
 
@@ -235,6 +293,7 @@ import { TagGroup } from '@douyinfe/semi-ui';
 | size | 标签的尺寸,可选 `small`、 `large` | string | `small` | |
 | style | 样式 | CSSProperties |    | |
 | tagList | 标签组  | (TagProps)[] |     | |
+| onTagClose | 删除TagGroup中的Tag时候的回调函数 | (tagChildren: ReactNode, e: MouseEvent, tagKey: string \| number ) => void | - |  2.18.0 |
 
 ## Accessibility
 

+ 50 - 40
packages/semi-ui/tag/_story/tag.stories.js

@@ -1,5 +1,5 @@
 /* argus-disable unPkgSensitiveInfo */
-import React from 'react';
+import React, { useCallback, useState } from 'react';
 import withPropsCombinations from 'react-storybook-addon-props-combinations';
 import { BASE_CLASS_PREFIX } from '../../../semi-foundation/base/constants';
 
@@ -233,45 +233,55 @@ AvatarTagGroup.story = {
   name: 'avatar tagGroup',
 };
 
-const TagGroupCloseableDemo = () => {
-  const src = 'https://sf6-cdn-tos.douyinstatic.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/avatarDemo.jpeg';
-  const tagList2 = [
-      { tagKey: '1', color: 'white', children:'Douyin', avatarSrc:src,closable:true},
-      { tagKey: '2', color: 'white', children:'Hotsoon', avatarSrc:src,closable:true},
-      { tagKey: '3', color: 'white', children:'Capcut', avatarSrc:src,closable:true},
-      { tagKey: '4', color: 'black', children:'bytedance', avatarSrc:src,closable:true},
-      { tagKey: '5', color: 'white', children:'vvvvv', avatarSrc:src,closable:true},
-      { tagKey: '6', color: 'white', children:'Pipixia', avatarSrc:src,closable:true},
-  ];
-  const divStyle = {
-      backgroundColor: 'var(--semi-color-fill-0)',
-      height: 35,
-      width: 300,
-      display: 'flex',
-      alignItems: 'center',
-      padding: '0 10px',
-      marginBottom: 30,
-  };
-  const tagGroupStyle = {
-      display: 'flex',
-      alignItems: 'center',
-      width: 350,
-  };
-  return (
-      <>
-          <div style={divStyle}>
-              <TagGroup
-                  maxTagCount={3}
-                  style={tagGroupStyle}
-                  tagList={tagList2}
-                  size='large'
-                  avatarShape='circle'
-                  showPopover
-              />
-          </div>
-      </>
-  );
-};
+class TagGroupCloseableDemo extends React.Component {
+    constructor(props){
+        super(props);
+        this.state = {
+            tagList: [
+                { tagKey: '1', color: 'white', children: '抖音',  closable: true,},
+                { tagKey: '2',color: 'white', children: '火山小视频', closable: true,},
+                { tagKey: '3',color: 'white', children: '剪映', closable: true,},
+                { tagKey: '4',color: 'white', children: '皮皮虾', closable: true,},
+            ]
+        };
+        this.tagListClick = this.tagListClick.bind(this);
+    }
+
+    tagListClick(value, e, tagKey){
+        const newTagList = [...this.state.tagList];
+        const closeTagIndex = newTagList.findIndex(t => t.tagKey === tagKey);
+        newTagList.splice(closeTagIndex, 1);
+        this.setState({
+          tagList: newTagList,
+        });
+    }
+
+    render() {
+        return (
+            <div style={ {
+                backgroundColor: 'var(--semi-color-fill-0)',
+                height: 35,
+                width: 300,
+                display: 'flex',
+                alignItems: 'center',
+                padding: '0 10px',
+                marginBottom: 30,
+            }}>
+                <TagGroup
+                    maxTagCount={3}
+                    style={ {
+                        display: 'flex',
+                        alignItems: 'center',
+                        width: 350,
+                    }}
+                    tagList={this.state.tagList}
+                    size='large'
+                    onTagClose={this.tagListClick}
+                />
+            </div>
+        );
+    }
+}
 
 export const TagGroupCloseable = () => <TagGroupCloseableDemo />;
 

+ 13 - 43
packages/semi-ui/tag/group.tsx

@@ -1,4 +1,4 @@
-import React, { Children, PureComponent } from 'react';
+import React, { PureComponent } from 'react';
 import classNames from 'classnames';
 import PropTypes from 'prop-types';
 import { cssClasses, strings } from '@douyinfe/semi-foundation/tag/constants';
@@ -21,21 +21,20 @@ export interface TagGroupProps<T> {
     popoverProps?: PopoverProps;
     avatarShape?: AvatarShape;
     mode?: string;
+    onTagClose: (tagChildren: React.ReactNode, event: React.MouseEvent<HTMLElement>, tagKey: string | number) => void;
 }
 
-export type TagGroupState<T> = Pick<TagGroupProps<T>, 'tagList'>
-export default class TagGroup<T> extends PureComponent<TagGroupProps<T>, TagGroupState<T> > {
+export default class TagGroup<T> extends PureComponent<TagGroupProps<T>> {
     static defaultProps = {
         style: {},
         className: '',
         size: tagSize[0],
         avatarShape: 'square',
-        onClose: () => undefined,
+        onTagClose: () => undefined,
     };
 
     static propTypes = {
         children: PropTypes.node,
-        tagKey: PropTypes.oneOf([PropTypes.string, PropTypes.number]),
         style: PropTypes.object,
         className: PropTypes.string,
         maxTagCount: PropTypes.number,
@@ -43,36 +42,12 @@ export default class TagGroup<T> extends PureComponent<TagGroupProps<T>, TagGrou
         tagList: PropTypes.array,
         size: PropTypes.oneOf(tagSize),
         mode: PropTypes.string,
-        onClose: PropTypes.func,
+        onTagClose: PropTypes.func,
         showPopover: PropTypes.bool,
         popoverProps: PropTypes.object,
         avatarShape: PropTypes.oneOf(avatarShapeSet),
     };
 
-    constructor(props: TagGroupProps<T>) {
-        super(props);
-        this.state = {
-            tagList: this.props.tagList
-        };
-        this.onClose = this.onClose.bind(this);
-    }
-
-    static getDerivedStateFromProps(nextProps, prevState) {
-        // 自定义 TagGroup 需要根据 props 来 rerender, normal TagGroup 根据 state 进行 rerender
-        if (nextProps.mode !== 'custom') {
-            return {
-                tagList: prevState.tagList
-            };
-        }
-        if (prevState.tagList !== nextProps.tagList) {
-            return {
-                tagList: nextProps.tagList
-            };
-        }
-        return null;
-    }
-
-    
     renderNTag(n: number, restTags: React.ReactNode) {
         const { size, showPopover, popoverProps } = this.props;
         let nTag = (
@@ -107,9 +82,7 @@ export default class TagGroup<T> extends PureComponent<TagGroupProps<T>, TagGrou
     }
 
     renderMergeTags(tags: (Tag | React.ReactNode)[]) {
-        const { maxTagCount, restCount } = this.props;
-        const { tagList } = this.state;
-
+        const { maxTagCount, tagList, restCount } = this.props;
         const n = restCount ? restCount : tagList.length - maxTagCount;
         let renderTags: (Tag | React.ReactNode)[] = tags;
 
@@ -125,13 +98,11 @@ export default class TagGroup<T> extends PureComponent<TagGroupProps<T>, TagGrou
     }
 
     renderAllTags() {
-        const { size, mode, avatarShape } = this.props;
-        const { tagList } = this.state;
+        const { tagList, size, mode, avatarShape, onTagClose } = this.props;
         const renderTags = tagList.map((tag): (Tag | React.ReactNode) => {
             if (mode === 'custom') {
                 return tag as React.ReactNode;
             }
-            
             if (!(tag as TagProps).size) {
                 (tag as TagProps).size = size;
             }
@@ -147,17 +118,16 @@ export default class TagGroup<T> extends PureComponent<TagGroupProps<T>, TagGrou
                     (tag as TagProps).tagKey = Math.random();
                 }
             }
-            return <Tag {...(tag as TagProps)} key={(tag as TagProps).tagKey} onClose={this.onClose} />;
+            return <Tag {...(tag as TagProps)} key={(tag as TagProps).tagKey} onClose={(tagChildren, e, tagKey) => {
+                if ((tag as TagProps).onClose) {
+                    (tag as TagProps).onClose(tagChildren, e, tagKey);
+                }
+                onTagClose && onTagClose(tagChildren, e, tagKey);
+            }} />;
         });
         return renderTags;
     }
 
-    onClose(value, e, tagKey) {
-        const { tagList } = this.state;
-        const newTagList = tagList.filter(tag => (tag as TagProps).tagKey !== tagKey);
-        this.setState({ tagList: newTagList });
-    }
-
     render() {
         const { style, className, maxTagCount, size } = this.props;
 

+ 1 - 1
packages/semi-ui/tag/interface.ts

@@ -21,7 +21,7 @@ export type TagSize = 'default' | 'small' | 'large';
 export type AvatarShape = 'circle' | 'square';
 
 export interface TagProps {
-    children?: React.ReactNode | string | number;
+    children?: React.ReactNode;
     tagKey?: string | number;
     size?: TagSize;
     color?: TagColor;

+ 152 - 3
packages/semi-ui/tree/_story/tree.stories.js

@@ -1,9 +1,9 @@
-import React, { useRef, useState } from 'react';
+import React, { useRef, useState, useCallback } from 'react';
 import { cloneDeep, difference, isEqual } from 'lodash';
 import { IconEdit, IconMapPin, IconMore } from '@douyinfe/semi-icons';
 import Tree from '../index';
 import AutoSizer from '../autoSizer';
-import { Button, ButtonGroup, Input, Popover, Toast, Space } from '../../index';
+import { Button, ButtonGroup, Input, Popover, Toast, Space, Select, Switch } from '../../index';
 import BigTree from './BigData';
 import testData from './data';
 const TreeNode = Tree.TreeNode;
@@ -2398,4 +2398,153 @@ export const ValueImpactExpansionWithDynamicTreeData = () => {
       </Space>
     </>
   )
-}
+}
+
+class DemoV extends React.Component {
+    constructor() {
+        super();
+        this.state = {
+            gData: [],
+            total: 0,
+            align: 'center',
+            scrollKey: '',
+            expandAll: false,
+        };
+        this.onGen = this.onGen.bind(this);
+        this.onScroll = this.onScroll.bind(this);
+        this.onInputChange = this.onInputChange.bind(this);
+        this.onInputBlur = this.onInputBlur.bind(this);
+        this.onSelectChange = this.onSelectChange.bind(this);
+        this.treeRef = React.createRef();
+    }
+
+    generateData(x = 5, y = 4, z = 3, gData = []) {
+        // x:每一级下的节点总数。y:每级节点里有y个节点、存在子节点。z:树的level层级数(0表示一级)
+        function _loop(_level, _preKey, _tns) {
+            const preKey = _preKey || '0';
+            const tns = _tns || gData;
+
+            const children = [];
+            for (let i = 0; i < x; i++) {
+                const key = `${preKey}-${i}`;
+                tns.push({ label: `${key}-标签`, key: `${key}-key`, value: `${key}-value` });
+                if (i < y) {
+                    children.push(key);
+                }
+            }
+            if (_level < 0) {
+                return tns;
+            }
+            const __level = _level - 1;
+            children.forEach((key, index) => {
+                tns[index].children = [];
+                return _loop(__level, key, tns[index].children);
+            });
+
+            return null;
+        }
+        _loop(z);
+
+        function calcTotal(x, y, z) {
+            const rec = n => (n >= 0 ? x * y ** n-- + rec(n) : 0);
+            return rec(z + 1);
+        }
+        return { gData, total: calcTotal(x, y, z) };
+    }
+
+    onGen() {
+        const { gData, total } = this.generateData();
+        this.setState({
+            gData,
+            total
+        });
+    };
+
+    onScroll(scrollKey, align) {
+      this.treeRef?.current.scrollTo({ key: scrollKey, align});
+    }
+
+    onInputChange(value) {
+      this.setState({
+        scrollKey: value,
+      })
+    }
+
+    onInputBlur(e) {
+      const { value } = e.target;
+      this.onScroll(value, this.state.align);
+    }
+
+    onSelectChange(align){
+      this.setState({
+        align: align,
+      })
+      this.onScroll(this.state.scrollKey, align);
+    }
+
+    render() {
+        const style = {
+            width: 260,
+            border: '1px solid var(--semi-color-border)'
+        };
+        return (
+            <div style={{ padding: '0 20px' }}>
+                <Button onClick={this.onGen}>生成数据: </Button>
+                <span>共 {this.state.total} 个节点</span>
+                <br/>
+                <br/>
+                <div style={{ display: 'flex', alignItems: 'center', }}>
+                  <span>defaultExpandAll</span>
+                  <Switch onChange={(value) => {
+                      this.setState({
+                        expandAll: value,
+                      })
+                  }}/>
+                </div>
+                <br/>
+                <span>跳转的key:</span>
+                <Input
+                  placeholder={'格式:x-x-key'} 
+                  style={{ width: 180, marginRight: 20 }} 
+                  onChange={this.onInputChange}
+                  onBlur={this.onInputBlur}
+                ></Input>
+                <span>scroll align:</span>
+                <Select 
+                  defaultValue='center'
+                  style={{ width: 180 }} 
+                  optionList={['center', 'start', 'end', 'smart', 'auto'].map(item => ({
+                    value: item,
+                    label: item,
+                  }))}
+                  onChange={this.onSelectChange}
+                >
+                </Select>
+                <br />
+                <br />
+                {this.state.gData.length ? (
+                    <Tree
+                        key={`key-${this.state.expandAll}`}
+                        ref={this.treeRef}
+                        defaultExpandAll={this.state.expandAll}
+                        treeData={this.state.gData}
+                        filterTreeNode
+                        showFilteredOnly
+                        style={style}
+                        virtualize={{
+                            // if set height for tree, it will fill 100%
+                            height: 300,
+                            itemSize: 28,
+                        }}
+                    />
+                ) : null}
+            </div>
+        );
+    }
+}
+
+export const virtualizeTree = () => <DemoV />;
+
+virtualizeTree.story = {
+  name: 'virtualize tree',
+};

+ 16 - 1
packages/semi-ui/tree/index.tsx

@@ -39,7 +39,8 @@ import {
     TreeNodeData,
     FlattenNode,
     KeyEntity,
-    OptionProps
+    OptionProps,
+    ScrollData,
 } from './interface';
 import CheckboxGroup from '../checkbox/checkboxGroup';
 
@@ -146,6 +147,7 @@ class Tree extends BaseComponent<TreeProps, TreeState> {
     onNodeClick: any;
     onMotionEnd: any;
     context: ContextValue;
+    virtualizedListRef: React.RefObject<any>;
 
     constructor(props: TreeProps) {
         super(props);
@@ -179,6 +181,7 @@ class Tree extends BaseComponent<TreeProps, TreeState> {
         this.optionsRef = React.createRef();
         this.foundation = new TreeFoundation(this.adapter);
         this.dragNode = null;
+        this.virtualizedListRef = React.createRef();
     }
 
     /**
@@ -493,6 +496,17 @@ class Tree extends BaseComponent<TreeProps, TreeState> {
         this.foundation.handleInputChange(value);
     };
 
+    scrollTo = (scrollData: ScrollData) => {
+        const { key, align = 'center' } = scrollData;
+        const { flattenNodes } = this.state;
+        if (key) {
+            const index = flattenNodes?.findIndex((node) => {
+                return node.key === key;
+            });
+            index >= 0 && (this.virtualizedListRef.current as any)?.scrollToItem(index, align);
+        }
+    }
+
     renderInput() {
         const {
             searchClassName,
@@ -664,6 +678,7 @@ class Tree extends BaseComponent<TreeProps, TreeState> {
             <AutoSizer defaultHeight={virtualize.height} defaultWidth={virtualize.width}>
                 {({ height, width }: { width: string | number; height: string | number }) => (
                     <VirtualList
+                        ref={this.virtualizedListRef}
                         itemCount={flattenNodes.length}
                         itemSize={virtualize.itemSize}
                         height={height}

+ 6 - 0
packages/semi-ui/tree/interface.ts

@@ -140,3 +140,9 @@ export interface NodeListState {
     cachedMotionKeys?: Set<string>;
     cachedData?: FlattenNode[];
 }
+
+export interface ScrollData {
+    key: string;
+    // The align parameter is consistent with react-window
+    align?: 'center' | 'start' | 'end' | 'smart' | 'auto';
+}

+ 73 - 0
yarn.lock

@@ -1460,6 +1460,16 @@
   resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70"
   integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==
 
+"@douyinfe/[email protected]":
+  version "2.16.1"
+  resolved "https://registry.yarnpkg.com/@douyinfe/semi-animation-react/-/semi-animation-react-2.16.1.tgz#e89b07d9706d0c03fbeb706b320c730c7bd43302"
+  integrity sha512-eKipErYiy1NZgwyWGANQxhqIa3dAjJ8rVB5bjRVq78f9lmcwln4Xk/RWO3CAFUqUZz6pR3uQpsahSBseMH+vgw==
+  dependencies:
+    "@babel/runtime-corejs3" "^7.15.4"
+    "@douyinfe/semi-animation" "2.12.0"
+    "@douyinfe/semi-animation-styled" "2.16.1"
+    classnames "^2.2.6"
+
 "@douyinfe/[email protected]":
   version "2.9.1"
   resolved "https://registry.yarnpkg.com/@douyinfe/semi-animation-react/-/semi-animation-react-2.9.1.tgz#f2e4c6ef7899729ee6145edf0579598ba195bfdd"
@@ -1470,6 +1480,13 @@
     "@douyinfe/semi-animation-styled" "2.9.1"
     classnames "^2.2.6"
 
+"@douyinfe/[email protected]":
+  version "2.16.1"
+  resolved "https://registry.yarnpkg.com/@douyinfe/semi-animation-styled/-/semi-animation-styled-2.16.1.tgz#f88d1625d006ead2f2009c86d7b2f0aae146f77a"
+  integrity sha512-49Z3acgVoNofmY0Ze8TNS5JONEX7kSsUZR2vNrP8V2I9NHGpZpeR5FLpvVdJ6E7Y8DokKiUvgygsrpsJM3fdMA==
+  dependencies:
+    "@babel/runtime-corejs3" "^7.15.4"
+
 "@douyinfe/[email protected]":
   version "2.9.1"
   resolved "https://registry.yarnpkg.com/@douyinfe/semi-animation-styled/-/semi-animation-styled-2.9.1.tgz#0a4a3c521626118b209604b2d6447fbcaa4839a4"
@@ -1493,6 +1510,21 @@
     "@babel/runtime-corejs3" "^7.15.4"
     bezier-easing "^2.1.0"
 
+"@douyinfe/[email protected]":
+  version "2.16.1"
+  resolved "https://registry.yarnpkg.com/@douyinfe/semi-foundation/-/semi-foundation-2.16.1.tgz#de41d76835e25048291f0bfb08a6cff8118ddab0"
+  integrity sha512-d5jZTT9LE43v2HKfa49uxpz0Rzq7N7Aw4V7YzgcZGDdUH8sJokkqVeDLeMB8MVx/3JQlFbyX24FBuqFjMZ2XmA==
+  dependencies:
+    "@babel/runtime-corejs3" "^7.15.4"
+    "@douyinfe/semi-animation" "2.12.0"
+    async-validator "^3.5.0"
+    classnames "^2.2.6"
+    date-fns "^2.9.0"
+    date-fns-tz "^1.0.10"
+    lodash "^4.17.21"
+    memoize-one "^5.2.1"
+    scroll-into-view-if-needed "^2.2.24"
+
 "@douyinfe/[email protected]":
   version "2.9.1"
   resolved "https://registry.yarnpkg.com/@douyinfe/semi-foundation/-/semi-foundation-2.9.1.tgz#1300bb97d6ceb92274ca4c9e6c66c5c16dc284ea"
@@ -1508,6 +1540,14 @@
     memoize-one "^5.2.1"
     scroll-into-view-if-needed "^2.2.24"
 
+"@douyinfe/[email protected]", "@douyinfe/semi-icons@^2.0.0":
+  version "2.16.1"
+  resolved "https://registry.yarnpkg.com/@douyinfe/semi-icons/-/semi-icons-2.16.1.tgz#e3a3ac1aab7c9a7c9c53894cc3b7bf5e3fdecce3"
+  integrity sha512-ZUDfNEsXbKlKHZH7psSLYhO42UNbRwBneJyVW+ipCmIvKpQdK8JXOaMkswGCedWnpV5W/PLJA+q8i37cbg3uoA==
+  dependencies:
+    "@babel/runtime-corejs3" "^7.15.4"
+    classnames "^2.2.6"
+
 "@douyinfe/[email protected]", "@douyinfe/semi-icons@latest":
   version "2.9.1"
   resolved "https://registry.yarnpkg.com/@douyinfe/semi-icons/-/semi-icons-2.9.1.tgz#7a04e1a77070220b04f63e6f65aac30155ed8ddd"
@@ -1586,6 +1626,13 @@
     monaco-themes "^0.3.3"
     react-live "^2.2.2"
 
+"@douyinfe/[email protected]":
+  version "2.16.1"
+  resolved "https://registry.yarnpkg.com/@douyinfe/semi-theme-default/-/semi-theme-default-2.16.1.tgz#2b6d42261e7b94fc1f3021208daa4b7dc9c2bfed"
+  integrity sha512-nzb4gw8S44DEfM9iSwarwXWXbgE6dmz3xzvCbHPzwPViRjsT5+nU39T117S/LdiwLAL3gqcxYzcgg5Ej7L2Odw==
+  dependencies:
+    glob "^7.1.6"
+
 "@douyinfe/[email protected]":
   version "2.9.1"
   resolved "https://registry.yarnpkg.com/@douyinfe/semi-theme-default/-/semi-theme-default-2.9.1.tgz#734113e9783ca58b69afe1769005e7e57e5a4da7"
@@ -1593,6 +1640,32 @@
   dependencies:
     glob "^7.1.6"
 
+"@douyinfe/semi-ui@^2.0.0":
+  version "2.16.1"
+  resolved "https://registry.yarnpkg.com/@douyinfe/semi-ui/-/semi-ui-2.16.1.tgz#cbc135c671baa3b49bb61f9aa4b0951a0a172f2a"
+  integrity sha512-J5DvPV5EPWEuBerftEr+9lUkEsE1KGmBvFIikD1n/C70uyS4B/oPg7oJigQ5mImZCo1DzPEfSMnKBGOKCc/nuA==
+  dependencies:
+    "@babel/runtime-corejs3" "^7.15.4"
+    "@douyinfe/semi-animation" "2.12.0"
+    "@douyinfe/semi-animation-react" "2.16.1"
+    "@douyinfe/semi-foundation" "2.16.1"
+    "@douyinfe/semi-icons" "2.16.1"
+    "@douyinfe/semi-illustrations" "2.15.0"
+    "@douyinfe/semi-theme-default" "2.16.1"
+    async-validator "^3.5.0"
+    classnames "^2.2.6"
+    copy-text-to-clipboard "^2.1.1"
+    date-fns "^2.9.0"
+    date-fns-tz "^1.0.10"
+    lodash "^4.17.21"
+    prop-types "^15.7.2"
+    react-resizable "^1.8.0"
+    react-sortable-hoc "^2.0.0"
+    react-window "^1.8.2"
+    resize-observer-polyfill "^1.5.1"
+    scroll-into-view-if-needed "^2.2.24"
+    utility-types "^3.10.0"
+
 "@douyinfe/semi-ui@latest":
   version "2.9.1"
   resolved "https://registry.yarnpkg.com/@douyinfe/semi-ui/-/semi-ui-2.9.1.tgz#505d4783ea1fa73d307b75f62091030f1fee9332"