Browse Source

Merge branch 'main' into release

pointhalo 2 years ago
parent
commit
197351116d
34 changed files with 351 additions and 247 deletions
  1. 12 12
      content/input/cascader/index-en-US.md
  2. 13 13
      content/input/cascader/index.md
  3. 14 14
      content/input/treeselect/index-en-US.md
  4. 14 14
      content/input/treeselect/index.md
  5. 12 12
      content/input/upload/index-en-US.md
  6. 18 19
      content/input/upload/index.md
  7. 24 23
      content/navigation/tree/index-en-US.md
  8. 27 27
      content/navigation/tree/index.md
  9. 7 0
      content/start/changelog/index-en-US.md
  10. 7 0
      content/start/changelog/index.md
  11. 1 1
      lerna.json
  12. 1 1
      packages/semi-animation-react/package.json
  13. 1 1
      packages/semi-animation-styled/package.json
  14. 1 1
      packages/semi-animation/package.json
  15. 1 1
      packages/semi-eslint-plugin/package.json
  16. 4 0
      packages/semi-foundation/dropdown/dropdown.scss
  17. 1 1
      packages/semi-foundation/package.json
  18. 1 1
      packages/semi-icons/package.json
  19. 1 1
      packages/semi-illustrations/package.json
  20. 1 1
      packages/semi-next/package.json
  21. 1 1
      packages/semi-scss-compile/package.json
  22. 1 1
      packages/semi-theme-default/package.json
  23. 16 0
      packages/semi-ui/dropdown/_story/C2D/index.tsx
  24. 2 0
      packages/semi-ui/dropdown/_story/dropdown.stories.jsx
  25. 11 3
      packages/semi-ui/dropdown/dropdownItem.tsx
  26. 45 0
      packages/semi-ui/form/__test__/field.test.js
  27. 71 1
      packages/semi-ui/form/_story/Validate/validateDemo.jsx
  28. 6 0
      packages/semi-ui/form/_story/form.stories.jsx
  29. 25 3
      packages/semi-ui/form/hoc/withField.tsx
  30. 7 7
      packages/semi-ui/package.json
  31. 1 1
      packages/semi-webpack/package.json
  32. 1 1
      src/sitePages/newHome/components/operateButton/operateButton.jsx
  33. 2 2
      src/templates/postTemplate.js
  34. 1 84
      yarn.lock

+ 12 - 12
content/input/cascader/index-en-US.md

