Browse Source

Merge branch 'release'

DaiQiangReal 11 months ago
parent
commit
4bd4f7199a
48 changed files with 1472 additions and 1255 deletions
  1. 80 22
      content/basic/resizable/index-en-US.md
  2. 124 64
      content/basic/resizable/index.md
  3. 265 255
      content/input/form/index.md
  4. 40 21
      content/navigation/navigation/index-en-US.md
  5. 49 42
      content/navigation/navigation/index.md
  6. 3 3
      content/plus/chat/index-en-US.md
  7. 3 3
      content/plus/chat/index.md
  8. 1 0
      content/plus/markdownrender/index-en-US.md
  9. 10 9
      content/plus/markdownrender/index.md
  10. 77 189
      content/show/dropdown/index-en-US.md
  11. 146 244
      content/show/dropdown/index.md
  12. 8 0
      content/start/changelog/index-en-US.md
  13. 9 0
      content/start/changelog/index.md
  14. 1 1
      lerna.json
  15. 3 3
      packages/semi-animation-react/package.json
  16. 1 1
      packages/semi-animation-styled/package.json
  17. 1 1
      packages/semi-animation/package.json
  18. 1 1
      packages/semi-eslint-plugin/package.json
  19. 13 7
      packages/semi-foundation/markdownRender/foundation.ts
  20. 2 2
      packages/semi-foundation/package.json
  21. 5 16
      packages/semi-foundation/resizable/foundation.ts
  22. 92 29
      packages/semi-foundation/resizable/group/index.ts
  23. 0 25
      packages/semi-foundation/resizable/groupConstants.ts
  24. 100 3
      packages/semi-foundation/resizable/resizable.scss
  25. 1 1
      packages/semi-foundation/resizable/single/index.ts
  26. 0 65
      packages/semi-foundation/resizable/types.ts
  27. 7 6
      packages/semi-foundation/resizable/utils.ts
  28. 8 0
      packages/semi-foundation/resizable/variables.scss
  29. 1 1
      packages/semi-icons-lab/package.json
  30. 1 1
      packages/semi-icons/package.json
  31. 1 1
      packages/semi-illustrations/package.json
  32. 2 2
      packages/semi-next/package.json
  33. 1 1
      packages/semi-rspack/package.json
  34. 1 1
      packages/semi-scss-compile/package.json
  35. 1 1
      packages/semi-theme-default/package.json
  36. 2 1
      packages/semi-theme-default/scss/variables.scss
  37. 2 0
      packages/semi-ui/_utils/semi-global.ts
  38. 4 2
      packages/semi-ui/markdownRender/index.tsx
  39. 7 7
      packages/semi-ui/package.json
  40. 163 5
      packages/semi-ui/resizable/_story/resizable.stories.jsx
  41. 1 1
      packages/semi-ui/resizable/group/resizeContext.ts
  42. 51 40
      packages/semi-ui/resizable/group/resizeGroup.tsx
  43. 8 9
      packages/semi-ui/resizable/group/resizeHandler.tsx
  44. 22 4
      packages/semi-ui/resizable/group/resizeItem.tsx
  45. 2 12
      packages/semi-ui/resizable/single/resizable.tsx
  46. 2 3
      packages/semi-ui/resizable/single/resizableHandler.tsx
  47. 1 1
      packages/semi-webpack/package.json
  48. 149 149
      sitemap.xml

+ 80 - 22
content/basic/resizable/index-en-US.md