@@ -576,7 +576,7 @@ When multiple selection (`multiple=true`), `displayRender((item: Entity, index:
 ```typescript
 interface Entity {
     children?: Entity[];         // children list
-    data: treeNode;              // treedata
+    data: CascaderData;              // treedata
     ind: number;                 // index
     key: string;                 // key
     level: number;               // node level
@@ -1529,7 +1529,7 @@ function Demo() {
 | className | ClassName | string | - | - |
 | clearIcon | Can be used to customize the clear button, valid when showClear is true | ReactNode | - | 2.25.0 |
 | defaultOpen | Set whether to open the dropDown by default | boolean | false | - |
-| defaultValue | Default selected value | string\|number\|TreeNode\|(string\|number\|TreeNode)[] | - | -  |
+| defaultValue | Default selected value | string\|number\|CascaderData\|(string\|number\|CascaderData)[] | - | -  |
 | disabled | Makes the element disabled | boolean | false | - |
 | displayProp | Set the attribute value displayed by the backfill option displayed | string | `label` | - |
 | displayRender | Set the backfill format value | (selected: string[] \| Entity, idx?: number) => ReactNode | selected => selected.join ('/') | -  |
@@ -1542,7 +1542,7 @@ function Demo() {
 | getPopupContainer | Specify the parent DOM, the drop-down box will be rendered into the DOM, the customization needs to set position: relative |() => HTMLElement|() => document.body|-|
 | insetLabel | Prefix alias, used mainly in Form | ReactNode | - | 0.28.0 |
 | leafOnly | When multiple selections, the set value only includes leaf nodes, that is, the displayed Tag and onChange value parameters only include leaf nodes. Does not support dynamic switching | boolean | false | 2.2.0  |
-| loadData | Load data asynchronously and the return value should be a promise | (selectOptions: TreeNode[]) => Promise< void > |-| 1.8.0|
+| loadData | Load data asynchronously and the return value should be a promise | (selectOptions: CascaderData[]) => Promise< void > |-| 1.8.0|
 | max| In the case of multiple selections, the number of multiple selections is limited, and the onExceed callback will be triggered when max is exceeded | number |-|1.28.0|
 | maxTagCount| When multiple selections, the maximum number of labels to be displayed will be displayed in the form of +N after exceeding| number |-|1.28.0|
 | motion | Set the pop-up animation of the dropdown box |boolean|true|-|
@@ -1564,30 +1564,30 @@ function Demo() {
 | style | Inline style | CSSProperties | - | - |
 | suffix | Suffix label | ReactNode | -  | 0.28.0  |
 | topSlot | top slot | ReactNode | - |  1.27.0 |
-| treeData | Render data. Refer to [TreeNode](#TreeNode)  for detailed formatting. | TreeNode[] |  []  | - |
-| treeNodeFilterProp | When searching, the input item filters the corresponding treeNode property. | string | `label`   | - |
+| treeData | Render data. Refer to [CascaderData](#CascaderData)  for detailed formatting. | CascaderData[] |  []  | - |
+| treeNodeFilterProp | When searching, the input item filters the corresponding CascaderData property. | string | `label`   | - |
 | triggerRender | Method to create a custom trigger  | (triggerRenderData: object) => ReactNode | - | 0.34.0 |
-| value | Selected value (controlled mode) | string\|number\|TreeNode\|(string\|number\|TreeNode)[][]  | - | -  |
+| value | Selected value (controlled mode) | string\|number\|CascaderData\|(string\|number\|CascaderData)[][]  | - | -  |
 | validateStatus |The validation status of the trigger only affects the display style. Optional: default、error、warning | string | `default` | - |
 | zIndex | zIndex for dropdown menu | number | 1030 | - |
 | enableLeafClick | Multiple mode, click the leaf option enable trigger check | boolean | false | 2.2.0 |
 | onBlur | Out of focus Cascader's callback | (e: MouseEvent) => void | - | - |
-| onChange | Callback function when the tree node is selected | (value: string\|number\|TreeNode\|(string\|number\|TreeNode)[]) => void | - | - |
+| onChange | Callback function when the tree node is selected | (value: string\|number\|CascaderData\|(string\|number\|CascaderData)[]) => void | - | - |
 | onClear| When showClear is true, click the clear button to trigger the callback | () => void |-|1.29.0|
-| onChangeWithObject | Toggle whether to return all properties in an option as a return value. When set to true, return value looks like TreeNode. For controlled mode, you need to pass TreeNode to value correspondingly. DefaultValue similarly. | boolean | false | 1.16.0 |
+| onChangeWithObject | Toggle whether to return all properties in an option as a return value. When set to true, return value looks like CascaderData. For controlled mode, you need to pass CascaderData to value correspondingly. DefaultValue similarly. | boolean | false | 1.16.0 |
 | onDropdownVisibleChange | Callback function when dropdown menu visibility changes   | (visible: boolean) => void | - | 0.35.0 |
 | onExceed| When multiple selections are made, the callback triggered after max is exceeded | (checkedItem: Entity[]) => void |-|1.28.0|
 | onFocus| Focus on Cascader's callback | (e: MouseEvent) => void | - | - |
-| onListScroll | Callback function when panel list scroll | (e: React.Event, panel: { panelIndex: number; activeNode: TreeNode; } ) => void | - | 1.15.0 |
-| onLoad | Callback function when a node is loaded | (newLoadedKeys: Set< string >, data: TreeNode) => void | - | 1.8.0|
+| onListScroll | Callback function when panel list scroll | (e: React.Event, panel: { panelIndex: number; activeNode: CascaderData; } ) => void | - | 1.15.0 |
+| onLoad | Callback function when a node is loaded | (newLoadedKeys: Set< string >, data: CascaderData) => void | - | 1.8.0|
 | onSearch | Callback function when the values for search input changes | (value: string) => void | - | - |
 | onSelect | Callback function when selected | (value: string \| number \| (string \| number)[]) => void | - | - |
 
-### TreeNode
+### CascaderData
 
 | Properties | Instructions                   | type           | Default |
 | ---------- | -------------------------------| -------------- | ------- |
-| children   | children node                  | TreeNode[]     | -       |
+| children   | children node                  | CascaderData[]     | -       |
 | disabled   | Disabled status **>=0.35.0**   | boolean        | -       |
 | isLeaf     | leaf node                      | boolean        | -       |
 | label      | Text to be displayed (required)| ReactNode      | -       |

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

@@ -581,7 +581,7 @@ import { Cascader, Typography } from '@douyinfe/semi-ui';
 ```typescript
 interface Entity {
     children?: Entity[];         // children list
-    data: treeNode;              // treedata
+    data: CascaderData;              // treedata
     ind: number;                 // index
     key: string;                 // key
     level: number;               // node level
@@ -1516,7 +1516,7 @@ function Demo() {
 | className | 选择框的 className 属性 | string | - | - |
 | clearIcon | 可用于自定义清除按钮, showClear为true时有效 | ReactNode | - | 2.25.0  |
 | defaultOpen | 设置是否默认打开下拉菜单  | boolean | false | - |
-| defaultValue | 指定默认选中的条目  | string\|number\|TreeNode\|(string\|number\|TreeNode)[]| - | - |
+| defaultValue | 指定默认选中的条目  | string\|number\|CascaderData\|(string\|number\|CascaderData)[]| - | - |
 | disabled | 是否禁用 | boolean | false | -  |
 | displayProp | 设置回填选项显示的属性值 | string  | `label` | - |
 | displayRender | 设置回填格式 | (selected: string[] \| Entity, idx?: number) => ReactNode | selected => selected.join('/') | - |
@@ -1525,11 +1525,11 @@ function Demo() {
 | dropdownStyle | 下拉菜单的样式 | object | - | - |
 | emptyContent | 当搜索无结果时展示的内容 | ReactNode | `暂无数据` | - |
 | filterLeafOnly |  搜索结果是否只展示叶子结点路径 | boolean  | true | 1.26.0 |
-| filterTreeNode | 设置筛选,默认用 treeNodeFilterProp 的值作为要筛选的 TreeNode 的属性值 | ((inputValue: string, treeNodeString: string) => boolean) \| boolean | false | - |
+| filterTreeNode | 设置筛选,默认用 treeNodeFilterProp 的值作为要筛选的 CascaderData 的属性值 | ((inputValue: string, treeNodeString: string) => boolean) \| boolean | false | - |
 | getPopupContainer | 指定父级 DOM,下拉框将会渲染至该 DOM 中,自定义需要设置 position: relative |() => HTMLElement|() => document.body | - |
 | insetLabel | 前缀标签别名,主要用于 Form | ReactNode | - | 0.28.0 |
 | leafOnly | 多选时设置 value 只包含叶子节点,即显示的 Tag 和 onChange 的 value 参数只包含叶子节点。不支持动态切换 | boolean | false | 2.2.0 |
-| loadData | 异步加载数据,需要返回一个Promise | (selectOptions: TreeNode[]) => Promise< void > |- | 1.8.0 |
+| loadData | 异步加载数据,需要返回一个Promise | (selectOptions: CascaderData[]) => Promise< void > |- | 1.8.0 |
 | max| 多选时,限制多选选中的数量,超出 max 后将触发 onExceed 回调 | number | - | 1.28.0  |
 | maxTagCount| 多选时,标签的最大展示数量,超出后将以 +N 形式展示| number | - | 1.28.0 |
 | motion | 设置下拉框弹出的动画 |boolean| true |-|
@@ -1552,30 +1552,30 @@ function Demo() {
 | style | 选择框的样式 | CSSProperties | -  | - |
 | suffix | 后缀标签 | ReactNode  | -   | 0.28.0 |
 | topSlot | 顶部插槽 | ReactNode | - | 1.27.0  |
-| treeData | 展示数据,具体属性参考 [TreeNode](#TreeNode) | TreeNode[] | [] | - |
-| treeNodeFilterProp | 搜索时输入项过滤对应的 treeNode 属性 | string | `label` | - |
+| treeData | 展示数据,具体属性参考 [CascaderData](#CascaderData) | CascaderData[] | [] | - |
+| treeNodeFilterProp | 搜索时输入项过滤对应的 CascaderData 属性 | string | `label` | - |
 | triggerRender | 自定义触发器渲染方法  | (triggerRenderData: object) => ReactNode | - | 0.34.0 |
 | validateStatus | trigger 的校验状态,仅影响展示样式。可选: default、error、warning | string | `default` | - |
-| value |(受控)选中的条目 | string\|number\|TreeNode\|(string\|number\|TreeNode)[] | - | - |
+| value |(受控)选中的条目 | string\|number\|CascaderData\|(string\|number\|CascaderData)[] | - | - |
 | zIndex | 下拉菜单的 zIndex | number | 1030 | - |
 | enableLeafClick | 多选时,是否启动点击叶子节点选项触发勾选 | boolean | false | 2.2.0 |
 | onBlur | 失焦 Cascader 的回调 | (e: MouseEvent) => void | - | - |
-| onChange | 选中树节点时调用此函数,默认返回选中项 path 的 value 数组 | (value: string\|number\| TreeNode |(string\|number\|TreeNode)[]) => void | - | - |
-| onChangeWithObject | 是否将选中项 option 的其他属性作为回调。设为 true 时,onChange 的入参类型会从 string/number 变为 TreeNode。此时如果是受控,也需要把 value 设置成 TreeNode 类型,且必须含有 value 的键值,defaultValue 同理 | boolean | false | 1.16.0 |
+| onChange | 选中树节点时调用此函数,默认返回选中项 path 的 value 数组 | (value: string\|number\| CascaderData |(string\|number\|CascaderData)[]) => void | - | - |
+| onChangeWithObject | 是否将选中项 option 的其他属性作为回调。设为 true 时,onChange 的入参类型会从 string/number 变为 TreeNode。此时如果是受控,也需要把 value 设置成 CascaderData 类型,且必须含有 value 的键值,defaultValue 同理 | boolean | false | 1.16.0 |
 | onClear| showClear 为 true 时,点击清空按钮触发的回调 | () => void | - | 1.29.0 |
 | onDropdownVisibleChange       | 下拉框切换时的回调   | (visible: boolean) => void | - | 0.35.0 |
 | onExceed| 多选时,超出 max 后触发的回调 | (checkedItem: Entity[]) => void | - | 1.28.0 |
 | onFocus| 聚焦 Cascader 的回调 | (e: MouseEvent) => void | - | - |
-| onListScroll | 下拉面板滚动的回调 | (e: React.Event, panel: { panelIndex: number; activeNode: TreeNode; } ) => void | - | 1.15.0 |
-| onLoad | 节点加载完毕时触发的回调 | (newLoadedKeys: Set< string >, data: TreeNode) => void |- | 1.8.0 |
+| onListScroll | 下拉面板滚动的回调 | (e: React.Event, panel: { panelIndex: number; activeNode: CascaderData; } ) => void | - | 1.15.0 |
+| onLoad | 节点加载完毕时触发的回调 | (newLoadedKeys: Set< string >, data: CascaderData) => void |- | 1.8.0 |
 | onSearch | 文本框值变化时回调 | (value: string) => void | - | - |
 | onSelect | 被选中时调用,返回选中项的 value | (value: string \| number \| (string \| number)[]) => void| - | - |
 
-### TreeNode
+### CascaderData
 
 | 属性      | 说明                  | 类型            | 默认值 |
 | -------- | --------------------- | -------------- | ----- |
-| children | 子节点                 | TreeNode[]     | -     |
+| children | 子节点                 | CascaderData[]     | -     |
 | disabled | 不可选状态 **>=0.35.0** | boolean        | -     |
 | isLeaf   | 叶子节点                | boolean        | -     |
 | label    | 展示的文本(必填)       | ReactNode       | -     |

+ 14 - 14
content/input/treeselect/index-en-US.md

@@ -1213,7 +1213,7 @@ The triggerRender input is as follows:
 interface triggerRenderProps {
     componentProps: TreeSelectProps;// TreeSelect props
     disabled: boolean;              // disabled status
-    value: TreeNode[];              // data of the selected node
+    value: TreeNodeData[];              // data of the selected node
     inputValue: string;             // value of the input box
     onClear: e => void;             // onClear function
     placeholder: string;            // placeholder
@@ -1292,8 +1292,8 @@ function Demo() {
 
 You can use renderSelectedItem to customize the rendering structure of the selected item in the selection box.
 
-- In not multiple mode: `renderSelectedItem(treeNode:TreeNode) => content:ReactNode`
-- In multiple mode: `renderSelectedItem(treeNode:TreeNode, { index:number, onClose:function }) => { isRenderInTag:bool, content:ReactNode }`
+- In not multiple mode: `renderSelectedItem(treeNode: TreeNodeData) => content: ReactNode`
+- In multiple mode: `renderSelectedItem(treeNode: TreeNodeData, { index:number, onClose:function }) => { isRenderInTag: bool, content: ReactNode }`
     - When isRenderInTag is true, content wraps are automatically rendered in the Tag (with background color and close button)
     - When isRenderInTag is false, the returned content will be rendered directly
 
@@ -1389,7 +1389,7 @@ function Demo() {
 | defaultExpandAll    | Set whether to expand all nodes during initialization. And if the data (`treeData`) changes, this api cannot affect the expansion of the node. If you need this, you can use `expandAll`    | boolean                     | false   | 0.32.0 |
 | defaultExpandedKeys | Keys of default expanded nodes. Direct child nodes will be displayed. | string\[] | - | 0.32.0 |
 | defaultOpen | Toggle whether to open dropdown menu by default | boolean | false | 0.32.0 |
-| defaultValue             | Default value         | <ApiType detail='string \| number \| TreeNode \| (string \| number \| TreeNode)[]'>ValueType</ApiType>   | -   | -     |
+| defaultValue             | Default value         | <ApiType detail='string \| number \| TreeNodeData \| (string \| number \| TreeNodeData)[]'>ValueType</ApiType>   | -   | -     |
 | disabled                 | Disabled                                                                            | boolean                                                           | false       | -       |
 | disableStrictly | Disable Strictly | boolean | false | 1.30.0 |
 | dropdownClassName        | `className` property for dropDown                                                   | string                                                            | -           | -       |
@@ -1405,7 +1405,7 @@ function Demo() {
 | insetLabel               | Prefix alias,used mainly in Form                                                   | ReactNode                                                         | -           | 0.28.0  |
 | labelEllipsis | Toggle whether to ellipsis label when overflow | boolean | false\|true(virtualized) | 1.8.0 |  
 | leafOnly | Toggle whether to display tags for leaf nodes only and for onChange callback params in multiple mode | boolean | false |0.32.0 |
-| loadData | Load data asynchronously and the return value should be a promise | (treeNode: TreeNode) => Promise |-| 1.32.0|
+| loadData | Load data asynchronously and the return value should be a promise | (treeNode: TreeNodeData) => Promise |-| 1.32.0|
 | loadedKeys | (Controlled)Mark node as loaded, working with `loadData` | Set< string > | - | 1.32.0|
 | maxTagCount              | Maximum number of tags displayed                                                    | number                                                            | -           | -       |
 | motionExpand             | Toggle whether to turn on animation for expansion                                   | boolean                                                           | true        | -       |
@@ -1418,7 +1418,7 @@ function Demo() {
 | prefix                   | Prefix                                                                              | ReactNode                                                         | -           | 0.28.0  |
 | 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 |  |  |
 | renderFullLabel | Custom option render function, [Detailed Params and Usage](/en-US/navigation/tree#Advanced%20FullRender) | (obj) => ReactNode | 1.7.0 |
-| renderLabel | Custom label render function | <ApiType detail='(label:ReactNode, data:TreeNode) => ReactNode'>(label, data) => ReactNode</ApiType> | 1.6.0 | 
+| renderLabel | Custom label render function | <ApiType detail='(label: ReactNode, data: TreeNodeData) => ReactNode'>(label, data) => ReactNode</ApiType> | 1.6.0 | 
 | renderSelectedItem | render selected item | Function | - | 1.26.0 | 
 | restTagsPopoverProps | The configuration properties of the [Popover](/en-US/show/popover#API%20Reference)     | PopoverProps     | {}        | 2.22.0 |
 | searchAutoFocus        | Whether autofocus for search box           | boolean      | false           | 1.27.0       |
@@ -1431,12 +1431,12 @@ function Demo() {
 | size                     | Size for input box,one of `large`,`small`,`default`                              | string                                                            | `default`   | -       |
 | style                    | Inline style                                                            | CSSProperties             | -           | -       |
 | suffix                   | Suffix                                                                              | ReactNode                                                         | -           | 0.28.0  |
-| treeData                 | Data for treeNodes                                                                  | TreeNode[]                                                  | \[]         | -       |
-| treeNodeFilterProp       | Property in a `treeNode` used to search                                             | string                                                            | `label`     | -       |
-| treeNodeLabelProp        | Property in a `treeNode` used to display                                            | string                                                            | `label`     | -       |
+| treeData                 | Data for treeNodes                                                                  | TreeNodeData[]                                                  | \[]         | -       |
+| treeNodeFilterProp       | Property in a `TreeNodeData` used to search                                             | string                                                            | `label`     | -       |
+| treeNodeLabelProp        | Property in a `TreeNodeData` used to display                                            | string                                                            | `label`     | -       |
 | triggerRender | Method to create a custom trigger  | (TriggerProps) => ReactNode | - | 0.34.0 |
 | validateStatus | Validate status,one of `warning`、`error`、 `default`, only affects the background color of the component | string | - | 0.32.0 |
-| value                    | Value data of current item, used when TreeSelect is a controlled component     | <ApiType detail='string \| number \| TreeNode \| (string \| number \| TreeNode)[]'>ValueType</ApiType>    | -           | -       |
+| value                    | Value data of current item, used when TreeSelect is a controlled component     | <ApiType detail='string \| number \| TreeNodeData \| (string \| number \| TreeNodeData)[]'>ValueType</ApiType>    | -           | -       |
 | virtualize | Efficiently rendering large lists, refer to Tree - VirtualizeObj. Motion is disabled when tree is rendered as virtualized list. | object | - | 0.32.0 |
 | zIndex | zIndex for treeSelect dropDown menu | number | 1030 | 0.30.0 |
 | onBlur                 | Callback function when treeSelect blur | function(event)                            | -           | -       |
@@ -1444,14 +1444,14 @@ function Demo() {
 | onChange                 | Callback function when the tree node is selected, return the value property of data | Function                           | -           | -       |
 | onChangeWithObject        | Toggle whether to return all properties in an option as a return value. When set to true, onChange turn to Function(node, e)   | boolean                     | false   | 1.0.0 |
 | onExpand                 | Callback function when expand or collapse a node                                    | <ApiType detail='(expandedKeys:array, {expanded: bool, node}) => void'>(expandedKeys, object) => void</ApiType>             | -           | -       |
-| onLoad | Callback function when a node is loaded | <ApiType detail='(loadedKeys: Set<string\>, treeNode: TreeNode) => void'>(loadedKeys, treeNode) => void</ApiType> | - | 1.32.0|
+| onLoad | Callback function when a node is loaded | <ApiType detail='(loadedKeys: Set<string\>, treeNode: TreeNodeData) => void'>(loadedKeys, treeNode) => void</ApiType> | - | 1.32.0|
 | onSearch                 | Callback function when search value changes. `filteredExpandedKeys` represents the key of the node expanded due to search or value/defaultValue, which can be used when expandedKeys is controlled<br/> **filteredExpandedKeys is supported in 2.6.0**      | function(input: string, filteredExpandedKeys: string[])                                        | -           |     |
-| onSelect                 | Callback function when selected, return the key property of data                    | function(selectedKey:string, selected: bool, selectedNode: TreeNode)                      | -           | -       |
+| onSelect                 | Callback function when selected, return the key property of data                    | function(selectedKey:string, selected: bool, selectedNode: TreeNodeData)                      | -           | -       |
 | onVisibleChange     | A callback triggered when the pop-up layer is displayed/hidden   | function(isVisible:boolean) |     |   1.4.0  |
 
-### TreeNode
+### TreeNodeData
 
-> **Key for `TreeNode` is required and must be unique**, `label` can be duplicated. Before **v>=1.7.0** value is also required and must be unique.
+> **Key for `TreeNodeData` is required and must be unique**, `label` can be duplicated. Before **v>=1.7.0** value is also required and must be unique.
 > After **v>=1.7.0**, value is not required. In this case, the value property in `onChange`, `value`, `defaultValue` and `onChangeWithObject` will point to key property.
 > To ensure everything behave as expected, keep a consistency of whether to have value or not to have value.
 

+ 14 - 14
content/input/treeselect/index.md

@@ -1181,7 +1181,7 @@ triggerRender 入参如下:
 interface triggerRenderProps {
     componentProps: TreeSelectProps;// 所有用户传给 TreeSelect 的 props
     disabled: boolean;              // 是否禁用 TreeSelect
-    value: TreeNode[];              // 已选中的 node 的数据
+    value: TreeNodeData[];              // 已选中的 node 的数据
     inputValue: string;             // 当前 input 框的输入值
     onClear: e => void;             // 用于清空值的函数
     placeholder: string;            // placeholder
@@ -1261,8 +1261,8 @@ function Demo() {
 
 你可以通过 renderSelectedItem 自定义选择框中已选项标签的渲染结构。
 
-- 单选时 `renderSelectedItem(treeNode: TreeNode) => content:ReactNode`
-- 多选时 `renderSelectedItem(treeNode: TreeNode, { index:number, onClose:function }) => { isRenderInTag:bool, content:ReactNode }`
+- 单选时 `renderSelectedItem(treeNode: TreeNodeData) => content:ReactNode`
+- 多选时 `renderSelectedItem(treeNode: TreeNodeData, { index:number, onClose:function }) => { isRenderInTag:bool, content:ReactNode }`
     - isRenderInTag 为 true 时,会自动将 content 包裹在 Tag 中渲染(带有背景色以及关闭按钮)
     - isRenderInTag 为 false 时,将直接渲染返回的 content
 
@@ -1372,7 +1372,7 @@ function Demo() {
 | defaultExpandAll | 设置在初始化时是否展开所有节点。而如果后续数据(`treeData`)发生改变,这个 api 是无法影响节点的展开情况的,如果有这个需要可以使用 `expandAll` | boolean | false | 0.32.0 |
 | defaultExpandedKeys | 默认展开的节点,显示其直接子级 | string\[] | - | 0.32.0 |
 | defaultOpen | 默认展开下拉菜单 | boolean | false | 0.32.0 |
-| defaultValue | 指定默认选中的条目 | <ApiType detail='string \| number \| TreeNode \| (string \| number \| TreeNode)[]'>ValueType</ApiType> | - | - |
+| defaultValue | 指定默认选中的条目 | <ApiType detail='string \| number \| TreeNodeData \| (string \| number \| TreeNodeData)[]'>ValueType</ApiType> | - | - |
 | disabled | 是否禁用 | boolean | false | - |
 | disableStrictly | 是否严格禁用 | boolean | false | 1.30.0 |
 | dropdownClassName | 下拉菜单的 `className` 属性 | string | - | - |
@@ -1383,12 +1383,12 @@ function Demo() {
 | expandAction             | 展开逻辑,可选 false, 'click', 'doubleClick'。默认值为 false,即仅当点击展开按钮时才会展开  | boolean \| string   | false | 1.4.0      |
 | expandAll | 设置是否默认展开所有节点,若后续数据(`treeData`)发生改变,默认的展开情况也是会受到这个 api 影响的 | boolean | false | 1.30.0 |
 | expandedKeys | (受控)展开的节点,默认展开节点显示其直接子级 | string[] | - | 0.32.0 |
-| filterTreeNode | 是否根据输入项进行筛选,默认用 `treeNodeFilterProp` 的值作为要筛选的 `TreeNode` 的属性值 | boolean\| <ApiType detail='(inputValue: string, treeNodeString: string => boolean'>Function</ApiType> | false | - |
+| filterTreeNode | 是否根据输入项进行筛选,默认用 `treeNodeFilterProp` 的值作为要筛选的 `TreeNodeData` 的属性值 | boolean\| <ApiType detail='(inputValue: string, treeNodeString: string => boolean'>Function</ApiType> | false | - |
 | getPopupContainer  | 指定父级 DOM,弹层将会渲染至该 DOM 中,自定义需要设置 `position: relative`     | function():HTMLElement | - | - |
 | insetLabel | 前缀标签别名,主要用于 Form | ReactNode | - |0.28.0 |
 | labelEllipsis | 是否开启label的超出省略,默认虚拟化状态下开启 | boolean | false\|true | 1.8.0 | 
 | leafOnly | 多选模式下是否开启 onChange 回调入参及展示标签只有叶子节点 | boolean | false |0.32.0 |
-| loadData | 异步加载数据,需要返回一个Promise | (treeNode: TreeNode) => Promise |- |  1.32.0|
+| loadData | 异步加载数据,需要返回一个Promise | (treeNode: TreeNodeData) => Promise |- |  1.32.0|
 | loadedKeys | (受控)已经加载的节点,配合 loadData 使用 | Set< string > | - | 1.32.0|
 | maxTagCount | 最多显示多少个 tag | number | - | - |
 | motionExpand | 是否开启选项树节点动画 | boolean | true | - |
@@ -1401,7 +1401,7 @@ function Demo() {
 | prefix | 前缀标签 | ReactNode | - |0.28.0 |
 | preventScroll | 指示浏览器是否应滚动文档以显示新聚焦的元素,作用于组件内的 focus 方法 | boolean |  |  |
 | renderFullLabel | 完全自定义label的渲染函数,[入参及用法详见](/zh-CN/navigation/tree#高级定制) | (obj) => ReactNode | - | 1.7.0 | 
-| renderLabel | 自定义label的渲染函数,[入参及用法详见](/zh-CN/navigation/tree#自定义节点内容)  | <ApiType detail='(label:ReactNode, data:TreeNode) => ReactNode'>(label, data) => ReactNode</ApiType> | - | 1.6.0 | 
+| renderLabel | 自定义label的渲染函数,[入参及用法详见](/zh-CN/navigation/tree#自定义节点内容)  | <ApiType detail='(label:ReactNode, data:TreeNodeData) => ReactNode'>(label, data) => ReactNode</ApiType> | - | 1.6.0 | 
 | renderSelectedItem | 自定义渲染已选项 | Function | - | 1.26.0 | 
 | restTagsPopoverProps | Popover 的配置属性,可以控制 position、zIndex、trigger 等,具体参考[Popover](/zh-CN/show/popover#API%20%E5%8F%82%E8%80%83) | PopoverProps     | {} | 2.22.0 |
 | searchAutoFocus | 搜索框自动聚焦 | boolean | false | 1.27.0 |
@@ -1414,12 +1414,12 @@ function Demo() {
 | size | 选择框大小,可选 `large`,`small`,`default` | string | `default` | - |
 | style | 选择框的样式  | CSSProperties | - | - |
 | suffix | 后缀标签 | ReactNode | - |0.28.0|
-| treeData | `treeNodes` 数据,如果设置则不需要手动构造 `TreeNode` 节点(`key` 值在整个树范围内唯一) | TreeNode[] | \[] | - |
-| treeNodeFilterProp | 搜索时输入项过滤对应的 `treeNode` 属性 | string | `label` | - |
+| treeData | `treeNodes` 数据,如果设置则不需要手动构造 `TreeNode` 节点(`key` 值在整个树范围内唯一) | TreeNodeData[] | \[] | - |
+| treeNodeFilterProp | 搜索时输入项过滤对应的 `TreeNodeData` 属性 | string | `label` | - |
 | treeNodeLabelProp | 作为显示的 `prop` 设置 | string | `label` | - |
 | triggerRender | 自定义触发器渲染方法  | ({ placeholder: string }) => ReactNode | - | 0.34.0 |
 | validateStatus | 校验结果,可选 `warning`、`error`、 `default`(只影响样式背景色) | string | - | 0.32.0 |
-| value | 当前选中的节点的value值,传入该值时将作为受控组件 | <ApiType detail='string \| number \| TreeNode \| (string \| number \| TreeNode)[]'>ValueType</ApiType>| - | - |
+| value | 当前选中的节点的value值,传入该值时将作为受控组件 | <ApiType detail='string \| number \| TreeNodeData \| (string \| number \| TreeNodeData)[]'>ValueType</ApiType>| - | - |
 | virtualize | 列表虚拟化,用于大量树节点的情况,由 height, width, itemSize 组成,参考 Tree - Virtualize Object。开启后将关闭动画效果。 | object | - | 0.32.0 |
 | zIndex | treeSelect下拉菜单的zIndex | number | 1030 | 0.30.0 |
 | onBlur | 失去焦点时的回调 | function(event) | - | - |
@@ -1427,14 +1427,14 @@ function Demo() {
 | onChangeWithObject | 是否将选中项 option 的其他属性作为回调。设为 true 时,onChange 的入参类型Function(node\|node[], e) 此时如果是受控,也需要把 value 设置成 object,且必须含有 value 的键值;defaultValue同理。 | boolean | false | 1.0.0 |
 | onExpand | 展示节点时调用 | <ApiType detail='(expandedKeys:array, {expanded: bool, node}) => void'>(expandedKeys, object) => void</ApiType> | - | - |
 | onFocus | 聚焦时的回调 | function(event) | - | - |
-| onLoad | 节点加载完毕时触发的回调 | <ApiType detail='(loadedKeys: Set<string\>, treeNode: TreeNode) => void'>(loadedKeys, treeNode) => void</ApiType> |- |  1.32.0|
+| onLoad | 节点加载完毕时触发的回调 | <ApiType detail='(loadedKeys: Set<string\>, treeNode: TreeNodeData) => void'>(loadedKeys, treeNode) => void</ApiType> |- |  1.32.0|
 | onSearch | 文本框值变化时回调。 入参 filteredExpandedKeys 表示因为搜索或 value / defaultValue 而展开的节点的 key, <br/>可以配合 expandedKeys 受控时使用。filteredExpandedKeys 在 2.6.0 中新增 |  <ApiType detail='function(sugInput: string, filteredExpandedKeys: string[])'>(sugInput, filteredExpandedKeys)=>void</ApiType>  |  |  |
-| onSelect | 被选中时调用,返回值为当前事件选项的key值 | <ApiType detail='(selectedKey:string, selected: bool, selectedNode: TreeNode) => void'>(selectedKey, selected, selectedNode)=>void</ApiType> | - | - |
+| onSelect | 被选中时调用,返回值为当前事件选项的key值 | <ApiType detail='(selectedKey:string, selected: bool, selectedNode: TreeNodeData) => void'>(selectedKey, selected, selectedNode)=>void</ApiType> | - | - |
 | onVisibleChange     | 弹出层展示/隐藏时触发的回调   | function(isVisible:boolean) |     |   1.4.0  |
 
-### TreeNode
+### TreeNodeData
 
-> __不同 `TreeNode` 的 key 值要求必填且唯一。__`label` 允许重复。**v>=1.7.0** 之前 value 值要求必须必填且唯一。
+> __不同 `TreeNodeData` 的 key 值要求必填且唯一。__`label` 允许重复。**v>=1.7.0** 之前 value 值要求必须必填且唯一。
 > **v>=1.7.0** 之后 value 值非必填。此时 onChange, value, defaultValue 及 onChangeWithObject 中所取的 value 属性值将改为 key 值。
 > 为了保证行为的符合预期,treeData 中的 value 值或者全部不填写,或者全部填写且唯一,不建议混写。
 

+ 12 - 12
content/input/upload/index-en-US.md

@@ -389,20 +389,20 @@ import { IconPlus } from '@douyinfe/semi-icons';
     const defaultFileList = [
         {
             uid: '1',
-            name: 'vigo.png',
+            name: 'dyBag.jpeg',
             status: 'success',
             size: '130KB',
             preview: true,
-            url: 'https://sf6-cdn-tos.douyinstatic.com/img/ee-finolhu/c2a65140483e4a20802d64af5fec1b39~noop.image',
+            url: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/edit-bag.jpeg',
         },
         {
             uid: '2',
-            name: 'abc.jpeg',
+            name: 'dyBag2.jpeg',
             status: 'success',
             size: '222KB',
             preview: true,
             fileInstance: new File([new ArrayBuffer(2048)], 'abc.jpeg', { type: 'image/png' }),
-            url: 'https://sf6-cdn-tos.douyinstatic.com/img/ee-finolhu/c2a65140483e4a20802d64af5fec1b39~noop.image',
+            url: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/edit-bag.jpeg',
         },
     ];
     return (
@@ -464,10 +464,10 @@ import { IconUpload, IconFile } from '@douyinfe/semi-icons';
     const defaultFileList = [
         {
             uid: '1',
-            name: 'vigo.png',
+            name: 'dyBag.jpeg',
             status: 'success',
             size: '130KB',
-            url: 'https://sf6-cdn-tos.douyinstatic.com/img/ee-finolhu/c2a65140483e4a20802d64af5fec1b39~noop.image',
+            url: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/edit-bag.jpeg',
         },
     ];
     return (
@@ -499,11 +499,11 @@ import { IconUpload, IconDownload, IconEyeOpened, IconDelete } from '@douyinfe/s
     const defaultFileList = [
         {
             uid: '1',
-            name: 'vigo.png',
+            name: 'dyBag.jpeg',
             status: 'success',
             size: '130KB',
             preview: true,
-            url: 'https://sf6-cdn-tos.douyinstatic.com/img/ee-finolhu/c2a65140483e4a20802d64af5fec1b39~noop.image',
+            url: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/edit-bag.jpeg',
         }
     ];
     const renderFileOperation = (fileItem) => (
@@ -536,11 +536,11 @@ import { IconUpload } from '@douyinfe/semi-icons';
     const defaultFileList = [
         {
             uid: '1',
-            name: 'vigo.png',
+            name: 'dyBag.jpeg',
             status: 'success',
             size: '130KB',
             preview: true,
-            url: 'https://sf6-cdn-tos.douyinstatic.com/img/ee-finolhu/c2a65140483e4a20802d64af5fec1b39~noop.image',
+            url: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/edit-bag.jpeg',
         },
         {
             uid: '2',
@@ -578,7 +578,7 @@ import { IconUpload } from '@douyinfe/semi-icons';
     const initList = [
         {
             uid: '1',
-            name: 'vigo.png',
+            name: 'dyBag.jpeg',
             status: 'success',
             size: '130KB',
             preview: true,
@@ -795,7 +795,7 @@ import { IconUpload } from '@douyinfe/semi-icons';
     const defaultFileList = [
         {
             uid: '1',
-            name: 'vigo.png',
+            name: 'dyBag.jpeg',
             status: 'success',
             size: '130KB',
             preview: true,

+ 18 - 19
content/input/upload/index.md

@@ -59,8 +59,7 @@ import { IconUpload } from '@douyinfe/semi-icons';
     };
     const button = (
         <Button icon={<IconUpload />} theme="light">
-            {' '}
-            点击上传{' '}
+            点击上传
         </Button>
     );
     const positions = ['right', 'left', 'bottom'];
@@ -393,20 +392,20 @@ import { IconPlus } from '@douyinfe/semi-icons';
     const defaultFileList = [
         {
             uid: '1',
-            name: 'vigo.png',
+            name: 'dyBag.png',
             status: 'success',
             size: '130KB',
             preview: true,
-            url: 'https://sf6-cdn-tos.douyinstatic.com/img/ee-finolhu/c2a65140483e4a20802d64af5fec1b39~noop.image',
+            url: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/edit-bag.jpeg',
         },
         {
             uid: '2',
-            name: 'vigo2.jpeg',
+            name: 'dyBag2.jpeg',
             status: 'success',
             size: '222KB',
             preview: true,
-            fileInstance: new File([new ArrayBuffer(2048)], 'vigo2.jpeg', { type: 'image/png' }),
-            url: 'https://sf6-cdn-tos.douyinstatic.com/img/ee-finolhu/c2a65140483e4a20802d64af5fec1b39~noop.image',
+            fileInstance: new File([new ArrayBuffer(2048)], 'dyBag2.jpeg', { type: 'image/png' }),
+            url: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/edit-bag.jpeg',
         },
     ];
     return (
@@ -468,10 +467,10 @@ import { IconUpload, IconFile } from '@douyinfe/semi-icons';
     const defaultFileList = [
         {
             uid: '1',
-            name: 'vigo.png',
+            name: 'dyBag.png',
             status: 'success',
             size: '130KB',
-            url: 'https://sf6-cdn-tos.douyinstatic.com/img/ee-finolhu/c2a65140483e4a20802d64af5fec1b39~noop.image',
+            url: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/edit-bag.jpeg',
         },
     ];
     return (
@@ -503,11 +502,11 @@ import { IconUpload, IconDownload, IconEyeOpened } from '@douyinfe/semi-icons';
     const defaultFileList = [
         {
             uid: '1',
-            name: 'vigo.png',
+            name: 'dyBag.png',
             status: 'success',
             size: '130KB',
             preview: true,
-            url: 'https://sf6-cdn-tos.douyinstatic.com/img/ee-finolhu/c2a65140483e4a20802d64af5fec1b39~noop.image',
+            url: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/edit-bag.jpeg',
         }
     ];
     const renderFileOperation = (fileItem) => (
@@ -543,20 +542,20 @@ import { IconUpload } from '@douyinfe/semi-icons';
     const defaultFileList = [
         {
             uid: '1',
-            name: 'vigo.png',
+            name: 'dyBag.jpeg',
             status: 'success',
             size: '130KB',
             preview: true,
-            url: 'https://sf6-cdn-tos.douyinstatic.com/img/ee-finolhu/c2a65140483e4a20802d64af5fec1b39~noop.image',
+            url: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/edit-bag.jpeg',
         },
         {
             uid: '2',
-            name: 'vigo2.jpeg',
+            name: 'dyBag2.jpeg',
             status: 'uploadFail',
             size: '222KB',
             preview: true,
-            fileInstance: new File([new ArrayBuffer(2048)], 'vigo2.jpeg', { type: 'image/png' }),
-            url: 'https://sf6-cdn-tos.douyinstatic.com/img/ee-finolhu/c2a65140483e4a20802d64af5fec1b39~noop.image',
+            fileInstance: new File([new ArrayBuffer(2048)], 'dyBag2.jpeg', { type: 'image/png' }),
+            url: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/edit-bag.jpeg',
         },
     ];
 
@@ -585,11 +584,11 @@ import { IconUpload } from '@douyinfe/semi-icons';
     const initList = [
         {
             uid: '1',
-            name: 'vigo.png',
+            name: 'dyBag.jpeg',
             status: 'success',
             size: '130KB',
             preview: true,
-            url: 'https://sf6-cdn-tos.douyinstatic.com/img/ee-finolhu/c2a65140483e4a20802d64af5fec1b39~noop.image',
+            url: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/edit-bag.jpeg',
         },
         {
             uid: '2',
@@ -1158,7 +1157,7 @@ class ValidateDemo extends React.Component {
 ### 自定义请求
 
 当传入 customRequest 时, 相当于使用的自定义的请求方法替换了 upload 内置的 xhr 请求,用户需要自行接管上传行为。  
-可在入参中获取到当前操作的 file 对象,用户自行实现上传过程,并且在适当的时候调用 customRequest 入参中的 onProgress、onError、onSuccess 以更新 Upload 组件内部状态  
+可在入参中获取到当前操作的 file 对象,用户自行实现上传过程,并且在适当的时候调用 customRequest 入参中的 onProgress、onError、onSuccess 以更新 Upload 组件内部状态进而驱动 UI 更新  
 customRequest 包含以下入参
 
 ```ts

+ 24 - 23
content/navigation/tree/index-en-US.md

@@ -548,7 +548,7 @@ import { Tree } from '@douyinfe/semi-ui';
 
 ### Custom TreeNode Label
 
-You could pass in ReactNode for `label` in `treeNode` to customize label. Pay attention that by default `filterTreeNode` searches data by label. When label is a ReactNode, it is advised to pass in customized search function for a searchable tree.
+You could pass in ReactNode for `label` in `TreeNodeData` to customize label. Pay attention that by default `filterTreeNode` searches data by label. When label is a ReactNode, it is advised to pass in customized search function for a searchable tree.
 
 ```jsx live=true
 import React from 'react';
@@ -1390,18 +1390,19 @@ You could use `draggable` along with `onDrop` to achieve a draggable Tree.
 </Notice>
 
 The callback input parameters of the drag event are as follows:
+
 ```
-- onDragEnd: function({ event, node:treeNode })
-- onDragEnter:function({ event, node:treeNode, expandedKeys:string[] })
-- onDragLeave:function({ event, node:treeNode })
-- onDragOver:function({ event, node:treeNode })
-- onDragStart: function({ event, node })
-- onDrop:function({ event, node, dragNode:treeNode, dragNodesKeys:string[], dropPosition:number, dropToGap:Boolean })
+- onDragEnd: function({ event, node: DragTreeNode })
+- onDragEnter:function({ event, node: DragTreeNode, expandedKeys: string[] })
+- onDragLeave:function({ event, node: DragTreeNode })
+- onDragOver:function({ event, node: DragTreeNode })
+- onDragStart: function({ event, node: DragTreeNode })
+- onDrop:function({ event, node: DragTreeNode, dragNode: DragTreeNode, dragNodesKeys: string[], dropPosition: number, dropToGap: Boolean })
 ```
 
-The node, in addition to the original data originalData, also contains:
+The data type DragTreeNode, in addition to all the attributes of TreeNodeData, also includes expanded and pos attributes,
 ```
-treeNode {
+DragTreeNode {
     expanded: Boolean,
     pos: string
     value?: string | number;
@@ -2118,7 +2119,7 @@ import { IconFixedStroked, IconSectionStroked, IconAbsoluteStroked, IconInnerSec
 | className           | Class name| string                      | -       | - |
 | defaultExpandAll    | Set whether to expand all nodes during initialization. And if the subsequent data (`treeData`/`treeDataSimpleJson`) changes, this api cannot affect the default expansion of the node. If you need this, you can use `expandAll`    | boolean                     | false   | - |
 | defaultExpandedKeys | Keys of default expanded nodes. Direct child nodes will be displayed.     | string\[]                   | -       | - |
-| defaultValue        | Default value                      | string \| number \| TreeNode \| (string \| number \| TreeNode)[]            | -       | - |
+| defaultValue        | Default value                      | string \| number \| TreeNodeData \| (string \| number \| TreeNodeData)[]            | -       | - |
 | directory           | Toggle whether to display tree in directory mode | boolean                     | false   | - |
 | disableStrictly | When a node is disabled, its status could not be changed by its parent or child nodes | boolean | false | 1.4.0 | 
 | disabled | Toggle whether to disable the entire tree to be unselectable | boolean | false | 0.32.0 |
@@ -2132,14 +2133,14 @@ import { IconFixedStroked, IconSectionStroked, IconAbsoluteStroked, IconInnerSec
 | icon       | Icon | ReactNode         | -       | - |
 | labelEllipsis | Toggle whether to ellipsis label when overflow. Set to false iff there are other requirements | boolean | false\|true(virtualized) | 1.8.0 | 
 | leafOnly | Toggle whether to display tags for leaf nodes only and for onChange callback params in multiple mode | boolean | false | 1.18.0 |
-| loadData | Load data asynchronously and the return value should be a promise | (treeNode?: TreeNode) => Promise< void > |-| 1.0.0|
+| loadData | Load data asynchronously and the return value should be a promise | (treeNode?: TreeNodeData) => Promise< void > |-| 1.0.0|
 | loadedKeys | (Controlled)Mark node as loaded, working with `loadData` | string[] | - | 1.0.0|
 | motion              | Toggle whether to turn on animation| boolean                     | true    | - |
 | multiple            | Toggle whether in multi-choice mode| boolean                     | false   | - |
 | 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 |  |  |
-| renderDraggingNode | Custom render function to render html element of dragImg for dragging node | (nodeInstance: HTMLElement, node: TreeNode) => HTMLElement | - | 1.8.0 | 
+| renderDraggingNode | Custom render function to render html element of dragImg for dragging node | (nodeInstance: HTMLElement, node: TreeNodeData) => HTMLElement | - | 1.8.0 | 
 | renderFullLabel | Custom option render function | (data: object) => ReactNode | - | 1.7.0 | 
-| renderLabel | Custom label render function | (label: ReactNode, data: TreeNode) => ReactNode | - | 1.6.0 | 
+| renderLabel | Custom label render function | (label: ReactNode, data: TreeNodeData) => ReactNode | - | 1.6.0 | 
 | searchClassName     | Classname property for search box  | string                      | -       | - |
 | searchPlaceholder   | Placeholder for search box         | string                      | -       | - |
 | searchRender | Custom method to render search input; hide search box if set to false(**V>=1.0.0**) | ((searchRenderProps: object) => ReactNode) \| false | - | 0.35.0 |
@@ -2147,29 +2148,29 @@ import { IconFixedStroked, IconSectionStroked, IconAbsoluteStroked, IconInnerSec
 | showClear   | Toggle whether to support clear input box | boolean                     | true   | 0.35.0|
 | showFilteredOnly | Toggle whether to displayed filtered result only in search mode | boolean | false | 0.32.0 |
 | style               | Inline style                       | CSSProperties                      | -       | - |
-| treeData            | Data for treeNodes                 | TreeNode[]            | \[]     | - |
+| treeData            | Data for treeNodes                 | TreeNodeData[]            | \[]     | - |
 | treeDataSimpleJson  | Data for treeNodes in JSON format, return value in JSON format as well    | TreeDataSimpleJson                      | \{}     | - |
 | treeNodeFilterProp  | Property in a `treeNode` used to search   | string                      | `label` | - |
-| value               | Current value, used when tree is a controlled component                   | string \| number \| TreeNode \| (string \| number \| TreeNode)[]           | -       | - |
+| value               | Current value, used when tree is a controlled component                   | string \| number \| TreeNodeData \| (string \| number \| TreeNodeData)[]           | -       | - |
 | virtualize | Efficiently rendering large lists, refer to VirtualizeObj. Motion is disabled when tree is rendered as virtualized list. | VirtualizeObj | - | 0.32.0 |
-| onChange            | Callback function when the tree node is selected, return the value property of data                   | (string \| number \| TreeNode \| (string \| number \| TreeNode)[]) => void   | -       | - |
+| onChange            | Callback function when the tree node is selected, return the value property of data                   | (string \| number \| TreeNodeData \| (string \| number \| TreeNodeData)[]) => void   | -       | - |
 | onChangeWithObject        | Toggle whether to return all properties in an option as a return value. When set to true, return value looks like: { value, label, ...rest }. For controlled mode, you need to pass an object with { value: value } to value correspondingly. DefaultValue similarly.  | boolean                     | false   | - |
-| onDoubleClick | (e: MouseEvent, node: TreeNode) => void | - | 0.35.0 |
+| onDoubleClick | (e: MouseEvent, node: TreeNodeData) => void | - | 0.35.0 |
 | onDragEnd | Callback function for onDragEnd  | (dragProps: object) => void | - | 1.8.0 | 
 | onDragEnter | Callback function for onDragEnter  | (dragEnterProps: object) => void | - | 1.8.0 | 
 | onDragLeave | Callback function for onDragLeave  | (dragProps: object) => void | - | 1.8.0 | 
 | onDragOver | Callback function for onDragOver  | (dragProps: object) => void | - | 1.8.0 | 
 | onDragStart | Callback function for onDragStart  | (dragProps: object) => void | - | 1.8.0 | 
 | onDrop | Callback function for onDrop  | (onDragProps: object) => void | - | 1.8.0 | 
-| onExpand            | Callback function when expand or collapse a node | (expandedKeys: string[], {expanded: boolean, node: TreeNode}) => void               | -       | - |
-| onLoad | Callback function when a node is loaded | (loadedKeys: Set< string >, treeNode: TreeNode) => void | - | 1.0.0|
-| onContextMenu | Callback function when right click on an item | (e: MouseEvent, node: TreeNode) => void | - | 0.35.0 |
+| onExpand            | Callback function when expand or collapse a node | (expandedKeys: string[], {expanded: boolean, node: TreeNodeData}) => void               | -       | - |
+| onLoad | Callback function when a node is loaded | (loadedKeys: Set< string >, treeNode: TreeNodeData) => void | - | 1.0.0|
+| onContextMenu | Callback function when right click on an item | (e: MouseEvent, node: TreeNodeData) => void | - | 0.35.0 |
 | onSearch            | Callback function when the values for search input changes                | (sunInput: string) => void  | -       | - |
-| onSelect            | Callback function when selected, return the key property of data          | (selectedKey:string, selected: bool, selectedNode: TreeNode) => void | -       | - |
+| onSelect            | Callback function when selected, return the key property of data          | (selectedKey:string, selected: bool, selectedNode: TreeNodeData) => void | -       | - |
 
-### TreeNode
+### TreeNodeData
 
-> **Key for `TreeNode` is required and must be unique**, `label` can be duplicated. Before **v>=1.7.0** value is also required and must be unique.
+> **Key for `TreeNodeData` is required and must be unique**, `label` can be duplicated. Before **v>=1.7.0** value is also required and must be unique.
 > After **v>=1.7.0**, value is not required. In this case, the value property in `onChange`, `value`, `defaultValue` and `onChangeWithObject` will point to key property.
 > To ensure everything behave as expected, keep a consistency of whether to have value or not to have value.
 

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

@@ -417,7 +417,7 @@ import { Tree, Input } from '@douyinfe/semi-ui';
 ```
 
 ### 简单 JSON 格式的数据
-可以通过 `treeDataSimpleJson` 传入 JSON 形式的 `treeNodes` 数据。此时 key-value 键值对中的 key 值将作为 `treeNode` 的 `key` 和 `label`,`value` 值将作为 `treeNode` 的 `value`。返回值为包含选中节点的 JSON 数据。
+可以通过 `treeDataSimpleJson` 传入 JSON 形式的 `treeNodes` 数据。此时 key-value 键值对中的 key 值将作为 `TreeNodeData` 的 `key` 和 `label`,`value` 值将作为 `TreeNodeData` 的 `value`。返回值为包含选中节点的 JSON 数据。
 
 ```jsx live=true hideInDSM
 import React from 'react';
@@ -533,7 +533,7 @@ import { Tree } from '@douyinfe/semi-ui';
 ```
 
 ### 自定义节点内容
-`treeNode` 的 label 属性支持传入 ReactNode 来自定义显示的节点内容。注意如果设置 `filterTreeNode` 开启搜索,默认是对 label 的值进行搜索,当 label 为节点时,需要自定义 `filterTreeNode` 的函数来满足搜索需求。
+`TreeNodeData` 的 label 属性支持传入 ReactNode 来自定义显示的节点内容。注意如果设置 `filterTreeNode` 开启搜索,默认是对 label 的值进行搜索,当 label 为节点时,需要自定义 `filterTreeNode` 的函数来满足搜索需求。
 
 在**v>=1.6.0**的版本中,你也可以使用 `renderLabel` 来传入自定义的渲染方法,此时搜索值仍为treeData中的相应的label属性。
 ```jsx live=true
@@ -1420,17 +1420,17 @@ import { Tree } from '@douyinfe/semi-ui';
 
 拖拽事件的回调入参如下:
 ```
-- onDragEnd: function({ event, node: treeNode })
-- onDragEnter:function({ event, node: treeNode, expandedKeys: string[] })
-- onDragLeave:function({ event, node: treeNode })
-- onDragOver:function({ event, node :treeNode })
-- onDragStart: function({ event, node })
-- onDrop:function({ event, node, dragNode:treeNode, dragNodesKeys:string[], dropPosition:number, dropToGap:Boolean })
+- onDragEnd: function({ event, node: DragTreeNode })
+- onDragEnter:function({ event, node: DragTreeNode, expandedKeys: string[] })
+- onDragLeave:function({ event, node: DragTreeNode })
+- onDragOver:function({ event, node: DragTreeNode })
+- onDragStart: function({ event, node: DragTreeNode })
+- onDrop:function({ event, node: DragTreeNode, dragNode: DragTreeNode, dragNodesKeys: string[], dropPosition: number, dropToGap: Boolean })
 ```
 
-其中node,除了原有数据originalData外,还包含:
+数据类型 DragTreeNode,除了包含 TreeNodeData 所有属性外,还包含 expanded 和 pos 属性,
 ```
-treeNode {
+DragTreeNode {
     expanded: Boolean,
     pos: string
     value?: string | number;
@@ -2111,7 +2111,7 @@ import { IconFixedStroked, IconSectionStroked, IconAbsoluteStroked, IconInnerSec
 | className | 类名 | string | - | - |
 | defaultExpandAll | 设置在初始化时是否展开所有节点。而如果后续数据(`treeData`/`treeDataSimpleJson`)发生改变,这个 api 是无法影响节点的默认展开情况的,如果有这个需要可以使用 `expandAll` | boolean | false | - |
 | defaultExpandedKeys | 默认展开的节点,显示其直接子级 | string\[] | - | - |
-| defaultValue | 指定默认选中的条目 | string \| number \| TreeNode \| (string \| number \| TreeNode)[] | - | - |
+| defaultValue | 指定默认选中的条目 | string \| number \| TreeNodeData \| (string \| number \| TreeNodeData)[] | - | - |
 | directory | 目录树模式 | boolean | false | - |
 | disableStrictly | 当节点的disabled状态确定时,不可通过子级或者父级的关系选中 | boolean | false | 1.4.0 | 
 | disabled | 禁用整个树,不可选择 | boolean | false | 0.32.0 |
@@ -2120,19 +2120,19 @@ import { IconFixedStroked, IconSectionStroked, IconAbsoluteStroked, IconInnerSec
 | expandAction             | 展开逻辑,可选 false, 'click', 'doubleClick'。默认值为 false,即仅当点击展开按钮时才会展开  | boolean \| string   | false | 0.35.0       |
 | expandAll | 设置是否默认展开所有节点,若后续数据(`treeData`/`treeDataSimpleJson`)发生改变,默认展开情况也是会受到这个 api 影响的 | boolean | false | 1.30.0 |
 | expandedKeys | (受控)展开的节点,默认展开节点显示其直接子级 | string[] | - | - |
-| filterTreeNode | 是否根据输入项进行筛选,默认用 `treeNodeFilterProp` 的值作为要筛选的 `TreeNode` 的属性值 | boolean \| ((inputValue: string, treeNodeString: string) => boolean) | false | - |
+| filterTreeNode | 是否根据输入项进行筛选,默认用 `treeNodeFilterProp` 的值作为要筛选的 `TreeNodeData` 的属性值 | boolean \| ((inputValue: string, treeNodeString: string) => boolean) | false | - |
 | hideDraggingNode | 是否隐藏正在拖拽的节点的 dragImg | boolean | false | 1.8.0 | 
 | icon | 自定义图标 | ReactNode | - | - |
 | labelEllipsis | 是否开启label的超出省略,默认虚拟化状态开启,如果有其他省略需求可以设置关闭 | boolean | false\|true(virtualized) | 1.8.0 |
 | leafOnly | 多选模式下是否开启 onChange 回调入参及展示标签只有叶子节点 | boolean | false | 1.18.0 |  
-| loadData | 异步加载数据,需要返回一个Promise | (treeNode?: TreeNode) => Promise< void > |- |  1.0.0|
+| loadData | 异步加载数据,需要返回一个Promise | (treeNode?: TreeNodeData) => Promise< void > |- |  1.0.0|
 | loadedKeys | (受控)已经加载的节点,配合 loadData 使用 | string[] | - | 1.0.0|
 | motion | 是否开启动画 | boolean | true | - |
 | multiple | 是否支持多选 | boolean | false | - |
 | preventScroll | 指示浏览器是否应滚动文档以显示新聚焦的元素,作用于组件内的 focus 方法 | boolean |  |  |
-| renderDraggingNode | 自定义正在拖拽节点的 dragImg 的 Html 元素 | (nodeInstance: HTMLElement, node: TreeNode) => HTMLElement | - | 1.8.0 | 
+| renderDraggingNode | 自定义正在拖拽节点的 dragImg 的 Html 元素 | (nodeInstance: HTMLElement, node: TreeNodeData) => HTMLElement | - | 1.8.0 | 
 | renderFullLabel | 完全自定义label的渲染函数 | (data: object) => ReactNode | - | 1.7.0 | 
-| renderLabel | 自定义label的渲染函数 | (label: ReactNode, data: TreeNode) => ReactNode |- |  1.6.0 | 
+| renderLabel | 自定义label的渲染函数 | (label: ReactNode, data: TreeNodeData) => ReactNode |- |  1.6.0 | 
 | searchClassName | 搜索框的 `className` 属性 | string | - | - |
 | searchPlaceholder | 搜索框默认文字 | string | - | - |
 | searchRender | 自定义搜索框的渲染方法,为 false 时可以隐藏组件的搜索框(**V>=1.0.0**) | ((searchRenderProps: object) => ReactNode) \| false | - | 0.35.0 |
@@ -2140,29 +2140,29 @@ import { IconFixedStroked, IconSectionStroked, IconAbsoluteStroked, IconInnerSec
 | showClear | 支持清除搜索框 | boolean | true | 0.35.0 |
 | showFilteredOnly | 搜索状态下是否只展示过滤后的结果 | boolean | false | 0.32.0 |
 | style | 样式  | CSSProperties | - | - |
-| treeData | treeNodes 数据,如果设置则不需要手动构造 `TreeNode` 节点(key值在整个树范围内唯一) | TreeNode[] | \[] | - |
-| treeDataSimpleJson | 简单 JSON 形式的 `treeNodes` 数据,如果设置则不需要手动构造 TreeNode 节点,返回值为包含选中节点的Json数据 | TreeDataSimpleJson | \{} | - |
-| treeNodeFilterProp | 搜索时输入项过滤对应的 `treeNode` 属性 | string | `label` | - |
-| value | 当前选中的节点的value值,传入该值时将作为受控组件 | string \| number \| TreeNode \| (string \| number \| TreeNode)[] | - | - |
+| treeData | treeNodes 数据,如果设置则不需要手动构造 TreeNode 节点(key值在整个树范围内唯一) | TreeNodeData[] | \[] | - |
+| treeDataSimpleJson | 简单 JSON 形式的 `TreeNodeData` 数据,如果设置则不需要手动构造 TreeNode 节点,返回值为包含选中节点的Json数据 | TreeDataSimpleJson | \{} | - |
+| treeNodeFilterProp | 搜索时输入项过滤对应的 `TreeNodeData` 属性 | string | `label` | - |
+| value | 当前选中的节点的value值,传入该值时将作为受控组件 | string \| number \| TreeNodeData \| (string \| number \| TreeNodeData)[] | - | - |
 | virtualize | 列表虚拟化,用于大量树节点的情况,由 height, width, itemSize 组成,参考 Virtualize Object。开启后将关闭动画效果。 | VirtualizeObj | - | 0.32.0 |
-| onChange | 选中树节点时调用此函数,默认返回值为当前所有选中项的value值 | (value?: string \| number \| TreeNode \| (string \| number \| TreeNode)[]) => void | - | - |
+| onChange | 选中树节点时调用此函数,默认返回值为当前所有选中项的value值 | (value?: string \| number \| TreeNodeData \| (string \| number \| TreeNodeData)[]) => void | - | - |
 | onChangeWithObject | 是否将选中项 option 的其他属性作为回调。设为 true 时,onChange 的入参类型会从 string 变为 object: { value, label, ...rest }。此时如果是受控,也需要把 value 设置成 object,且必须含有 value 的键值;defaultValue同理。 | boolean | false | - |
-| onDoubleClick | 双击事件的回调 | (e: MouseEvent, node: TreeNode) => void | - | 0.35.0 |
+| onDoubleClick | 双击事件的回调 | (e: MouseEvent, node: TreeNodeData) => void | - | 0.35.0 |
 | onDragEnd | onDragEnd 事件回调 | (dragProps: object) => void | - | 1.8.0 | 
 | onDragEnter | onDragEnter 事件回调 | (dragEnterProps: object) => void | - | 1.8.0 | 
 | onDragLeave | onDragLeave 事件回调 | (dragProps: object) => void | - | 1.8.0 | 
 | onDragOver | onDragOver 事件回调 | (dragProps: object) => void | - | 1.8.0 | 
 | onDragStart | onDragStart 事件回调 | (dragProps: object) => void | - | 1.8.0 | 
 | onDrop | onDrop 事件回调 | (onDragProps: object) => void | - | 1.8.0 | 
-| onExpand | 展示节点时调用 | (expandedKeys: string[], {expanded: boolean, node: TreeNode}) => void | - | - |
-| onLoad | 节点加载完毕时触发的回调 | (loadedKeys: Set<string/>, treeNode: TreeNode) => void |- |  1.0.0|
-| onContextMenu | 右键点击的回调 | (e: MouseEvent, node: TreeNode) => void | - | 0.35.0 |
+| onExpand | 展示节点时调用 | (expandedKeys: string[], {expanded: boolean, node: TreeNodeData}) => void | - | - |
+| onLoad | 节点加载完毕时触发的回调 | (loadedKeys: Set<string/>, treeNode: TreeNodeData) => void |- |  1.0.0|
+| onContextMenu | 右键点击的回调 | (e: MouseEvent, node: TreeNodeData) => void | - | 0.35.0 |
 | onSearch | 文本框值变化时回调 | (sunInput: string) => void | - | - |
-| onSelect | 被选中时调用,返回值为当前事件选项的key值 | (selectedKey:string, selected: bool, selectedNode: TreeNode) => void | - | - |
+| onSelect | 被选中时调用,返回值为当前事件选项的key值 | (selectedKey:string, selected: bool, selectedNode: TreeNodeData) => void | - | - |
 
-### TreeNode
+### TreeNodeData
 
-> __不同 `TreeNode` 的 key 值要求必填且唯一。__`label` 允许重复。**v>=1.7.0** 之前 value 值要求必须必填且唯一。
+> __不同 `TreeNodeData` 的 key 值要求必填且唯一。__`label` 允许重复。**v>=1.7.0** 之前 value 值要求必须必填且唯一。
 > **v>=1.7.0** 之后 value 值非必填。此时 onChange, value, defaultValue 及 onChangeWithObject 中所取的 value 属性值将改为 key 值。
 > 为了保证行为的符合预期,treeData 中的 value 值或者全部不填写,或者全部填写且唯一,不建议混写。
 

+ 7 - 0
content/start/changelog/index-en-US.md

@@ -16,6 +16,13 @@ Version:Major.Minor.Patch (follow the **Semver** specification)
 
 ---
 
+#### 🎉 2.27.1 (2023-01-12)
+- 【Fix】
+    - Fix Form Field level validation. When using props.rules, there is a race condition asynchronous, and the validation performed later will be overwritten by the validation performed before  [#1375](https://github.com/DouyinFE/semi-design/issues/1375) [@SyMind](https://github.com/SyMind)
+    - Fix Form Field level validation. When using props.validate, there is a race condition asynchronous, and the validation performed later will be overwritten by the validation performed before,  [#1375 ](https://github.com/DouyinFE/semi-design/issues/1375)
+- 【Docs】
+    - Modify the treeData API type name in the Cascader / TreeSelect / Tree documentation to make it consistent with the code
+
 #### 🎉 2.27.0 (2023-01-06)
 - 【Fix】
     - Fix the problem that after Select is configured with outerBottomSlot, outTopSlot, innerBottomSlot, and innerTopSlot, when hovering to the slot, the Option still maintains the focus style, which easily confuses users [#1370](https://github.com/DouyinFE/semi-design/pull/1370)

+ 7 - 0
content/start/changelog/index.md

@@ -16,6 +16,13 @@ Semi 版本号遵循 **Semver** 规范(主版本号-次版本号-修订版本
 
 ---
 
+#### 🎉 2.27.1 (2023-01-12)
+- 【Fix】
+    - 修复Form Field 级别校验,使用 props.rules 时存在竞态异步,后执行的校验会被前执行的校验覆盖的问题,  [#1375](https://github.com/DouyinFE/semi-design/issues/1375) [@SyMind](https://github.com/SyMind)
+    - 修复Form Field 级别校验,使用 props.validate 时存在竞态异步,后执行的校验会被前执行的校验覆盖的问题,  [#1375 ](https://github.com/DouyinFE/semi-design/issues/1375)
+- 【Docs】
+    - 修改 Cascader / TreeSelect / Tree 文档中 treeData API 类型名, 使其和代码一致
+
 #### 🎉 2.27.0 (2023-01-06)
 - 【Fix】
     - 修复 Select 在配置了 outerBottomSlot、outTopSlot、innerBottomSlot、innerTopSlot 后,hover到 Slot 中,Option 仍保持 focus 样式,易使用户产生疑惑的问题 [#1370](https://github.com/DouyinFE/semi-design/pull/1370)

+ 1 - 1
lerna.json

@@ -1,5 +1,5 @@
 {
     "useWorkspaces": true,
     "npmClient": "yarn",
-    "version": "2.27.0-beta.0"
+    "version": "2.27.1"
 }

+ 1 - 1
packages/semi-animation-react/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@douyinfe/semi-animation-react",
-  "version": "2.27.0-beta.0",
+  "version": "2.27.1",
   "description": "motion library for semi-ui-react",
   "keywords": [
     "motion",

+ 1 - 1
packages/semi-animation-styled/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@douyinfe/semi-animation-styled",
-  "version": "2.27.0-beta.0",
+  "version": "2.27.1",
   "description": "semi styled animation",
   "keywords": [
     "semi",

+ 1 - 1
packages/semi-animation/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@douyinfe/semi-animation",
-  "version": "2.27.0-beta.0",
+  "version": "2.27.1",
   "description": "animation base library for semi-ui",
   "keywords": [
     "animation",

+ 1 - 1
packages/semi-eslint-plugin/package.json

@@ -1,6 +1,6 @@
 {
   "name": "eslint-plugin-semi-design",
-  "version": "2.27.0-beta.0",
+  "version": "2.27.1",
   "description": "semi ui eslint plugin",
   "keywords": [
     "semi",

+ 4 - 0
packages/semi-foundation/dropdown/dropdown.scss

@@ -47,6 +47,10 @@ $module: #{$prefix}-dropdown;
         transition: background-color $transition_duration-dropdown_item-bg $transition_function-dropdown_item-bg
             $transition_delay-dropdown_item-bg;
 
+        &-hover {
+            background-color: $color-dropdown_item-bg-hover;
+        }
+
         &:not(.#{$module}-item-active):hover {
             background-color: $color-dropdown_item-bg-hover;
             cursor: pointer;

+ 1 - 1
packages/semi-foundation/package.json

@@ -1,6 +1,6 @@
 {
     "name": "@douyinfe/semi-foundation",
-    "version": "2.27.0-beta.0",
+    "version": "2.27.1",
     "description": "",
     "scripts": {
         "build:lib": "node ./scripts/compileLib.js",

+ 1 - 1
packages/semi-icons/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@douyinfe/semi-icons",
-  "version": "2.27.0-beta.0",
+  "version": "2.27.1",
   "description": "semi icons",
   "keywords": [
     "semi",

+ 1 - 1
packages/semi-illustrations/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@douyinfe/semi-illustrations",
-  "version": "2.27.0-beta.0",
+  "version": "2.27.1",
   "description": "semi illustrations",
   "keywords": [
     "semi",

+ 1 - 1
packages/semi-next/package.json

@@ -1,6 +1,6 @@
 {
     "name": "@douyinfe/semi-next",
-    "version": "2.27.0-beta.0",
+    "version": "2.27.1",
     "description": "Plugin that support Semi Design in Next.js",
     "author": "伍浩威 <[email protected]>",
     "homepage": "",

+ 1 - 1
packages/semi-scss-compile/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@douyinfe/semi-scss-compile",
-  "version": "2.27.0-beta.0",
+  "version": "2.27.1",
   "description": "compile semi scss to css",
   "author": "[email protected]",
   "license": "MIT",

+ 1 - 1
packages/semi-theme-default/package.json

@@ -1,6 +1,6 @@
 {
     "name": "@douyinfe/semi-theme-default",
-    "version": "2.27.0-beta.0",
+    "version": "2.27.1",
     "description": "semi-theme-default",
     "keywords": [
         "semi-theme",

+ 16 - 0
packages/semi-ui/dropdown/_story/C2D/index.tsx

@@ -0,0 +1,16 @@
+import React from "react";
+import Dropdown from '../../index';
+import Space from '../../../space';
+import { IconBox } from "@douyinfe/semi-icons";
+
+export function DropdownItem() {
+    return (
+        <Space vertical>
+            <Dropdown.Item>Douyin</Dropdown.Item>
+            <Dropdown.Item disabled>Douyin</Dropdown.Item>
+            <Dropdown.Item hover>Douyin</Dropdown.Item>
+            <Dropdown.Item showTick active>Douyin</Dropdown.Item>
+            <Dropdown.Item icon={<IconBox />}>Douyin</Dropdown.Item>
+        </Space>
+    );
+}

+ 2 - 0
packages/semi-ui/dropdown/_story/dropdown.stories.jsx

@@ -10,6 +10,8 @@ import InHoverElements from './InHoverElements';
 import WrapAvatar from './WrapAvatar';
 import { IconChevronDown, IconBox, IconSimilarity } from '@douyinfe/semi-icons';
 
+export * from '../_story/C2D';
+
 export default {
   title: 'Dropdown',
   parameters: {

+ 11 - 3
packages/semi-ui/dropdown/dropdownItem.tsx

@@ -24,6 +24,9 @@ export interface DropdownItemProps extends BaseProps {
     active?: boolean;
     icon?: React.ReactNode;
     onKeyDown?: (e: React.KeyboardEvent) => void;
+    showTick?: boolean;
+    /** internal prop, please do not use  */
+    hover?: boolean
 }
 
 const prefixCls = css.PREFIX;
@@ -48,6 +51,8 @@ class DropdownItem extends BaseComponent<DropdownItemProps> {
     };
 
     static contextType = DropdownContext;
+    static elementType: string;
+
     context: DropdownContextType;
 
     static defaultProps = {
@@ -61,12 +66,13 @@ class DropdownItem extends BaseComponent<DropdownItemProps> {
 
 
     render() {
-        const { children, disabled, className, forwardRef, style, type, active, icon, onKeyDown } = this.props;
-        const { showTick } = this.context;
+        const { children, disabled, className, forwardRef, style, type, active, icon, onKeyDown, showTick, hover } = this.props;
+        const { showTick: contextShowTick } = this.context;
         const itemclass = cls(className, {
             [`${prefixCls}-item`]: true,
             [`${prefixCls}-item-disabled`]: disabled,
-            [`${prefixCls}-item-withTick`]: showTick,
+            [`${prefixCls}-item-hover`]: hover,
+            [`${prefixCls}-item-withTick`]: contextShowTick ?? showTick,
             [`${prefixCls}-item-${type}`]: type,
             [`${prefixCls}-item-active`]: active,
         });
@@ -107,4 +113,6 @@ class DropdownItem extends BaseComponent<DropdownItemProps> {
     }
 }
 
+DropdownItem.elementType = 'Dropdown.Item';
+
 export default DropdownItem;

+ 45 - 0
packages/semi-ui/form/__test__/field.test.js

@@ -2,6 +2,9 @@ import { Form, Select } from '../../index';
 import { noop } from 'lodash';
 import { func } from 'prop-types';
 import { BASE_CLASS_PREFIX } from '../../../semi-foundation/base/constants';
+import { sleep as baseSleep } from '../../_test_/utils/index';
+
+const sleep = (ms = 200) => baseSleep(ms);
 
 function getForm(props) {
     return mount(<Form {...props}></Form>);
@@ -414,6 +417,48 @@ describe('Form-field', () => {
         expect(fieldsDOM.at(5).instance().value).toEqual('f');
     });
 
+    it('validate race condition', async () => {
+        let formApi = null;
+        let asyncValidatorCallback = null;
+
+        const fieldProps = {
+            field: 'text',
+            rules: [
+                { type: 'string', max: 10 },
+                {
+                    asyncValidator(rule, value, callback) {
+                        if (!asyncValidatorCallback) {
+                            asyncValidatorCallback = callback;
+                        } else {
+                            callback();
+                        }
+                    }
+                }
+            ]
+        }
+        const props = {
+            getFormApi(api) {
+                formApi = api;
+            },
+            children: getInput(fieldProps),
+        };
+        const form = getForm(props);
+
+        const event1 = { target: { value: 'semi' } };
+        form.find(`.${BASE_CLASS_PREFIX}-input`).simulate('change', event1);
+        await sleep(200);
+        form.update();
+        expect(formApi.getError('text')).toBeUndefined();
+
+        const event2 = { target: { value: 'Prefer knowledge to wealth, for the one is transitory, the other perpetual.' } };
+        form.find(`.${BASE_CLASS_PREFIX}-input`).simulate('change', event2);
+        await sleep(200);
+        asyncValidatorCallback();
+        await sleep(200);
+        form.update();
+        expect(formApi.getError('text')).not.toBeUndefined();
+    });
+
     // TODO
     // it('allowEmptyString', () => {});
     // it('extraText')

+ 71 - 1
packages/semi-ui/form/_story/Validate/validateDemo.jsx

@@ -418,4 +418,74 @@ class RulesExample extends React.Component {
         );
     }
 }
-export { ValidateFieldsDemo, CustomValidateDemo, PartValidAndResetDemo, RulesValidateDemo, SetBugDemo, UnmountedLeafDemo, RulesExample };
+
+
+
+class RaceAsyncDemo extends React.Component {
+    constructor() {
+        super();
+        this.asyncValidate = this.asyncValidate.bind(this);
+    }
+
+    asyncValidate(val, values) {
+        const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
+        let time = 1000; 
+        if (val === 'semi') {
+            time = 4000;
+        } 
+        return sleep(time).then(() => {
+            if (!val) {
+                return 'can\'t be empty';
+            } else if (val === 'semi') {
+                return 'sleep 4000';
+            } else if (val === 'sem') {
+                return 'sleep 1000';
+            } else {
+                return '';
+            }
+        });
+    }
+
+    render() {
+        return (
+            <Form>
+                <Form.Input
+                    field='name'
+                    label='props.rules ract async validate'
+                    // validate={this.asyncValidate}
+                    trigger='blur'
+                    rules={[
+                        {
+                            type: 'string',
+                            asyncValidator: (rule, value) => {
+                                const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
+                                let time = 1000; 
+                                if (value === 'semi') {
+                                    time = 4000;
+                                }
+                                return sleep(time).then(() => {
+                                    if (value === 'semi') {
+                                        throw Error('sleep 4000');
+                                    } else if (value === 'sem') {
+                                        throw Error('sleep 1000');
+                                    } else {
+                                        return;
+                                    }
+                                });
+                            }
+                        }
+                    ]}
+                />
+                <Form.Input
+                    field='nick'
+                    label='props.validate ract async validate'
+                    validate={this.asyncValidate}
+                    trigger='blur'
+                />
+                <Button htmlType="reset">reset</Button>
+            </Form>
+        );
+    }
+}
+
+export { ValidateFieldsDemo, CustomValidateDemo, PartValidAndResetDemo, RulesValidateDemo, SetBugDemo, UnmountedLeafDemo, RulesExample, RaceAsyncDemo };

+ 6 - 0
packages/semi-ui/form/_story/form.stories.jsx

@@ -62,6 +62,7 @@ import {
   SetBugDemo,
   UnmountedLeafDemo,
   RulesExample,
+  RaceAsyncDemo,
 } from './Validate/validateDemo';
 
 // field props
@@ -248,6 +249,11 @@ ValidateUseRules.story = {
   name: 'Validate-use rules',
 };
 
+RaceAsyncDemo.story = {
+  name: 'Validate - race async'
+}
+export const RaceAsync = () => <RaceAsyncDemo />;
+
 export const HooksUseFormApi = () => <UseFormApiDemo />;
 
 HooksUseFormApi.story = {

+ 25 - 3
packages/semi-ui/form/hoc/withField.tsx

@@ -128,6 +128,7 @@ function withField<
 
         const rulesRef = useRef(rules);
         const validateRef = useRef(validate);
+        const validatePromise = useRef<Promise<any> | null>(null);
 
         // notNotify is true means that the onChange of the Form does not need to be triggered
         // notUpdate is true means that this operation does not need to trigger the forceUpdate
@@ -182,7 +183,7 @@ function withField<
                 [field]: val,
             };
 
-            return new Promise((resolve, reject) => {
+            const rootPromise = new Promise((resolve, reject) => {
                 validator
                     .validate(
                         model,
@@ -193,12 +194,18 @@ function withField<
                         (errors, fields) => {}
                     )
                     .then(res => {
+                        if (validatePromise.current !== rootPromise) {
+                            return;
+                        }
                         // validation passed
                         setStatus('success');
                         updateError(undefined, callOpts);
                         resolve({});
                     })
                     .catch(err => {
+                        if (validatePromise.current !== rootPromise) {
+                            return;
+                        }
                         let { errors, fields } = err;
                         if (errors && fields) {
                             let messages = errors.map((e: any) => e.message);
@@ -220,11 +227,16 @@ function withField<
                         }
                     });
             });
+
+            validatePromise.current = rootPromise;
+
+            return rootPromise;
         };
 
         // execute custom validate function
-        const _validate = (val: any, values: any, callOpts: CallOpts) =>
-            new Promise(resolve => {
+        const _validate = (val: any, values: any, callOpts: CallOpts) => {
+
+            const rootPromise = new Promise(resolve => {
                 let maybePromisedErrors;
                 // let errorThrowSync;
                 try {
@@ -238,6 +250,11 @@ function withField<
                     updateError(undefined, callOpts);
                 } else if (isPromise(maybePromisedErrors)) {
                     maybePromisedErrors.then((result: any) => {
+                        // If the async validate is outdated (a newer validate occurs), the result should be discarded
+                        if (validatePromise.current !== rootPromise) {
+                            return;
+                        }
+
                         if (isValid(result)) {
                             // validate success,no need to do anything with result
                             updateError(undefined, callOpts);
@@ -258,6 +275,11 @@ function withField<
                     }
                 }
             });
+            
+            validatePromise.current = rootPromise;
+
+            return rootPromise;
+        };
 
         const fieldValidate = (val: any, callOpts?: CallOpts) => {
             let finalVal = val;

+ 7 - 7
packages/semi-ui/package.json

@@ -1,6 +1,6 @@
 {
     "name": "@douyinfe/semi-ui",
-    "version": "2.27.0-beta.0",
+    "version": "2.27.1",
     "description": "",
     "main": "lib/cjs/index.js",
     "module": "lib/es/index.js",
@@ -17,12 +17,12 @@
         "lib/*"
     ],
     "dependencies": {
-        "@douyinfe/semi-animation": "2.27.0-beta.0",
-        "@douyinfe/semi-animation-react": "2.27.0-beta.0",
-        "@douyinfe/semi-foundation": "2.27.0-beta.0",
-        "@douyinfe/semi-icons": "2.27.0-beta.0",
-        "@douyinfe/semi-illustrations": "2.27.0-beta.0",
-        "@douyinfe/semi-theme-default": "2.27.0-beta.0",
+        "@douyinfe/semi-animation": "2.27.1",
+        "@douyinfe/semi-animation-react": "2.27.1",
+        "@douyinfe/semi-foundation": "2.27.1",
+        "@douyinfe/semi-icons": "2.27.1",
+        "@douyinfe/semi-illustrations": "2.27.1",
+        "@douyinfe/semi-theme-default": "2.27.1",
         "async-validator": "^3.5.0",
         "classnames": "^2.2.6",
         "copy-text-to-clipboard": "^2.1.1",

+ 1 - 1
packages/semi-webpack/package.json

@@ -1,6 +1,6 @@
 {
     "name": "@douyinfe/semi-webpack-plugin",
-    "version": "2.27.0-beta.0",
+    "version": "2.27.1",
     "description": "",
     "author": "伍浩威 <[email protected]>",
     "homepage": "",

+ 1 - 1
src/sitePages/newHome/components/operateButton/operateButton.jsx

@@ -15,7 +15,7 @@ function OperateButton() {
     };
     return (<div className={styles.group2835}>
         <a href={`/${getLocale()}/start/getting-started`}>
-            <Button tabindex={-1} onClick={goStart} size="large" theme="solid" className={styles.extraLarge}>{_t("start_using", { }, "开始使用")}</Button>
+            <Button tabIndex={-1} onClick={goStart} size="large" theme="solid" className={styles.extraLarge}>{_t("start_using", { }, "开始使用")}</Button>
         </a>
         <Button
             onClick={goGithub} 

+ 2 - 2
src/templates/postTemplate.js

@@ -4,7 +4,7 @@ import { graphql, Link } from 'gatsby';
 import Blocks from '@douyinfe/semi-site-markdown-blocks';
 import '@douyinfe/semi-site-markdown-blocks/dist/index.css';
 import SearchAllInOne from '../components/SearchAllInOne';
-import { Icon, Row, Col, Tag, Tooltip, Popover, Checkbox, Button, Radio, Skeleton, Toast, Table, CheckboxGroup, Description, Dropdown, Form, Typography, Empty } from '@douyinfe/semi-ui';
+import { Icon, Row, Col, Tag, Tooltip, Popover, Checkbox, Button, Radio, Skeleton, Toast, Table, CheckboxGroup, Descriptions, Dropdown, Form, Typography, Empty } from '@douyinfe/semi-ui';
 import { IllustrationNoAccess, IllustrationNoAccessDark } from '@douyinfe/semi-illustrations';
 import NotificationCard from '../../packages/semi-ui/notification/notice';
 import ToastCard from '../../packages/semi-ui/toast/toast';
@@ -99,7 +99,7 @@ const SemiComponents = {
     ImageBox,
     // content guideline demo 
     CheckboxGroup: CheckboxGroup,
-    Description: Description,
+    Descriptions: Descriptions,
     NotificationCard,
     ToastCard,
     Dropdown,

+ 1 - 84
yarn.lock

@@ -1456,15 +1456,6 @@
   resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70"
   integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==
 
-"@douyinfe/[email protected]":
-  version "2.26.0"
-  resolved "https://registry.yarnpkg.com/@douyinfe/semi-animation-react/-/semi-animation-react-2.26.0.tgz#3c932a5e568a777d8a04fbebf0073901ddc21fd9"
-  integrity sha512-MU9HMHll0ek6drr+4M6bU5nBLIRcZ3PEpvPnTcycgCQBa8FB/uIKEdxlfsWml9VzT54TUOhTi1HIJ3o++o8eyQ==
-  dependencies:
-    "@douyinfe/semi-animation" "2.12.0"
-    "@douyinfe/semi-animation-styled" "2.23.2"
-    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"
@@ -1495,13 +1486,6 @@
     "@babel/runtime-corejs3" "^7.15.4"
     bezier-easing "^2.1.0"
 
-"@douyinfe/[email protected]":
-  version "2.26.0"
-  resolved "https://registry.yarnpkg.com/@douyinfe/semi-animation/-/semi-animation-2.26.0.tgz#3a05b231ff656f9e52c03f1e1681a7b7d1d430be"
-  integrity sha512-FfW54CArI4OOS20g6t9610d5p73CuVVM3U3CupF/MARPEgTe6fDS49uU2iBR2LHtbEKBbHp/RP8sdWE+d7/q2Q==
-  dependencies:
-    bezier-easing "^2.1.0"
-
 "@douyinfe/[email protected]":
   version "2.9.1"
   resolved "https://registry.yarnpkg.com/@douyinfe/semi-animation/-/semi-animation-2.9.1.tgz#4345fd86823b51e7c6fb5e9079d8f5c3ffe608f8"
@@ -1510,20 +1494,6 @@
     "@babel/runtime-corejs3" "^7.15.4"
     bezier-easing "^2.1.0"
 
-"@douyinfe/[email protected]":
-  version "2.26.0"
-  resolved "https://registry.yarnpkg.com/@douyinfe/semi-foundation/-/semi-foundation-2.26.0.tgz#8446c893d85d3081e578cd83e826fe24d09335af"
-  integrity sha512-MOOnJ8n8uvb+Aitx4RQGK/YJ4U8F1lT9jyk181BaUI9Qzq5av3ldiZxsb6RUN45JEYqju6fTlyn29sE4Pi4QjA==
-  dependencies:
-    "@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"
@@ -1539,13 +1509,6 @@
     memoize-one "^5.2.1"
     scroll-into-view-if-needed "^2.2.24"
 
-"@douyinfe/[email protected]", "@douyinfe/semi-icons@^2.0.0":
-  version "2.26.0"
-  resolved "https://registry.yarnpkg.com/@douyinfe/semi-icons/-/semi-icons-2.26.0.tgz#603438476dc7933e0a158778aa71576d14bc292a"
-  integrity sha512-aA3P5iuEj5ILPAXas41DWjTQgqpQ5g2NRzVXPY4NtbWEU2vG492bUSq+fcsyOKlBgEJKAwclFHberoGabrnLKg==
-  dependencies:
-    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"
@@ -1554,11 +1517,6 @@
     "@babel/runtime-corejs3" "^7.15.4"
     classnames "^2.2.6"
 
-"@douyinfe/[email protected]":
-  version "2.26.0"
-  resolved "https://registry.yarnpkg.com/@douyinfe/semi-illustrations/-/semi-illustrations-2.26.0.tgz#d3488f5f8f9308bc233c0486284962c5d2cb2b54"
-  integrity sha512-iRMQSVNuFhRLSq7qbiydq9epr2U4h4ZWpvUf9Veu1cWoMCsN4JoFC3D471HjtTg99F/ocmLne9FHnTf+VrQutA==
-
 "@douyinfe/[email protected]":
   version "2.9.1"
   resolved "https://registry.yarnpkg.com/@douyinfe/semi-illustrations/-/semi-illustrations-2.9.1.tgz#1a448d1854ee1beeba57ea612da052b549ea105f"
@@ -1632,13 +1590,6 @@
     monaco-themes "^0.3.3"
     react-live "^2.2.2"
 
-"@douyinfe/[email protected]":
-  version "2.26.0"
-  resolved "https://registry.yarnpkg.com/@douyinfe/semi-theme-default/-/semi-theme-default-2.26.0.tgz#24f195c8e25a69898a771be2dc6dcd8c3d7025fd"
-  integrity sha512-UvfdFH7SjVsNa87lkT19rvWL8fR69a3b8I3hCck1nvl4q3DTGm6czJIzm7q5QgBtLGmNFFf9q7VFRTIDOZfe8w==
-  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"
@@ -1646,31 +1597,6 @@
   dependencies:
     glob "^7.1.6"
 
-"@douyinfe/semi-ui@^2.0.0":
-  version "2.26.0"
-  resolved "https://registry.yarnpkg.com/@douyinfe/semi-ui/-/semi-ui-2.26.0.tgz#b49993977860ad13c6a7cc6ec3c1580201848ec9"
-  integrity sha512-AI1sFinCLzZRly4MtBTMj7f3fNHffcRZBLU5Zeim2LnVuN+5IlaBrwRdtdOTq+kUSpNS7Lu+RAeUzyowsCkAVg==
-  dependencies:
-    "@douyinfe/semi-animation" "2.26.0"
-    "@douyinfe/semi-animation-react" "2.26.0"
-    "@douyinfe/semi-foundation" "2.26.0"
-    "@douyinfe/semi-icons" "2.26.0"
-    "@douyinfe/semi-illustrations" "2.26.0"
-    "@douyinfe/semi-theme-default" "2.26.0"
-    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"
@@ -20206,15 +20132,6 @@ prop-types-exact@^1.2.0:
     object.assign "^4.1.0"
     reflect.ownkeys "^0.2.0"
 
[email protected]:
-  version "15.7.2"
-  resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5"
-  integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==
-  dependencies:
-    loose-envify "^1.4.0"
-    object-assign "^4.1.1"
-    react-is "^16.8.1"
-
 [email protected], prop-types@^15.0.0, prop-types@^15.5.0, prop-types@^15.5.10, prop-types@^15.5.4, prop-types@^15.5.7, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1:
   version "15.8.1"
   resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5"
@@ -20759,7 +20676,7 @@ react-intl@^3.12.1:
     intl-messageformat-parser "^3.6.4"
     shallow-equal "^1.2.1"
 
-react-is@^16.12.0, react-is@^16.13.1, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.4, react-is@^16.8.6:
+react-is@^16.12.0, react-is@^16.13.1, react-is@^16.7.0, react-is@^16.8.4, react-is@^16.8.6:
   version "16.13.1"
   resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
   integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==