@@ -225,6 +225,7 @@ function Demo() {
 ```
 
 ### Control Width/Height
+
 You can control the size of the element through the size prop.
 
 ```jsx live=true
@@ -232,22 +233,20 @@ import React, { useState } from 'react';
 import { Resizable } from '@douyinfe/semi-ui';
 
 function Demo() {
-  const [size, setSize] = useState({ width: 200, height: 300 });
-
-  const onChange = (() => {
+  const [size, setSize] = useState({ width: 200, height: 100 });
+  const onButtonClick = (() => {
     let realSize = { width: size.width + 10, height: size.height + 10 };
     setSize(realSize);
   })
+  const onChange = (s) => { setSize(s); }
+
   return (
     <div style={{ width: '500px', height: '60%' }}>
-      <Button onClick={onChange}>set += 10</Button>
+      <Button onClick={onButtonClick}>set += 10</Button>
       <Resizable
         style={{ backgroundColor: 'rgba(var(--semi-grey-1), 1)', marginTop: '10px' }}
-        defaultSize={{
-          width: 100,
-          height: 100,
-        }}
         size={size}
+        onChange={onChange}
       >
         <div style={{ marginLeft: '20%' }}>
           Control Width/Height
@@ -256,7 +255,6 @@ function Demo() {
     </div>
   );
 }
-
 ```
 
 
@@ -675,16 +673,76 @@ function Demo() {
 }
 ```
 
+### Dynamic Direction
+```jsx live=true 
+import React, { useState } from 'react';
+import { ResizeItem, ResizeHandler, ResizeGroup } from '@douyinfe/semi-ui';
+
+function Demo() {
+  const [text, setText] = useState('drag to resize')
+  const [direction, setDirection] = useState('horizontal')
+
+  const changeDirection = () => {
+    if (direction === 'horizontal') {
+      setDirection('vertical')
+    } else {
+      setDirection('horizontal')
+    }
+  }
+  return (
+    <div style={{ width: '400px', height: '300px' }}>
+      <Button onClick={changeDirection}>{direction}</Button>
+      <ResizeGroup direction={direction} >
+        <ResizeItem
+          onChange={() => { setText('resizing') }}
+          onResizeEnd={() => { setText('drag to resize') }}
+          defaultSize={5}
+        >
+            <ResizeGroup direction='horizontal'>
+              <ResizeItem
+                style={{ backgroundColor: 'rgba(var(--semi-grey-1), 1)', }}
+                onChange={() => { setText('resizing') }}
+                onResizeEnd={() => { setText('drag to resize') }}
+              >
+                <div style={{ marginLeft: '20%',  padding:'5px' }}>
+                  {text}
+                </div>
+              </ResizeItem>
+              <ResizeHandler></ResizeHandler>
+              <ResizeItem
+                style={{ backgroundColor: 'rgba(var(--semi-grey-1), 1)', }}
+                onChange={() => { setText('resizing') }}
+              >
+                <div style={{ marginLeft: '20%',  padding:'5px' }}>
+                  {text}
+                </div>
+              </ResizeItem>
+            </ResizeGroup>
+        </ResizeItem>
+        <ResizeHandler></ResizeHandler>
+        <ResizeItem
+          style={{ backgroundColor: 'rgba(var(--semi-grey-1), 1)',  }}
+          defaultSize={1.3}
+          onChange={() => { setText('resizing') }}
+        >
+          <div style={{ marginLeft: '20%',  padding:'5px' }}>
+            {text}
+          </div>
+        </ResizeItem>
+      </ResizeGroup>
+    </div>
+  );
+}
+```
+
 
 ## API
 
 ### Resizable
 
-单个伸缩框组件。
-
 | 参数      | 说明                                                                          | 类型                    | 默认值     | 版本   |
 | --------- | ----------------------------------------------------------------------------- | ----------------------- | ---------- | ------ |
-| className | 类名                                                                          | string                  |            |        |
+| className | ClassName                                                                          | string                  |            |        |
 | size   | Controls the size of the resizable box, supports both numeric and string (px/vw/vh/%) formats | [Size](#basic-usage-and-callbacks)                  |           |        |
 | defaultSize   | Sets the initial width and height, supports both numeric and string (px/vw/vh/%) formats | [Size](#basic-usage-and-callbacks)                  |           |        |
 | minWidth | Specifies the minimum width of the resizable box      |  string \| number                  |   |        |
@@ -698,40 +756,40 @@ function Demo() {
 | handleNode     | Custom nodes for the drag handles in each direction             | [HandleNode](#customizing-corner-handler-styles)          |            |        |
 | handleStyle    | Styles for the drag handles in each direction             | [HandleNode](#customizing-corner-handler-styles)            |            |        |
 | handleClass   | Class names for the drag handles in each direction              | [HandleNode](#customizing-corner-handler-styles)            |            |        |
-| style |  | CSSProperties |      |
+| style | Style | CSSProperties |      |
 | snapGap      | Specifies the minimum gap required to snap to the next target                        | number                  | 0       |  |
 | snap      | Specifies the pixel values to snap to during resizing. Both x and y are optional, allowing the definition of specific axes only                        | [Snap](#allowing-incremental-width-and-height-adjustment)                  | null       |  |
 | grid      | Specifies the increment to align to when resizing                          | \[number, number\]                  | \[1,1\]       |  |
-| onChange  | Callback during the dragging process                                                    | (e: Event; direction: String;size: Size) => void | -          |  |
+| onChange  | Callback during the dragging process                                                    | (size: Size; e: Event; direction: String) => void | -          |  |
 | onResizeStart  | Callback when resizing starts                                                  | (e: Event; direction: String) => void | -          |  |
-| onResizeEnd  | Callback when resizing ends                                                   | (e: Event; direction: String) => void | -          |  |
+| onResizeEnd  | Callback when resizing ends                                                   | (size: Size; e: Event; direction: String) => void | -          |  |
 
 ### ResizeGroup
 
 | 参数        | 说明                                                                                                                        | 类型                               | 默认值 | 版本 |
 | ----------- | --------------------------------------------------------------------------------------------------------------------------- | ---------------------------------- | ------ | ---- |
-| className   |                                                                                                                         | string                             |        |      |
+| className   | ClassName | string                             |        |      |
 | direction | Specifies the resize direction within the group  | 'horizontal' \| 'vertical' | 'horizontal' |      |
 
 ### ResizeHandler
 
 | 参数        | 说明                                                                                                                        | 类型                               | 默认值 | 版本 |
 | ----------- | --------------------------------------------------------------------------------------------------------------------------- | ---------------------------------- | ------ | ---- |
-| className   |                                                                                                                         | string                             |        |      |
-| style |  | CSSProperties |      |
+| className   | ClassName | string  |        |      |
+| style | Style | CSSProperties |      |
 
 ### ResizeItem
 
 | 参数      | 说明                                                                          | 类型                    | 默认值     | 版本   |
 | --------- | ----------------------------------------------------------------------------- | ----------------------- | ---------- | ------ |
-| className |                                                                           | string                  |            |        |
+| className | ClassName                                                                     | string                  |            |        |
 | defaultSize   | Used to set the initial width and height. **The string supports % and px units, and when the string is a pure number or a number is set directly, it represents the proportional allocation of the remaining space based on the value.**  | string \| number                  |           |        |
 | min | Specifies the minimum size of the resizable box (as percentage or pixel)     |  string                  |   |        |
 | max | Specifies the maximum size of the resizable box (as percentage or pixel)     |  string                  |   |        |   
-| style |  | CSSProperties |      |
-| onChange  | Callback during the dragging process                                                    | (e: Event; direction: String;size: Size) => void | -          |  |
+| style | Style | CSSProperties |      |
+| onChange  | Callback during the dragging process                                                    | (size: Size; e: Event; direction: String) => void | -          |  |
 | onResizeStart  | Callback when resizing starts                                                  | (e: Event; direction: String) => void | -          |  |
-| onResizeEnd  | Callback when resizing ends                                                   | (e: Event; direction: String) => void | -          |  |
+| onResizeEnd  | Callback when resizing ends                                                   | (size: Size; e: Event; direction: String) => void | -          |  |
 
 
 ## Design Tokens

+ 124 - 64
content/basic/resizable/index.md

@@ -219,27 +219,27 @@ import React, { useState } from 'react';
 import { Resizable } from '@douyinfe/semi-ui';
 
 function Demo() {
-    const [size, setSize] = useState({ width: 200, height: 300 });
-
-    const onChange = () => {
-        let realSize = { width: size.width + 10, height: size.height + 10 };
-        setSize(realSize);
-    };
-    return (
-        <div style={{ width: '500px', height: '60%' }}>
-            <Button onClick={onChange}>set += 10</Button>
-            <Resizable
-                style={{ backgroundColor: 'rgba(var(--semi-grey-1), 1)', marginTop: '10px' }}
-                defaultSize={{
-                    width: 100,
-                    height: 100,
-                }}
-                size={size}
-            >
-                <div style={{ marginLeft: '20%' }}>受控</div>
-            </Resizable>
+  const [size, setSize] = useState({ width: 200, height: 100 });
+  const onButtonClick = () => {
+    let realSize = { width: size.width + 10, height: size.height + 10 };
+    setSize(realSize);
+  };
+  const onChange = (s) => { setSize(s); }
+
+  return (
+    <div style={{ width: '500px', height: '60%' }}>
+      <Button onClick={onButtonClick}>set += 10</Button>
+      <Resizable
+        style={{ backgroundColor: 'rgba(var(--semi-grey-1), 1)', marginTop: '10px' }}
+        size={size}
+        onChange={onChange}
+      >
+        <div style={{ marginLeft: '20%' }}>
+          受控
         </div>
-    );
+      </Resizable>
+    </div>
+  );
 }
 ```
 
@@ -698,62 +698,122 @@ function Demo() {
 }
 ```
 
+### 动态方向
+
+```jsx live=true
+import React, { useState } from 'react';
+import { ResizeItem, ResizeHandler, ResizeGroup } from '@douyinfe/semi-ui';
+
+function Demo() {
+  const [text, setText] = useState('drag to resize')
+  const [direction, setDirection] = useState('horizontal')
+
+  const changeDirection = () => {
+    if (direction === 'horizontal') {
+      setDirection('vertical')
+    } else {
+      setDirection('horizontal')
+    }
+  }
+  return (
+    <div style={{ width: '400px', height: '300px' }}>
+      <Button onClick={changeDirection}>{direction}</Button>
+      <ResizeGroup direction={direction} >
+        <ResizeItem
+          onChange={() => { setText('resizing') }}
+          onResizeEnd={() => { setText('drag to resize') }}
+          defaultSize={5}
+        >
+            <ResizeGroup direction='horizontal'>
+              <ResizeItem
+                style={{ backgroundColor: 'rgba(var(--semi-grey-1), 1)', }}
+                onChange={() => { setText('resizing') }}
+                onResizeEnd={() => { setText('drag to resize') }}
+              >
+                <div style={{ marginLeft: '20%',  padding:'5px' }}>
+                  {text}
+                </div>
+              </ResizeItem>
+              <ResizeHandler></ResizeHandler>
+              <ResizeItem
+                style={{ backgroundColor: 'rgba(var(--semi-grey-1), 1)', }}
+                onChange={() => { setText('resizing') }}
+              >
+                <div style={{ marginLeft: '20%',  padding:'5px' }}>
+                  {text}
+                </div>
+              </ResizeItem>
+            </ResizeGroup>
+        </ResizeItem>
+        <ResizeHandler></ResizeHandler>
+        <ResizeItem
+          style={{ backgroundColor: 'rgba(var(--semi-grey-1), 1)',  }}
+          defaultSize={1.3}
+          onChange={() => { setText('resizing') }}
+        >
+          <div style={{ marginLeft: '20%',  padding:'5px' }}>
+            {text}
+          </div>
+        </ResizeItem>
+      </ResizeGroup>
+    </div>
+  );
+}
+```
+
 ## API 参考
 
 ### Resizable
 
 单个伸缩框组件。
 
-| 参数 | 说明 | 类型 | 默认值 | 版本 |
-| --- | --- | --- | --- | --- |
-| className | 类名 | string |  |  |
-| size | 控制伸缩框的大小,支持数字和字符串(px/vw/vh/%)两种格式 | [Size](#基本使用与回调) |  |  |
-| defaultSize | 用于设置初始宽高,支持数字和字符串(px/vw/vh/%)两种格式 | [Size](#基本使用与回调) |  |  |
-| minWidth | 指定伸缩框最小宽度 | string \| number |  |  |
-| maxWidth | 指定伸缩框最大宽度 | string \| number |  |  |
-| minHeight | 指定伸缩框最小高度 | string \| number |  |  |
-| maxHeight | 指定伸缩框最大高度 | string \| number |  |
-| lockAspectRatio | 设置伸缩框横纵比,当为`true`时按照初始宽高锁定 | boolean \| number |  |  |
-| enable | 指定伸缩框可以伸缩的方向,没有设置为 false,则默认允许该方向的拖动 | [Enable](#控制伸缩方向) |
-| scale | 可伸缩元素被缩放的比例 | number | 1 |  |
-| boundElement | 用于限制可伸缩元素宽高的元素,传入 `parent` 设置父节点为限制节点 | string |  |  |
-| handleNode | 用于设置拖拽处理元素各个方向的自定义节点 | [HandleNode](#自定义边角handler样式) |  |  |
-| handleStyle | 用于设置拖拽处理元素各个方向的样式 | [HandleStyles](#自定义边角handler样式) |  |  |
-| handleClass | 用于设置拖拽处理元素各个方向的类名称 | [HandleClasses](#自定义边角handler样式) |  |  |
-| style | 样式 | CSSProperties |  |
-| snapGap | 用于指定移动到下一个目标所需的最小间隙。 | number | 0 |  |
-| snap | 指定调整大小时应对齐的绝对像素值。 x 和 y 都是可选的,允许仅包含要定义的轴 | [Snap](#允许阶段性调整宽高) | null |  |
-| grid | 指定调整大小应对齐的增量 | \[number, number\] | \[1,1\] |  |
-| onChange | 拖拽过程中的回调 | (e: Event; direction: String;size: Size) => void | - |  |
-| onResizeStart | 开始伸缩的回调 | (e: Event; direction: String) => void | - |  |
-| onResizeEnd | 结束伸缩的回调 | (e: Event; direction: String) => void | - |  |
+| 参数      | 说明                                                                          | 类型                    | 默认值     | 版本   |
+| --------- | ----------------------------------------------------------------------------- | ----------------------- | ---------- | ------ |
+| className | 类名                                                                          | string                  |            |        |
+| size   | 控制伸缩框的大小,支持数字和字符串(px/vw/vh/%)两种格式 | [Size](#基本使用与回调)                  |           |        |
+| defaultSize   | 用于设置初始宽高,支持数字和字符串(px/vw/vh/%)两种格式 | [Size](#基本使用与回调)                  |           |        |
+| minWidth | 指定伸缩框最小宽度      |  string \| number                  |   |        |
+| maxWidth | 指定伸缩框最大宽度      |  string \| number                  |   |        |
+| minHeight | 指定伸缩框最小高度      |  string \| number                  |   |        |
+| maxHeight | 指定伸缩框最大高度      |  string \| number                  |   |     
+| lockAspectRatio | 设置伸缩框横纵比,当为`true`时按照初始宽高锁定    |  boolean \| number                  |   |        |
+| enable | 指定伸缩框可以伸缩的方向,没有设置为 false,则默认允许该方向的拖动      |    [Enable](#控制伸缩方向) 
+| scale | 可伸缩元素被缩放的比例      |   number                  |  1 |        |   
+| boundElement | 用于限制可伸缩元素宽高的元素,传入 `parent` 设置父节点为限制节点    | string                  |            |        |
+| handleNode     | 用于设置拖拽处理元素各个方向的自定义节点             | [HandleNode](#自定义边角handler样式)          |            |        |
+| handleStyle    | 用于设置拖拽处理元素各个方向的样式              | [HandleStyles](#自定义边角handler样式)            |            |        |
+| handleClass  | 用于设置拖拽处理元素各个方向的类名称              | [HandleClasses](#自定义边角handler样式)            |            |        |
+| style | 样式 | CSSProperties |      |
+| snapGap      | 用于指定移动到下一个目标所需的最小间隙。                        | number                  | 0       |  |
+| snap      | 指定调整大小时应对齐的绝对像素值。 x 和 y 都是可选的,允许仅包含要定义的轴                        | [Snap](#允许阶段性调整宽高)                  | null       |  |
+| grid      | 指定调整大小应对齐的增量                           | \[number, number\]                  | \[1,1\]       |  |
+| onChange  | 拖拽过程中的回调                                                    | (size: Size; e: Event; direction: String) => void | -          |  |
+| onResizeStart  | 开始伸缩的回调                                                   | (e: Event; direction: String) => void | -          |  |
+| onResizeEnd  | 结束伸缩的回调                                                    | (size: Size; e: Event; direction: String) => void | -          |  |
 
 ### ResizeGroup
 
-| 参数      | 说明                    | 类型                       | 默认值       | 版本 |
-| --------- | ----------------------- | -------------------------- | ------------ | ---- |
-| className | 类名                    | string                     |              |      |
-| direction | 指定 Group 内的伸缩方向 | 'horizontal' \| 'vertical' | 'horizontal' |      |
-
+| 参数        | 说明                                                                                                                        | 类型                               | 默认值 | 版本 |
+| ----------- | --------------------------------------------------------------------------------------------------------------------------- | ---------------------------------- | ------ | ---- |
+| className   | 类名                                                                                                                        | string                             |        |      |
+| direction | 指定Group内的伸缩方向  | 'horizontal' \| 'vertical' | 'horizontal' |      |
 ### ResizeHandler
-
-| 参数      | 说明 | 类型          | 默认值 | 版本 |
-| --------- | ---- | ------------- | ------ | ---- |
-| className | 类名 | string        |        |      |
-| style     | 样式 | CSSProperties |        |
-
+| 参数        | 说明                                                                                                                        | 类型                               | 默认值 | 版本 |
+| ----------- | --------------------------------------------------------------------------------------------------------------------------- | ---------------------------------- | ------ | ---- |
+| className   | 类名                                                                                                                        | string                             |        |      |
+| style | 样式 | CSSProperties |      |
 ### ResizeItem
+| 参数      | 说明                                                                          | 类型                    | 默认值     | 版本   |
+| --------- | ----------------------------------------------------------------------------- | ----------------------- | ---------- | ------ |
+| className | 类名                                                                          | string                  |            |        |
+| defaultSize   | 用于设置初始宽高,**字符串支持%和px单位,当字符串为纯数字或直接设置数字时表示按照值的比例分配剩余空间** | string \| number                 |           |        |
+| min | 指定伸缩框最小尺寸(百分比或像素值)      |  string                   |   |        |
+| max | 指定伸缩框最大尺寸(百分比或像素值)     |  string                   |   |        |
+| style | 样式 | CSSProperties |      |
+| onChange  | 拖拽过程中的回调                                                    | (size: Size; e: Event; direction: String) => void | -          |  |
+| onResizeStart  | 开始伸缩的回调                                                   | (e: Event; direction: String) => void | -          |  |
+| onResizeEnd  | 结束伸缩的回调                                                    | (size: Size; e: Event; direction: String) => void | -          |  |
 
-| 参数 | 说明 | 类型 | 默认值 | 版本 |
-| --- | --- | --- | --- | --- |
-| className | 类名 | string |  |  |
-| defaultSize | 用于设置初始宽高,**字符串支持%和 px 单位,当字符串为纯数字或直接设置数字时表示按照值的比例分配剩余空间** | string \| number |  |  |
-| min | 指定伸缩框最小尺寸(百分比或像素值) | string |  |  |
-| max | 指定伸缩框最大尺寸(百分比或像素值) | string |  |  |
-| style | 样式 | CSSProperties |  |
-| onChange | 拖拽过程中的回调 | (e: Event; direction: String;size: Size) => void | - |  |
-| onResizeStart | 开始伸缩的回调 | (e: Event; direction: String) => void | - |  |
-| onResizeEnd | 结束伸缩的回调 | (e: Event; direction: String) => void | - |  |
 
 ## 设计变量
 

+ 265 - 255
content/input/form/index.md

@@ -185,256 +185,249 @@ import { Form } from '@douyinfe/semi-ui';
 
 ```jsx live=true dir="column"
 import React from 'react';
-import { Form, Col, Row, Button } from '@douyinfe/semi-ui';
+import { Form, Col, Row, Button, Space } from '@douyinfe/semi-ui';
 import { IconUpload } from '@douyinfe/semi-icons';
 
-class BasicDemoWithInit extends React.Component {
-    constructor() {
-        super();
-        this.state = {
-            initValues: {
-                name: 'semi',
-                business: ['ulikeCam'],
-                role: 'ued',
-                switch: true,
-                files: [
-                    {
-                        uid: '1',
-                        name: 'vigo.png',
-                        status: 'success',
-                        size: '130KB',
-                        preview: true,
-                        url: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/vigo.png'
-                    },
-                    {
-                        uid: '2',
-                        name: 'resso.jpeg',
-                        status: 'validateFail',
-                        size: '222KB',
-                        percent: 50,
-                        preview: true,
-                        fileInstance: new File([new ArrayBuffer(2048)], 'resso.jpeg', { type: 'image/jpeg' }),
-                        url: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/Resso.png'
-                    },
-                    {
-                        uid: '3',
-                        name: 'dy.jpeg',
-                        status: 'uploading',
-                        size: '222KB',
-                        percent: 50,
-                        preview: true,
-                        fileInstance: new File([new ArrayBuffer(2048)], 'dy.jpeg', { type: 'image/jpeg' }),
-                        url: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/dy.png'
-                    }
-                ]
-            }
-        };
-    }
-
-    render() {
-        const { Section, Input, InputNumber, AutoComplete, Select, TreeSelect, Cascader, DatePicker, TimePicker, TextArea, CheckboxGroup, Checkbox, RadioGroup, Radio, Slider, Rating, Switch, TagInput } = Form;
-        const { initValues } = this.state;
-        const plainOptions = ['A', 'B', 'C'];
-        const style = { width: '90%' };
-        const treeData = [
+() => {
+    const initValues = {
+        name: 'semi',
+        business: ['ulikeCam'],
+        role: 'ued',
+        switch: true,
+        files: [
             {
-                label: '亚洲',
-                value: 'Asia',
-                key: '0',
-                children: [
-                    {
-                        label: '中国',
-                        value: 'China',
-                        key: '0-0',
-                        children: [
-                            {
-                                label: '北京',
-                                value: 'Beijing',
-                                key: '0-0-0',
-                            },
-                            {
-                                label: '上海',
-                                value: 'Shanghai',
-                                key: '0-0-1',
-                            },
-                        ],
-                    },
-                ],
+                uid: '1',
+                name: 'vigo.png',
+                status: 'success',
+                size: '130KB',
+                preview: true,
+                url: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/vigo.png'
+            },
+            {
+                uid: '2',
+                name: 'resso.jpeg',
+                status: 'validateFail',
+                size: '222KB',
+                percent: 50,
+                preview: true,
+                fileInstance: new File([new ArrayBuffer(2048)], 'resso.jpeg', { type: 'image/jpeg' }),
+                url: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/Resso.png'
             },
             {
-                label: '北美洲',
-                value: 'North America',
-                key: '1',
+                uid: '3',
+                name: 'douyin.jpeg',
+                status: 'uploading',
+                size: '222KB',
+                percent: 50,
+                preview: true,
+                fileInstance: new File([new ArrayBuffer(2048)], 'dy.jpeg', { type: 'image/jpeg' }),
+                url: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/dy.png'
             }
-        ];
+        ]
+    };
+    const { Section, Input, InputNumber, AutoComplete, Select, TreeSelect, Cascader, DatePicker, TimePicker, TextArea, CheckboxGroup, Checkbox, RadioGroup, Radio, Slider, Rating, Switch, TagInput } = Form;
+    const plainOptions = ['A', 'B', 'C'];
+    const style = { width: '90%' };
+    const treeData = [
+        {
+            label: '亚洲',
+            value: 'Asia',
+            key: '0',
+            children: [
+                {
+                    label: '中国',
+                    value: 'China',
+                    key: '0-0',
+                    children: [
+                        {
+                            label: '北京',
+                            value: 'Beijing',
+                            key: '0-0-0',
+                        },
+                        {
+                            label: '上海',
+                            value: 'Shanghai',
+                            key: '0-0-1',
+                        },
+                    ],
+                },
+            ],
+        },
+        {
+            label: '北美洲',
+            value: 'North America',
+            key: '1',
+        }
+    ];
 
-        return (
-            <Form
-                initValues={initValues}
-                style={{ padding: 10, width: '100%' }}
-                onValueChange={(v)=>console.log(v)}
-            >
-                <Section text={'基本信息'}>
-                    <Row>
-                        <Col span={12}>
-                            <Input
-                                field="name"
-                                label="名称(Input)"
-                                initValue={'mikeya'}
-                                style={style}
-                                trigger='blur'
-                            />
-                        </Col>
-                        <Col span={12}>
-                            <DatePicker field="date" label='日期(DatePicker)' style={style} initValue={new Date()} placeholder='请选择生效日期' />
-                        </Col>
-                    </Row>
-                    <Row>
-                        <Col span={12}>
-                            <Select field="role" style={style} label='角色(Select)' placeholder='请选择你的角色'>
-                                <Select.Option value="operate">运营</Select.Option>
-                                <Select.Option value="rd">开发</Select.Option>
-                                <Select.Option value="pm">产品</Select.Option>
-                                <Select.Option value="ued">设计</Select.Option>
-                            </Select>
-                        </Col>
-                        <Col span={12}>
-                            <Select
-                                field="business"
-                                multiple
-                                style={style}
-                                placeholder='请选择业务线'
-                                label="业务线(多选Select)"
-                                extraText={
-                                    <div style={{
-                                        color: 'rgba(var(--semi-blue-5), 1)',
-                                        fontSize: 14,
-                                        userSelect: 'none',
-                                        cursor: 'pointer'
-                                    }}>
-                                        没有找到合适的业务线?
-                                    </div>
-                                }
-                            >
-                                <Select.Option value="abc">Semi</Select.Option>
-                                <Select.Option value="ulikeCam">轻颜相机</Select.Option>
-                                <Select.Option value="toutiao">今日头条</Select.Option>
-                            </Select>
-                        </Col>
-                    </Row>
-                    <Row>
-                        <Col span={12}>
-                            <Form.Cascader
-                                placeholder="请选择所在地区"
-                                treeData={treeData}
-                                field='area'
-                                label='地区(Cascader)'
-                                style={style}
-                            >
-                            </Form.Cascader>
-                        </Col>
-                        <Col span={12}>
-                            <Form.TreeSelect
-                                field="tree"
-                                style={style}
-                                label='节点(TreeSelect)'
-                                placeholder='请选择服务节点'
-                                treeData={treeData}
-                                filterTreeNode
-                            >
-                            </Form.TreeSelect>
-                        </Col>
-                    </Row>
-                    <Row>
-                        <Col span={12}>
-                            <TagInput 
-                                field="product"
-                                label='产品(TagInput)'
-                                initValue={['abc', 'ulikeCam']}
-                                placeholder='请输入产品'
-                                style={style}
-                            />
-                        </Col>
-                    </Row>
-                    <Row>
-                        <Col span={24}>
-                            <Form.Upload
-                                field='files'
-                                label='证明文件(Upload)'
-                                action='//semi.design/api/upload'
-                            >
-                                <Button icon={<IconUpload />} theme="light">
-                                    点击上传
-                                </Button>
-                            </Form.Upload>
-                        </Col>
-                    </Row>
-                </Section>
-                <Section text='资源详情'>
-                    <Row>
-                        <Col span={12}>
-                            <TextArea
-                                style={{ ...style, height: 120 }}
-                                field='description'
-                                label='申请理由(TextArea)'
-                                placeholder='请填写申请资源理由'
-                            />
-                        </Col>
-                        <Col span={12}>
-                            <CheckboxGroup
-                                field="type"
-                                direction='horizontal'
-                                label='申请类型(CheckboxGroup)'
-                                initValue={['user', 'admin']}
-                                rules={[
-                                    { required: true }
-                                ]}
-                            >
-                                <Checkbox value="admin">admin</Checkbox>
-                                <Checkbox value="user">user</Checkbox>
-                                <Checkbox value="guest">guest</Checkbox>
-                                <Checkbox value="root">root</Checkbox>
-                            </CheckboxGroup>
-                            <RadioGroup field="isMonopolize" label='是否独占资源(Radio)' rules={[
-                                { type: 'boolean' },
-                                { required: true, message: '必须选择是否独占 ' }
-                            ]}>
-                                <Radio value={1}>是</Radio>
-                                <Radio value={0}>否</Radio>
-                            </RadioGroup>
-                        </Col>
-                    </Row>
-                    <Row>
-                        <Col span={12}>
-                            <TimePicker field="time" label='截止时刻(TimePicker)' style={{ width: '90%' }}/>
-                        </Col>
-                        <Col span={12}>
-                            <InputNumber field='number' label='申请数量(InputNumber)' initValue={20} style={style}/>
-                        </Col>
-                    </Row>
-                    <Row>
-                        <Col span={12}>
-                            <Slider field="range" label='资源使用报警阈值(%)(Slider)' initValue={10} style={{ width: '90%' }}/>
-                        </Col>
-                        <Col span={12}>
-                            <Switch field='switch' label='开关(Switch)'/>
-                        </Col>
-                    </Row>
-                    <Row>
-                        <Col span={12}>
-                            <Rating field="rating" label='满意度(Rating)' initValue={2} style={{ width: '90%' }}/>
-                        </Col>
-                    </Row>
-                </Section>
-                <Checkbox value="false" field="agree" noLabel={true}>
-                    我已阅读并清楚相关规定(Checkbox)
-                </Checkbox>
+    return (
+        <Form
+            initValues={initValues}
+            style={{ padding: 10, width: '100%' }}
+            onValueChange={(v)=>console.log(v)}
+        >
+            <Section text={'基本信息'}>
+                <Row>
+                    <Col span={12}>
+                        <Input
+                            field="name"
+                            label="名称(Input)"
+                            initValue={'mikeya'}
+                            style={style}
+                            trigger='blur'
+                        />
+                    </Col>
+                    <Col span={12}>
+                        <DatePicker field="date" label='日期(DatePicker)' style={style} initValue={new Date()} placeholder='请选择生效日期' />
+                    </Col>
+                </Row>
+                <Row>
+                    <Col span={12}>
+                        <Select field="role" style={style} label='角色(Select)' placeholder='请选择你的角色'>
+                            <Select.Option value="operate">运营</Select.Option>
+                            <Select.Option value="rd">开发</Select.Option>
+                            <Select.Option value="pm">产品</Select.Option>
+                            <Select.Option value="ued">设计</Select.Option>
+                        </Select>
+                    </Col>
+                    <Col span={12}>
+                        <Select
+                            field="business"
+                            multiple
+                            style={style}
+                            placeholder='请选择业务线'
+                            label="业务线(多选Select)"
+                            extraText={
+                                <div style={{
+                                    color: 'rgba(var(--semi-blue-5), 1)',
+                                    fontSize: 14,
+                                    userSelect: 'none',
+                                    cursor: 'pointer'
+                                }}>
+                                    没有找到合适的业务线?
+                                </div>
+                            }
+                        >
+                            <Select.Option value="abc">Semi</Select.Option>
+                            <Select.Option value="ulikeCam">轻颜相机</Select.Option>
+                            <Select.Option value="toutiao">今日头条</Select.Option>
+                        </Select>
+                    </Col>
+                </Row>
+                <Row>
+                    <Col span={12}>
+                        <Form.Cascader
+                            placeholder="请选择所在地区"
+                            treeData={treeData}
+                            field='area'
+                            label='地区(Cascader)'
+                            style={style}
+                        >
+                        </Form.Cascader>
+                    </Col>
+                    <Col span={12}>
+                        <Form.TreeSelect
+                            field="tree"
+                            style={style}
+                            label='节点(TreeSelect)'
+                            placeholder='请选择服务节点'
+                            treeData={treeData}
+                            filterTreeNode
+                        >
+                        </Form.TreeSelect>
+                    </Col>
+                </Row>
+                <Row>
+                    <Col span={12}>
+                        <TagInput 
+                            field="product"
+                            label='产品(TagInput)'
+                            initValue={['abc', 'ulikeCam']}
+                            placeholder='请输入产品'
+                            style={style}
+                        />
+                    </Col>
+                </Row>
+                <Row>
+                    <Col span={24}>
+                        <Form.Upload
+                            field='files'
+                            label='证明文件(Upload)'
+                            action='//semi.design/api/upload'
+                        >
+                            <Button icon={<IconUpload />} theme="light">
+                                点击上传
+                            </Button>
+                        </Form.Upload>
+                    </Col>
+                </Row>
+            </Section>
+            <Section text='资源详情'>
+                <Row>
+                    <Col span={12}>
+                        <TextArea
+                            style={{ ...style, height: 120 }}
+                            field='description'
+                            label='申请理由(TextArea)'
+                            placeholder='请填写申请资源理由'
+                        />
+                    </Col>
+                    <Col span={12}>
+                        <CheckboxGroup
+                            field="type"
+                            direction='horizontal'
+                            label='申请类型(CheckboxGroup)'
+                            initValue={['user', 'admin']}
+                            rules={[
+                                { required: true }
+                            ]}
+                        >
+                            <Checkbox value="admin">admin</Checkbox>
+                            <Checkbox value="user">user</Checkbox>
+                            <Checkbox value="guest">guest</Checkbox>
+                            <Checkbox value="root">root</Checkbox>
+                        </CheckboxGroup>
+                        <RadioGroup field="isMonopolize" label='是否独占资源(Radio)' rules={[
+                            { type: 'boolean' },
+                            { required: true, message: '必须选择是否独占 ' }
+                        ]}>
+                            <Radio value={1}>是</Radio>
+                            <Radio value={0}>否</Radio>
+                        </RadioGroup>
+                    </Col>
+                </Row>
+                <Row>
+                    <Col span={12}>
+                        <TimePicker field="time" label='截止时刻(TimePicker)' style={{ width: '90%' }}/>
+                    </Col>
+                    <Col span={12}>
+                        <InputNumber field='number' label='申请数量(InputNumber)' initValue={20} style={style}/>
+                    </Col>
+                </Row>
+                <Row>
+                    <Col span={12}>
+                        <Slider field="range" label='资源使用报警阈值(%)(Slider)' initValue={10} style={{ width: '90%' }}/>
+                    </Col>
+                    <Col span={12}>
+                        <Switch field='switch' label='开关(Switch)'/>
+                    </Col>
+                </Row>
+                <Row>
+                    <Col span={12}>
+                        <Rating field="rating" label='满意度(Rating)' initValue={2} style={{ width: '90%' }}/>
+                    </Col>
+                </Row>
+            </Section>
+            <Checkbox value="false" field="agree" noLabel={true}>
+                我已阅读并清楚相关规定(Checkbox)
+            </Checkbox>
+            <Space>
                 <Button type="primary" htmlType="submit" className="btn-margin-right">提交(submit)</Button>
                 <Button htmlType="reset">重置(reset)</Button>
-            </Form>
-        );
-    }
-}
+            </Space>
+        </Form>
+    );
+};
 ```
 
 ### 表单控件值的绑定
@@ -1580,22 +1573,31 @@ import { Form, ArrayField, Button, Card, Typography, } from "@douyinfe/semi-ui";
 import { IconPlusCircle, IconMinusCircle } from "@douyinfe/semi-icons";
 import React from "react";
 
+const selectOption = [
+    { label: '发件人地址', value: 'address' },
+    { label: '邮件主题', value: 'title' },
+    { label: '发送时间', value: 'sendTime' },
+    { label: '接收时间', value: 'receiveTime' },
+    { label: '正文', value: 'main' },
+    { label: '附件名称', value: 'attachmentName' },
+];
+
 const initValue = {
     group: [
         {
             name: "收信规则1",
             rules: [
-                { itemName: "发件人地址", type: "include" },
-                { itemName: "邮件主题", type: "exclude" },
+                { ruleType: "address", type: "include", text: "bytedance.com" },
+                { ruleType: "title", type: "exclude", text: "更新日志" },
             ],
         },
         {
             name: "收信规则2",
             rules: [
-                { itemName: "发送时间", type: "include" }
+                { ruleType: "sendTime", type: "include", text: "2019" }
             ],
         },
-    ]
+    ] 
 };
 
 const NestedField = (props) => {
@@ -1609,22 +1611,29 @@ const NestedField = (props) => {
                 <React.Fragment>
                     {arrayFields.map(({ field, key, remove }, i) => (
                         <div style={{ display: "flex" }} key={key}>
-                            <Form.Input
-                                field={`${field}[itemName]`}
-                                label={`${field}.itemName`}
+                            <Form.Select
+                                field={`${field}[ruleType]`}
+                                label={`${field}.ruleType`}
                                 noLabel
-                                style={{ width: 100, marginRight: 12 }}
-                            ></Form.Input>
+                                optionList={selectOption}
+                                style={{ width: 120, marginRight: 12 }}
+                            ></Form.Select>
                             <Form.Select
                                 field={`${field}[type]`}
                                 label={`${field}.type`}
                                 noLabel
-                                style={{ width: 100 }}
+                                style={{ width: 100, marginRight: 12 }}
                                 optionList={[
                                     { label: "包含", value: "include" },
                                     { label: "不包含", value: "exclude" },
                                 ]}
                             ></Form.Select>
+                            <Form.Input 
+                                field={`${field}[text]`}
+                                label={`${field}.text`}
+                                noLabel
+                                style={{ width: 200 }}
+                            ></Form.Input>
                             <Button
                                 type="danger"
                                 theme="borderless"
@@ -1638,7 +1647,7 @@ const NestedField = (props) => {
                                 disabled={i !== arrayFields.length - 1}
                                 onClick={() => {
                                     addWithInitValue({
-                                        itemName: `条件${arrayFields.length + 1}`,
+                                        ruleType: `条件${arrayFields.length + 1}`,
                                         type: "include",
                                     });
                                 }}
@@ -1670,13 +1679,13 @@ const NestArrayFieldDemo = () => {
                                 addWithInitValue({
                                     name: "新规则名称",
                                     rules: [
-                                        { itemName: "正文", type: "include" },
-                                        { itemName: "附件名称", type: "include" },
+                                        { ruleType: "main", type: "include", text: "" },
+                                        { ruleType: "attachmentName", type: "include", text: "" },
                                     ],
                                 });
                             }}
                         >
-                            新增收信规则
+                            新增收信规则 
                         </Button>
                         {arrayFields.map(({ field, key, remove }, i) => (
                             <div
@@ -1717,6 +1726,7 @@ const NestArrayFieldDemo = () => {
 };
 
 render(NestArrayFieldDemo);
+
 ```
 
 

+ 40 - 21
content/navigation/navigation/index-en-US.md

@@ -444,35 +444,53 @@ class NavApp extends React.Component {
         return (
             <Nav
                 mode={'horizontal'}
+                items={[
+                    { itemKey: 'user', text: 'User Management', icon: <IconUser /> },
+                    { itemKey: 'union', text: 'Union Center', icon: <IconStar /> },
+                    {
+                        itemKey: 'approve-management',
+                        text: 'Approval Management',
+                        icon: <IconEdit />,
+                        items: [
+                            'Check-in Review',
+                            {
+                                itemKey: 'operation-management',
+                                text: 'Operations Management',
+                                items: [
+                                    'Personnel Management',
+                                    'Personnel Change'
+                                ]
+                            }
+                        ]
+                    },
+                    {
+                        text: 'Task Platform',
+                        icon: <IconSetting />,
+                        itemKey: 'job',
+                        items: ['Task Management', 'User Task Query'],
+                    },
+                ]}
                 onSelect={key => console.log(key)}
                 header={{
                     logo: <img src="https://sf6-cdn-tos.douyinstatic.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/webcast_logo.svg" />,
                     text: 'Live Platform'
                 }}
                 footer={
-                    <>
-                        <Select defaultValue='English' style={{ width: 120, marginRight: 10 }} insetLabel={<IconLanguage />}>
-                            <Select.Option value='Chinese'>中文</Select.Option>
-                            <Select.Option value='English'>English</Select.Option>
-                            <Select.Option value='Korean'>한국어</Select.Option>
-                            <Select.Option value='Japanese'>日本語</Select.Option>
-                        </Select>
-                        <Button style={{ marginRight: 10 }}>Switch to Overseas Version</Button>
-                        <Dropdown
-                            position="bottomRight"
-                            render={
-                                <Dropdown.Menu>
-                                    <Dropdown.Item>Detail</Dropdown.Item>
-                                    <Dropdown.Item>Quit</Dropdown.Item>
-                                </Dropdown.Menu>
-                            }
-                        >
-                            <Avatar size="small" color='light-blue' style={{ margin: 4 }}>BD</Avatar>
-                            <span>Bytedancer</span>
-                        </Dropdown>
-                    </>
+                    <Dropdown
+                        position="bottomRight"
+                        render={
+                            <Dropdown.Menu>
+                                <Dropdown.Item>Detail</Dropdown.Item>
+                                <Dropdown.Item>Quit</Dropdown.Item>
+                            </Dropdown.Menu>
+                        }
+                    >
+                        <Avatar size="small" color='light-blue' style={{ margin: 4 }}>BD</Avatar>
+                        <span>Bytedancer</span>
+                    </Dropdown>
                 }
             />
+
         );
     }
 
@@ -498,6 +516,7 @@ class NavApp extends React.Component {
         );
     }
 }
+
 ```
 
 ### Expand and collapse arrow position

+ 49 - 42
content/navigation/navigation/index.md

@@ -349,49 +349,54 @@ import { IconTreeSelect, IconForm, IconBreadcrumb, IconBanner, IconBadge, IconNo
     const TopHeader = () => (
         <Header style={{ backgroundColor: 'var(--semi-color-bg-1)' }}>
             <div>
-                <Nav mode="horizontal" defaultSelectedKeys={['Home']}>
-                    <Nav.Header>
-                        <IconSemiLogo style={{ height: '36px', fontSize: 36 }} />
-                    </Nav.Header>
-                    <span
-                        style={{
-                            color: 'var(--semi-color-text-2)',
-                        }}
-                    >
-                        <span
-                            style={{
-                                marginRight: '24px',
-                                color: 'var(--semi-color-text-0)',
-                                fontWeight: '600',
-                            }}
+                <Nav
+                    mode={'horizontal'}
+                    items={[
+                        { itemKey: 'user', text: '用户管理', icon: <IconBadge /> },
+                        { itemKey: 'union', text: '活动管理', icon: <IconTreeSelect /> },
+                        {
+                            itemKey: 'approve-management',
+                            text: '审批管理',
+                            icon: <IconBreadcrumb />,
+                            items: [
+                                '入驻审核',
+                                {
+                                    itemKey: 'operation-management',
+                                    text: '运营管理',
+                                    items: [
+                                        '人员管理',
+                                        '人员变更'
+                                    ]
+                                }
+                            ]
+                        },
+                        {
+                            text: '任务平台',
+                            icon: <IconSteps />,
+                            itemKey: 'job',
+                            items: ['任务管理', '用户任务查询'],
+                        },
+                    ]}
+                    onSelect={key => console.log(key)}
+                    header={{
+                        logo: <IconSemiLogo style={{ height: '36px', fontSize: 36 }} />,
+                        text: 'Semi 运营后台'
+                    }}
+                    footer={
+                        <Dropdown
+                            position="bottomRight"
+                            render={
+                                <Dropdown.Menu>
+                                    <Dropdown.Item>详情</Dropdown.Item>
+                                    <Dropdown.Item>退出</Dropdown.Item>
+                                </Dropdown.Menu>
+                            }
                         >
-                            模版推荐
-                        </span>
-                        <span style={{ marginRight: '24px' }}>所有模版</span>
-                        <span>我的模版</span>
-                    </span>
-                    <Nav.Footer>
-                        <Button
-                            theme="borderless"
-                            icon={<IconBell size="large" />}
-                            style={{
-                                color: 'var(--semi-color-text-2)',
-                                marginRight: '12px',
-                            }}
-                        />
-                        <Button
-                            theme="borderless"
-                            icon={<IconHelpCircle size="large" />}
-                            style={{
-                                color: 'var(--semi-color-text-2)',
-                                marginRight: '12px',
-                            }}
-                        />
-                        <Avatar color="orange" size="small">
-                            YJ
-                        </Avatar>
-                    </Nav.Footer>
-                </Nav>
+                            <Avatar size="small" color='light-blue' style={{ margin: 4 }}>BD</Avatar>
+                            <span>Bytedancer</span>
+                        </Dropdown>
+                    }
+                />
             </div>
         </Header>
     );
@@ -498,6 +503,8 @@ import { IconTreeSelect, IconForm, IconBreadcrumb, IconBanner, IconBadge, IconNo
     );
 };
 
+
+
 ```
 
 ### 展开收起箭头位置

+ 3 - 3
content/plus/chat/index-en-US.md

@@ -34,7 +34,7 @@ The prompt text of the upload button can be set through `uploadTipProps`. For de
 
 Dialogue is a scene involving multiple parties and multiple rounds of interaction. Role information (including name, avatar, etc.) can be passed in through `roleConfig`, and the specific parameter details are [RoleConfig](#roleConfig).
 
-Use the `align` attribute to set the alignment of the dialog, supporting left and right alignment (`leftRight`, default) and left alignment (`leftAlign`).
+Use the `align` attribute to set the layout of the dialog, supporting left and right layout (`leftRight`, default) and left alignment (`leftAlign`).
 
 ```jsx live=true noInline=true dir="column"
 import React, {useState, useCallback} from 'react';
@@ -146,7 +146,7 @@ function DefaultChat() {
                     </RadioGroup>
                 </span>
                 <span style={{ display: 'flex', alignItems: 'center', columnGap: '10px'}}>
-                    Chat align
+                    Chat layout
                     <RadioGroup onChange={onAlignChange} value={align} type={"button"}>
                         <Radio value={'leftRight'}>leftRight</Radio>
                         <Radio value={'leftAlign'}>leftAlign</Radio>
@@ -1605,7 +1605,7 @@ render(DefaultChat);
 
 | PROPERTIES | INSTRUCTIONS | TYPE | DEFAULT |
 |------|--------|-------|-------|
-| align | Dialog alignment, supports `leftRight`,`leftAlign` | string | `leftRight` |
+| align | Dialog layout, supports `leftRight`,`leftAlign` | string | `leftRight` |
 | bottomSlot | bottom slot for chat | React.ReactNode | - |
 | chatBoxRenderConfig | chatBox rendering configuration | ChatBoxRenderConfig | - |
 | chats | Controlled conversation list | Message | - |

+ 3 - 3
content/plus/chat/index.md

@@ -36,7 +36,7 @@ import { Chat } from '@douyinfe/semi-ui';
 
 对话是多方参与,多轮交互的场景。可通过 `roleConfig` 传入角色信息(包括名称,头像等),具体参数细节 [RoleConfig](#roleConfig)。
 
-使用 `align` 属性可以设置对话的对齐方式,支持左右对齐(`leftRight`, 默认)和左对齐(`leftAlign`)。
+使用 `align` 属性可以设置对话的布局,支持左右分布(`leftRight`, 默认)和左对齐(`leftAlign`)。
 
 ```jsx live=true noInline=true dir="column"
 import React, {useState, useCallback} from 'react';
@@ -148,7 +148,7 @@ function DefaultChat() {
                     </RadioGroup>
                 </span>
                 <span style={{ display: 'flex', alignItems: 'center', columnGap: '10px'}}>
-                    会话对齐方式
+                    会话布局方式
                     <RadioGroup onChange={onAlignChange} value={align} type={"button"}>
                         <Radio value={'leftRight'}>左右分布</Radio>
                         <Radio value={'leftAlign'}>左对齐</Radio>
@@ -1608,7 +1608,7 @@ render(DefaultChat);
 
 | 属性  | 说明   | 类型   | 默认值 |
 |------|--------|-------|-------|
-| align | 对话对齐方式,支持 `leftRight`、`leftAlign` | string | `leftRight` |
+| align | 对话布局方式,支持 `leftRight`、`leftAlign` | string | `leftRight` |
 | bottomSlot | 底部插槽 | React.ReactNode | - |
 | chatBoxRenderConfig | chatBox 渲染配置 | ChatBoxRenderConfig | - |
 | chats | 受控对话列表 | Message | - |

+ 1 - 0
content/plus/markdownrender/index-en-US.md

@@ -172,6 +172,7 @@ Support all RemarkPlugin and RehypePlugins plugins of MDXJS through `remarkPlugi
 | components | Used to override Markdown elements and add custom components | Record<string, JSXElementConstructor> | - |
 | format | The incoming raw type, whether it is pure Markdown | 'md'\|'mdx' | 'mdx' |
 | raw | plain text in Markdown or MDX | string | - |
+| remarkGfm | Whether to enable Github GFM syntax. Safari 16.3 and earlier does not support lookaround assertions and will report an error. | bool | true |
 | remarkPlugins | custom Remark Plugin          | Remark Plugin Array                | - |
 | rehypePlugins | custom Rehype Plugin          | Rehype Plugin Array               | - |
 | style | style | CSSProperties | - |

+ 10 - 9
content/plus/markdownrender/index.md

@@ -184,15 +184,16 @@ function Demo() {
 
 ### API
 
-| 属性         | 说明                         | 类型                                   | 默认值   |
-|------------|----------------------------|--------------------------------------|-------|
-| className | 类名                         | string                               | -   |
-| components | 用于覆盖 Markdown 元素,也可添加自定义组件 | Record<string, JSXElementConstructor> | -     |
-| format     | 传入的 raw 类型,是否是纯 Markdown   | 'md'\|'mdx'                          | 'mdx' |
-| raw        | Markdown 或 MDX 的纯文本        | string                               | -     |
-| remarkPlugins | 自定义 Remark Plugin          | Remark Plugin Array                | - |
-| rehypePlugins | 自定义 Rehype Plugin          | Rehype Plugin Array               | - |
-| style | 样式                         | CSSProperties                        | - |
+| 属性         | 说明                                          | 类型                                   | 默认值   |
+|------------|---------------------------------------------|--------------------------------------|-------|
+| className | 类名                                          | string                               | -   |
+| components | 用于覆盖 Markdown 元素,也可添加自定义组件                  | Record<string, JSXElementConstructor> | -     |
+| format     | 传入的 raw 类型,是否是纯 Markdown                    | 'md'\|'mdx'                          | 'mdx' |
+| raw        | Markdown 或 MDX 的纯文本                         | string                               | -     |
+| remarkGfm | 是否开启 Github GFM 语法,safari 16.3 之前不支持环视断言会报错 | bool | true |
+| remarkPlugins | 自定义 Remark Plugin                           | Remark Plugin Array                | - |
+| rehypePlugins | 自定义 Rehype Plugin                           | Rehype Plugin Array               | - |
+| style | 样式                                          | CSSProperties                        | - |
 
 ## 设计变量
 

+ 77 - 189
content/show/dropdown/index-en-US.md

@@ -18,27 +18,65 @@ import { Dropdown } from '@douyinfe/semi-ui';
 
 ### Basic Usage
 
+- For the Trigger of the Dropdown within its children: By default, it is displayed on hover. You can modify it to values like `click`, `custom`, `contextMenu`, etc. through the `props.trigger` to specify different triggering methods.
+- Use `render` to specify the specific content of the dropdown box: Use `Dropdown.Menu` as the parent container, and use `Dropdown.Item`, `Dropdown.Divider`, and `Dropdown.Title` in combination. Of course, in simple scenarios, you can also just combine `Dropdown.Menu` with `Dropdown.Item`, and the other elements are not mandatory.
+- `Dropdown.Item` can disable a certain option by setting `disabled`. By configuring `type`, text in different colors can be displayed. By setting `icon`, icons can be quickly configured. For more complex custom structures, you can pass in `ReactNode` through `children` for custom rendering. 
+
 ```jsx live=true
 import React from 'react';
-import { Dropdown, Tag } from '@douyinfe/semi-ui';
+import { Dropdown, Button, HotKeys } from '@douyinfe/semi-ui';
+import { IconBox, IconSetting, IconForward, IconRefresh, IconSearch, IconAlertCircle } from "@douyinfe/semi-icons";
+import { IconToken } from "@douyinfe/semi-icons-lab";
 
 function Demo() {
     return (
         <Dropdown
+            position="bottomLeft"
             render={
                 <Dropdown.Menu>
-                    <Dropdown.Item>Menu Item 1</Dropdown.Item>
-                    <Dropdown.Item>Menu Item 2</Dropdown.Item>
-                    <Dropdown.Item>Menu Item 3</Dropdown.Item>
+                    <Dropdown.Title>Group 1</Dropdown.Title>
+                    <Dropdown.Item icon={<IconBox />}>
+                        Menu Item 1
+                        <HotKeys
+                            style={{ marginLeft: 20 }}
+                            hotKeys={[HotKeys.Keys.Control, HotKeys.Keys.B]}
+                            content={['Ctrl', 'B']}
+                        ></HotKeys>
+                    </Dropdown.Item>
+                    <Dropdown.Item icon={<IconSetting />}>
+                        Menu Item 2
+                        <HotKeys
+                            style={{ marginLeft: 20 }}
+                            hotKeys={[HotKeys.Keys.Control, HotKeys.Keys.V]}
+                            content={['Ctrl', 'V']}
+                        ></HotKeys>
+                    </Dropdown.Item>
+                    <Dropdown.Item disabled icon={<IconForward />}>
+                        Menu Item 3
+                        <HotKeys
+                            style={{ marginLeft: 20 }}
+                            hotKeys={[HotKeys.Keys.Control, HotKeys.Keys.F3]}
+                            content={['Ctrl', 'F3']}
+                        ></HotKeys>
+                    </Dropdown.Item>
+                    <Dropdown.Divider />
+                    <Dropdown.Title>Group 2</Dropdown.Title>
+                    <Dropdown.Item type="tertiary" icon={<IconRefresh />}>Tertiary text</Dropdown.Item>
+                    <Dropdown.Item type="warning" icon={<IconSearch />}>
+                        Warning Text
+                    </Dropdown.Item>
+                    <Dropdown.Item type="danger" icon={<IconAlertCircle />}>Danger text</Dropdown.Item>
                 </Dropdown.Menu>
             }
         >
-            <Tag>Hover Me</Tag>
+            <Button theme="outline" type="tertiary" icon={<IconToken />}>
+                Hover Me
+            </Button>
         </Dropdown>
     );
 }
-```
 
+```
 ### Nested Usage
 
 Users can nested `Dropdown`, which is suitable for situations with multiple sublevel options.
@@ -81,96 +119,6 @@ function Demo() {
 }
 ```
 
-### Element Properties
-
-By configuing `disabled` for `Dropdown.Item`, you can disabled an item.  
-By configuring `type` on `Dropdown.Item`, you can display text in different colors.  
-By configuring `icon` on `Dropdown.Item` (`icon` needs to be ReactNode), you can quickly configured icon of item.
-
-```jsx live=true
-import React from 'react';
-import { Dropdown, Button } from '@douyinfe/semi-ui';
-import { IconBox, IconSimilarity, IconSetting, IconForward, IconColorPalette, IconRefresh, IconSearch, IconBranch } from '@douyinfe/semi-icons';
-
-function Demo() {
-    return (
-        <div>
-            <Dropdown
-                trigger="custom"
-                position="bottomLeft"
-                visible
-                render={
-                    <Dropdown.Menu>
-                        <Dropdown.Item icon={<IconBox />}>Menu Item 1</Dropdown.Item>
-                        <Dropdown.Item icon={<IconSetting />}>Menu Item 2</Dropdown.Item>
-                        <Dropdown.Item disabled icon={<IconForward />}>
-                            Menu Item 3
-                        </Dropdown.Item>
-                        <Dropdown.Item type="primary" icon={<IconBranch />}>
-                            primary
-                        </Dropdown.Item>
-                        <Dropdown.Item icon={<IconColorPalette />} type="secondary">
-                            secondary
-                        </Dropdown.Item>
-                        <Dropdown.Item icon={<IconRefresh />} type="tertiary">
-                            tertiary
-                        </Dropdown.Item>
-                        <Dropdown.Item icon={<IconSearch />} type="warning">
-                            warning
-                        </Dropdown.Item>
-                        <Dropdown.Item
-                            icon={<IconSimilarity style={{ color: 'var(--semi-color-tertiary)' }} />}
-                            type="danger"
-                        >
-                            danger
-                        </Dropdown.Item>
-                    </Dropdown.Menu>
-                }
-            >
-                <Button>Always Show</Button>
-            </Dropdown>
-            <Dropdown
-                trigger="custom"
-                position="bottomLeft"
-                showTick
-                visible
-                render={
-                    <Dropdown.Menu>
-                        <Dropdown.Item icon={<IconBox />} active>
-                            Menu Item 1
-                        </Dropdown.Item>
-                        <Dropdown.Item icon={<IconSetting />}>Menu Item 2</Dropdown.Item>
-                        <Dropdown.Item disabled icon={<IconForward />}>
-                            Menu Item 3
-                        </Dropdown.Item>
-                        <Dropdown.Item type="primary" icon={<IconBranch />}>
-                            primary
-                        </Dropdown.Item>
-                        <Dropdown.Item icon={<IconColorPalette />} type="secondary">
-                            secondary
-                        </Dropdown.Item>
-                        <Dropdown.Item icon={<IconRefresh />} type="tertiary">
-                            tertiary
-                        </Dropdown.Item>
-                        <Dropdown.Item icon={<IconSearch />} type="warning">
-                            warning
-                        </Dropdown.Item>
-                        <Dropdown.Item
-                            icon={<IconSimilarity style={{ color: 'var(--semi-color-tertiary)' }} />}
-                            type="danger"
-                        >
-                            danger
-                        </Dropdown.Item>
-                    </Dropdown.Menu>
-                }
-            >
-                <Button style={{ marginLeft: 90 }}>Always ShowTick</Button>
-            </Dropdown>
-        </div>
-    );
-}
-```
-
 ### Popup Position
 
 The position of support is the same. [Tooltip](https://semi.design/en-US/show/tooltip#Position), commonly used are: "bottom", "bottomLeft", "bottomRight".
@@ -300,99 +248,36 @@ Click on the menu item to trigger different mouse events, support `onClick`, `on
 ```jsx live=true
 import React from 'react';
 import { Dropdown, Button, Toast } from '@douyinfe/semi-ui';
+import { IconToken } from "@douyinfe/semi-icons-lab";
 
-class DropdownEvents extends React.Component {
-    constructor() {
-        super();
-        this.click = this.click.bind(this);
-        this.mouseEnter = this.mouseEnter.bind(this);
-        this.mouseLeave = this.mouseLeave.bind(this);
-        this.rightClick = this.rightClick.bind(this);
-    }
-
-    click(value) {
-        Toast.info({ content: 'You clicked me!' });
-    }
-
-    mouseEnter(value) {
-        Toast.info({ content: 'Nice to meet you!' });
-    }
-
-    mouseLeave(value) {
-        Toast.info({ content: 'See ya!' });
-    }
-
-    rightClick(value) {
-        Toast.info({ content: 'Right clicked!' });
-    }
-
-    render() {
-        return (
-            <Dropdown
-                trigger={'click'}
-                position={'bottomLeft'}
-                render={
-                    <Dropdown.Menu>
-                        <Dropdown.Item onClick={this.click}>1: click me!</Dropdown.Item>
-                        <Dropdown.Item onMouseEnter={this.mouseEnter}>2: mouse enter</Dropdown.Item>
-                        <Dropdown.Item onMouseLeave={this.mouseLeave}>3: mouse leave</Dropdown.Item>
-                        <Dropdown.Item onContextMenu={this.rightClick}>4: right click</Dropdown.Item>
-                    </Dropdown.Menu>
-                }
-            >
-                <Button>Click me</Button>
-            </Dropdown>
-        );
-    }
-}
-```
-
-### Group Combinations
-
-Combination uses`Dropdown.Title`, `Dropdown.Divider`, `Dropdown.Item`.
-
-Configure type `Dropdown.Item` to show different colors of text.
-
-```jsx live=true
-import React from 'react';
-import { Dropdown, Button, Toast } from '@douyinfe/semi-ui';
-
-class DropdownEvents extends React.Component {
-    constructor() {
-        super();
-        this.click = this.click.bind(this);
-    }
-
-    click(value) {
-        Toast.info({ content: 'You clicked me!' });
-    }
-
-    render() {
-        return (
-            <Dropdown
-                trigger={'click'}
-                showTick
-                position={'bottomLeft'}
-                render={
-                    <Dropdown.Menu>
-                        <Dropdown.Title>Group 1</Dropdown.Title>
-                        <Dropdown.Item type="primary">primary</Dropdown.Item>
-                        <Dropdown.Item type="secondary">secondary</Dropdown.Item>
-                        <Dropdown.Divider />
-                        <Dropdown.Title>Group 2</Dropdown.Title>
-                        <Dropdown.Item type="tertiary">tertiary</Dropdown.Item>
-                        <Dropdown.Item type="warning" active>
-                            warning
-                        </Dropdown.Item>
-                        <Dropdown.Item type="danger">danger</Dropdown.Item>
-                    </Dropdown.Menu>
-                }
-            >
-                <Button>Click me</Button>
-            </Dropdown>
-        );
-    }
-}
+() => {
+    return (
+        <Dropdown
+            trigger={'click'}
+            position={'bottomLeft'}
+            render={
+                <Dropdown.Menu>
+                    <Dropdown.Item onClick={() => Toast.info({ content: 'You clicked me!' })}>
+                        1: click me!
+                    </Dropdown.Item>
+                    <Dropdown.Item onMouseEnter={() => Toast.info({ content: 'Nice to meet you!' })}>
+                        2: mouse enter
+                    </Dropdown.Item>
+                    <Dropdown.Item onMouseLeave={() => Toast.info({ content: 'See ya!' })}>
+                        3: mouse leave
+                    </Dropdown.Item>
+                    <Dropdown.Item onContextMenu={() => Toast.info({ content: 'Right clicked!' })}>
+                        4: right click
+                    </Dropdown.Item>
+                </Dropdown.Menu>
+            }
+        >
+            <Button theme="outline" type="tertiary" icon={<IconToken />}>
+                Click Me
+            </Button>
+        </Dropdown>
+    );
+};
 ```
 
 ### Json Usage
@@ -402,6 +287,7 @@ Can use the menu attribute to configure the Dropdown content menu
 ```jsx live=true
 import React from 'react';
 import { Dropdown, Button } from '@douyinfe/semi-ui';
+import { IconToken } from "@douyinfe/semi-icons-lab";
 
 function DropdownEvents() {
     const menu = [
@@ -416,7 +302,9 @@ function DropdownEvents() {
     ];
     return (
         <Dropdown trigger={'click'} showTick position={'bottomLeft'} menu={menu}>
-            <Button>Click me</Button>
+            <Button theme="outline" type="tertiary" icon={<IconToken />}>
+                Click Me
+            </Button>
         </Dropdown>
     );
 }

+ 146 - 244
content/show/dropdown/index.md

@@ -17,25 +17,65 @@ import { Dropdown } from '@douyinfe/semi-ui';
 
 ### 基本用法
 
+-   在 Dropdown 的 children 中为它的 Trigger 触发器:默认为 hover 展示,可通过 props.trigger 修改为 `click`、`custom`、`contextMenu`等值指定不同触发方式  
+-   通过 render 指定下拉框的具体内容:使用 `Dropdown.Menu` 作为父容器,组合使用 `Dropdown.Item`、`Dropdown.Divider`、`Dropdown.Title` 。  
+    当然简单场景你也可以仅搭配 `Dropdown.Menu` 与 `Dropdown.Item`,其他元素不是必须的。  
+-   `Dropdown.Item` 通过设置 `disabled` 可以禁用某个选项,配置 `type`,可以展示不同颜色的文本,上设置 `icon` 可以快速配置图标。更复杂的自定义结构,你可以通过 children 传入 ReactNode自定义渲染
+
 ```jsx live=true
 import React from 'react';
-import { Dropdown, Tag } from '@douyinfe/semi-ui';
+import { Dropdown, Button, HotKeys } from '@douyinfe/semi-ui';
+import { IconBox, IconSetting, IconForward, IconRefresh, IconSearch, IconAlertCircle } from "@douyinfe/semi-icons";
+import { IconToken } from "@douyinfe/semi-icons-lab";
 
 function Demo() {
     return (
         <Dropdown
+            position="bottomLeft"
             render={
                 <Dropdown.Menu>
-                    <Dropdown.Item>Menu Item 1</Dropdown.Item>
-                    <Dropdown.Item>Menu Item 2</Dropdown.Item>
-                    <Dropdown.Item>Menu Item 3</Dropdown.Item>
+                    <Dropdown.Title>分组1</Dropdown.Title>
+                    <Dropdown.Item icon={<IconBox />}>
+                        Menu Item 1
+                        <HotKeys
+                            style={{ marginLeft: 20 }}
+                            hotKeys={[HotKeys.Keys.Control, HotKeys.Keys.B]}
+                            content={['Ctrl', 'B']}
+                        ></HotKeys>
+                    </Dropdown.Item>
+                    <Dropdown.Item icon={<IconSetting />}>
+                        Menu Item 2
+                        <HotKeys
+                            style={{ marginLeft: 20 }}
+                            hotKeys={[HotKeys.Keys.Control, HotKeys.Keys.V]}
+                            content={['Ctrl', 'V']}
+                        ></HotKeys>
+                    </Dropdown.Item>
+                    <Dropdown.Item disabled icon={<IconForward />}>
+                        Menu Item 3
+                        <HotKeys
+                            style={{ marginLeft: 20 }}
+                            hotKeys={[HotKeys.Keys.Control, HotKeys.Keys.F3]}
+                            content={['Ctrl', 'F3']}
+                        ></HotKeys>
+                    </Dropdown.Item>
+                    <Dropdown.Divider />
+                    <Dropdown.Title>分组2</Dropdown.Title>
+                    <Dropdown.Item type="tertiary" icon={<IconRefresh />}>tertiary</Dropdown.Item>
+                    <Dropdown.Item type="warning" icon={<IconSearch />}>
+                        warning
+                    </Dropdown.Item>
+                    <Dropdown.Item type="danger" icon={<IconAlertCircle />}>danger</Dropdown.Item>
                 </Dropdown.Menu>
             }
         >
-            <Tag>Hover Me</Tag>
+            <Button theme="outline" type="tertiary" icon={<IconToken />}>
+                Hover Me
+            </Button>
         </Dropdown>
     );
 }
+
 ```
 
 ### 嵌套使用
@@ -44,15 +84,16 @@ function Demo() {
 
 ```jsx live=true
 import React, { useMemo } from 'react';
-import { Dropdown, Tag } from '@douyinfe/semi-ui';
+import { Dropdown, Button, HotKeys } from '@douyinfe/semi-ui';
+import { IconToken } from "@douyinfe/semi-icons-lab";
 
 function Demo() {
     const subDropdown = useMemo(
         () => (
             <Dropdown.Menu>
-                <Dropdown.Item>Menu Item 1</Dropdown.Item>
-                <Dropdown.Item>Menu Item 2</Dropdown.Item>
-                <Dropdown.Item>Menu Item 3</Dropdown.Item>
+                <Dropdown.Item>Nested Menu Item 1</Dropdown.Item>
+                <Dropdown.Item>Nested  Menu Item 2</Dropdown.Item>
+                <Dropdown.Item>Nested  Menu Item 3</Dropdown.Item>
             </Dropdown.Menu>
         ),
         []
@@ -73,97 +114,9 @@ function Demo() {
                     </Dropdown.Menu>
                 }
             >
-                <Tag>Hover Me</Tag>
-            </Dropdown>
-        </div>
-    );
-}
-```
-
-### 元素属性
-
-通过设置 `disabled` 可以禁用某个选项  
-通过给 `Dropdown.Item` 配置 `type`,可以展示不同颜色的文本  
-通过在 `Dropdown.Item` 上设置 `icon` 可以快速配置图标
-
-```jsx live=true
-import React from 'react';
-import { Dropdown, Button } from '@douyinfe/semi-ui';
-import { IconBox, IconSimilarity, IconSetting, IconForward, IconColorPalette, IconRefresh, IconSearch, IconBranch } from '@douyinfe/semi-icons';
-
-function Demo() {
-    return (
-        <div>
-            <Dropdown
-                trigger="custom"
-                position="bottomLeft"
-                visible
-                render={
-                    <Dropdown.Menu>
-                        <Dropdown.Item icon={<IconBox />}>Menu Item 1</Dropdown.Item>
-                        <Dropdown.Item icon={<IconSetting />}>Menu Item 2</Dropdown.Item>
-                        <Dropdown.Item disabled icon={<IconForward />}>
-                            Menu Item 3
-                        </Dropdown.Item>
-                        <Dropdown.Item icon={<IconBranch />} type="primary">
-                            primary
-                        </Dropdown.Item>
-                        <Dropdown.Item icon={<IconColorPalette />} type="secondary">
-                            secondary
-                        </Dropdown.Item>
-                        <Dropdown.Item icon={<IconRefresh />} type="tertiary">
-                            tertiary
-                        </Dropdown.Item>
-                        <Dropdown.Item icon={<IconSearch />} type="warning">
-                            warning
-                        </Dropdown.Item>
-                        <Dropdown.Item
-                            icon={<IconSimilarity style={{ color: 'var(--semi-color-tertiary)' }} />}
-                            type="danger"
-                        >
-                            danger
-                        </Dropdown.Item>
-                    </Dropdown.Menu>
-                }
-            >
-                <Button>始终展示</Button>
-            </Dropdown>
-            <Dropdown
-                trigger="custom"
-                position="bottomLeft"
-                showTick
-                visible
-                render={
-                    <Dropdown.Menu>
-                        <Dropdown.Item icon={<IconBox />} active>
-                            Menu Item 1
-                        </Dropdown.Item>
-                        <Dropdown.Item icon={<IconSetting />}>Menu Item 2</Dropdown.Item>
-                        <Dropdown.Item disabled icon={<IconForward />}>
-                            Menu Item 3
-                        </Dropdown.Item>
-                        <Dropdown.Item icon={<IconBranch />} type="primary">
-                            primary
-                        </Dropdown.Item>
-                        <Dropdown.Item icon={<IconColorPalette />} type="secondary">
-                            secondary
-                        </Dropdown.Item>
-                        <Dropdown.Item icon={<IconRefresh />} type="tertiary">
-                            tertiary
-                        </Dropdown.Item>
-                        <Dropdown.Item icon={<IconSearch />} type="warning">
-                            warning
-                        </Dropdown.Item>
-                        <Dropdown.Item
-                            icon={<IconSimilarity style={{ color: 'var(--semi-color-tertiary)' }} />}
-                            type="danger"
-                        >
-                            danger
-                        </Dropdown.Item>
-                    </Dropdown.Menu>
-                }
-            >
-                <Button style={{ marginLeft: 90 }}>ShowTick+始终展示</Button>
+                <Button theme="outline" type="tertiary" icon={<IconToken />}>
+                    Hover Me
+                </Button>
             </Dropdown>
         </div>
     );
@@ -229,7 +182,7 @@ function Demo() {
 ### 触发方式
 
 默认是移入触发,可通过获取焦点(focus),点击(click)或自定义事件触发菜单展开。  
-contextMenu方式在 v2.42 后提供
+contextMenu 方式在 v2.42 后提供
 
 ```jsx live=true
 import React from 'react';
@@ -264,12 +217,14 @@ function Demo() {
                     </Dropdown.Menu>
                 }
             >
-                <div style={{
-                    border: '1px solid var(--semi-color-border)',
-                    borderRadius: 4,
-                    height: 36,
-                    width: 220
-                }}>
+                <div
+                    style={{
+                        border: '1px solid var(--semi-color-border)',
+                        borderRadius: 4,
+                        height: 36,
+                        width: 220,
+                    }}
+                >
                     Please use Tab to focus this div
                 </div>
             </Dropdown>
@@ -301,7 +256,9 @@ function Demo() {
                     </Dropdown.Menu>
                 }
             >
-                <Button theme='solid' type='secondary' style={{ marginBottom: 20 }}>Right click (ContextMenu)</Button>
+                <Button theme="solid" type="secondary" style={{ marginBottom: 20 }}>
+                    Right click (ContextMenu)
+                </Button>
             </Dropdown>
         </div>
     );
@@ -315,97 +272,36 @@ function Demo() {
 ```jsx live=true
 import React from 'react';
 import { Dropdown, Button, Toast } from '@douyinfe/semi-ui';
+import { IconToken } from "@douyinfe/semi-icons-lab";
 
-class DropdownEvents extends React.Component {
-    constructor() {
-        super();
-        this.click = this.click.bind(this);
-        this.mouseEnter = this.mouseEnter.bind(this);
-        this.mouseLeave = this.mouseLeave.bind(this);
-        this.rightClick = this.rightClick.bind(this);
-    }
-
-    click(value) {
-        Toast.info({ content: 'You clicked me!' });
-    }
-
-    mouseEnter(value) {
-        Toast.info({ content: 'Nice to meet you!' });
-    }
-
-    mouseLeave(value) {
-        Toast.info({ content: 'See ya!' });
-    }
-
-    rightClick(value) {
-        Toast.info({ content: 'Right clicked!' });
-    }
-
-    render() {
-        return (
-            <Dropdown
-                trigger={'click'}
-                position={'bottomLeft'}
-                render={
-                    <Dropdown.Menu>
-                        <Dropdown.Item onClick={this.click}>1: click me!</Dropdown.Item>
-                        <Dropdown.Item onMouseEnter={this.mouseEnter}>2: mouse enter</Dropdown.Item>
-                        <Dropdown.Item onMouseLeave={this.mouseLeave}>3: mouse leave</Dropdown.Item>
-                        <Dropdown.Item onContextMenu={this.rightClick}>4: right click</Dropdown.Item>
-                    </Dropdown.Menu>
-                }
-            >
-                <Button>Click me</Button>
-            </Dropdown>
-        );
-    }
-}
-```
-
-### 分组组合
-
-使用 `Dropdown.Divider` 可以插入分割线使用 `Dropdown.Title` 可以插入分组名组合使用 `Dropdown.Title`、`Dropdown.Divider`、`Dropdown.Item`。
-
-```jsx live=true
-import React from 'react';
-import { Dropdown, Button, Toast } from '@douyinfe/semi-ui';
-
-class DropdownEvents extends React.Component {
-    constructor() {
-        super();
-        this.click = this.click.bind(this);
-    }
-
-    click(value) {
-        Toast.info({ content: 'You clicked me!' });
-    }
-
-    render() {
-        return (
-            <Dropdown
-                trigger={'click'}
-                showTick
-                position={'bottomLeft'}
-                render={
-                    <Dropdown.Menu>
-                        <Dropdown.Title>分组1</Dropdown.Title>
-                        <Dropdown.Item type="primary">primary</Dropdown.Item>
-                        <Dropdown.Item type="secondary">secondary</Dropdown.Item>
-                        <Dropdown.Divider />
-                        <Dropdown.Title>分组2</Dropdown.Title>
-                        <Dropdown.Item type="tertiary">tertiary</Dropdown.Item>
-                        <Dropdown.Item type="warning" active>
-                            warning
-                        </Dropdown.Item>
-                        <Dropdown.Item type="danger">danger</Dropdown.Item>
-                    </Dropdown.Menu>
-                }
-            >
-                <Button>Click me</Button>
-            </Dropdown>
-        );
-    }
-}
+() => {
+    return (
+        <Dropdown
+            trigger={'click'}
+            position={'bottomLeft'}
+            render={
+                <Dropdown.Menu>
+                    <Dropdown.Item onClick={() => Toast.info({ content: 'You clicked me!' })}>
+                        1: click me!
+                    </Dropdown.Item>
+                    <Dropdown.Item onMouseEnter={() => Toast.info({ content: 'Nice to meet you!' })}>
+                        2: mouse enter
+                    </Dropdown.Item>
+                    <Dropdown.Item onMouseLeave={() => Toast.info({ content: 'See ya!' })}>
+                        3: mouse leave
+                    </Dropdown.Item>
+                    <Dropdown.Item onContextMenu={() => Toast.info({ content: 'Right clicked!' })}>
+                        4: right click
+                    </Dropdown.Item>
+                </Dropdown.Menu>
+            }
+        >
+            <Button theme="outline" type="tertiary" icon={<IconToken />}>
+                Click Me
+            </Button>
+        </Dropdown>
+    );
+};
 ```
 
 ### Json 用法
@@ -415,6 +311,7 @@ class DropdownEvents extends React.Component {
 ```jsx live=true
 import React from 'react';
 import { Dropdown, Button } from '@douyinfe/semi-ui';
+import { IconToken } from "@douyinfe/semi-icons-lab";
 
 function DropdownEvents() {
     const menu = [
@@ -429,7 +326,9 @@ function DropdownEvents() {
     ];
     return (
         <Dropdown trigger={'click'} showTick position={'bottomLeft'} menu={menu}>
-            <Button>Click me</Button>
+            <Button theme="outline" type="tertiary" icon={<IconToken />}>
+                Click Me
+            </Button>
         </Dropdown>
     );
 }
@@ -439,33 +338,33 @@ function DropdownEvents() {
 
 ### Dropdown
 
-| 属性 | 说明                                                                                                                           | 类型 | 默认值 | 版本 |
-| --- |------------------------------------------------------------------------------------------------------------------------------| --- | --- | --- |
-| autoAdjustOverflow | 弹出层被遮挡时是否自动调整方向                                                                                                              | boolean | true |  |
-| closeOnEsc | 在 trigger 或 弹出层按 Esc 键是否关闭面板,受控时不生效                                                                                          | boolean | true | **2.13.0** |
-| className | 下拉弹层外层样式类名                                                                                                                   | string |  |  |
-| children | 触发弹出层的 Trigger 元素                                                                                                            | ReactNode |  |  |
-| clickToHide | 在弹出层内点击时是否自动关闭弹出层                                                                                                            | boolean |  | **0.24.0** |
-| contentClassName | 下拉菜单根元素类名                                                                                                                    | string |  |  |
-| getPopupContainer | 指定父级 DOM,弹层将会渲染至该 DOM 中,自定义需要设置 `position: relative` 这会改变浮层 DOM 树位置,但不会改变视图渲染位置。                                                                         | function():HTMLElement | () => document.body |  |
+| 属性 | 说明 | 类型 | 默认值 | 版本 |
+| --- | --- | --- | --- | --- |
+| autoAdjustOverflow | 弹出层被遮挡时是否自动调整方向 | boolean | true |  |
+| closeOnEsc | 在 trigger 或 弹出层按 Esc 键是否关闭面板,受控时不生效 | boolean | true | **2.13.0** |
+| className | 下拉弹层外层样式类名 | string |  |  |
+| children | 触发弹出层的 Trigger 元素 | ReactNode |  |  |
+| clickToHide | 在弹出层内点击时是否自动关闭弹出层 | boolean |  | **0.24.0** |
+| contentClassName | 下拉菜单根元素类名 | string |  |  |
+| getPopupContainer | 指定父级 DOM,弹层将会渲染至该 DOM 中,自定义需要设置 `position: relative` 这会改变浮层 DOM 树位置,但不会改变视图渲染位置。 | function():HTMLElement | () => document.body |  |
 | keepDOM | 关闭时是否保留内部组件 DOM 不销毁 | boolean | false | **2.31.0** |
-| margin| 弹出层计算溢出时的增加的冗余值,详见[issue#549](https://github.com/DouyinFE/semi-design/issues/549),作用同 Tooltip margin                         | number\|object  |  |  **2.25.0**   |
-| mouseEnterDelay | 鼠标移入 Trigger 后,延迟显示的时间,单位毫秒(仅当 trigger 为 hover/focus 时生效)                                                                    | number | 50 |  |
-| mouseLeaveDelay | 鼠标移出弹出层后,延迟消失的时间,单位毫秒(仅当 trigger 为 hover/focus 时生效)                                                                          | number | 50 |  |
-| menu | 通过传入 JSON Array 来快速配置 Dropdown 内容                                                                                            | Array<DropdownMenuItem\> | [] | **1.12.0** |
+| margin | 弹出层计算溢出时的增加的冗余值,详见[issue#549](https://github.com/DouyinFE/semi-design/issues/549),作用同 Tooltip margin | number\|object |  | **2.25.0** |
+| mouseEnterDelay | 鼠标移入 Trigger 后,延迟显示的时间,单位毫秒(仅当 trigger 为 hover/focus 时生效) | number | 50 |  |
+| mouseLeaveDelay | 鼠标移出弹出层后,延迟消失的时间,单位毫秒(仅当 trigger 为 hover/focus 时生效) | number | 50 |  |
+| menu | 通过传入 JSON Array 来快速配置 Dropdown 内容 | Array<DropdownMenuItem\> | [] | **1.12.0** |
 | position | 弹出菜单的位置,常用:"bottom", "bottomLeft", "bottomRight",更多详见[Tooltip 位置](https://semi.design/zh-CN/show/tooltip#%E4%BD%8D%E7%BD%AE) | string | "bottom" |  |
-| render | 弹出层的内容,由 `Dropdown.Menu` 及 `Dropdown.Item`、`Dropdown.Title` 构成                                                               | ReactNode |  |  |
-| rePosKey | 可以更新该项值手动触发弹出层的重新定位                                                                                                          | string \| number |  |  |
-| spacing | 弹出层与 Trigger 元素(即 Dropdown children)的距离,单位 px                                                                                | number | 4 |  |
-| style | 弹出层内联样式                                                                                                                      | object |  |  |
-| showTick | 是否自动在 active 的 Dropdown.Item 项左侧展示表示选中的勾                                                                                     | boolean | false | **0.26.0** |
-| stopPropagation | 是否阻止弹出层上的点击事件冒泡                                                                                                              | boolean | false | **0.34.0** |
-| trigger | 触发下拉的行为,可选 "hover", "focus", "click", "custom", "contextMenu"(v2.42后提供)                                                                               | string | "hover" |  |
-| visible | 是否显示菜单,需配合 trigger custom 使用                                                                                                 | boolean | 无 |  |
-| zIndex | 弹出层 z-index 值                                                                                                                | number | 1050 |  |
-| onClickOutSide | 当弹出层处于展示状态,点击非Children、非弹出层内部区域时的回调(仅trigger为custom、click时有效)                                                                | function(e:event) |  | **2.1.0** |
-| onEscKeyDown | 在 trigger 或 弹出层按 Esc 键时调用                                                                                                    |  function(e:event) |  |  **2.13.0** | 
-| onVisibleChange | 弹出层显示状态改变时的回调                                                                                                                | function(visible: boolean) |  |  |
+| render | 弹出层的内容,由 `Dropdown.Menu` 及 `Dropdown.Item`、`Dropdown.Title` 构成 | ReactNode |  |  |
+| rePosKey | 可以更新该项值手动触发弹出层的重新定位 | string \| number |  |  |
+| spacing | 弹出层与 Trigger 元素(即 Dropdown children)的距离,单位 px | number | 4 |  |
+| style | 弹出层内联样式 | object |  |  |
+| showTick | 是否自动在 active 的 Dropdown.Item 项左侧展示表示选中的勾 | boolean | false | **0.26.0** |
+| stopPropagation | 是否阻止弹出层上的点击事件冒泡 | boolean | false | **0.34.0** |
+| trigger | 触发下拉的行为,可选 "hover", "focus", "click", "custom", "contextMenu"(v2.42 后提供) | string | "hover" |  |
+| visible | 是否显示菜单,需配合 trigger custom 使用 | boolean | 无 |  |
+| zIndex | 弹出层 z-index 值 | number | 1050 |  |
+| onClickOutSide | 当弹出层处于展示状态,点击非 Children、非弹出层内部区域时的回调(仅 trigger  custom、click 时有效) | function(e:event) |  | **2.1.0** |
+| onEscKeyDown | 在 trigger 或 弹出层按 Esc 键时调用 | function(e:event) |  | **2.13.0** |
+| onVisibleChange | 弹出层显示状态改变时的回调 | function(visible: boolean) |  |  |
 
 ### Dropdown.Menu
 
@@ -508,28 +407,28 @@ function DropdownEvents() {
 ## Accessibility
 
 ### ARIA
-- Dropdown.Menu `role` 设置为 `menu`,`aria-orientatio` 设置为 `vertical`
-- Dropdown.Item `role` 设置为 `menuitem`
-- ### 键盘和焦点
-- Dropdown 的触发器可被聚焦,目前支持 3 种触发方式:
-    - 触发方式设置为 hover 或 focus 时:鼠标悬浮或聚焦时打开 Dropdown,Dropdown 打开后,用户可以使用 `下箭头` 将焦点移动到Dropdown 内
-    - 触发方式设置为 click 时:点击触发器或聚焦时使用 `Enter` 或 `Space` 键可以打开 Dropdown,此时焦点自动聚焦到 Dropdown 中的第一个非禁用项上
-- 当焦点位于 Dropdown 内的菜单项上时:
-    - 键盘用户可以使用键盘 `上箭头` 或 `下箭头` 切换可交互元素
-    - 使用 `Enter` 键 或 `Space` 键可以激活聚焦的菜单项, 若菜单项绑定了onClick,事件会被触发
-- 键盘用户可以通过按 `Esc` 关闭 Dropdown,关闭后焦点返回到触发器上
-- 键盘交互暂未完整支持嵌套场景
 
-## 文案规范
+-   Dropdown.Menu `role` 设置为 `menu`,`aria-orientatio` 设置为 `vertical`
+-   Dropdown.Item `role` 设置为 `menuitem`
+-   ### 键盘和焦点
+-   Dropdown 的触发器可被聚焦,目前支持 3 种触发方式:
+    -   触发方式设置为 hover 或 focus 时:鼠标悬浮或聚焦时打开 Dropdown,Dropdown 打开后,用户可以使用 `下箭头` 将焦点移动到 Dropdown 内
+    -   触发方式设置为 click 时:点击触发器或聚焦时使用 `Enter` 或 `Space` 键可以打开 Dropdown,此时焦点自动聚焦到 Dropdown 中的第一个非禁用项上
+-   当焦点位于 Dropdown 内的菜单项上时:
+    -   键盘用户可以使用键盘 `上箭头` 或 `下箭头` 切换可交互元素
+    -   使用 `Enter` 键 或 `Space` 键可以激活聚焦的菜单项, 若菜单项绑定了 onClick,事件会被触发
+-   键盘用户可以通过按 `Esc` 关闭 Dropdown,关闭后焦点返回到触发器上
+-   键盘交互暂未完整支持嵌套场景
 
-- 下拉框内选项内容需要表述准确且包含信息,使用户在浏览时更加容易在选项中选择
-- 使用语句式的大小写,并且简洁明了地书写选项
-- 如果是动作选项,使用动词或者动词短语来描述用户选择该选项后会发生的动作。举个例子,"Move", "Log time", or "Hide labels" 
-- 不使用介词
+## 文案规范
 
+-   下拉框内选项内容需要表述准确且包含信息,使用户在浏览时更加容易在选项中选择
+-   使用语句式的大小写,并且简洁明了地书写选项
+-   如果是动作选项,使用动词或者动词短语来描述用户选择该选项后会发生的动作。举个例子,"Move", "Log time", or "Hide labels"
+-   不使用介词
 
-| ✅ 推荐用法 | ❌ 不推荐用法 |   
-| --- | --- | 
+| ✅ 推荐用法 | ❌ 不推荐用法 |
+| --- | --- |
 | <div style={{ height: 150}}><Dropdown visible trigger={'custom'} autoAdjustOverflow={false} position={'bottomLeft'} menu={[{ node: 'item', name: 'Add text' },{ node: 'item', name: 'Add link' },{ node: 'item', name: 'Add image' },{ node: 'item', name: 'Add video' }]} /></div> | <div style={{ height: 150}}><Dropdown visible trigger={'custom'} autoAdjustOverflow={false} position={'bottomLeft'} menu={[{ node: 'item', name: 'Add a text' },{ node: 'item', name: 'Add a link' },{ node: 'item', name: 'Add a image' },{ node: 'item', name: 'Add a video' }]} /></div> |
 
 ## 设计变量
@@ -537,8 +436,9 @@ function DropdownEvents() {
 <DesignToken/>
 
 ## FAQ
+
 -   **为什么 Dropdown 浮层在靠近屏幕边界宽度不够时,丢失宽度意外换行?**  
-    在 chromium 104 后 对于屏幕边界文本宽度不够时的换行渲染策略发生变化,详细原因可查看 [issue #1022](https://github.com/DouyinFE/semi-design/issues/1022),semi侧已经在v2.17.0版本修复了这个问题。
+    在 chromium 104 后 对于屏幕边界文本宽度不够时的换行渲染策略发生变化,详细原因可查看 [issue #1022](https://github.com/DouyinFE/semi-design/issues/1022),semi 侧已经在 v2.17.0 版本修复了这个问题。
 
 <!--
 ## 相关物料
@@ -546,5 +446,7 @@ function DropdownEvents() {
 ```material
 5
 ``` -->
+
 ## 相关物料
-<semi-material-list code="5"></semi-material-list>
+
+<semi-material-list code="5"></semi-material-list>

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

@@ -15,6 +15,14 @@ Version:Major.Minor.Patch (follow the **Semver** specification)
 -   **Patch version**: Only include bug fix, the release time is not limited
 
 ---
+#### 🎉 2.70.0-beta.0 (2024-11-18)
+- 【Fix】
+    - When all items except the disabled item in the left panel of transfer are selected, the operation button should display Cancel all selections  [#2575 ](https://github.com/DouyinFE/semi-design/issues/2575)
+    - fix resizeItem size offset caused by float,invalid min/max setting caused by browser resizing and incorrect behavior in react strictMode  [@Nathon2Y](https://github.com/Nathon2Y)
+    - Fix the problem that the placeholder of TreeSelect is blocked when single selection and search box are in trigger,  affecting versions v2.61.0 - 2.69.0
+- 【Feat】
+    - direction in ResizeGroup can be dynamic [@Nathon2Y](https://github.com/Nathon2Y)
+    - MarkdownRender adds the remarkGfm switch to prevent errors reported by lower versions of Safari that do not support lookaround assertions
 
 #### 🎉 2.69.2 (2024-11-19)
 - 【Fix】

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

@@ -13,6 +13,15 @@ Semi 版本号遵循 **Semver** 规范(主版本号-次版本号-修订版本
 -   修订版本号(patch):仅会进行 bugfix,发布时间不限
 -   不同版本间的详细关系,可查阅 [FAQ](/zh-CN/start/faq)
 
+#### 🎉 2.70.0-beta.0 (2024-11-18)
+- 【Fix】
+    - 当 Transfer 的左侧面板中除去被禁用项外的其他项目都被选中时,操作按钮应当显示取消全选  [#2575 ](https://github.com/DouyinFE/semi-design/issues/2575) [#2574](https://github.com/DouyinFE/semi-design/pull/2574)
+    - 修复计算中浮点数导致伸缩框组件尺寸的误差,浏览器拖动导致的最大最小值失效的问题,以及strictMode引起的问题 [@Nathon2Y](https://github.com/Nathon2Y) [#2551](https://github.com/DouyinFE/semi-design/pull/2551)
+    - 修复当单选,搜索框在 trigger 时,TreeSelect 的 placeholder被遮挡问题 ,影响版本 2.61.0-2.69.0 [#2566](https://github.com/DouyinFE/semi-design/pull/2566)
+- 【Feat】
+    - ResizeGroup的伸缩方向支持动态切换 [@Nathon2Y](https://github.com/Nathon2Y) [#2551](https://github.com/DouyinFE/semi-design/pull/2551)
+    - MarkdownRender 新增 remarkGfm 开关用于防止低版本 safari 不支持环视断言报错的问题 [#2576](https://github.com/DouyinFE/semi-design/pull/2576)
+
 #### 🎉 2.69.2 (2024-11-19)
 - 【Fix】
     - 修复点击触发排序的表头会透出被遮盖的内容问题,影响版本 2.65.0-2.69.1 [#2578](https://github.com/DouyinFE/semi-design/pull/2578)

+ 1 - 1
lerna.json

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

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

@@ -1,6 +1,6 @@
 {
     "name": "@douyinfe/semi-animation-react",
-    "version": "2.69.2",
+    "version": "2.70.0-beta.0",
     "description": "motion library for semi-ui-react",
     "keywords": [
         "motion",
@@ -25,8 +25,8 @@
         "prepublishOnly": "npm run build:lib"
     },
     "dependencies": {
-        "@douyinfe/semi-animation": "2.69.2",
-        "@douyinfe/semi-animation-styled": "2.69.2",
+        "@douyinfe/semi-animation": "2.70.0-beta.0",
+        "@douyinfe/semi-animation-styled": "2.70.0-beta.0",
         "classnames": "^2.2.6"
     },
     "devDependencies": {

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

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

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

@@ -1,6 +1,6 @@
 {
     "name": "@douyinfe/semi-animation",
-    "version": "2.69.2",
+    "version": "2.70.0-beta.0",
     "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.69.2",
+    "version": "2.70.0-beta.0",
     "description": "semi ui eslint plugin",
     "keywords": [
         "semi",

+ 13 - 7
packages/semi-foundation/markdownRender/foundation.ts

@@ -16,7 +16,8 @@ export interface MarkdownRenderBaseProps{
     components: MDXProps['components'];
     format: "md"|"mdx";
     remarkPlugins?: PluggableList;
-    rehypePlugins?: PluggableList
+    rehypePlugins?: PluggableList;
+    remarkGfm?: boolean
 }
 
 
@@ -26,16 +27,21 @@ export interface MarkdownRenderBaseState{
 
 class MarkdownRenderFoundation extends BaseFoundation<MarkdownRenderAdapter> {
 
-    private getOptions = ()=>{
+    private getOptions = () => {
+        const enableRemarkGfm = this._adapter.getProp("remarkGfm");
+        const remarkPlugins = [...(this.getProp("remarkPlugins") ?? [])];
+        if (enableRemarkGfm) {
+            remarkPlugins.unshift(remarkGfm);
+        }
         return {
             evaluateOptions: {
-                remarkPlugins: [remarkGfm, ...(this.getProp("remarkPlugins") ?? [])],
+                remarkPlugins: remarkPlugins,
                 rehypePlugins: this.getProp("rehypePlugins") ?? [],
                 format: this.getProp("format")
             },
             compileOptions: {
                 format: this.getProp("format"),
-                remarkPlugins: [remarkGfm, ...(this.getProp("remarkPlugins") ?? [])],
+                remarkPlugins: remarkPlugins,
                 rehypePlugins: this.getProp("rehypePlugins") ?? [],
             },
             runOptions: {
@@ -47,11 +53,11 @@ class MarkdownRenderFoundation extends BaseFoundation<MarkdownRenderAdapter> {
         };
     }
 
-    compile = async (mdxRaw: string)=>{
+    compile = async (mdxRaw: string) => {
         return await compile(mdxRaw, this.getOptions().compileOptions);
     }
 
-    evaluate = async (mdxRaw: string)=>{
+    evaluate = async (mdxRaw: string) => {
         return (await evaluate(mdxRaw, {
             ...this.getOptions().runOptions,
             ...this.getOptions().evaluateOptions,
@@ -59,7 +65,7 @@ class MarkdownRenderFoundation extends BaseFoundation<MarkdownRenderAdapter> {
         })).default;
     }
 
-    evaluateSync = (mdxRaw: string)=>{
+    evaluateSync = (mdxRaw: string) => {
         return ( evaluateSync(mdxRaw, {
             ...this.getOptions().runOptions,
             ...this.getOptions().evaluateOptions,

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

@@ -1,13 +1,13 @@
 {
     "name": "@douyinfe/semi-foundation",
-    "version": "2.69.2",
+    "version": "2.70.0-beta.0",
     "description": "",
     "scripts": {
         "build:lib": "node ./scripts/compileLib.js",
         "prepublishOnly": "npm run build:lib"
     },
     "dependencies": {
-        "@douyinfe/semi-animation": "2.69.2",
+        "@douyinfe/semi-animation": "2.70.0-beta.0",
         "@mdx-js/mdx": "^3.0.1",
         "async-validator": "^3.5.0",
         "classnames": "^2.2.6",

+ 5 - 16
packages/semi-foundation/resizable/foundation.ts

@@ -1,26 +1,15 @@
-import { 
+export {
+    ResizableHandlerAdapter, 
     ResizableHandlerFoundation, 
     ResizableFoundation, 
+    ResizableAdapter 
 } from './single';
 
-import { 
-    ResizeGroupFoundation,
-    ResizeItemFoundation,
-    ResizeHandlerFoundation
-} from './group';
-
-import type { ResizableHandlerAdapter, ResizableAdapter } from './single';
-import type { ResizeGroupAdapter, ResizeItemAdapter, ResizeHandlerAdapter } from './group';
-
-export { 
-    ResizableHandlerAdapter, 
-    ResizableHandlerFoundation, 
-    ResizableFoundation, 
-    ResizableAdapter,
+export {
     ResizeGroupAdapter,
     ResizeItemAdapter,
     ResizeHandlerAdapter,
     ResizeGroupFoundation,
     ResizeItemFoundation,
     ResizeHandlerFoundation
-}; 
+} from './group';

+ 92 - 29
packages/semi-foundation/resizable/group/index.ts

@@ -1,7 +1,8 @@
 import { getItemDirection, getPixelSize } from "../utils";
 import BaseFoundation, { DefaultAdapter } from '../../base/foundation';
-import { ResizeStartCallback, ResizeCallback } from "../singleConstants";
+import { ResizeStartCallback, ResizeCallback } from "../types";
 import { adjustNewSize, judgeConstraint, getOffset } from "../utils";
+import { debounce } from "lodash";
 export interface ResizeHandlerAdapter<P = Record<string, any>, S = Record<string, any>> extends DefaultAdapter<P, S> {
     registerEvents: () => void;
     unregisterEvents: () => void
@@ -61,16 +62,23 @@ export class ResizeGroupFoundation<P = Record<string, any>, S = Record<string, a
         return this._adapter.getGroupRef();
     }
 
+    get groupSize(): number {
+        const { direction } = this.getProps();
+        let groupSize = direction === 'horizontal' ? this.groupRef.offsetWidth : this.groupRef.offsetHeight;
+        return groupSize;
+    }
+
     direction: 'horizontal' | 'vertical'
-    itemMinusMap: Map<number, number>;
+    itemMinusMap: Map<number, number>; // 这个是为了给handler留出空间,方便维护每一个item的size为cal(percent% - minus)
     totalMinus: number;
-    avaliableSize: number;
+    itemPercentMap: Map<number, number>; // 内部维护一个百分比数组,消除浮点计算误差
 
 
     init(): void {
         this.direction = this.getProp('direction');
         this.itemMinusMap = new Map();
-        this.calculateSpace();
+        this.itemPercentMap = new Map();
+        this.initSpace();
     }
     get window(): Window | null {
         return this.groupRef.ownerDocument.defaultView as Window ?? null;
@@ -93,16 +101,18 @@ export class ResizeGroupFoundation<P = Record<string, any>, S = Record<string, a
         const lastStyle = this.window.getComputedStyle(lastItem);
         const nextStyle = this.window.getComputedStyle(nextItem);
 
-        lastOffset = getOffset(lastStyle, this.direction);
-        nextOffset = getOffset(nextStyle, this.direction);
+        lastOffset = getOffset(lastStyle, this.direction) + this.itemMinusMap.get(handlerIndex);
+        nextOffset = getOffset(nextStyle, this.direction) + this.itemMinusMap.get(handlerIndex + 1);
+        let lastItemSize = (this.direction === 'horizontal' ? lastItem.offsetWidth : lastItem.offsetHeight) + this.itemMinusMap.get(handlerIndex),
+            nextItemSize = (this.direction === 'horizontal' ? nextItem.offsetWidth : nextItem.offsetHeight) + this.itemMinusMap.get(handlerIndex + 1);
         const states = this.getStates();
         this.setState({
             isResizing: true,
             originalPosition: {
                 x: clientX,
                 y: clientY,
-                lastItemSize: (this.direction === 'horizontal' ? lastItem.offsetWidth : lastItem.offsetHeight),
-                nextItemSize: (this.direction === 'horizontal' ? nextItem.offsetWidth : nextItem.offsetHeight),
+                lastItemSize,
+                nextItemSize,
                 lastOffset,
                 nextOffset,
             },
@@ -138,33 +148,38 @@ export class ResizeGroupFoundation<P = Record<string, any>, S = Record<string, a
         const props = this.getProps();
         const { direction } = props;
         let lastItem = this._adapter.getItem(curHandler), nextItem = this._adapter.getItem(curHandler + 1);
-        let parentSize = this.direction === 'horizontal' ? this.groupRef.offsetWidth : this.groupRef.offsetHeight;
-        let availableSize = parentSize - this.totalMinus;
-
+        let parentSize = this.groupSize;
         let delta = direction === 'horizontal' ? (clientX - initX) : (clientY - initY);
         let lastNewSize = lastItemSize + delta;
         let nextNewSize = nextItemSize - delta;
 
         // 判断是否超出限制
-        let lastFlag = judgeConstraint(lastNewSize, this._adapter.getItemMin(curHandler), this._adapter.getItemMax(curHandler), availableSize, lastOffset),
-            nextFlag = judgeConstraint(nextNewSize, this._adapter.getItemMin(curHandler + 1), this._adapter.getItemMax(curHandler + 1), availableSize, nextOffset);
+        let lastFlag = judgeConstraint(lastNewSize, this._adapter.getItemMin(curHandler), this._adapter.getItemMax(curHandler), parentSize, lastOffset),
+            nextFlag = judgeConstraint(nextNewSize, this._adapter.getItemMin(curHandler + 1), this._adapter.getItemMax(curHandler + 1), parentSize, nextOffset);
 
         if (lastFlag) {
-            lastNewSize = adjustNewSize(lastNewSize, this._adapter.getItemMin(curHandler), this._adapter.getItemMax(curHandler), availableSize, lastOffset);
+            lastNewSize = adjustNewSize(lastNewSize, this._adapter.getItemMin(curHandler), this._adapter.getItemMax(curHandler), parentSize, lastOffset);
             nextNewSize = lastItemSize + nextItemSize - lastNewSize;
         }
 
         if (nextFlag) {
-            nextNewSize = adjustNewSize(nextNewSize, this._adapter.getItemMin(curHandler + 1), this._adapter.getItemMax(curHandler + 1), availableSize, nextOffset);
+            nextNewSize = adjustNewSize(nextNewSize, this._adapter.getItemMin(curHandler + 1), this._adapter.getItemMax(curHandler + 1), parentSize, nextOffset);
             lastNewSize = lastItemSize + nextItemSize - nextNewSize;
         }
 
+        let lastItemPercent = this.itemPercentMap.get(curHandler),
+            nextItemPercent = this.itemPercentMap.get(curHandler + 1);
+
+        let lastNewPercent = (lastNewSize) / parentSize * 100;
+        let nextNewPercent = lastItemPercent + nextItemPercent - lastNewPercent; // 消除浮点误差
+        this.itemPercentMap.set(curHandler, lastNewPercent);
+        this.itemPercentMap.set(curHandler + 1, nextNewPercent);
         if (direction === 'horizontal') {     
-            lastItem.style.width = (lastNewSize) / parentSize * 100 + '%';
-            nextItem.style.width = (nextNewSize) / parentSize * 100 + '%';
+            lastItem.style.width = `calc(${lastNewPercent}% - ${this.itemMinusMap.get(curHandler)}px)`;
+            nextItem.style.width = `calc(${nextNewPercent}% - ${this.itemMinusMap.get(curHandler + 1)}px)`;
         } else if (direction === 'vertical') {
-            lastItem.style.height = (lastNewSize) / parentSize * 100 + '%';
-            nextItem.style.height = (nextNewSize) / parentSize * 100 + '%';
+            lastItem.style.height = `calc(${lastNewPercent}% - ${this.itemMinusMap.get(curHandler)}px)`;
+            nextItem.style.height = `calc(${nextNewPercent}% - ${this.itemMinusMap.get(curHandler + 1)}px)`;
         }
 
         let lastFunc = this._adapter.getItemChange(curHandler),
@@ -197,13 +212,13 @@ export class ResizeGroupFoundation<P = Record<string, any>, S = Record<string, a
         this.unregisterEvents();
     }
 
-    calculateSpace = () => {
+    initSpace = () => {
         const props = this.getProps();
         const { direction } = props;
 
         // calculate accurate space for group item
         let handlerSizes = new Array(this._adapter.getHandlerCount()).fill(0);
-        let groupSize = direction === 'horizontal' ? this.groupRef.offsetWidth : this.groupRef.offsetHeight;
+        let parentSize = this.groupSize;
         this.totalMinus = 0;
         for (let i = 0; i < this._adapter.getHandlerCount(); i++) {
             let handlerSize = direction === 'horizontal' ? this._adapter.getHandler(i).offsetWidth : this._adapter.getHandler(i).offsetHeight;
@@ -225,8 +240,8 @@ export class ResizeGroupFoundation<P = Record<string, any>, S = Record<string, a
             }
             const child = this._adapter.getItem(i);
             let minSize = this._adapter.getItemMin(i), maxSize = this._adapter.getItemMax(i);
-            let minSizePercent = minSize ? getPixelSize(minSize, groupSize) / groupSize * 100 : 0,
-                maxSizePercent = maxSize ? getPixelSize(maxSize, groupSize) / groupSize * 100 : 100;
+            let minSizePercent = minSize ? getPixelSize(minSize, parentSize) / parentSize * 100 : 0,
+                maxSizePercent = maxSize ? getPixelSize(maxSize, parentSize) / parentSize * 100 : 100;
             if (minSizePercent > maxSizePercent) {
                 console.warn('[Semi ResizableItem]: min size bigger than max size');
             }    
@@ -237,21 +252,21 @@ export class ResizeGroupFoundation<P = Record<string, any>, S = Record<string, a
                 if (typeof defaultSize === 'string') {
                     if (defaultSize.endsWith('%')) {
                         itemSizePercent = parseFloat(defaultSize.slice(0, -1));
+                        this.itemPercentMap.set(i, itemSizePercent);
                     } else if (defaultSize.endsWith('px')) {
-                        itemSizePercent = parseFloat(defaultSize.slice(0, -2)) / groupSize * 100;
+                        itemSizePercent = parseFloat(defaultSize.slice(0, -2)) / parentSize * 100;
+                        this.itemPercentMap.set(i, itemSizePercent);
                     } else if (/^-?\d+(\.\d+)?$/.test(defaultSize)) {
                         // 仅由数字组成,表示按比例分配剩下空间
                         undefineLoc.set(i, parseFloat(defaultSize));
                         undefinedTotal += parseFloat(defaultSize);
                         continue;
                     }
-                } else {
+                } else if (typeof defaultSize === 'number') {
                     undefineLoc.set(i, defaultSize);
                     undefinedTotal += defaultSize;
                     continue;
                 }
-                
-
                 totalSizePercent += itemSizePercent;
                 
                 if (direction === 'horizontal') {
@@ -279,14 +294,62 @@ export class ResizeGroupFoundation<P = Record<string, any>, S = Record<string, a
     
         undefineLoc.forEach((value, key) => {
             const child = this._adapter.getItem(key);
+            const percent = value / undefinedTotal * undefineSizePercent;
+            this.itemPercentMap.set(key, percent);
             if (direction === 'horizontal') {
-                child.style.width = `calc(${undefineSizePercent / undefinedTotal * value}% - ${this.itemMinusMap.get(key)}px)`;
+                child.style.width = `calc(${percent}% - ${this.itemMinusMap.get(key)}px)`;
             } else {
-                child.style.height = `calc(${undefineSizePercent / undefinedTotal * value}% - ${this.itemMinusMap.get(key)}px)`;
+                child.style.height = `calc(${percent}% - ${this.itemMinusMap.get(key)}px)`;
             }
         });
     }
 
+    ensureConstraint = debounce(() => {
+        // 浏览器拖拽时保证px值最大最小仍生效
+        const { direction } = this.getProps();
+        const itemCount = this._adapter.getItemCount();
+        let continueFlag = true;
+        for (let i = 0; i < itemCount; i++) {
+            const child = this._adapter.getItem(i);
+            const childSize = direction === 'horizontal' ? child.offsetWidth : child.offsetHeight;
+            // 判断由非鼠标拖拽导致item的size变化过程中是否有超出限制的情况
+            const childFlag = judgeConstraint(childSize, this._adapter.getItemMin(i), this._adapter.getItemMax(i), this.groupSize, this.itemMinusMap.get(i));
+            if (childFlag) {
+                const childNewSize = adjustNewSize(childSize, this._adapter.getItemMin(i), this._adapter.getItemMax(i), this.groupSize, this.itemMinusMap.get(i));
+                for (let j = i + 1; j < itemCount; j++) {
+                    // 找到下一个没有超出限制的item
+                    const item = this._adapter.getItem(j);
+                    const itemSize = direction === 'horizontal' ? item.offsetWidth : item.offsetHeight;
+                    const itemFlag = judgeConstraint(itemSize, this._adapter.getItemMin(j), this._adapter.getItemMax(j), this.groupSize, this.itemMinusMap.get(j));
+                    if (!itemFlag) {
+                        let childPercent = this.itemPercentMap.get(i),
+                            itemPercent = this.itemPercentMap.get(j);
+                        let childNewPercent = childNewSize / this.groupSize * 100;
+                        let itemNewPercent = childPercent + itemPercent - childNewPercent;
+                        this.itemPercentMap.set(i, childNewPercent);
+                        this.itemPercentMap.set(j, itemNewPercent);
+                        if (direction === 'horizontal') {
+                            child.style.width = `calc(${childNewPercent}% - ${this.itemMinusMap.get(i)}px)`;
+                            item.style.width = `calc(${itemNewPercent}% - ${this.itemMinusMap.get(j)}px)`;
+                        } else {
+                            child.style.height = `calc(${childNewPercent}% - ${this.itemMinusMap.get(i)}px)`;
+                            item.style.height = `calc(${itemNewPercent}% - ${this.itemMinusMap.get(j)}px)`;
+                        }
+                        break;
+                    } else {
+                        if (j === itemCount - 1) {
+                            continueFlag = false;
+                            console.warn('[Semi ResizableGroup]: no enough space to adjust min/max size');
+                        }
+                    }
+                }
+            }
+            if (!continueFlag) {
+                break;
+            }
+        }
+    }, 200) 
+
     destroy(): void {
         
     }

+ 0 - 25
packages/semi-foundation/resizable/groupConstants.ts

@@ -1,25 +0,0 @@
-// group
-const rowStyleBase = {
-    width: '100%',
-    height: '8px',
-    flexShrink: 0,
-    margin: '0',
-    cursor: 'row-resize',
-} as const;
-const colStyleBase = {
-    width: '8px',
-    flexShrink: 0,
-    height: '100%',
-    margin: '0',
-    cursor: 'col-resize',
-} as const;
-
-export const directionStyles = {
-    horizontal: {
-        ...colStyleBase,
-    },
-    vertical: {
-        ...rowStyleBase,
-    }
-} as const;
-

+ 100 - 3
packages/semi-foundation/resizable/resizable.scss

@@ -1,5 +1,4 @@
-@import './variables.scss';
-
+@import "./variables.scss";
 $module: #{$prefix}-resizable;
 
 .#{$module} {
@@ -13,8 +12,83 @@ $module: #{$prefix}-resizable;
         position: absolute;
         user-select: none;
         z-index: $z-resizable_handler;
+
+        // 基础样式
+        @mixin row-resize-base {
+            width: 100%;
+            height: $height-row-handler;
+            top: 0;
+            left: 0;
+            cursor: row-resize;
+        }
+
+        @mixin col-resize-base {
+            width: $width-col-handler;
+            height: 100%;
+            top: 0;
+            left: 0;
+            cursor: col-resize;
+        }
+
+        @mixin edge-resize-base {
+            width: $width-edge-handler;
+            height: $height-edge-handler;
+            position: absolute;
+        }
+
+        // 方向样式
+        &-top {
+            @include row-resize-base;
+            top: calc(-1 * $height-row-handler / 2);
+        }
+
+        &-right {
+            @include col-resize-base;
+            left: auto;
+            right: calc(-1 * $width-col-handler / 2);
+        }
+
+        &-bottom {
+            @include row-resize-base;
+            top: auto;
+            bottom: calc(-1 * $height-row-handler / 2);
+        }
+
+        &-left {
+            @include col-resize-base;
+            left: calc(-1 * $width-col-handler / 2);
+        }
+
+        // 边角样式
+        &-topRight {
+            @include edge-resize-base;
+            right: calc(-1 * $width-edge-handler / 2);
+            top: calc(-1 * $height-edge-handler / 2);
+            cursor: ne-resize;
+        }
+
+        &-bottomRight {
+            @include edge-resize-base;
+            right: calc(-1 * $width-edge-handler / 2);
+            bottom: calc(-1 * $height-edge-handler / 2);
+            cursor: se-resize;
+        }
+
+        &-bottomLeft {
+            @include edge-resize-base;
+            left: calc(-1 * $width-edge-handler / 2);
+            bottom: calc(-1 * $height-edge-handler / 2);
+            cursor: sw-resize;
+        }
+
+        &-topLeft {
+            @include edge-resize-base;
+            left: calc(-1 * $width-edge-handler / 2);
+            top: calc(-1 * $height-edge-handler / 2);
+            cursor: nw-resize;
+        }
     }
-    
+
     &-group {
         display: flex;
         position: relative;
@@ -37,5 +111,28 @@ $module: #{$prefix}-resizable;
         justify-content: center;
         background-color: var(--semi-color-fill-0);
         opacity: 1;
+
+        &-vertical {
+            width: 100%;
+            height: $height-vertical-handler;
+            flex-shrink: 0;
+            cursor: row-resize;
+        }
+
+        &-horizontal {
+            height: 100%;
+            width: $width-horizontal-handler;
+            flex-shrink: 0;
+            cursor: col-resize;
+        }
+    }
+
+    &-background {
+        height: 100%;
+        width: 100%;
+        inset: 0;
+        z-index: $z-resizable_background;
+        opacity: 0;
+        position: fixed;
     }
 }

+ 1 - 1
packages/semi-foundation/resizable/single/index.ts

@@ -1,5 +1,5 @@
 import BaseFoundation, { DefaultAdapter } from '../../base/foundation';
-import { DEFAULT_SIZE, Size, NumberSize, Direction, NewSize } from "../singleConstants";
+import { DEFAULT_SIZE, Size, NumberSize, Direction, NewSize } from "../types";
 import { getStringSize, getNumberSize, has, calculateNewMax, findNextSnap, snap, clamp } from "../utils";
 export interface ResizableHandlerAdapter<P = Record<string, any>, S = Record<string, any>> extends DefaultAdapter<P, S> {
     registerEvent: () => void;

+ 0 - 65
packages/semi-foundation/resizable/singleConstants.ts → packages/semi-foundation/resizable/types.ts

@@ -1,71 +1,6 @@
 // single
-const rowStyleBase = {
-    width: '100%',
-    height: '10px',
-    top: '0px',
-    left: '0px',
-    cursor: 'row-resize',
-} as const;
-const colStyleBase = {
-    width: '10px',
-    height: '100%',
-    top: '0px',
-    left: '0px',
-    cursor: 'col-resize',
-} as const;
-const edgeStyleBase = {
-    width: '20px',
-    height: '20px',
-    position: 'absolute',
-} as const;
-
 export const directions = ['top', 'right', 'bottom', 'left', 'topRight', 'bottomRight', 'bottomLeft', 'topLeft'] as const;
 
-export const directionStyles = {
-    top: {
-        ...rowStyleBase,
-        top: '-5px',
-    },
-    right: {
-        ...colStyleBase,
-        left: undefined,
-        right: '-5px',
-    },
-    bottom: {
-        ...rowStyleBase,
-        top: undefined,
-        bottom: '-5px',
-    },
-    left: {
-        ...colStyleBase,
-        left: '-5px',
-    },
-    topRight: {
-        ...edgeStyleBase,
-        right: '-10px',
-        top: '-10px',
-        cursor: 'ne-resize',
-    },
-    bottomRight: {
-        ...edgeStyleBase,
-        right: '-10px',
-        bottom: '-10px',
-        cursor: 'se-resize',
-    },
-    bottomLeft: {
-        ...edgeStyleBase,
-        left: '-10px',
-        bottom: '-10px',
-        cursor: 'sw-resize',
-    },
-    topLeft: {
-        ...edgeStyleBase,
-        left: '-10px',
-        top: '-10px',
-        cursor: 'nw-resize',
-    },
-} as const;
-
 export type Direction = 'top' | 'right' | 'bottom' | 'left' | 'topRight' | 'bottomRight' | 'bottomLeft' | 'topLeft';
 
 export interface HandleClassName {

+ 7 - 6
packages/semi-foundation/resizable/utils.ts

@@ -80,7 +80,8 @@ export const calculateNewMax = (
         minWidth,
         minHeight,
     };
-};export const getItemDirection = (dir: 'vertical' | 'horizontal') => {
+};
+export const getItemDirection = (dir: 'vertical' | 'horizontal') => {
     if (dir === 'vertical') {
         return ['bottom', 'top'];
     } else {
@@ -104,10 +105,10 @@ export const judgeConstraint = (newSize: number, min: string, max: string, paren
     max = max ?? "100%";
     const minSize = getPixelSize(min, parentSize);
     const maxSize = getPixelSize(max, parentSize);
-    if (newSize <= minSize + offset) {
+    if (newSize < minSize + offset) {
         return true;
     }
-    if (newSize >= maxSize - offset) {
+    if (newSize > maxSize) {
         return true;
     }
     return false;
@@ -118,11 +119,11 @@ export const adjustNewSize = (newSize: number, min: string, max: string, parentS
     max = max ?? "100%";
     const minSize = getPixelSize(min, parentSize);
     const maxSize = getPixelSize(max, parentSize);
-    if (newSize <= minSize + offset) {
+    if (newSize < minSize + offset) {
         return minSize + offset;
     }
-    if (newSize >= maxSize - offset) {
-        return maxSize - offset;
+    if (newSize > maxSize) {
+        return maxSize;
     }
     return newSize;
 };

+ 8 - 0
packages/semi-foundation/resizable/variables.scss

@@ -1 +1,9 @@
 $z-resizable_handler: 2000 !default; // 伸缩框组件中handler的z-index
+$z-resizable_background: 2010; // 伸缩框组件中背景的z-index
+
+$height-row-handler: 10px; // 单个伸缩框中上下handler的高度
+$width-col-handler: 10px;  // 单个伸缩框中左右handler的宽度
+$width-edge-handler: 20px; // 单个伸缩框中边角handler的宽度
+$height-edge-handler: 20px; // 单个伸缩框中边角handler的高度
+$width-horizontal-handler: 10px; // 组合伸缩框中水平方向handler的宽度
+$height-vertical-handler: 10px;  // 组合伸缩框中垂直方向handler的高度

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

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

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

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

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

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

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

@@ -1,6 +1,6 @@
 {
     "name": "@douyinfe/semi-next",
-    "version": "2.69.2",
+    "version": "2.70.0-beta.0",
     "description": "Plugin that support Semi Design in Next.js",
     "author": "伍浩威 <[email protected]>",
     "homepage": "",
@@ -22,7 +22,7 @@
         "typescript": "^4"
     },
     "dependencies": {
-        "@douyinfe/semi-webpack-plugin": "2.69.2"
+        "@douyinfe/semi-webpack-plugin": "2.70.0-beta.0"
     },
     "gitHead": "eb34a4f25f002bb4cbcfa51f3df93bed868c831a"
 }

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

@@ -1,6 +1,6 @@
 {
     "name": "@douyinfe/semi-rspack-plugin",
-    "version": "2.69.2",
+    "version": "2.70.0-beta.0",
     "description": "",
     "homepage": "",
     "license": "MIT",

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

@@ -1,6 +1,6 @@
 {
     "name": "@douyinfe/semi-scss-compile",
-    "version": "2.69.2",
+    "version": "2.70.0-beta.0",
     "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.69.2",
+    "version": "2.70.0-beta.0",
     "description": "semi-theme-default",
     "keywords": [
         "semi-theme",

+ 2 - 1
packages/semi-theme-default/scss/variables.scss

@@ -48,7 +48,8 @@ $z-image_preview_header: 1; // Image 组件预览层中 header 部分 z-index
 // 正在拖拽中的元素的 z-index,需要高于所有的弹出层组件 z-index
 $z-transfer_right_item_drag_item_move: 2000; // 穿梭框右侧面板中正在拖拽元素的z-index
 $z-tagInput_drag_item_move: 2000; // 标签输入框中正在拖拽元素的z-index
-$z-resizable_handler: 2000; // 伸缩框组件中handler的z-index   
+$z-resizable_handler: 2000; // 伸缩框组件中handler的z-index 
+// $z-resizable_background: 2010; // 伸缩框组件中背景的z-index
 
 // font
 $font-family-regular: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI',

+ 2 - 0
packages/semi-ui/_utils/semi-global.ts

@@ -17,6 +17,7 @@ import type { TabsProps } from "../tabs";
 import type { TimePickerProps } from "../timePicker";
 import type { ToastReactProps } from "../toast";
 import type { TooltipProps } from "../tooltip";
+import type { MarkdownRenderProps } from "../markdownRender";
 
 class SemiGlobal {
 
@@ -25,6 +26,7 @@ class SemiGlobal {
             // "Anchor"?: Partial<AnchorProps>;
             "AutoComplete"?: Partial<AutoCompleteProps<any>>;
             "Avatar"?: Partial<AvatarProps>;
+            "MarkdownRender"?: Partial<MarkdownRenderProps>;
             // BackTop?: Partial<BackTopProps>;
             // Badge?: Partial<BadgeProps>;
             // Banner?: Partial<BannerProps>;

+ 4 - 2
packages/semi-ui/markdownRender/index.tsx

@@ -41,11 +41,13 @@ class MarkdownRender extends BaseComponent<MarkdownRenderProps, MarkdownRenderSt
         raw: PropTypes.string,
         remarkPlugins: PropTypes.arrayOf(PropTypes.object),
         rehypePlugins: PropTypes.arrayOf(PropTypes.object),
+        remarkGfm: PropTypes.bool,
     }
 
     static __SemiComponentName__ = "MarkdownRender";
     static defaultProps = getDefaultPropsFromGlobalConfig(MarkdownRender.__SemiComponentName__, {
-        format: "mdx"
+        format: "mdx",
+        remarkGfm: true,
     })
 
     componentDidUpdate(prevProps: Readonly<MarkdownRenderProps>, prevState: Readonly<MarkdownRenderState>, snapshot?: any) {
@@ -57,7 +59,7 @@ class MarkdownRender extends BaseComponent<MarkdownRenderProps, MarkdownRenderSt
     get adapter(): MarkdownRenderAdapter<MarkdownRenderProps, MarkdownRenderState> {
         return {
             ...super.adapter,
-            getRuntime: ()=>runtime
+            getRuntime: () => runtime
         };
     }
 

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

@@ -1,6 +1,6 @@
 {
     "name": "@douyinfe/semi-ui",
-    "version": "2.69.2",
+    "version": "2.70.0-beta.0",
     "description": "A modern, comprehensive, flexible design system and UI library. Connect DesignOps & DevOps. Quickly build beautiful React apps. Maintained by Douyin-fe team.",
     "main": "lib/cjs/index.js",
     "module": "lib/es/index.js",
@@ -20,12 +20,12 @@
         "@dnd-kit/core": "^6.0.8",
         "@dnd-kit/sortable": "^7.0.2",
         "@dnd-kit/utilities": "^3.2.1",
-        "@douyinfe/semi-animation": "2.69.2",
-        "@douyinfe/semi-animation-react": "2.69.2",
-        "@douyinfe/semi-foundation": "2.69.2",
-        "@douyinfe/semi-icons": "2.69.2",
-        "@douyinfe/semi-illustrations": "2.69.2",
-        "@douyinfe/semi-theme-default": "2.69.2",
+        "@douyinfe/semi-animation": "2.70.0-beta.0",
+        "@douyinfe/semi-animation-react": "2.70.0-beta.0",
+        "@douyinfe/semi-foundation": "2.70.0-beta.0",
+        "@douyinfe/semi-icons": "2.70.0-beta.0",
+        "@douyinfe/semi-illustrations": "2.70.0-beta.0",
+        "@douyinfe/semi-theme-default": "2.70.0-beta.0",
         "async-validator": "^3.5.0",
         "classnames": "^2.2.6",
         "copy-text-to-clipboard": "^2.1.1",

+ 163 - 5
packages/semi-ui/resizable/_story/resizable.stories.jsx

@@ -7,6 +7,108 @@ export default {
 
 import { ResizeItem, ResizeHandler, ResizeGroup } from '../../index'
 
+export const Group = () => {
+  const [text, setText] = useState('Drag to resize')
+  return (
+    <div style={{ width: '1118px', height: '600px' }}>
+      <ResizeGroup direction='vertical'>
+        <ResizeItem
+          defaultSize={"80%"}
+        >
+          <ResizeGroup direction='horizontal'>
+            <ResizeItem
+              style={{ backgroundColor: 'rgba(var(--semi-grey-1), 1)', border: 'var(--semi-color-border) 1px solid' }}
+              defaultSize={"25%"}
+              min={'10%'}
+              max={'30%'}
+            >
+              <div style={{ marginLeft: '20%' }}>
+                {text + ' min:10% max:30%'}
+              </div>
+            </ResizeItem>
+            <ResizeHandler></ResizeHandler>
+            <ResizeItem
+              style={{ border: 'var(--semi-color-border) 1px solid' }}
+              defaultSize={"50%"}
+            >
+              <div style={{ height: '100%' }}>
+                <ResizeGroup direction='vertical'>
+                  <ResizeItem
+                    style={{ backgroundColor: 'rgba(var(--semi-grey-1), 1)', border: 'var(--semi-color-border) 1px solid' }}
+                    defaultSize={'33%'}
+                    min={'10%'}
+                    onChange={(a, b, c) => { setText('resizing'); console.log(a, b, c)  }}
+                    onResizeEnd={() => { setText('Drag to resize') }}
+                  >
+                    <div style={{ marginLeft: '20%' }}>
+                      {text + " min:10%"}
+                    </div>
+                  </ResizeItem>
+                  <ResizeHandler></ResizeHandler>
+                  <ResizeItem
+                    style={{ backgroundColor: 'rgba(var(--semi-grey-1), 1)', border: 'var(--semi-color-border) 1px solid' }}
+                    defaultSize={'33%'}
+                    min={'10%'}
+                    max={'40%'}
+                  >
+                    <div style={{ marginLeft: '20%' }}>
+                      {text + " min:10% max:40%"}
+                    </div>
+                  </ResizeItem>
+                  <ResizeHandler></ResizeHandler>
+                  <ResizeItem
+                    style={{ backgroundColor: 'rgba(var(--semi-grey-1), 1)', border: 'var(--semi-color-border) 1px solid' }}
+                  >
+                    <div style={{ marginLeft: '20%' }}>
+                      {text}
+                    </div>
+                  </ResizeItem>
+                </ResizeGroup>
+              </div>
+            </ResizeItem>
+            <ResizeHandler></ResizeHandler>
+            <ResizeItem
+              style={{ backgroundColor: 'rgba(var(--semi-grey-1), 1)', border: 'var(--semi-color-border) 1px solid' }}
+              defaultSize={"1"}
+              max={'30%'}
+            >
+              <div style={{ marginLeft: '20%' }}>
+                {text + ' max:30%'}
+              </div>
+            </ResizeItem>
+            
+          </ResizeGroup>
+        </ResizeItem>
+        <ResizeHandler></ResizeHandler>
+        <ResizeItem
+          defaultSize={"20%"}
+          onChange={() => { setText('resizing') }}
+        >
+          <ResizeGroup direction='horizontal'>
+            <ResizeItem
+              style={{ backgroundColor: 'rgba(var(--semi-grey-1), 1)', border: 'var(--semi-color-border) 1px solid' }}
+              defaultSize={"50%"}
+            >
+              <div style={{ marginLeft: '20%' }}>
+                {'tab'}
+              </div>
+            </ResizeItem>
+            <ResizeHandler></ResizeHandler>
+            <ResizeItem
+              style={{ backgroundColor: 'rgba(var(--semi-grey-1), 1)', border: 'var(--semi-color-border) 1px solid' }}
+              defaultSize={"50%"}
+            >
+              <div style={{ marginLeft: '20%' }}>
+                {'content'}
+              </div>
+            </ResizeItem>
+          </ResizeGroup>
+        </ResizeItem>
+      </ResizeGroup>
+    </div>
+  );
+}
+
 export const Group_layout = () => {
   const [text, setText] = useState('test')
   const opts_1 = {
@@ -228,13 +330,13 @@ export const Group_horizontal = () => {
       <ResizeGroup direction='horizontal'>
         <ResizeItem
           style={{ backgroundColor: 'rgba(var(--semi-grey-1), 1)', }}
-          defaultSize={2}
-          min={'10%'}
+          defaultSize={'15%'}
+          min={'50px'}
           onChange={() => { setText('resizing') }}
           onResizeEnd={() => { setText('test') }}
         >
           <div style={{ marginLeft: '20%', border: 'var(--semi-color-border) solid 1px', padding:'5px' }}>
-            {text + " min:10%"}
+            {text + " min:50px"}
           </div>
         </ResizeItem>
         <ResizeHandler></ResizeHandler>
@@ -252,13 +354,69 @@ export const Group_horizontal = () => {
         <ResizeHandler></ResizeHandler>
         <ResizeItem
           style={{ backgroundColor: 'rgba(var(--semi-grey-1), 1)',  }}
-          defaultSize={'600px'}
+          defaultSize={'300px'}
+          onChange={() => { setText('resizing') }}
+        >
+          <div style={{ marginLeft: '20%', border: 'var(--semi-color-border) solid 1px', padding:'5px' }}>
+            {text}
+          </div>
+        </ResizeItem>
+        <ResizeHandler></ResizeHandler>
+        <ResizeItem
+          style={{ backgroundColor: 'rgba(var(--semi-grey-1), 1)',  }}
+          defaultSize={1.3}
           onChange={() => { setText('resizing') }}
         >
           <div style={{ marginLeft: '20%', border: 'var(--semi-color-border) solid 1px', padding:'5px' }}>
             {text}
           </div>
         </ResizeItem>
+      </ResizeGroup>
+    </div>
+  );
+}
+
+export const Group_dynamic_direction = () => {
+  const [text, setText] = useState('drag to resize')
+  const [direction, setDirection] = useState('horizontal')
+
+  const changeDirection = () => {
+    if (direction === 'horizontal') {
+      setDirection('vertical')
+    } else {
+      setDirection('horizontal')
+    }
+  }
+  return (
+    <div style={{ width: '1000px', height: '500px' }}>
+      <Button onClick={changeDirection}>{direction}</Button>
+      <ResizeGroup direction={direction}>
+        <ResizeItem
+          onChange={() => { setText('resizing') }}
+          onResizeEnd={() => { setText('drag to resize') }}
+          defaultSize={8}
+        >
+            <ResizeGroup direction='horizontal'>
+              <ResizeItem
+                style={{ backgroundColor: 'rgba(var(--semi-grey-1), 1)', }}
+                onChange={() => { setText('resizing') }}
+                onResizeEnd={() => { setText('drag to resize') }}
+              >
+                <div style={{ marginLeft: '20%', border: 'var(--semi-color-border) solid 1px', padding:'5px' }}>
+                  {text}
+                </div>
+              </ResizeItem>
+              <ResizeHandler></ResizeHandler>
+              <ResizeItem
+                style={{ backgroundColor: 'rgba(var(--semi-grey-1), 1)', }}
+                onChange={() => { setText('resizing') }}
+              >
+                <div style={{ marginLeft: '20%', border: 'var(--semi-color-border) solid 1px', padding:'5px' }}>
+                  {text}
+                </div>
+              </ResizeItem>
+            </ResizeGroup>
+        </ResizeItem>
         <ResizeHandler></ResizeHandler>
         <ResizeItem
           style={{ backgroundColor: 'rgba(var(--semi-grey-1), 1)',  }}
@@ -307,7 +465,7 @@ export const Single_defaultSize = () => {
   );
 }
 
-export const Single_Enabel = () => {
+export const Single_Enable = () => {
   const [b, setB] = useState(false)
   return (
     <div style={{ width: '500px', height: '60%' }}>

+ 1 - 1
packages/semi-ui/resizable/group/resizeContext.ts

@@ -1,5 +1,5 @@
 import React, { createContext, RefObject } from 'react';
-import { ResizeCallback, ResizeStartCallback } from '@douyinfe/semi-foundation/resizable/singleConstants';
+import { ResizeCallback, ResizeStartCallback } from '@douyinfe/semi-foundation/resizable/types';
 
 export interface ResizeContextProps {
     direction: 'horizontal' | 'vertical';

+ 51 - 40
packages/semi-ui/resizable/group/resizeGroup.tsx

@@ -1,11 +1,11 @@
-import React, { createContext, createRef, ReactNode, Ref, RefObject } from 'react';
+import React, { createRef, ReactNode, RefObject } from 'react';
 import classNames from 'classnames';
 import PropTypes from 'prop-types';
 import { ResizeGroupFoundation, ResizeGroupAdapter } from '@douyinfe/semi-foundation/resizable/foundation';
 import { cssClasses } from '@douyinfe/semi-foundation/resizable/constants';
 import BaseComponent from '../../_base/baseComponent';
 import { ResizeContext, ResizeContextProps } from './resizeContext';
-import { ResizeCallback, ResizeStartCallback } from '@douyinfe/semi-foundation/resizable/singleConstants';
+import { ResizeCallback, ResizeStartCallback } from '@douyinfe/semi-foundation/resizable/types';
 import "@douyinfe/semi-foundation/resizable/resizable.scss";
 
 const prefixCls = cssClasses.PREFIX;
@@ -27,7 +27,8 @@ export interface ResizeGroupState {
         nextOffset: number
     };
     backgroundStyle: React.CSSProperties;
-    curHandler: number
+    curHandler: number;
+    contextValue: ResizeContextProps
 }
 
 class ResizeGroup extends BaseComponent<ResizeGroupProps, ResizeGroupState> {
@@ -41,6 +42,8 @@ class ResizeGroup extends BaseComponent<ResizeGroupProps, ResizeGroupState> {
 
     constructor(props: ResizeGroupProps) {
         super(props);
+        this.groupRef = createRef();
+        this.foundation = new ResizeGroupFoundation(this.adapter);
         this.state = {
             isResizing: false,
             originalPosition: {
@@ -52,68 +55,69 @@ class ResizeGroup extends BaseComponent<ResizeGroupProps, ResizeGroupState> {
                 nextOffset: 0,
             },
             backgroundStyle: {
-                height: '100%',
-                width: '100%',
-                backgroundColor: 'rgba(0,0,0,0)',
                 cursor: 'auto',
-                opacity: 0,
-                position: 'fixed',
-                zIndex: 9999,
-                top: '0',
-                left: '0',
-                bottom: '0',
-                right: '0',
             },
             curHandler: null,
-        };
-        
-        this.groupRef = createRef();
-        this.foundation = new ResizeGroupFoundation(this.adapter);
-        this.contextValue = {
-            direction: props.direction,
-            registerItem: this.registerItem,
-            registerHandler: this.registerHandler,
-            notifyResizeStart: this.foundation.onResizeStart,
-            getGroupSize: this.getGroupSize,
+            contextValue: {
+                direction: props.direction,
+                registerItem: this.registerItem,
+                registerHandler: this.registerHandler,
+                notifyResizeStart: this.foundation.onResizeStart,
+                getGroupSize: this.getGroupSize,
+            },
         };
     }
 
-    contextValue: ResizeContextProps;
     foundation: ResizeGroupFoundation;
     groupRef: React.RefObject<HTMLDivElement>;
     groupSize: number;
     availableSize: number;
     static contextType = ResizeContext;
     context: ResizeGroupProps;
-    itemRefs: RefObject<HTMLDivElement>[] = [];
+    // 在context中使用的属性需要考虑在strictMode下会执行两次,所以用Map来维护
+    itemRefs: Map<number, RefObject<HTMLDivElement>> = new Map();
     itemMinMap: Map<number, string> = new Map();
     itemMaxMap: Map<number, string> = new Map();
     itemMinusMap: Map<number, number> = new Map();
-    itemDefaultSizeList: (string|number)[] = []
+    itemDefaultSizeList: Map<number, (string|number)> = new Map();
     itemResizeStart: Map<number, ResizeStartCallback> = new Map();
     itemResizing: Map<number, ResizeCallback> = new Map();
     itemResizeEnd: Map<number, ResizeCallback> = new Map();
-    handlerRefs: RefObject<HTMLDivElement>[] = [];
+    handlerRefs: Map<number, RefObject<HTMLDivElement>> = new Map();
 
     componentDidMount() {
         this.foundation.init();
+        // 监听窗口大小变化,保证一些限制仍生效
+        window.addEventListener('resize', this.foundation.ensureConstraint);
     }
 
-    componentDidUpdate(_prevProps: ResizeGroupProps) {
+    componentDidUpdate(prevProps: ResizeGroupProps) {
+        // 支持动态调整伸缩direction
+        if (this.props.direction !== prevProps.direction) {
+            this.setState((prevState) => ({
+                ...prevState, // 保留其他状态
+                contextValue: {
+                    ...prevState.contextValue, // 保留其他上下文值
+                    direction: this.props.direction,
+                }
+            }));
+            this.foundation.direction = this.props.direction;
+        }
     }
 
     componentWillUnmount() {
         this.foundation.destroy();
+        window.removeEventListener('resize', this.foundation.ensureConstraint);
     }
 
     get adapter(): ResizeGroupAdapter<ResizeGroupProps, ResizeGroupState> {
         return {
             ...super.adapter,
             getGroupRef: () => this.groupRef.current,
-            getItem: (id: number) => this.itemRefs[id].current,
-            getItemCount: () => this.itemRefs.length,
-            getHandler: (id: number) => this.handlerRefs[id].current,
-            getHandlerCount: () => this.handlerRefs.length,
+            getItem: (id: number) => this.itemRefs.get(id).current,
+            getItemCount: () => this.itemRefs.size,
+            getHandler: (id: number) => this.handlerRefs.get(id).current,
+            getHandlerCount: () => this.handlerRefs.size,
             getItemMin: (index) => {
                 return this.itemMinMap.get(index);
             },
@@ -130,7 +134,7 @@ class ResizeGroup extends BaseComponent<ResizeGroupProps, ResizeGroupState> {
                 return this.itemResizeStart.get(index);
             },
             getItemDefaultSize: (index) => {
-                return this.itemDefaultSizeList[index];
+                return this.itemDefaultSizeList.get(index);
             },
             registerEvents: this.registerEvent,
             unregisterEvents: this.unregisterEvent,
@@ -161,11 +165,14 @@ class ResizeGroup extends BaseComponent<ResizeGroupProps, ResizeGroupState> {
         min: string, max: string, defaultSize: string|number,
         onResizeStart: ResizeStartCallback, onChange: ResizeCallback, onResizeEnd: ResizeCallback
     ) => {
-        this.itemRefs.push(ref);
-        let index = this.itemRefs.length - 1;
+        if (Array.from(this.itemRefs.values()).some(r => r === ref)) {
+            return -1;
+        }
+        let index = this.itemRefs.size;
+        this.itemRefs.set(index, ref);
         this.itemMinMap.set(index, min);
         this.itemMaxMap.set(index, max);
-        this.itemDefaultSizeList.push(defaultSize);
+        this.itemDefaultSizeList.set(index, defaultSize);
         this.itemResizeStart.set(index, onResizeStart);
         this.itemResizing.set(index, onChange);
         this.itemResizeEnd.set(index, onResizeEnd);
@@ -173,8 +180,12 @@ class ResizeGroup extends BaseComponent<ResizeGroupProps, ResizeGroupState> {
     }
 
     registerHandler = (ref: RefObject<HTMLDivElement>) => {
-        this.handlerRefs.push(ref);
-        return this.handlerRefs.length - 1;
+        if (Array.from(this.handlerRefs.values()).some(r => r === ref)) {
+            return -1;
+        }
+        let index = this.handlerRefs.size;
+        this.handlerRefs.set(index, ref);
+        return index;
     }
 
     getGroupSize = () => {
@@ -184,7 +195,7 @@ class ResizeGroup extends BaseComponent<ResizeGroupProps, ResizeGroupState> {
     render() {
         const { children, direction, className, ...rest } = this.props;
         return (
-            <ResizeContext.Provider value={this.contextValue}>
+            <ResizeContext.Provider value={this.state.contextValue}>
                 <div
                     style={{
                         flexDirection: direction === 'vertical' ? 'column' : 'row',
@@ -193,7 +204,7 @@ class ResizeGroup extends BaseComponent<ResizeGroupProps, ResizeGroupState> {
                     className={classNames(className, prefixCls + '-group')}
                     {...rest}
                 >
-                    {this.state.isResizing && <div style={this.state.backgroundStyle} />}
+                    {this.state.isResizing && <div style={this.state.backgroundStyle} className={classNames(className, prefixCls + '-background')}/>}
                     {children}
                 </div>
             </ResizeContext.Provider>

+ 8 - 9
packages/semi-ui/resizable/group/resizeHandler.tsx

@@ -3,8 +3,7 @@ import classNames from 'classnames';
 import PropTypes from 'prop-types';
 import { ResizeHandlerFoundation, ResizeHandlerAdapter } from '@douyinfe/semi-foundation/resizable/foundation';
 import { cssClasses } from '@douyinfe/semi-foundation/resizable/constants';
-import { Direction, HandlerCallback } from '@douyinfe/semi-foundation/resizable/singleConstants';
-import { directionStyles } from '@douyinfe/semi-foundation/resizable/groupConstants';
+import { Direction, HandlerCallback } from '@douyinfe/semi-foundation/resizable/types';
 import BaseComponent from '../../_base/baseComponent';
 import { ResizeContext, ResizeContextProps } from './resizeContext';
 import { IconHandle } from '@douyinfe/semi-icons';
@@ -43,11 +42,14 @@ class ResizeHandler extends BaseComponent<ResizeHandlerProps, ResizeHandlerState
         };
         this.handlerRef = createRef();
         this.foundation = new ResizeHandlerFoundation(this.adapter);
+        this.handlerIndex = -1;
     }
 
     componentDidMount() {
         this.foundation.init();
-        this.handlerIndex = this.context.registerHandler(this.handlerRef);
+        if (this.handlerIndex === -1) {
+            this.handlerIndex = this.context.registerHandler(this.handlerRef);
+        }
     }
 
     componentDidUpdate(_prevProps: ResizeHandlerProps) {
@@ -85,15 +87,12 @@ class ResizeHandler extends BaseComponent<ResizeHandlerProps, ResizeHandlerState
     handlerIndex: number;
 
     render() {
-        
         const { style, className, children } = this.props;
+        const { direction } = this.context;
         return (
             <div
-                className={classNames(className, prefixCls + '-handler')}
-                style={{
-                    ...directionStyles[this.context.direction],
-                    ...style
-                }}
+                className={classNames(className, prefixCls + '-handler', prefixCls + '-handler-' + direction)}
+                style={style}
                 ref={this.handlerRef}
             >
                 {children ?? <IconHandle size='inherit' style={{

+ 22 - 4
packages/semi-ui/resizable/group/resizeItem.tsx

@@ -1,10 +1,10 @@
-import React, { createRef, ReactNode, useContext } from 'react';
+import React, { createRef } from 'react';
 import classNames from 'classnames';
 import PropTypes from 'prop-types';
 import { ResizeItemFoundation, ResizeItemAdapter } from '@douyinfe/semi-foundation/resizable/foundation';
 import { cssClasses } from '@douyinfe/semi-foundation/resizable/constants';
 import BaseComponent from '../../_base/baseComponent';
-import { ResizeCallback, ResizeStartCallback } from '@douyinfe/semi-foundation/resizable/singleConstants';
+import { ResizeCallback, ResizeStartCallback } from '@douyinfe/semi-foundation/resizable/types';
 import { ResizeContext, ResizeContextProps } from './resizeContext';
 import { noop } from 'lodash';
 
@@ -51,16 +51,33 @@ class ResizeItem extends BaseComponent<ResizeItemProps, ResizeItemState> {
         this.state = {
             isResizing: false,
         };
-
+        this.itemIndex = -1;
     }
 
     componentDidMount() {
         this.foundation.init();
         const { min, max, onResizeStart, onChange, onResizeEnd, defaultSize } = this.props;
-        this.itemIndex = this.context.registerItem(this.itemRef, min, max, defaultSize, onResizeStart, onChange, onResizeEnd);
+        if (this.itemIndex === -1) {
+            // 开发过程在StrictMode下context方法会执行两次,需要判断一下是否已经注册过
+            this.itemIndex = this.context.registerItem(this.itemRef, min, max, defaultSize, onResizeStart, onChange, onResizeEnd);
+        }
+        this.direction = this.context.direction; // 留一个direction的引用,方便在componentDidUpdate中判断方向是否有变化
     }
 
     componentDidUpdate(_prevProps: ResizeItemProps) {
+        // 支持动态方向,修改item的style
+        if (this.context.direction !== this.direction) {
+            this.direction = this.context.direction;
+            if (this.direction === 'horizontal') {
+                const newWidth = this.itemRef.current?.style.height;
+                this.itemRef.current.style.width = newWidth;
+                this.itemRef.current.style.removeProperty('height');
+            } else {
+                const newHeight = this.itemRef.current?.style.width;
+                this.itemRef.current.style.height = newHeight;
+                this.itemRef.current.style.removeProperty('width');
+            }
+        }
     }
 
     componentWillUnmount() {
@@ -74,6 +91,7 @@ class ResizeItem extends BaseComponent<ResizeItemProps, ResizeItemState> {
     }
     static contextType = ResizeContext;
     context: ResizeContextProps;
+    direction: 'horizontal' | 'vertical';
     itemRef: React.RefObject<HTMLDivElement | null>;
     itemIndex: number;
 

+ 2 - 12
packages/semi-ui/resizable/single/resizable.tsx

@@ -4,7 +4,7 @@ import PropTypes from 'prop-types';
 import { ResizableFoundation, ResizableAdapter } from '@douyinfe/semi-foundation/resizable/foundation';
 
 import { cssClasses, } from '@douyinfe/semi-foundation/resizable/constants';
-import { Direction, Size, Enable, ResizeStartCallback, ResizeCallback, HandleClassName, directions } from '@douyinfe/semi-foundation/resizable/singleConstants';
+import { Direction, Size, Enable, ResizeStartCallback, ResizeCallback, HandleClassName, directions } from '@douyinfe/semi-foundation/resizable/types';
 import BaseComponent from '../../_base/baseComponent';
 import ResizableHandler from './resizableHandler';
 import '@douyinfe/semi-foundation/resizable/resizable.scss';
@@ -159,17 +159,7 @@ class Resizable extends BaseComponent<ResizableProps, ResizableState> {
                 height: 0,
             },
             backgroundStyle: {
-                height: '100%',
-                width: '100%',
-                backgroundColor: 'rgba(0,0,0,0)',
                 cursor: 'auto',
-                opacity: 0,
-                position: 'fixed',
-                zIndex: 9999,
-                top: '0',
-                left: '0',
-                bottom: '0',
-                right: '0',
             },
             flexBasis: undefined,
         };        
@@ -262,7 +252,7 @@ class Resizable extends BaseComponent<ResizableProps, ResizableState> {
                 ref={this.resizableRef}
                 {...this.getDataAttr(this.props)}
             >
-                {this.state.isResizing && <div style={this.state.backgroundStyle} />}
+                {this.state.isResizing && <div style={this.state.backgroundStyle} className={classNames(className, prefixCls + '-background')}/>}
                 {children}
                 {this.renderResizeHandler()}
             </div>

+ 2 - 3
packages/semi-ui/resizable/single/resizableHandler.tsx

@@ -4,7 +4,7 @@ import PropTypes from 'prop-types';
 import { ResizableHandlerFoundation, ResizableHandlerAdapter } from '@douyinfe/semi-foundation/resizable/foundation';
 
 import { cssClasses } from '@douyinfe/semi-foundation/resizable/constants';
-import { directionStyles, Direction, HandlerCallback } from '@douyinfe/semi-foundation/resizable/singleConstants';
+import { Direction, HandlerCallback } from '@douyinfe/semi-foundation/resizable/types';
 import BaseComponent from '../../_base/baseComponent';
 
 const prefixCls = cssClasses.PREFIX;
@@ -74,9 +74,8 @@ class ResizableHandler extends BaseComponent<ResizableHandlerProps, ResizableHan
         const { children, style, className } = this.props;
         return (
             <div 
-                className={classNames(className, prefixCls + '-resizableHandler')}
+                className={classNames(className, prefixCls + '-resizableHandler', prefixCls + '-resizableHandler-' + this.props.direction)}
                 style={{
-                    ...directionStyles[this.props.direction],
                     ...style
                 }} 
                 ref={this.resizeHandlerRef}

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

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

+ 149 - 149
sitemap.xml

@@ -2,22 +2,22 @@
 <urlset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd" xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
     <url>
         <loc>https://juejin.cn/post/7267418854124699702</loc>
-        <lastmod>2024-11-19T06:14:58.919Z</lastmod>
+        <lastmod>2024-11-18T09:42:21.798Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://medium.com/front-end-weekly/how-we-test-semi-design-component-libraries-64b854f63b65</loc>
-        <lastmod>2024-11-19T06:14:58.319Z</lastmod>
+        <lastmod>2024-11-18T09:42:19.844Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://mp.weixin.qq.com/s/noHoWRuA25PgqFNcurhIUA</loc>
-        <lastmod>2024-11-19T06:15:17.036Z</lastmod>
+        <lastmod>2024-11-18T09:42:22.627Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://mp.weixin.qq.com/s/O3js-SZDNPEOjGxh-aAkbw</loc>
-        <lastmod>2024-11-19T06:15:01.521Z</lastmod>
+        <lastmod>2024-11-18T09:42:22.323Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
@@ -784,82 +784,82 @@
     </url>
     <url>
         <loc>https://semi.design/dsm/landing</loc>
-        <lastmod>2024-11-19T06:15:08.173Z</lastmod>
+        <lastmod>2024-11-18T09:42:33.769Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/basic/divider</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/basic/grid</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/basic/icon</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/basic/layout</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/basic/space</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/basic/tokens</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/basic/typography</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/feedback/banner</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/feedback/notification</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/feedback/popconfirm</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/feedback/progress</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/feedback/skeleton</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/feedback/spin</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/feedback/toast</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/input/autocomplete</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
@@ -869,362 +869,362 @@
     </url>
     <url>
         <loc>https://semi.design/en-US/input/cascader</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/input/checkbox</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/input/datepicker</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/input/form</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/input/input</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/input/inputnumber</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/input/radio</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/input/rating</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/input/select</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/input/slider</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/input/switch</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/input/taginput</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/input/timepicker</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/input/transfer</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/input/treeselect</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/input/upload</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/navigation/anchor</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/navigation/backtop</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/navigation/breadcrumb</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/navigation/navigation</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/navigation/pagination</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/navigation/steps</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/navigation/tabs</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/navigation/tree</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/other/configprovider</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/other/locale</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/show/avatar</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/show/badge</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/show/calendar</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/show/card</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/show/carousel</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/show/collapse</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/show/collapsible</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/show/descriptions</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/show/dropdown</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/show/empty</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/show/highlight</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/show/image</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/show/list</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/show/modal</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/show/overflowlist</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/show/popover</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/show/scrolllist</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/show/sidesheet</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/show/table</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/show/tag</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/show/timeline</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/show/tooltip</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/start/accessibility</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/start/changelog</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/start/customize-theme</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/start/dark-mode</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/start/faq</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/start/getting-started</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/start/introduction</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/start/overview</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/start/update-to-v2</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/basic/divider</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/basic/grid</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/basic/icon</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/basic/layout</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/basic/space</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/basic/tokens</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/basic/typography</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/feedback/banner</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/feedback/notification</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/feedback/popconfirm</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/feedback/progress</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/feedback/skeleton</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/feedback/spin</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/feedback/toast</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/input/autocomplete</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
@@ -1234,287 +1234,287 @@
     </url>
     <url>
         <loc>https://semi.design/zh-CN/input/cascader</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/input/checkbox</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/input/datepicker</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/input/form</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/input/input</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/input/inputnumber</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/input/radio</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/input/rating</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/input/select</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/input/slider</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/input/switch</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/input/taginput</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/input/timepicker</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/input/transfer</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/input/treeselect</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/input/upload</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/navigation/anchor</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/navigation/backtop</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/navigation/breadcrumb</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/navigation/navigation</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/navigation/pagination</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/navigation/steps</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/navigation/tabs</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/navigation/tree</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/other/configprovider</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/other/locale</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/show/avatar</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/show/badge</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/show/calendar</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/show/card</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/show/carousel</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/show/collapse</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/show/collapsible</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/show/descriptions</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/show/dropdown</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/show/empty</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/show/highlight</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/show/image</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/show/list</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/show/modal</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/show/overflowlist</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/show/popover</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/show/scrolllist</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/show/sidesheet</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/show/table</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/show/tag</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/show/timeline</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/show/tooltip</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/start/accessibility</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/start/changelog</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/start/customize-theme</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/start/dark-mode</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/start/faq</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/start/getting-started</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/start/introduction</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/start/overview</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/start/update-to-v2</loc>
-        <lastmod>2024-11-19T06:11:54.000Z</lastmod>
+        <lastmod>2024-11-18T09:32:30.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
 </urlset>