代强 1 год назад
Родитель
Сommit
23e8755de5
79 измененных файлов с 3163 добавлено и 586 удалено
  1. 1 1
      content/feedback/progress/index-en-US.md
  2. 1 1
      content/feedback/progress/index.md
  3. 1 1
      content/input/datepicker/index-en-US.md
  4. 1 1
      content/input/datepicker/index.md
  5. 35 34
      content/input/input/index.md
  6. 44 27
      content/input/slider/index-en-US.md
  7. 43 26
      content/input/slider/index.md
  8. 1 0
      content/input/treeselect/index-en-US.md
  9. 1 0
      content/input/treeselect/index.md
  10. 167 17
      content/show/avatar/index-en-US.md
  11. 164 17
      content/show/avatar/index.md
  12. 47 0
      content/show/modal/index-en-US.md
  13. 47 0
      content/show/modal/index.md
  14. 292 0
      content/show/table/index-en-US.md
  15. 290 0
      content/show/table/index.md
  16. 18 0
      content/start/changelog/index-en-US.md
  17. 18 0
      content/start/changelog/index.md
  18. 8 0
      cypress/e2e/datePicker.spec.js
  19. 34 1
      cypress/e2e/table.spec.js
  20. 1 1
      lerna.json
  21. 1 1
      package.json
  22. 3 3
      packages/semi-animation-react/package.json
  23. 1 1
      packages/semi-animation-styled/package.json
  24. 1 1
      packages/semi-animation/package.json
  25. 1 1
      packages/semi-eslint-plugin/package.json
  26. 19 0
      packages/semi-foundation/avatar/animation.scss
  27. 313 0
      packages/semi-foundation/avatar/avatar.scss
  28. 66 10
      packages/semi-foundation/avatar/variables.scss
  29. 7 4
      packages/semi-foundation/datePicker/foundation.ts
  30. 12 3
      packages/semi-foundation/input/input.scss
  31. 5 0
      packages/semi-foundation/input/variables.scss
  32. 5 1
      packages/semi-foundation/modal/modal.scss
  33. 2 1
      packages/semi-foundation/modal/modalFoundation.ts
  34. 4 0
      packages/semi-foundation/modal/variables.scss
  35. 2 2
      packages/semi-foundation/package.json
  36. 3 4
      packages/semi-foundation/select/select.scss
  37. 7 6
      packages/semi-foundation/select/variables.scss
  38. 1 0
      packages/semi-foundation/slider/constants.ts
  39. 8 1
      packages/semi-foundation/slider/foundation.ts
  40. 10 0
      packages/semi-foundation/slider/slider.scss
  41. 2 0
      packages/semi-foundation/slider/variables.scss
  42. 2 0
      packages/semi-foundation/treeSelect/foundation.ts
  43. 1 1
      packages/semi-icons-lab/package.json
  44. 1 1
      packages/semi-icons/package.json
  45. 1 1
      packages/semi-illustrations/package.json
  46. 2 2
      packages/semi-next/package.json
  47. 1 1
      packages/semi-rspack/package.json
  48. 1 1
      packages/semi-scss-compile/package.json
  49. 1 1
      packages/semi-theme-default/package.json
  50. 3 1
      packages/semi-ui/_utils/index.tsx
  51. 36 0
      packages/semi-ui/avatar/TopSlotSvg.tsx
  52. 121 1
      packages/semi-ui/avatar/_story/avatar.stories.jsx
  53. 177 24
      packages/semi-ui/avatar/index.tsx
  54. 26 3
      packages/semi-ui/avatar/interface.ts
  55. 23 0
      packages/semi-ui/datePicker/_story/v2/PresetsFunctionType.tsx
  56. 1 0
      packages/semi-ui/datePicker/_story/v2/index.js
  57. 1 1
      packages/semi-ui/dropdown/__test__/dropdown.test.js
  58. 5 4
      packages/semi-ui/dropdown/dropdownItem.tsx
  59. 2 2
      packages/semi-ui/input/_story/input.stories.jsx
  60. 15 3
      packages/semi-ui/input/index.tsx
  61. 7 1
      packages/semi-ui/modal/Modal.tsx
  62. 1 1
      packages/semi-ui/modal/_story/modal.stories.jsx
  63. 7 7
      packages/semi-ui/package.json
  64. 30 3
      packages/semi-ui/slider/index.tsx
  65. 187 109
      packages/semi-ui/table/ColumnFilter.tsx
  66. 59 16
      packages/semi-ui/table/Table.tsx
  67. 4 14
      packages/semi-ui/table/__test__/table.test.js
  68. 140 0
      packages/semi-ui/table/_story/RowSelectionRenderCell/index.jsx
  69. 10 0
      packages/semi-ui/table/_story/table.stories.jsx
  70. 135 0
      packages/semi-ui/table/_story/v2/FeatRenderFilterDropdown/index.tsx
  71. 117 0
      packages/semi-ui/table/_story/v2/InputFilter/index.tsx
  72. 2 0
      packages/semi-ui/table/_story/v2/index.js
  73. 31 11
      packages/semi-ui/table/interface.ts
  74. 21 0
      packages/semi-ui/treeSelect/__test__/treeSelect.test.js
  75. 7 1
      packages/semi-ui/treeSelect/index.tsx
  76. 1 1
      packages/semi-webpack/package.json
  77. 202 202
      sitemap.xml
  78. 5 3
      src/templates/postTemplate.js
  79. 90 4
      yarn.lock

+ 1 - 1
content/feedback/progress/index-en-US.md

@@ -403,7 +403,7 @@ import { IconChevronLeft, IconChevronRight } from '@douyinfe/semi-icons';
 | stroke | Fill color of progress bar, When of type `Array<{percent:number; color:string }>`, the `color` parameter supports the color types: `'Hex'` &#124; `'Hsl'` &#124; `'Hsla'` &#124; `'Rgb'` &#124; `'Rgba'` &#124; `'Semi Design Tokens'` | string &#124; Array<{percent:number; color:string }> | 'var(--semi-color-success)' |
 | strokeGradient | Whether to automatically generate gradient colors to fill color intervals, requires `stroke` to set at least one color interval | boolean | false |
 | strokeLinecap | round corner `round`/square corner `square` (only effective in type='circle' mode) | string | 'round' |
-| strokeWidth | When type is `line`, this property controls the height of the progress bar; when type is `circle`, this property controls the width of the progress bar | number | 4 |
+| strokeWidth |when type is `circle`, this property controls the width of the progress bar | number | 4 |
 | style | style | CSSProperties |  |
 | type | type, optional `line`, `circle` | string | 'line' |
 | width | Width of circular progress bar | number | 72 when size='default', 24 for 'small' |

+ 1 - 1
content/feedback/progress/index.md

@@ -424,7 +424,7 @@ import { IconChevronLeft, IconChevronRight } from '@douyinfe/semi-icons';
 | stroke | 进度条填充色,类型为 `Array<{percent:number; color:string }>` 时,`color` 参数支持颜色类型:`'Hex'` &#124; `'Hsl'` &#124; `'Hsla'` &#124; `'Rgb'` &#124; `'Rgba'` &#124; `'Semi Design Tokens'` | string &#124; Array<{percent:number; color:string }> | 'var(--semi-color-success)' |
 | strokeGradient | 是否自动生成渐变色补齐区间颜色,需要 `stroke` 设置至少一个颜色区间 | boolean | false |
 | strokeLinecap | 圆角`round`/方角`square`(仅在 type='circle'模式下生效) | string | 'round' |
-| strokeWidth | type 为`line`时,该属性控制进度条高度; type 为`circle`时,该属性控制进度条宽度 | number | 4 |
+| strokeWidth | type 为`circle`时,该属性控制进度条宽度 | number | 4 |
 | style | 样式 | CSSProperties |  |
 | type | 类型,可选`line`、`circle` | string | 'line' |
 | width | 环形进度条宽度 | number | size='default'时为 72,'small'为 24 |

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

@@ -915,7 +915,7 @@ function Demo() {
 | placeholder        | Input box prompts text                                                                                                                                                                                                                        | string\|string[]                                                                                                                                                                                                    | 'Select date'                                                                         |                           |
 | position           | Floating layer position, optional value with [Popover #API Reference · position](/en-US/show/popover#API%20Reference)                                                                                                                         | string                                                                                                                                                                                                    | 'bottomLeft'                                                                          |                           |
 | prefix             | Prefix content                                                                                                                                                                                                                                | string\|ReactNode                                                                                                                                                                                         |                                                                                       |                           |
-| presets            | Date Time Shortcut                                                                                                                                                                                                                            |  <ApiType detail='Array< { start: BaseValueType, end :BaseValueType, text: string } \| () => { start:B aseValueType, end: BaseValueType, text: string }>'>Array</ApiType>                                  | []                                                                                    |                           |
+| presets            | Date Time Shortcut, start and end support function type after v2.52                                                                                                                                                                                                                            |  <ApiType detail='type PresetType = { start?: BaseValueType \| (() => BaseValueType); end?: BaseValueType \| (() => BaseValueType); text?: string }; type PresetsType = Array<PresetType \| (() => PresetType)>;'>Array</ApiType>                                  | []                                                                                    |                           |
 | preventScroll | Indicates whether the browser should scroll the document to display the newly focused element, acting on the focus method inside the component, excluding the component passed in by the user                                                 | boolean |  |  |
 | presetPosition     | Date time shortcut panel position, optional 'left', 'right', 'top', 'bottom'                                                                                                                                                                  | 'bottom' | **2.18.0** |
 | rangeSeparator     | Custom range type picker separator of input trigger                                                                                                                                                                                           | string | '~' | **1.31.0** 

+ 1 - 1
content/input/datepicker/index.md

@@ -880,7 +880,7 @@ function Demo() {
 | placeholder | 输入框提示文字                                                                                              | string\|string[] | 'Select date' |  |
 | position | 浮层位置,可选值同[Popover#API 参考·position 参数](/zh-CN/show/popover#API参考)                                     | string | 'bottomLeft' |  |
 | prefix | 前缀内容                                                                                                 | string\|ReactNode |  |  |
-| presets | 日期时间快捷方式                                                                                             |  <ApiType detail='Array< { start: BaseValueType, end :BaseValueType, text: string } \| () => { start:B aseValueType, end: BaseValueType, text: string }>'>Array</ApiType> | [] |  |
+| presets | 日期时间快捷方式, start 和 end 在 v2.52 版本支持函数类型                                                                                            |  <ApiType detail='type PresetType = { start?: BaseValueType \| (() => BaseValueType); end?: BaseValueType \| (() => BaseValueType); text?: string }; type PresetsType = Array<PresetType \| (() => PresetType)>;'>Array</ApiType> | [] |  |
 | preventScroll | 指示浏览器是否应滚动文档以显示新聚焦的元素,作用于组件内的 focus 方法                                                               | boolean |  |  |
 | presetPosition | 日期时间快捷方式面板位置, 可选值'left', 'right', 'top', 'bottom'                                                    | string |  'bottom' | **2.18.0** |
 | rangeSeparator | 自定义范围类型输入框的日期分隔符                                                                                     | string | '~' | **1.31.0** |

+ 35 - 34
content/input/input/index.md

@@ -399,41 +399,42 @@ import { Input, Typography, Form, TextArea, Button } from '@douyinfe/semi-ui';
 ### Input
 > 其他属性与html input 标签保持一致
 
-| 属性                | 说明                                              | 类型                              | 默认值    |
-|-------------------|-------------------------------------------------|---------------------------------|-----------|
-| aria-describedby  | 设置 aria-describedby 属性                          | string                          | -  |
-| aria-errormessage | 设置 aria-errormessage 属性                         | string                          | -  |
-| aria-invalid      | 设置 aria-invalid 属性                              | string                          | -  |
-| aria-label        | 设置 aria-label 属性                                | string                          | -  |
-| aria-labelledby   | 设置 aria-labelledby 属性                           | string                          | -  |
-| aria-required     | 设置 aria-required 属性                             | string                          | -  |
-| addonAfter        | 后置标签                                            | ReactNode                       |           |
-| addonBefore       | 前置标签                                            | ReactNode                       |           |
-| borderless        | 无边框模式  >=2.33.0                                 | boolean                         |           |
-| className         | 类名                                              | string                          |           |
-| clearIcon         | 可用于自定义清除按钮, showClear为true时有效 **>=2.25.0**      | ReactNode                       |  |
-| defaultValue      | 输入框内容默认值                                        | ReactText                       |           |
-| disabled          | 是否禁用,默认为false                                   | boolean                         | false     |
-| getValueLength    | 自定义计算字符串长度                                      | (value: string) => number       |      |
-| hideSuffix        | 清除按钮与后缀标签并存时隐藏后缀标签,默认为false两者并列                 | boolean                         | false     |
-| mode              | 输入框的模式,可选值password **>=v1.3.0**                 | string                          |           |
-| prefix            | 前缀标签                                            | ReactNode                       |           |
-| preventScroll     | 指示浏览器是否应滚动文档以显示新聚焦的元素,作用于组件内的 focus 方法          | boolean                         |  |  |
-| showClear         | 输入框有内容且 hover 或 focus 时展示清除按钮 **>=1.0.0**       | boolean                         | false     |
-| size              | 输入框大小,large、default、small                       | string                          | 'default' |
-| style             | 样式                                              | CSSProperties                   |           |
-| suffix            | 后缀标签                                            | ReactNode                       |           |
-| type              | 声明input类型,同原生input标签的type属性                     | string                          | text     |
+| 属性                | 说明                                             | 类型                              | 默认值    |
+|-------------------|------------------------------------------------|---------------------------------|-----------|
+| aria-describedby  | 设置 aria-describedby 属性                         | string                          | -  |
+| aria-errormessage | 设置 aria-errormessage 属性                        | string                          | -  |
+| aria-invalid      | 设置 aria-invalid 属性                             | string                          | -  |
+| aria-label        | 设置 aria-label 属性                               | string                          | -  |
+| aria-labelledby   | 设置 aria-labelledby 属性                          | string                          | -  |
+| aria-required     | 设置 aria-required 属性                            | string                          | -  |
+| addonAfter        | 后置标签                                           | ReactNode                       |           |
+| addonBefore       | 前置标签                                           | ReactNode                       |           |
+| borderless        | 无边框模式  >=2.33.0                                | boolean                         |           |
+| className         | 类名                                             | string                          |           |
+| clearIcon         | 可用于自定义清除按钮, showClear为true时有效 **>=2.25.0**     | ReactNode                       |  |
+| defaultValue      | 输入框内容默认值                                       | ReactText                       |           |
+| disabled          | 是否禁用,默认为false                                  | boolean                         | false     |
+| getValueLength    | 自定义计算字符串长度                                     | (value: string) => number       |      |
+| hideSuffix        | 清除按钮与后缀标签并存时隐藏后缀标签,默认为false两者并列                | boolean                         | false     |
+| mode              | 输入框的模式,可选值password **>=v1.3.0**                | string                          |           |
+| prefix            | 前缀标签                                           | ReactNode                       |           |
+| preventScroll     | 指示浏览器是否应滚动文档以显示新聚焦的元素,作用于组件内的 focus 方法         | boolean                         |  |  |
+| showClear         | 输入框有内容且 hover 或 focus 时展示清除按钮 **>=1.0.0**      | boolean                         | false     |
+| size              | 输入框大小,large、default、small                      | string                          | 'default' |
+| style             | 样式                                             | CSSProperties                   |           |
+| suffix            | 后缀标签                                           | ReactNode                       |           |
+| type              | 声明input类型,同原生input标签的type属性                    | string                          | text     |
 | validateStatus    | 校验状态,可选值default、error、warning,默认default。仅影响展示样式 | string                          | 'default' |
-| value             | 输入框内容                                           | ReactText                       |           |
-| onBlur            | 输入框失去焦点时的回调                                     | function(e:event)               |           |
-| onChange          | 输入框内容变化时的回调                                     | function(value:string, e:event) |           |
-| onClear           | 点击清除按钮时的回调                                      | function(e:event)               |           |
-| onEnterPress      | 按回车时回调(keypress)                                | function(e:event)               |           |
-| onFocus           | 输入框focus时的回调                                    | function(e:event)               |           |
-| onKeyDown         | keydown回调                                       | function(e:event)               |           |
-| onKeyPress        | keypress回调                                      | function(e:event)               |           |
-| onKeyUp           | keyup回调                                         | function(e:event)               |           |
+| value             | 输入框内容                                          | ReactText                       |           |
+| onBlur            | 输入框失去焦点时的回调                                    | function(e:event)               |           |
+| onChange          | 输入框内容变化时的回调                                    | function(value:string, e:event) |           |
+| onClear           | 点击清除按钮时的回调                                     | function(e:event)               |           |
+| onEnterPress      | 按回车时回调(keypress)                               | function(e:event)               |           |
+| onFocus           | 输入框focus时的回调                                   | function(e:event)               |           |
+| onKeyDown         | keydown回调                                      | function(e:event)               |           |
+| onKeyPress        | keypress回调                                     | function(e:event)               |           |
+| onKeyUp           | keyup回调                                        | function(e:event)               |           |
+
 ### TextArea
 
 > 其他属性与 html textarea 标签保持一致

+ 44 - 27
content/input/slider/index-en-US.md

@@ -238,35 +238,52 @@ import { Slider } from '@douyinfe/semi-ui';
 );
 ```
 
+### Handle with dot
+```jsx live=true
+  <div>
+        <div>
+            <div>Default</div>
+            <Slider showBoundary={true} handleDot={{size:'4px',color:'blue'}}></Slider>
+        </div>
+        <br/>
+        <br/>
+        <div>
+            <div>Range</div>
+            <Slider defaultValue={[20, 60]} range handleDot={[{size:'4px',color:'blue'},{size:'4px',color:'pink'}]}></Slider>
+        </div>
+    </div>
+```
+
 ## API Reference
 
-| Property         | Instructions                                                                                                                                                                                                                                                                                          | type          | Default | Version | 
-|------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| ------------- |---------|------ |
-| aria-label       | [aria-label](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label) used to define a string that labels the current element. Use it in cases where a text label is not visible on the screen                                                                          | string | -       |-|
-| aria-labelledby  | [aria-labelledby](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-labelledby) attribute establishes relationships between objects and their label(s), and its value should be one or more element IDs, which refer to elements that have the text needed for labeling | string | -       |-|
-| aria-valuetext   | [aria-valuetext](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-valuetext) used to provide a user-friendly name for the current value of the slider                                                                                                                  | string | -       |-|
-| defaultValue     | Default value                                                                                                                                                                                                                                                                                         | number \| number[] | 0       |- |
-| disabled         | Disable slider                                                                                                                                                                                                                                                                                        | boolean       | false   |- |
-| showMarkLabel    | Whether to show the label                                                                                                                                                                                                                                                                             | boolean | true    | 2.48.0 |
-| included         | Takes effect when `marks` is not null, true means containment and false means coordination                                                                                                                                                                                                            | boolean       | true    |- |
-| marks            | Tick mark of Slider, type of key must be number, and must in closed interval [min, max]                                                                                                                                                                                                               | Record<number, string \>        | -       |- |
-| max              | Maximum value of the slider.                                                                                                                                                                                                                                                                          | number        | 100     |- |
-| min              | Minimum value of the slider.                                                                                                                                                                                                                                                                          | number        | 0       |- |
-| railStyle        | Style for slide rail                                                                                                                                                                                                                                                                                  | CSSProperties | -       |0.31.0|
-| range            | Toggle whether it is allow to move slider from both sides                                                                                                                                                                                                                                             | boolean       | false   |- |
-| showArrow        | whether the tooltip has an arrow                                                                                                                                                                                                                                                                      | boolean | true    | 2.48.0|
-| showBoundary     | Toggle whether show max/min value when hover                                                                                                                                                                                                                                                          | boolean       | false   |- |
-| step             | Increment between successive values                                                                                                                                                                                                                                                                   | number        | 1       |- |
-| tipFormatter     | Format Tooltip content, by default display current value                                                                                                                                                                                                                                              | (value: string \| number \| boolean \| (string \| number \| boolean)[]) => any      | v => v  |- |
-| tooltipOnMark    | Whether the mark on the slide rail has a tooltip                                                                                                                                                                                                                                                      | false | 2.48.0  |
-| tooltipVisible   | Toggle whether to display tooltip all the time                                                                                                                                                                                                                                                        | boolean       | -       |- |
-| value            | Set current value, used in controlled component                                                                                                                                                                                                                                                       | number \| number[] |         |- |
-| vertical         | Toggle whether to display slider vertically                                                                                                                                                                                                                                                           | boolean       | false   |- |
-| verticalReverse  | Vertical but reverse direction >=1.29.0                                                                                                                                                                                                                                                               | boolean | false   |-|
-| onAfterChange    | Triggered when slider changed, passed in current value as params                                                                                                                                                                                                                                      | (value: number \| number[]) => void      | -       |- |
-| onChange         | Callback function when slider value changes                                                                                                                                                                                                                                                           | (value: number \| number[]) => void      | -       |- |
-| onMouseUp        | Trigged when mouse up on handle                                                                                                                                                                                                                                                                       | (e: React.MouseEvent<HTMLDivElement\>) => void                                | -       | 2.41.0 |
-| getAriaValueText | Used to provide a user-friendly name for the current value of the slider, important for screen reader users,  The parameters value and index are the current slider value, order                                                                                                                      | (value: number, index?: number) => string | -       |-|
+| Property         | Instructions                                                                                                                                                                                                                                                                                          | type                                                                           | Default | Version | 
+|------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------|---------|------ |
+| aria-label       | [aria-label](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label) used to define a string that labels the current element. Use it in cases where a text label is not visible on the screen                                                                          | string                                                                         | -       |-|
+| aria-labelledby  | [aria-labelledby](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-labelledby) attribute establishes relationships between objects and their label(s), and its value should be one or more element IDs, which refer to elements that have the text needed for labeling | string                                                                         | -       |-|
+| aria-valuetext   | [aria-valuetext](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-valuetext) used to provide a user-friendly name for the current value of the slider                                                                                                                  | string                                                                         | -       |-|
+| defaultValue     | Default value                                                                                                                                                                                                                                                                                         | number \| number[]                                                             | 0       |- |
+| disabled         | Disable slider                                                                                                                                                                                                                                                                                        | boolean                                                                        | false   |- |
+| handleDot | Whether to show the dot on the handle                                                                                                                                                                                                                                                                 | { color: string, size: string} \| <br/> { color: string, size: string}[]       | -      | 2.52.0 |
+| included         | Takes effect when `marks` is not null, true means containment and false means coordination                                                                                                                                                                                                            | boolean                                                                        | true    |- |
+| marks            | Tick mark of Slider, type of key must be number, and must in closed interval [min, max]                                                                                                                                                                                                               | Record<number, string \>                                                       | -       |- |
+| max              | Maximum value of the slider.                                                                                                                                                                                                                                                                          | number                                                                         | 100     |- |
+| min              | Minimum value of the slider.                                                                                                                                                                                                                                                                          | number                                                                         | 0       |- |
+| railStyle        | Style for slide rail                                                                                                                                                                                                                                                                                  | CSSProperties                                                                  | -       |0.31.0|
+| range            | Toggle whether it is allow to move slider from both sides                                                                                                                                                                                                                                             | boolean                                                                        | false   |- |
+| showArrow        | whether the tooltip has an arrow                                                                                                                                                                                                                                                                      | boolean                                                                        | true    | 2.48.0|
+| showBoundary     | Toggle whether show max/min value when hover                                                                                                                                                                                                                                                          | boolean                                                                        | false   |- |
+| showMarkLabel    | Whether to show the label                                                                                                                                                                                                                                                                             | boolean                                                                        | true    | 2.48.0 |
+| step             | Increment between successive values                                                                                                                                                                                                                                                                   | number                                                                         | 1       |- |
+| tipFormatter     | Format Tooltip content, by default display current value                                                                                                                                                                                                                                              | (value: string \| number \| boolean \| (string \| number \| boolean)[]) => any | v => v  |- |
+| tooltipOnMark    | Whether the mark on the slide rail has a tooltip                                                                                                                                                                                                                                                      | false                                                                          | 2.48.0  |
+| tooltipVisible   | Toggle whether to display tooltip all the time                                                                                                                                                                                                                                                        | boolean                                                                        | -       |- |
+| value            | Set current value, used in controlled component                                                                                                                                                                                                                                                       | number \| number[]                                                             |         |- |
+| vertical         | Toggle whether to display slider vertically                                                                                                                                                                                                                                                           | boolean                                                                        | false   |- |
+| verticalReverse  | Vertical but reverse direction >=1.29.0                                                                                                                                                                                                                                                               | boolean                                                                        | false   |-|
+| onAfterChange    | Triggered when slider changed, passed in current value as params                                                                                                                                                                                                                                      | (value: number \| number[]) => void                                            | -       |- |
+| onChange         | Callback function when slider value changes                                                                                                                                                                                                                                                           | (value: number \| number[]) => void                                            | -       |- |
+| onMouseUp        | Trigged when mouse up on handle                                                                                                                                                                                                                                                                       | (e: React.MouseEvent<HTMLDivElement\>) => void                                 | -       | 2.41.0 |
+| getAriaValueText | Used to provide a user-friendly name for the current value of the slider, important for screen reader users,  The parameters value and index are the current slider value, order                                                                                                                      | (value: number, index?: number) => string                                      | -       |-|
 ## Accessibility
 
 ### ARIA

+ 43 - 26
content/input/slider/index.md

@@ -226,34 +226,51 @@ import { Slider } from '@douyinfe/semi-ui';
 
 ```
 
+### 滑块带圆点
+```jsx live=true
+  <div>
+        <div>
+            <div>Default</div>
+            <Slider showBoundary={true} handleDot={{size:'4px',color:'blue'}}></Slider>
+        </div>
+        <br/>
+        <br/>
+        <div>
+            <div>Range</div>
+            <Slider defaultValue={[20, 60]} range handleDot={[{size:'4px',color:'blue'},{size:'4px',color:'pink'}]}></Slider>
+        </div>
+    </div>
+```
+
 ## API参考
-| 属性               | 说明                                                                                                                                                                 | 类型                                                                            | 默认值    | 版本     | 
-|------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------|--------|--------|
-| aria-label       | [aria-label](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label)属性,用来给当前元素加上的标签描述, 提升可访问性                                       | string                                                                        | -      | -      |
-| aria-labelledby  | [aria-labelledby](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-labelledby)属性,表明某些元素的 id 是某一对象的标签。它被用来确定控件或控件组与它们标签之间的联系, 提升可访问性 | string                                                                        | -      | -      |
-| aria-valuetext   | [aria-valuetext](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-valuetext)属性,为滑块的当前值提供用户友好的名称。                                    | string                                                                        | -      | -      |
-| defaultValue     | 设置初始取值                                                                                                                                                             | number \| number[]                                                            | 0      | -      |
-| disabled         | 滑块是否禁用                                                                                                                                                             | boolean                                                                       | false  | -      |
-| showMarkLabel    | 是否隐藏标签 | boolean | true   | 2.48.0 |
-| included         | `marks` 不为空对象时有效,值为 true 时表示值为包含关系,false 表示并列                                                                                                                      | boolean                                                                       | true   | -      |
-| marks            | 刻度,key 的类型必须为 `number` 且取值在闭区间 \[min, max] 内                                                                                                                       | Record<number, string \>                                                      | 无      | -      |
-| max              | 最大值                                                                                                                                                                | number                                                                        | 100    | -      |
-| min              | 最小值                                                                                                                                                                | number                                                                        | 0      | -      |
-| railStyle        | 滑块轨道的样式                                                                                                                                                            | CSSProperties                                                                 | -      | 0.31.0 |
-| range            | 是否支持两边同时可滑动                                                                                                                                                        | boolean                                                                       | false  | -      |
-| showArrow        | tooltip 是否带箭头 | boolean | true   | 2.48.0|
-| showBoundary     | 是否在 hover 时展示最大值最小值                                                                                                                                                | boolean                                                                       | false  | -      |
-| step             | 步长                                                                                                                                                                 | number                                                                        | 1      | -      |
+| 属性               | 说明                                                                                                                                                                 | 类型                                                                             | 默认值    | 版本     | 
+|------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------|--------|--------|
+| aria-label       | [aria-label](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label)属性,用来给当前元素加上的标签描述, 提升可访问性                                       | string                                                                         | -      | -      |
+| aria-labelledby  | [aria-labelledby](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-labelledby)属性,表明某些元素的 id 是某一对象的标签。它被用来确定控件或控件组与它们标签之间的联系, 提升可访问性 | string                                                                         | -      | -      |
+| aria-valuetext   | [aria-valuetext](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-valuetext)属性,为滑块的当前值提供用户友好的名称。                                    | string                                                                         | -      | -      |
+| defaultValue     | 设置初始取值                                                                                                                                                             | number \| number[]                                                             | 0      | -      |
+| disabled         | 滑块是否禁用                                                                                                                                                             | boolean                                                                        | false  | -      |
+| handleDot | 滑块是否带有圆点 | { color: string, size: string} \| <br/> { color: string, size: string}[]                                                | -      | 2.52.0 |
+| included         | `marks` 不为空对象时有效,值为 true 时表示值为包含关系,false 表示并列                                                                                                                      | boolean                                                                        | true   | -      |
+| marks            | 刻度,key 的类型必须为 `number` 且取值在闭区间 \[min, max] 内                                                                                                                       | Record<number, string \>                                                       | 无      | -      |
+| max              | 最大值                                                                                                                                                                | number                                                                         | 100    | -      |
+| min              | 最小值                                                                                                                                                                | number                                                                         | 0      | -      |
+| railStyle        | 滑块轨道的样式                                                                                                                                                            | CSSProperties                                                                  | -      | 0.31.0 |
+| range            | 是否支持两边同时可滑动                                                                                                                                                        | boolean                                                                        | false  | -      |
+| showArrow        | tooltip 是否带箭头 | boolean                                                                        | true   | 2.48.0 |
+| showBoundary     | 是否在 hover 时展示最大值最小值                                                                                                                                                | boolean                                                                        | false  | -      |
+| showMarkLabel    | 是否隐藏标签 | boolean                                                                        | true   | 2.48.0 |
+| step             | 步长                                                                                                                                                                 | number                                                                         | 1      | -      |
 | tipFormatter     | 设置Tooltip的展示格式,默认显示当前选值                                                                                                                                            | (value: string \| number \| boolean \| (string \| number \| boolean)[]) => any | v => v | -      |
-| tooltipOnMark    | 滑轨上的 mark 是否带有 tooltip | false | 2.48.0 |
-| tooltipVisible   | 是否始终显示Tooltip                                                                                                                                                      | boolean                                                                       | 无      | -      |
-| value            | 设置当前取值                                                                                                                                                             | number \| number[]                                                            |        | -      |
-| vertical         | 是否设置方向为垂直                                                                                                                                                          | boolean                                                                       | false  | -      |
-| verticalReverse  | 反转垂直方向,即上大下小 >=1.29.0                                                                                                                                              | boolean                                                                       | false  | -      |
-| onAfterChange    | 值变化后触发,把当前值作为参数传入                                                                                                                                                  | (value: number \| number[]) => void                                           | 无      | -      |
-| onChange         | 当 Slider 的值发生改变时的回调                                                                                                                                                | (value: number \| number[]) => void                                           | 无      | -      |
-| onMouseUp        | 鼠标松开滑块时触发                                                                                                                                                          | (e: React.MouseEvent<HTMLDivElement\>) => void                                | 无      | 2.41.0 |
-| getAriaValueText | 用于给滑块的当前值提供一个用户友好的名称,对屏幕阅读器用户很重要,参数value为当前滑块的值,index为当前滑块的顺序                                                                                                      | (value: number, index?: number) => string                                     | -      | -      |
+| tooltipOnMark    | 滑轨上的 mark 是否带有 tooltip | false                                                                          | 2.48.0 |
+| tooltipVisible   | 是否始终显示Tooltip                                                                                                                                                      | boolean                                                                        | 无      | -      |
+| value            | 设置当前取值                                                                                                                                                             | number \| number[]                                                             |        | -      |
+| vertical         | 是否设置方向为垂直                                                                                                                                                          | boolean                                                                        | false  | -      |
+| verticalReverse  | 反转垂直方向,即上大下小 >=1.29.0                                                                                                                                              | boolean                                                                        | false  | -      |
+| onAfterChange    | 值变化后触发,把当前值作为参数传入                                                                                                                                                  | (value: number \| number[]) => void                                            | 无      | -      |
+| onChange         | 当 Slider 的值发生改变时的回调                                                                                                                                                | (value: number \| number[]) => void                                            | 无      | -      |
+| onMouseUp        | 鼠标松开滑块时触发                                                                                                                                                          | (e: React.MouseEvent<HTMLDivElement\>) => void                                 | 无      | 2.41.0 |
+| getAriaValueText | 用于给滑块的当前值提供一个用户友好的名称,对屏幕阅读器用户很重要,参数value为当前滑块的值,index为当前滑块的顺序                                                                                                      | (value: number, index?: number) => string                                      | -      | -      |
 
 ## Accessibility
 

+ 1 - 0
content/input/treeselect/index-en-US.md

@@ -1468,6 +1468,7 @@ function Demo() {
 | onFocus                 | Callback function when treeSelect focus  | function(event)                            | -           | -       |
 | onChange                 | Callback function when the tree node is selected, return the value property of data | Function                           | -           | -       |
 | onChangeWithObject        | Toggle whether to return all properties in an option as a return value. When set to true, onChange turn to Function(node, e)   | boolean                     | false   | 1.0.0 |
+| onClear     | Callback triggered when clear button is clicked   | (e: Event) => void |  -  |   2.52.0  |
 | onExpand                 | Callback function when expand or collapse a node                                    | <ApiType detail='(expandedKeys:array, {expanded: bool, node}) => void'>(expandedKeys, object) => void</ApiType>             | -           | -       |
 | onLoad | Callback function when a node is loaded | <ApiType detail='(loadedKeys: Set<string\>, treeNode: TreeNodeData) => void'>(loadedKeys, treeNode) => void</ApiType> | - | 1.32.0|
 | onSearch                 | Callback function when search value changes. `filteredExpandedKeys` represents the key of the node expanded due to search or value/defaultValue, which can be used when expandedKeys is controlled<br/> **filteredExpandedKeys is supported in 2.6.0**      | function(input: string, filteredExpandedKeys: string[])                                        | -           |     |

+ 1 - 0
content/input/treeselect/index.md

@@ -1448,6 +1448,7 @@ function Demo() {
 | onBlur | 失去焦点时的回调                                                                                                                                   | function(event) | - | - |
 | onChange | 选中树节点时调用此函数,默认返回值为当前所有选中项的value值及节点属性;如果是通过tag关闭,event参数为null                                                                              | Function | - | - |
 | onChangeWithObject | 是否将选中项 option 的其他属性作为回调。设为 true 时,onChange 的入参类型Function(node\|node[], e) 此时如果是受控,也需要把 value 设置成 object,且必须含有 value 的键值;defaultValue同理。    | boolean | false | 1.0.0 |
+| onClear     | 点击清除按钮时触发的回调                                                                                                                             | (e: Event) => void |  -  |   2.52.0  |
 | onExpand | 展示节点时调用                                                                                                                                    | <ApiType detail='(expandedKeys:array, {expanded: bool, node}) => void'>(expandedKeys, object) => void</ApiType> | - | - |
 | onFocus | 聚焦时的回调                                                                                                                                     | function(event) | - | - |
 | onLoad | 节点加载完毕时触发的回调                                                                                                                               | <ApiType detail='(loadedKeys: Set<string\>, treeNode: TreeNodeData) => void'>(loadedKeys, treeNode) => void</ApiType> |- |  1.32.0|

+ 167 - 17
content/show/avatar/index-en-US.md

@@ -165,6 +165,151 @@ import { IconCamera } from '@douyinfe/semi-icons';
 };
 ```
 
+
+### Top and Bottom Slot
+
+```jsx live=true
+import React from 'react';
+import { Avatar } from '@douyinfe/semi-ui';
+
+<Avatar
+            alt="beautiful cat"
+            src="https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/dy.png"
+            style={{ margin: 4 }}
+            size="large"
+            border={{color:"#FE2C55",motion:true}}
+            contentMotion={true}
+            topSlot={{
+                text: "LIVE", 
+                gradientStart:"rgb(255,23,100)",
+                gradientEnd:"rgb(237,52,148)"
+            }}
+            bottomSlot={{
+                shape: "circle",
+                bgColor:"#FE2C55",
+                text: <IconPlus/>
+            }}
+/>
+```
+
+#### Top
+
+```jsx live=true
+()=>{
+    return <div>
+
+        <Avatar color="amber" topSlot={{
+            text: "LIVE",
+            gradientStart:"rgb(255,23,100)",
+            gradientEnd:"rgb(237,52,148)"
+        }}>T</Avatar>
+
+        <Avatar color="amber" size="large" topSlot={{
+            text: "LIVE",
+            gradientStart:"rgb(255,23,100)",
+            gradientEnd:"rgb(237,52,148)"
+        }}>T</Avatar>
+
+        <Avatar color="amber" size="extra-large" topSlot={{
+            text: "LIVE",
+            gradientStart:"rgb(255,23,100)",
+            gradientEnd:"rgb(237,52,148)"
+        }}>T</Avatar>
+    
+    </div>
+}
+
+```
+
+
+#### Bottom
+
+```jsx live=true
+()=>{
+    return <div>
+
+        <Avatar color="amber" bottomSlot={{
+            shape: "square", 
+            bgColor:'#FE2C55',
+            content: "LIVE"
+        }}>T</Avatar>
+
+        <Avatar color="amber" size="large" bottomSlot={{
+            shape: "square", 
+            bgColor:'#FE2C55',
+            content: "LIVE"
+        }}>T</Avatar>
+        
+        <Avatar color="amber" size="extra-large" bottomSlot={{
+            shape: "square", 
+            bgColor:'#FE2C55',
+            content: "LIVE"
+        }}>T</Avatar>
+        
+        <br/>
+        <br/>
+        <br/>
+        <Avatar color="amber" bottomSlot={{
+            shape: "circle", 
+            bgColor:'#FE2C55',
+            content: <IconPlus/>
+        }}>T</Avatar>
+
+        <Avatar color="amber" size="large" bottomSlot={{
+            shape: "circle", 
+            bgColor:'#FE2C55',
+            content: <IconPlus/>
+        }}>T</Avatar>
+
+        <Avatar color="amber" size="extra-large" bottomSlot={{
+            shape: "circle", 
+            bgColor:'#FE2C55',
+            content: <IconPlus/>
+        }}>T</Avatar>
+    </div>
+}
+
+```
+
+### Additional border
+
+```jsx live=true
+
+()=>{
+    return <div>
+
+        <Avatar color="amber" border={true} style={{marginRight:'8px'}}>T</Avatar>
+
+        <Avatar color="amber" border={true} style={{marginRight:'8px'}}>T</Avatar>
+
+        <Avatar color="amber" border={true} style={{marginRight:'8px'}}>T</Avatar>
+    
+    </div>
+}
+
+```
+
+### Additional Animation
+
+Turn on additional animation effects for borders and content areas through `border={motion:true}` and `contentMotion`
+
+```jsx live=true
+
+()=>{
+    return <div>
+
+        <Avatar color="amber" border={true} style={{marginRight:'8px'}} borderMotion={true} contentMotion={true}>T</Avatar>
+
+        <Avatar color="amber" border={true}  size={"large"} style={{marginRight:'8px'}} borderMotion={true} contentMotion={true}>T</Avatar>
+
+        <Avatar color="amber" border={true} size={"extra-large"} style={{marginRight:'8px'}} borderMotion={true} contentMotion={true}>T</Avatar>
+    
+    </div>
+}
+
+```
+
+
 ### AvatarGroup
 
 You can use `AvatarGroup` component to display avatars as a group.
@@ -280,23 +425,28 @@ import { Avatar, AvatarGroup } from '@douyinfe/semi-ui';
 
 ### Avatar
 
-| Properties   | Instructions                                                                                                                                                                              | type           | Default  |
-| ------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------- | -------- |
-| alt          | Defines an alternative text description of the image.                                                                                                                                       | string         | -        |
-| className    | Class name                                                                                                                                                                                | string         | -        |
-| color        | Color of the avatar, one of `amber`, `blue`, `cyan`, `green`, `grey`, `indigo`, `light-blue`, `light-green`, `lime`, `orange`, `pink`, `rain`, `red`, `teal`, `violet`, `yellow`, `white` | string         | `grey`   |
-| gap          | Pixel size of the distance between the left and right sides of the character avatar | number                                     | 3        |
-| hoverMask    | Avatar content overlay when hover                                                                                                                                                         | ReactNode     | -        |
-| imgAttr | Native html img attributes **>=1.5.0**| React.ImgHTMLAttributes<HTMLImageElement\> | - |
-| shape        | Shape of the avatar, one of `circle`, `square`                                                                                                                                            | string         | `circle` |
-| size         | Size of the avatar, one of `extra-extra-small`,`extra-small`, `small`, `default`, `medium`, `large`, `extra-large`                                                                                                       | string         | `medium` |
-| src          | Resource address for imgage avatars                                                                                                                                                       | string         | -        |
-| srcSet       | Set the image avatar responsive resource address                                                                                                                                          | string         | -        |
-| style        | Style name                                                                                                                                                                                | CSSProperties         | -        |
-| onClick      | Click the callback of the avatar.                                                                                                                                                         | (e: Event) => void       | -        |
-| onError      | Image load failed event, returning false closes the default fallback behavior of the component                                                                                            | (e: Event) = > boolean | -        |
-| onMouseEnter | Callback to onMouseEnter event                                                                                                                                                            | (e: Event) => void       | -        |
-| onMouseLeave | Callback to onMouseLeave event                                                                                                                                                            | (e: Event) => void       | -        |
+| Properties   | Instructions                                                                                                                                                                              | type                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                | Default  |
+| ------------ |-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -------- |
+| alt          | Defines an alternative text description of the image.                                                                                                                                     | string                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              | -        |
+| border | additional border(>=2.52.0)                                                                                                                                                               | {color?:string //color, motion?:boolean // has animation} or boolean                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                | - |
+| bottomSlot | bottom Slot config (>= 2.52.0 )                                                                                                                                                           | {<br/><div style={{width:20,display:'inline-block'}}/>render?: () => React.ReactNode //Full control the rendering,<br/><div style={{width:20,display:'inline-block'}}/>shape?: "circle" or "square" // slot shape,<br/><div style={{width:20,display:'inline-block'}}/>content: React.ReactNode // slot content,<br/><div style={{width:20,display:'inline-block'}}/>bgColor:string // slot background <br/><div style={{width:20,display:'inline-block'}}/>textColor:string // text color <br/><div style={{width:20,display:'inline-block'}}/>className:string <br/><div style={{width:20,display:'inline-block'}}/>style?:CSSProperties<br/>}                                    | - |
+| className    | Class name                                                                                                                                                                                | string                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              | -        |
+| color        | Color of the avatar, one of `amber`, `blue`, `cyan`, `green`, `grey`, `indigo`, `light-blue`, `light-green`, `lime`, `orange`, `pink`, `rain`, `red`, `teal`, `violet`, `yellow`, `white` | string                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              | `grey`   |
+| contentMotion | avatar content area animation (>=2.xx.0)                                                                                                                                                  | boolean                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             | - |
+| gap          | Pixel size of the distance between the left and right sides of the character avatar                                                                                                       | number                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              | 3        |
+| hoverMask    | Avatar content overlay when hover                                                                                                                                                         | ReactNode                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           | -        |
+| imgAttr | Native html img attributes **>=1.5.0**                                                                                                                                                    | React.ImgHTMLAttributes<HTMLImageElement\>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          | - |
+| shape        | Shape of the avatar, one of `circle`, `square`                                                                                                                                            | string                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              | `circle` |
+| size         | Size of the avatar, one of `extra-extra-small`,`extra-small`, `small`, `default`, `medium`, `large`, `extra-large`                                                                        | string                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              | `medium` |
+| src          | Resource address for imgage avatars                                                                                                                                                       | string                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              | -        |
+| srcSet       | Set the image avatar responsive resource address                                                                                                                                          | string                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              | -        |
+| style        | Style name                                                                                                                                                                                | CSSProperties                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       | -        |
+| topSlot | top Slot config (>= 2.52.0 )                                                                                                                                                              | {<br/><div style={{width:20,display:'inline-block'}}/>render?: () => React.ReactNode //Full control the rendering,<br/> <div style={{width:20,display:'inline-block'}}/>gradientStart?: string // Top background gradient starting color <br/> <div style={{width:20,display:'inline-block'}}/>gradientEnd?: string // Top background gradient ending color<br/> <div style={{width:20,display:'inline-block'}}/>content: React.ReactNode <br/> <div style={{width:20,display:'inline-block'}}/>textColor:string //text color <br/> <div style={{width:20,display:'inline-block'}}/>className:string<br/><div style={{width:20,display:'inline-block'}}/>style?:CSSProperties<br/>} | - |
+| onClick      | Click the callback of the avatar.                                                                                                                                                         | (e: Event) => void                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  | -        |
+| onError      | Image load failed event, returning false closes the default fallback behavior of the component                                                                                            | (e: Event) = > boolean                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              | -        |
+| onMouseEnter | Callback to onMouseEnter event                                                                                                                                                            | (e: Event) => void                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  | -        |
+| onMouseLeave | Callback to onMouseLeave event                                                                                                                                                            | (e: Event) => void                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  | -        |
+
 
 ### AvatarGroup
 

+ 164 - 17
content/show/avatar/index.md

@@ -163,6 +163,147 @@ import { IconCamera } from '@douyinfe/semi-icons';
 };
 ```
 
+### 顶部和底部 Slot
+
+```jsx live=true
+import React from 'react';
+import { Avatar } from '@douyinfe/semi-ui';
+
+ <Avatar
+            alt="beautiful cat"
+            src="https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/dy.png"
+            style={{ margin: 4 }}
+            size="large"
+            border={{color:"#FE2C55",motion:true}}
+            contentMotion={true}
+            topSlot={{
+                text: "直播",
+                gradientStart:"rgb(255,23,100)",
+                gradientEnd:"rgb(237,52,148)"
+            }}
+            bottomSlot={{
+                shape: "circle",
+                bgColor:"#FE2C55", 
+                text: <IconPlus/>
+            }}
+/>
+```
+
+#### 顶部
+
+```jsx live=true
+()=>{
+    return <div>
+
+        <Avatar color="amber" topSlot={{
+            text: "直播",
+            gradientStart:"rgb(255,23,100)",
+            gradientEnd:"rgb(237,52,148)"
+        }}>T</Avatar>
+
+        <Avatar color="amber" size="large" topSlot={{
+            text: "直播",
+            gradientStart:"rgb(255,23,100)",
+            gradientEnd:"rgb(237,52,148)"
+        }}>T</Avatar>
+
+        <Avatar color="amber" size="extra-large" topSlot={{
+            text: "直播",
+            gradientStart:"rgb(255,23,100)",
+            gradientEnd:"rgb(237,52,148)"
+        }}>T</Avatar>
+    
+    </div>
+}
+
+```
+
+
+#### 底部
+
+```jsx live=true
+()=>{
+    return <div>
+
+        <Avatar color="amber" bottomSlot={{
+            shape: "square", 
+            bgColor:'#FE2C55',
+            text: "直播中"
+        }}>T</Avatar>
+
+        <Avatar color="amber" size="large" bottomSlot={{
+            shape: "square", 
+            bgColor:'#FE2C55',
+            text: "直播中"
+        }}>T</Avatar>
+
+        <Avatar color="amber" size="extra-large" bottomSlot={{
+            shape: "square", 
+            bgColor:'#FE2C55',
+            text: "直播中"
+        }}>T</Avatar>
+        <br/>
+        <br/>
+        <br/>
+        <Avatar color="amber" bottomSlot={{
+            shape: "circle", 
+            bgColor:'#FE2C55',
+            text: <IconPlus/>
+        }}>T</Avatar>
+
+        <Avatar color="amber" size="large" bottomSlot={{
+            shape: "circle", 
+            bgColor:'#FE2C55',
+            text: <IconPlus/>
+        }}>T</Avatar>
+
+        <Avatar color="amber" size="extra-large" bottomSlot={{
+            shape: "circle", 
+            bgColor:'#FE2C55',
+            text: <IconPlus/>
+        }}>T</Avatar>
+    </div>
+}
+```
+
+### 额外边框
+
+```jsx live=true
+
+()=>{
+    return <div>
+
+        <Avatar color="amber" border={true} style={{marginRight:'8px'}}>T</Avatar>
+
+        <Avatar color="amber" border={true} style={{marginRight:'8px'}}>T</Avatar>
+
+        <Avatar color="amber" border={true} style={{marginRight:'8px'}}>T</Avatar>
+    
+    </div>
+}
+
+```
+
+### 额外动效
+通过  `border={motion:true}` 和 contentMotion 开启边框和内容区域的额外动效
+
+```jsx live=true
+
+()=>{
+    return <div>
+
+        <Avatar color="amber" border={{motion:true}} style={{marginRight:'8px'}} contentMotion={true}>T</Avatar>
+
+        <Avatar color="amber" border={{motion:true}}  size={"large"} style={{marginRight:'8px'}}  contentMotion={true}>T</Avatar>
+
+        <Avatar color="amber" border={{motion:true}} size={"extra-large"} style={{marginRight:'8px'}}  contentMotion={true}>T</Avatar>
+    
+    </div>
+}
+
+```
+
+
 ### 头像组
 
 可以通过 AvatarGroup 将 `avatar` 显示为组。
@@ -279,23 +420,29 @@ import { AvatarGroup, Avatar } from '@douyinfe/semi-ui';
 
 ### Avatar
 
-| 属性 | 说明 | 类型 | 默认值 |
-| --- | --- | --- | --- |
-| alt | 图像的替代文本描述 | string | - |
-| className | 类名 | string | - |
-| color | 指定头像的颜色,支持 `amber`、 `blue`、 `cyan`、 `green`、 `grey`、 `indigo`、 `light-blue`、 `light-green`、 `lime`、 `orange`、 `pink`、 `purple`、 `red`、 `teal`、 `violet`、 `yellow` | string | `grey` |
-| hoverMask | hover 时头像内容覆盖层 | ReactNode | - |
-| gap | 字符头像距离左右两侧的像素大小 | number| 3 |
-| imgAttr | 原生 img 属性 **>=1.5.0** | React.ImgHTMLAttributes<HTMLImageElement\> | - |
-| shape | 指定头像的形状,支持 `circle`、`square` | string | `circle` |
-| size | 设置头像的大小,支持 `extra-extra-small`、`extra-small`、`small`、`default`、`medium`、`large`、`extra-large` | string | `medium` |
-| src | 图片类头像的资源地址 | string | - |
-| srcSet | 设置图片类头像响应式资源地址 | string | - |
-| style | 样式名 | CSSProperties | - |
-| onClick | 单击头像的回调 | (e: Event) => void | - |
-| onError | 图片加载失败的事件,返回 false 会关闭组件默认的 fallback 行为 | (e: Event) => boolean | - |
-| onMouseEnter | MouseEnter 事件的回调 | (e: Event) => void | - |
-| onMouseLeave | MouseLeave 事件的回调 | (e: Event) => void | - |
+| 属性 | 说明                                                                                                                                                                | 类型                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            | 默认值 |
+| --- |-------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| --- |
+| alt | 图像的替代文本描述                                                                                                                                                         | string                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        | - |
+| border | 额外边框 (>=2.52.0)                                                                                                                                                   | {color?:string //颜色, motion?:boolean //是否开启动画} or boolean                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     | - |
+| bottomSlot | 底部 Slot 配置 (>= 2.52.0 )                                                                                                                                           | {<br/><div style={{width:20,display:'inline-block'}}/>render?: () => React.ReactNode //完全控制渲染,<br/> <div style={{width:20,display:'inline-block'}}/>shape?: "circle" or "square" // Slot 形状,<br/> <div style={{width:20,display:'inline-block'}}/>content: React.ReactNode // Slot 内容,<br/> <div style={{width:20,display:'inline-block'}}/>bgColor:string // Slot 背景色 <br/> <div style={{width:20,display:'inline-block'}}/>textColor:string // 文字颜色 <br/> <div style={{width:20,display:'inline-block'}}/>className:string <br/> <div style={{width:20,display:'inline-block'}}/>style?:CSSProperties<br/>} | - |
+| className | 类名                                                                                                                                                                | string                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        | - |
+| color | 指定头像的颜色,支持 `amber`、 `blue`、 `cyan`、 `green`、 `grey`、 `indigo`、 `light-blue`、 `light-green`、 `lime`、 `orange`、 `pink`、 `purple`、 `red`、 `teal`、 `violet`、 `yellow` | string                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        | `grey` |
+| contentMotion | 头像内容区域动效 (>=2.xx.0)                                                                                                                                               | boolean                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       | - |
+| hoverMask | hover 时头像内容覆盖层                                                                                                                                                    | ReactNode                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     | - |
+| gap | 字符头像距离左右两侧的像素大小                                                                                                                                                   | number                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        | 3 |
+| imgAttr | 原生 img 属性 **>=1.5.0**                                                                                                                                             | React.ImgHTMLAttributes<HTMLImageElement\>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    | - |
+| shape | 指定头像的形状,支持 `circle`、`square`                                                                                                                                      | string                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        | `circle` |
+| size | 设置头像的大小,支持 `extra-extra-small`、`extra-small`、`small`、`default`、`medium`、`large`、`extra-large`                                                                     | string                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        | `medium` |
+| src | 图片类头像的资源地址                                                                                                                                                        | string                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        | - |
+| srcSet | 设置图片类头像响应式资源地址                                                                                                                                                    | string                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        | - |
+| style | 样式名                                                                                                                                                               | CSSProperties                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 | - |
+| topSlot | 顶部 Slot 配置 (>= 2.52.0 )                                                                                                                                           | {<br/> <div style={{width:20,display:'inline-block'}}/>render?: () => React.ReactNode //完全控制渲染,<br/> <div style={{width:20,display:'inline-block'}}/>gradientStart?: string // 顶部背景渐变起始色<br/> <div style={{width:20,display:'inline-block'}}/>gradientEnd?: string // 顶部背景渐变结束色<br/> <div style={{width:20,display:'inline-block'}}/>content: React.ReactNode <br/> <div style={{width:20,display:'inline-block'}}/>textColor:string //文字颜色 <br/> <div style={{width:20,display:'inline-block'}}/>className:string<br/><div style={{width:20,display:'inline-block'}}/>style?:CSSProperties<br/>}             | - |
+| onClick | 单击头像的回调                                                                                                                                                           | (e: Event) => void                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            | - |
+| onError | 图片加载失败的事件,返回 false 会关闭组件默认的 fallback 行为                                                                                                                           | (e: Event) => boolean                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         | - |
+| onMouseEnter | MouseEnter 事件的回调                                                                                                                                                  | (e: Event) => void                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            | - |
+| onMouseLeave | MouseLeave 事件的回调                                                                                                                                                  | (e: Event) => void                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            | - |
+
+
 
 ### AvatarGroup
 

+ 47 - 0
content/show/modal/index-en-US.md

@@ -73,6 +73,52 @@ class modalDemo extends React.Component {
 
 ```
 
+### Bottom Button Fill up
+
+Set `footerFill` to true to make the bottom buttons of the Modal footer fill up the arrangement.
+
+```jsx live=true
+import React from 'react';
+import { Modal, Button } from '@douyinfe/semi-ui';
+
+() => {
+    const [visible, setVisible] = useState(false);
+    const showDialog = () => {
+        setVisible(true);
+    };
+    const handleOk = () => {
+        setVisible(false);
+        console.log('Ok button clicked');
+    };
+    const handleCancel = () => {
+        setVisible(false);
+        console.log('Cancel button clicked');
+    };
+    const handleAfterClose = () => {
+        console.log('After Close callback executed');
+    };
+
+    return (
+        <>
+            <Button onClick={showDialog}>Open Modal</Button>
+            <Modal
+                title="Basic Modal"
+                visible={visible}
+                onOk={handleOk}
+                afterClose={handleAfterClose} //>=1.16.0
+                onCancel={handleCancel}
+                closeOnEsc={true}
+                footerFill={true}
+            >
+                This is the content of a basic modal.
+                <br />
+                More content...
+            </Modal>
+        </>
+    );
+};
+```
+
 ### Mask Closable
 
 You can set `maskClosable={false}` to prevent modal from closing when clicking on the mask.
@@ -574,6 +620,7 @@ function Demo(props = {}) {
 | confirmLoading    | Toggle loading state of confirm button                                                                                                                                                        | boolean | false   |
 | content            | Content                                                                                                                                                                                       | ReactNode  | -      |
 | footer            | Footer                                                                                                                                                                                        | ReactNode | -       |
+|footerFill| Is the bottom button full (>= 2.xx.0 ) | boolean | false | 
 | fullScreen        | Is modal FullScreen(will override width and height) <br/>**>= v1.18.0**                                                                                                                       | boolean     | false      |
 | getPopupContainer | Specifies the parent DOM, and the bullet layer will be rendered to the DOM, you need to set 'position: relative`  This will change the DOM tree position, but not the view's rendering position.  <br/>** >= v0.33.0 **                                                       | () => HTMLElement |() => document.body |   
 | hasCancel        | Toggle whether to show cancal button                                                                                                                                                          | boolean | true      |

+ 47 - 0
content/show/modal/index.md

@@ -58,6 +58,52 @@ import { Modal, Button } from '@douyinfe/semi-ui';
 };
 ```
 
+### 底部撑满
+
+设置 footerFill 为 true 可使 Modal footer 底部按钮撑满排列
+
+```jsx live=true
+import React from 'react';
+import { Modal, Button } from '@douyinfe/semi-ui';
+
+() => {
+    const [visible, setVisible] = useState(false);
+    const showDialog = () => {
+        setVisible(true);
+    };
+    const handleOk = () => {
+        setVisible(false);
+        console.log('Ok button clicked');
+    };
+    const handleCancel = () => {
+        setVisible(false);
+        console.log('Cancel button clicked');
+    };
+    const handleAfterClose = () => {
+        console.log('After Close callback executed');
+    };
+
+    return (
+        <>
+            <Button onClick={showDialog}>打开弹窗</Button>
+            <Modal
+                title="基本对话框"
+                visible={visible}
+                onOk={handleOk}
+                afterClose={handleAfterClose} //>=1.16.0
+                onCancel={handleCancel}
+                closeOnEsc={true}
+                footerFill={true}
+            >
+                This is the content of a basic modal.
+                <br />
+                More content...
+            </Modal>
+        </>
+    );
+};
+```
+
 ### 点击遮罩层不可关闭
 
 修改 `maskClosable` 为 `false` 则不可通过点击遮罩层来关闭对话框。
@@ -627,6 +673,7 @@ function Demo(props = {}) {
 | confirmLoading | 确认按钮 loading | boolean | false |
 | content | 对话框内容 | ReactNode | 无 |
 | footer | 对话框底部 | ReactNode | 无 |
+| footerFill| 底部按钮是否撑满 (>= 2.xx.0 ) | boolean | false | 
 | header | 对话框头部 | ReactNode | 无 |
 | height | 高度 | number | 无 |
 | icon | 自定义 icon | ReactNode | - |

+ 292 - 0
content/show/table/index-en-US.md

@@ -1318,6 +1318,296 @@ function App() {
 render(App);
 ```
 
+### Custom Header Filtering
+
+If you need to display the filter input box in the table header, you can pass ReactNode in the `title` and use it with `filteredValue`.
+
+```jsx live=true noInline=true dir="column"
+import React, { useState, useEffect, useRef } from 'react';
+import { Table, Avatar, Input, Space } from '@douyinfe/semi-ui';
+import * as dateFns from 'date-fns';
+
+function App() {
+    const [dataSource, setData] = useState([]);
+    const [filteredValue, setFilteredValue] = useState([]);
+    const compositionRef = useRef({ isComposition: false });
+
+    const DAY = 24 * 60 * 60 * 1000;
+    const figmaIconUrl = 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/figma-icon.png';
+
+
+    const handleChange = (value) => {
+        if (compositionRef.current.isComposition) {
+            return;
+        }
+        const newFilteredValue = value ? [value] : [];
+        setFilteredValue(newFilteredValue);
+    };
+    const handleCompositionStart = () => {
+        compositionRef.current.isComposition = true;
+    };
+
+    const handleCompositionEnd = (event) => {
+        compositionRef.current.isComposition = false;
+        const value = event.target.value;
+        const newFilteredValue = value ? [value] : [];
+        setFilteredValue(newFilteredValue);
+    };
+
+
+    const columns = [
+        {
+            title: (
+                <Space>
+                    <span>Title</span>
+                    <Input
+                        placeholder="Input filter value"
+                        style={{ width: 200 }}
+                        onCompositionStart={handleCompositionStart}
+                        onCompositionEnd={handleCompositionEnd}
+                        onChange={handleChange}
+                        showClear 
+                    />
+                </Space>
+            ),
+            dataIndex: 'name',
+            width: 400,
+            render: (text, record, index) => {
+                return (
+                    <div>
+                        <Avatar size="small" shape="square" src={figmaIconUrl} style={{ marginRight: 12 }}></Avatar>
+                        {text}
+                    </div>
+                );
+            },
+            onFilter: (value, record) => record.name.includes(value),
+            filteredValue,
+        },
+        {
+            title: 'Size',
+            dataIndex: 'size',
+            sorter: (a, b) => (a.size - b.size > 0 ? 1 : -1),
+            render: text => `${text} KB`,
+        },
+        {
+            title: 'Owner',
+            dataIndex: 'owner',
+            render: (text, record, index) => {
+                return (
+                    <div>
+                        <Avatar size="small" color={record.avatarBg} style={{ marginRight: 4 }}>
+                            {typeof text === 'string' && text.slice(0, 1)}
+                        </Avatar>
+                        {text}
+                    </div>
+                );
+            },
+        },
+        {
+            title: 'Update',
+            dataIndex: 'updateTime',
+            sorter: (a, b) => (a.updateTime - b.updateTime > 0 ? 1 : -1),
+            render: value => {
+                return dateFns.format(new Date(value), 'yyyy-MM-dd');
+            },
+        },
+    ];
+
+    const getData = () => {
+        const data = [];
+        for (let i = 0; i < 46; i++) {
+            const isSemiDesign = i % 2 === 0;
+            const randomNumber = (i * 1000) % 199;
+            data.push({
+                key: '' + i,
+                name: isSemiDesign ? `Semi Design design draft${i}.fig` : `Semi D2C design draft${i}.fig`,
+                owner: isSemiDesign ? 'Jiang Pengzhi' : 'Hao Xuan',
+                size: randomNumber,
+                updateTime: new Date().valueOf() + randomNumber * DAY,
+                avatarBg: isSemiDesign ? 'grey' : 'red',
+            });
+        }
+        return data;
+    };
+
+    useEffect(() => {
+        const data = getData();
+        setData(data);
+    }, []);
+
+    return <Table columns={columns} dataSource={dataSource} />;
+}
+
+render(App);
+```
+
+
+
+### Custom Filter Rendering
+
+Use `renderFilterDropdown` to customize the render filter panel. v2.52 supported.
+
+You can call `setTempFilteredValue` to store the filter value when the user enters the filter value, and call `confirm` to trigger the actual filtering after the filter value is entered. You can also filter directly through `confirm({ filteredValue })`.
+
+The reason for setting `tempFilteredValue` is that in scenarios where temporary filtered values need to be stored, there is no need to declare a state to save this temporary filtered value.
+
+```typescript
+type RenderFilterDropdown = (props?: RenderFilterDropdownProps) => React.ReactNode;
+interface RenderFilterDropdownProps {
+     /** Temporary filter value, the initial value is `filteredValue` or `defaultFilteredValue` */
+     tempFilteredValue: any[];
+     /** Set temporary filter value */
+     setTempFilteredValue: (tempFilteredValue: any[]) => void;
+     /** `confirm` will assign `tempFilteredValue` to `filteredValue` by default and trigger the `onChange` event. You can also set the filter value directly by passing in `filteredValue` */
+     confirm: (props?: { closeDropdown?: boolean; filteredValue?: any[] }) => void;
+     /** Clear filter values and temporary filter values */
+     clear: (props?: { closeDropdown?: boolean }) => void;
+     /** Close dropdown */
+     close: () => void;
+     /** Filter configuration items, do not pass if not required */
+     filters?: RenderDropdownProps['filters']
+}
+```
+
+
+```jsx live=true noInline=true dir="column"
+import React, { useState, useEffect, useRef } from 'react';
+import { Table, Avatar, Input, Button, Space } from '@douyinfe/semi-ui';
+import * as dateFns from 'date-fns';
+
+function App() {
+    const [dataSource, setData] = useState([]);
+    const inputRef = useRef();
+
+    const DAY = 24 * 60 * 60 * 1000;
+    const figmaIconUrl = 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/figma-icon.png';
+
+    const columns = [
+        {
+            title: 'Title',
+            dataIndex: 'name',
+            width: 400,
+            render: (text, record, index) => {
+                return (
+                    <div>
+                        <Avatar size="small" shape="square" src={figmaIconUrl} style={{ marginRight: 12 }}></Avatar>
+                        {text}
+                    </div>
+                );
+            },
+            onFilter: (value, record) => record.name.includes(value),
+            renderFilterDropdown: (props) => {
+                console.log('renderFilterDropdown', props);
+                const { tempFilteredValue, setTempFilteredValue, confirm, clear, close } = props;
+
+                const handleChange = value => {
+                    const filteredValue = value ? [value] : [];
+                    setTempFilteredValue(filteredValue);
+                    // You can also filter directly when the input value changes
+                    // confirm({ filteredValue });
+                };
+
+                return (
+                    <Space vertical align='start' style={{ padding: 8 }}>
+                        <Input ref={inputRef} value={tempFilteredValue[0]} onChange={handleChange}/>
+                        <Space>
+                            <Button onClick={() => confirm({ closeDropdown: true })}>Filter+Close</Button>
+                            <Button onClick={() => clear({ closeDropdown: true })}>Clear+Close</Button>
+                            <Button onClick={() => close()}>Close</Button>
+                        </Space>
+                    </Space>
+                );
+            },
+            onFilterDropdownVisibleChange: (visible) => {
+                console.log('inputRef', visible, inputRef);
+                if (inputRef.current && inputRef.current.focus) {
+                    inputRef.current.focus();
+                }
+            }
+        },
+        {
+            title: 'Size',
+            dataIndex: 'size',
+            sorter: (a, b) => (a.size - b.size > 0 ? 1 : -1),
+            render: text => `${text} KB`,
+        },
+        {
+            title: 'Owner',
+            dataIndex: 'owner',
+            render: (text, record, index) => {
+                return (
+                    <div>
+                        <Avatar size="small" color={record.avatarBg} style={{ marginRight: 4 }}>
+                            {typeof text === 'string' && text.slice(0, 1)}
+                        </Avatar>
+                        {text}
+                    </div>
+                );
+            },
+            onFilter: (value, record) => record.owner.includes(value),
+            defaultFilteredValue: ['Jiang Pengzhi'],
+            renderFilterDropdown: (props) => {
+                console.log('renderFilterDropdown', props);
+                const { tempFilteredValue, setTempFilteredValue, confirm, clear, close } = props;
+
+                const handleChange = (value) => {
+                    if (value) {
+                        setTempFilteredValue([value]);
+                    } else {
+                        setTempFilteredValue([]);
+                    }
+                };
+
+                return (
+                    <Space vertical align='start' style={{ padding: 8 }}>
+                        <Input value={tempFilteredValue[0]} onChange={handleChange}/>
+                        <Space>
+                            <Button onClick={() => confirm({ closeDropdown: false })}>Filter+Close</Button>
+                            <Button onClick={() => clear({ closeDropdown: false })}>Clear+Close</Button>
+                            <Button onClick={() => close()}>Close</Button>
+                        </Space>
+                    </Space>
+                );
+            },
+        },
+        {
+            title: 'Update',
+            dataIndex: 'updateTime',
+            sorter: (a, b) => (a.updateTime - b.updateTime > 0 ? 1 : -1),
+            render: value => {
+                return dateFns.format(new Date(value), 'yyyy-MM-dd');
+            },
+        },
+    ];
+
+    const getData = () => {
+        const data = [];
+        for (let i = 0; i < 46; i++) {
+            const isSemiDesign = i % 2 === 0;
+            const randomNumber = (i * 1000) % 199;
+            data.push({
+                key: '' + i,
+                name: isSemiDesign ? `Semi Design design draft${i}.fig` : `Semi D2C design draft${i}.fig`,
+                owner: isSemiDesign ? 'Jiang Pengzhi' : 'Hao Xuan',
+                size: randomNumber,
+                updateTime: new Date().valueOf() + randomNumber * DAY,
+                avatarBg: isSemiDesign ? 'grey' : 'red',
+            });
+        }
+        return data;
+    };
+
+    useEffect(() => {
+        const data = getData();
+        setData(data);
+    }, []);
+
+    return <Table columns={columns} dataSource={dataSource} />;
+}
+
+render(App);
+```
+
 ### Custom Filter Item Rendering
 
 Since the **1.1.0** version, it is supported to pass in `renderFilterDropdownItem` to customize the rendering method of each filter item.
@@ -5142,6 +5432,7 @@ import { Table } from '@douyinfe/semi-ui';
 | fixed | Whether the column is fixed, optional true (equivalent to left) 'left' 'right' | boolean\|string | false |
 | key | The key required by React, if a unique dataIndex has been set, can ignore this property | string |  |
 | render | A rendering function that generates complex data, the parameters are the value of the current row, the current row data, the row index, and the table row / column merge can be set in return object | (text: any, record: RecordType, index: number, { expandIcon?: ReactNode, selection?: ReactNode, indentText?: ReactNode }) => React\|object |  |
+| renderFilterDropdown | Custom filter dropdown panel, for usage details, see [Custom Filter Rendering](#Custom-Filter-Rendering) | (props?: RenderFilterDropdownProps) => React.ReactNode; | - | **2.52.0** |
 | renderFilterDropdownItem | Customize the rendering method of each filter item. For usage details, see [Custom Filter Item Rendering](#Custom-Filter-Item-Rendering) | ({ value: any, text: any, onChange: Function, level: number, ...otherProps }) => ReactNode | - | **1.1.0** |
 | resize | Whether to enable resize mode, this property will take effect only after Table resizable is enabled | boolean |  | **2.42.0** |
 | sortChildrenRecord | Whether to sort child data locally | boolean |  | **0.29.0** |
@@ -5178,6 +5469,7 @@ type Filter = {
 | getCheckboxProps | Default property configuration for the selection box | (record: RecordType) => object |  |  |
 | hidden | Hide selection column or not | boolean | false | **0.34.0** |
 | selectedRowKeys | Specifies the key array of the selected item, which needs to work with onChange | string [] |  |  |
+| renderCell         | Custom rendering checkbox                                                                                 | ({ selected: boolean, record: RecordType, originNode: JSX.Element, inHeader: boolean, disabled: boolean, indeterminate: boolean, index?: number, selectRow?: (selected: boolean, e: Event) => void, selectAll?: (selected: boolean, e: Event) => void }) => ReactNode |        |      **2.52.0**      |
 | width | Custom list selection box width | string | number |  |
 | onChange | A callback in the event of a change in the selected item. The first parameter will save the row keys selected last time, even if you do paging control or update the dataSource [FAQ](#faq) | (selectedRowKeys: number[]\|string[], selectedRows: RecordType[]) => void |  |  |
 | onSelect | Callback when the user manually clicks the selection box of a row | (record: RecordType, selected: boolean, selectedRows: RecordType[], nativeEvent: MouseEvent) => void |  |  |

+ 290 - 0
content/show/table/index.md

@@ -1324,6 +1324,294 @@ function App() {
 render(App);
 ```
 
+### 自定义表头筛选
+
+如果你需要将筛选器输入框展示在表头,可在 `title` 传入 ReactNode,配合 `filteredValue` 使用。
+
+```jsx live=true noInline=true dir="column"
+import React, { useState, useEffect, useRef } from 'react';
+import { Table, Avatar, Input, Space } from '@douyinfe/semi-ui';
+import * as dateFns from 'date-fns';
+
+function App() {
+    const [dataSource, setData] = useState([]);
+    const [filteredValue, setFilteredValue] = useState([]);
+    const compositionRef = useRef({ isComposition: false });
+
+    const DAY = 24 * 60 * 60 * 1000;
+    const figmaIconUrl = 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/figma-icon.png';
+
+
+    const handleChange = (value) => {
+        if (compositionRef.current.isComposition) {
+            return;
+        }
+        const newFilteredValue = value ? [value] : [];
+        setFilteredValue(newFilteredValue);
+    };
+    const handleCompositionStart = () => {
+        compositionRef.current.isComposition = true;
+    };
+
+    const handleCompositionEnd = (event) => {
+        compositionRef.current.isComposition = false;
+        const value = event.target.value;
+        const newFilteredValue = value ? [value] : [];
+        setFilteredValue(newFilteredValue);
+    };
+
+
+    const columns = [
+        {
+            title: (
+                <Space>
+                    <span>标题</span>
+                    <Input
+                        placeholder="请输入筛选值"
+                        style={{ width: 200 }}
+                        onCompositionStart={handleCompositionStart}
+                        onCompositionEnd={handleCompositionEnd}
+                        onChange={handleChange}
+                        showClear 
+                    />
+                </Space>
+            ),
+            dataIndex: 'name',
+            width: 400,
+            render: (text, record, index) => {
+                return (
+                    <div>
+                        <Avatar size="small" shape="square" src={figmaIconUrl} style={{ marginRight: 12 }}></Avatar>
+                        {text}
+                    </div>
+                );
+            },
+            onFilter: (value, record) => record.name.includes(value),
+            filteredValue,
+        },
+        {
+            title: '大小',
+            dataIndex: 'size',
+            sorter: (a, b) => (a.size - b.size > 0 ? 1 : -1),
+            render: text => `${text} KB`,
+        },
+        {
+            title: '所有者',
+            dataIndex: 'owner',
+            render: (text, record, index) => {
+                return (
+                    <div>
+                        <Avatar size="small" color={record.avatarBg} style={{ marginRight: 4 }}>
+                            {typeof text === 'string' && text.slice(0, 1)}
+                        </Avatar>
+                        {text}
+                    </div>
+                );
+            },
+        },
+        {
+            title: '更新日期',
+            dataIndex: 'updateTime',
+            sorter: (a, b) => (a.updateTime - b.updateTime > 0 ? 1 : -1),
+            render: value => {
+                return dateFns.format(new Date(value), 'yyyy-MM-dd');
+            },
+        },
+    ];
+
+    const getData = () => {
+        const data = [];
+        for (let i = 0; i < 46; i++) {
+            const isSemiDesign = i % 2 === 0;
+            const randomNumber = (i * 1000) % 199;
+            data.push({
+                key: '' + i,
+                name: isSemiDesign ? `Semi Design 设计稿${i}.fig` : `Semi D2C 首页${i}.fig`,
+                owner: isSemiDesign ? '姜鹏志' : '郝宣',
+                size: randomNumber,
+                updateTime: new Date('2024-01-25').valueOf() + randomNumber * DAY,
+                avatarBg: isSemiDesign ? 'grey' : 'red',
+            });
+        }
+        return data;
+    };
+
+    useEffect(() => {
+        const data = getData();
+        setData(data);
+    }, []);
+
+    return <Table columns={columns} dataSource={dataSource} />;
+}
+
+render(App);
+```
+
+### 自定义筛选器
+
+使用 `renderFilterDropdown` 自定义渲染筛选器面板。v2.52 支持。
+
+你可以在用户输入筛选值的时候调用 `setTempFilteredValue` 存储筛选值,在筛选值输入完毕后调用 `confirm` 触发真正的筛选。也可以通过 `confirm({ filteredValue })` 直接筛选。
+
+设置 `tempFilteredValue` 的原因是在需要存储临时筛选值的场景,不需要自己声明一个 state 保存这个临时筛选值。
+
+```typescript
+type RenderFilterDropdown = (props?: RenderFilterDropdownProps) => React.ReactNode;
+interface RenderFilterDropdownProps {
+    /** 临时筛选值,初始值为 `filteredValue` 或 `defaultFilteredValue`  */
+    tempFilteredValue: any[];
+    /** 设置临时筛选值  */
+    setTempFilteredValue: (tempFilteredValue: any[]) => void;
+    /** `confirm` 默认会将 `tempFilteredValue` 赋值给 `filteredValue` 并触发 `onChange` 事件。你也可以通过传入 `filteredValue` 直接设置筛选值  */
+    confirm: (props?: { closeDropdown?: boolean; filteredValue?: any[] }) => void;
+    /** 清除筛选值、临时筛选值  */
+    clear: (props?: { closeDropdown?: boolean }) => void;
+    /** 关闭 dropdown  */
+    close: () => void;
+    /** 筛选器配置项,如不需要可以不传  */
+    filters?: RenderDropdownProps['filters']
+}
+```
+
+
+```jsx live=true noInline=true dir="column"
+import React, { useState, useEffect, useRef } from 'react';
+import { Table, Avatar, Input, Button, Space } from '@douyinfe/semi-ui';
+import * as dateFns from 'date-fns';
+
+function App() {
+    const [dataSource, setData] = useState([]);
+    const inputRef = useRef();
+
+    const DAY = 24 * 60 * 60 * 1000;
+    const figmaIconUrl = 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/figma-icon.png';
+
+    const columns = [
+        {
+            title: '标题',
+            dataIndex: 'name',
+            width: 400,
+            render: (text, record, index) => {
+                return (
+                    <div>
+                        <Avatar size="small" shape="square" src={figmaIconUrl} style={{ marginRight: 12 }}></Avatar>
+                        {text}
+                    </div>
+                );
+            },
+            onFilter: (value, record) => record.name.includes(value),
+            renderFilterDropdown: (props) => {
+                console.log('renderFilterDropdown', props);
+                const { tempFilteredValue, setTempFilteredValue, confirm, clear, close } = props;
+
+                const handleChange = value => {
+                    const filteredValue = value ? [value] : [];
+                    setTempFilteredValue(filteredValue);
+                    // 你也可以在 input value 变化时直接筛选
+                    // confirm({ filteredValue });
+                };
+
+                return (
+                    <Space vertical align='start' style={{ padding: 8 }}>
+                        <Input ref={inputRef} value={tempFilteredValue[0]} onChange={handleChange}/>
+                        <Space>
+                            <Button onClick={() => confirm({ closeDropdown: true })}>筛选+关闭</Button>
+                            <Button onClick={() => clear({ closeDropdown: true })}>清除+关闭</Button>
+                            <Button onClick={() => close()}>直接关闭</Button>
+                        </Space>
+                    </Space>
+                );
+            },
+            onFilterDropdownVisibleChange: (visible) => {
+                console.log('inputRef', visible, inputRef);
+                if (inputRef.current && inputRef.current.focus) {
+                    inputRef.current.focus();
+                }
+            }
+        },
+        {
+            title: '大小',
+            dataIndex: 'size',
+            sorter: (a, b) => (a.size - b.size > 0 ? 1 : -1),
+            render: text => `${text} KB`,
+        },
+        {
+            title: '所有者',
+            dataIndex: 'owner',
+            render: (text, record, index) => {
+                return (
+                    <div>
+                        <Avatar size="small" color={record.avatarBg} style={{ marginRight: 4 }}>
+                            {typeof text === 'string' && text.slice(0, 1)}
+                        </Avatar>
+                        {text}
+                    </div>
+                );
+            },
+            onFilter: (value, record) => record.owner.includes(value),
+            defaultFilteredValue: ['姜鹏志'],
+            renderFilterDropdown: (props) => {
+                console.log('renderFilterDropdown', props);
+                const { tempFilteredValue, setTempFilteredValue, confirm, clear, close } = props;
+
+                const handleChange = (value) => {
+                    if (value) {
+                        setTempFilteredValue([value]);
+                    } else {
+                        setTempFilteredValue([]);
+                    }
+                };
+
+                return (
+                    <Space vertical align='start' style={{ padding: 8 }}>
+                        <Input value={tempFilteredValue[0]} onChange={handleChange}/>
+                        <Space>
+                            <Button onClick={() => confirm({ closeDropdown: false })}>筛选后不关闭</Button>
+                            <Button onClick={() => clear({ closeDropdown: false })}>清除后不关闭</Button>
+                            <Button onClick={() => close()}>直接关闭</Button>
+                        </Space>
+                    </Space>
+                );
+            },
+        },
+        {
+            title: '更新日期',
+            dataIndex: 'updateTime',
+            sorter: (a, b) => (a.updateTime - b.updateTime > 0 ? 1 : -1),
+            render: value => {
+                return dateFns.format(new Date(value), 'yyyy-MM-dd');
+            },
+        },
+    ];
+
+    const getData = () => {
+        const data = [];
+        for (let i = 0; i < 46; i++) {
+            const isSemiDesign = i % 2 === 0;
+            const randomNumber = (i * 1000) % 199;
+            data.push({
+                key: '' + i,
+                name: isSemiDesign ? `Semi Design 设计稿${i}.fig` : `Semi D2C 设计稿${i}.fig`,
+                owner: isSemiDesign ? '姜鹏志' : '郝宣',
+                size: randomNumber,
+                updateTime: new Date().valueOf() + randomNumber * DAY,
+                avatarBg: isSemiDesign ? 'grey' : 'red',
+            });
+        }
+        return data;
+    };
+
+    useEffect(() => {
+        const data = getData();
+        setData(data);
+    }, []);
+
+    return <Table columns={columns} dataSource={dataSource} />;
+}
+
+render(App);
+```
+
 
 
 ### 自定义筛选项渲染
@@ -5158,6 +5446,7 @@ import { Table } from '@douyinfe/semi-ui';
 | fixed | 列是否固定,可选 true(等效于 left) 'left' 'right',在 RTL 时会自动切换 | boolean\|string | false |
 | key | React 需要的 key,如果已经设置了唯一的 dataIndex,可以忽略这个属性 | string |  |
 | render | 生成复杂数据的渲染函数,参数分别为当前行的值,当前行数据,行索引,@return 里面可以设置表格行/列合并 | (text: any, record: RecordType, index: number, { expandIcon?: ReactNode, selection?: ReactNode, indentText?: ReactNode }) => object\|ReactNode |  |
+| renderFilterDropdown | 自定义筛选器 dropdown 面板,用法详见[自定义筛选器](#自定义筛选器) | (props?: RenderFilterDropdownProps) => React.ReactNode; | - | **2.52.0** |
 | renderFilterDropdownItem | 自定义每个筛选项渲染方式,用法详见[自定义筛选项渲染](#自定义筛选项渲染) | ({ value: any, text: any, onChange: Function, level: number, ...otherProps }) => ReactNode | - | **1.1.0** |
 | resize | 是否开启 resize 模式,只有 Table resizable 开启后此属性才会生效 | boolean |  | **2.42.0** |
 | sortChildrenRecord | 是否对子级数据进行本地排序 | boolean |  | **0.29.0** |
@@ -5195,6 +5484,7 @@ type Filter = {
 | fixed            | 把选择框列固定在左边                                                                                         | boolean                                                                                              | false  |            |
 | getCheckboxProps | 选择框的默认属性配置                                                                                         | (record: RecordType) => object                                                                       |        |            |
 | hidden           | 是否隐藏选择列                                                                                               | boolean                                                                                              | false  | **0.34.0** |
+| renderCell         | 自定义渲染勾选框                                                                                 | ({ selected: boolean, record: RecordType, originNode: JSX.Element, inHeader: boolean, disabled: boolean, indeterminate: boolean, index?: number, selectRow?: (selected: boolean, e: Event) => void, selectAll?: (selected: boolean, e: Event) => void }) => ReactNode |        |      **2.52.0**     |
 | selectedRowKeys  | 指定选中项的 key 数组,需要和 onChange 进行配合                                                               | string[]                                                                                             |        |            |
 | width            | 自定义列表选择框宽度                                                                                         | string\|number                                                                                       |        |            |
 | onChange         | 选中项发生变化时的回调。第一个参数会保存上次选中的 row keys,即使你做了分页受控或更新了 dataSource [FAQ](#faq) | (selectedRowKeys: number[]\|string[], selectedRows: RecordType[]) => void                            |        |            |

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

@@ -16,6 +16,20 @@ Version:Major.Minor.Patch (follow the **Semver** specification)
 
 ---
 
+#### 🎉 2.52.0-beta.0 (2024-01-31)
+- 【Fix】
+  - fix Table getCurrentPageData type  [@marshcat0](https://github.com/marshcat0)
+  - Fixed the problem that the onClick function of the Dropdown click submenu event is executed too early, which may cause the user to be unable to focus on the Dropdown external element and trigger the Blur of the external element within the onClick function. The scope of impact is 2.43.0-beta.0 ~ 2.50.0-beta .0.
+- 【Feat】
+  - Avatar adds `border` `bottomSlot` `topSlot` to control the border and add additional top and bottom content, and adds `contentMotion` and border `motion` to enable additional motion effects.
+  - Added `footerFill` API to the Modal configuration item, which is used to control whether the default bottom buttons of Modal are fully arranged.
+  - Slider add `handleDot` api to whether to show the dot inside the slider handle.
+  - Table support renderFilterDropdown  [#2015](https://github.com/DouyinFE/semi-design/issues/2015)
+  - RowSelection of Table component adds renderCell to render selection  [@changlin2569](https://github.com/changlin2569)
+  - TreeSelect component support onClear API  [#1331 ](https://github.com/DouyinFE/semi-design/issues/1331) [@changlin2569](https://github.com/changlin2569)
+  - DatePicker support presets start and end function type  [#2038](https://github.com/DouyinFE/semi-design/issues/2038)
+
+
 #### 🎉 2.51.4 (2024-01-31)
 - 【Fix】
     - Fixed the problem that after Cascader's key generation rules in keyEntities changed, the value parameter in triggerRender's parameters was inconsistent with the original one (Affected Scope 2.51.0~2.51.3) [#2051](https://github.com/DouyinFE/semi-design/pull/2051)
@@ -226,6 +240,10 @@ Version:Major.Minor.Patch (follow the **Semver** specification)
     - Fixed an issue where the Item click did not take effect in very few scenarios when nesting Dropdowns.
     - fixed resizable table onHeaderCell bug  [#1796](https://github.com/DouyinFE/semi-design/issues/1796)
 
+#### 🎉 2.42.3 (2023-09-01)
+- 【Fix】
+    - Fix: Fix Table baseRow onMouseLeave error [#1794](https://github.com/DouyinFE/semi-design/pull/1794)
+
 #### 🎉 2.42.2 (2023-08-28)
 - 【Fix】
     - Fix the problem that when the image file name has a query parameter, the image cannot be opened due to the wrong file name after downloading [@nekocode](https://github.com/nekocode) [#1782](https://github.com/DouyinFE/semi-design/pull/1784)

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

@@ -13,6 +13,20 @@ Semi 版本号遵循 **Semver** 规范(主版本号-次版本号-修订版本
 -   修订版本号(patch):仅会进行 bugfix,发布时间不限
 -   不同版本间的详细关系,可查阅 [FAQ](/zh-CN/start/faq)
 
+#### 🎉 2.52.0-beta.0 (2024-01-31)
+- 【Fix】
+    - 修复 Table getCurrentPageData 的类型  [@marshcat0](https://github.com/marshcat0)
+    - 修复 Dropdown 点击子菜单事件 onClick 函数执行时机过早的问题,可能导致用户在 onClick 函数内无法 Focus Dropdown 外部元素并触发外部元素的 Blur,影响范围,2.43.0-beta.0 ~ 2.50.0-beta.0。
+- 【Feat】
+    - Avatar 新增 `border` `bottomSlot` `topSlot` 用于控制边框,添加顶部和底部额外内容,新增 `contentMotion` 和 border `motion` 用于开启额外动效。
+    - Modal 配置项新增 `footerFill` API,用于控制 Modal 默认底部按钮是否撑满排列
+    - Slider 新增 `handleDot`,用于控制滑块内部是否展示圆点
+    - Table 支持使用 renderFilterDropdown 自定义筛选器 dropdown 内容  [#2015](https://github.com/DouyinFE/semi-design/issues/2015)
+    - Table 组件 rowSelection 新增 renderCell 渲染选择框  [@changlin2569](https://github.com/changlin2569)
+    - TreeSelect 组件支持 onClear API  [#1331 ](https://github.com/DouyinFE/semi-design/issues/1331) [@changlin2569](https://github.com/changlin2569)
+    - DatePicker presets start 和 end 支持函数类型  [#2038](https://github.com/DouyinFE/semi-design/issues/2038)
+
+
 #### 🎉 2.51.4 (2024-01-31)
 - 【Fix】
     - 修复 Cascader 在 keyEntities 中的 key 生成规则变化后,triggerRender 的参数中的value 参数和原来不一致问题(影响范围 2.51.0~2.51.3)[#2051](https://github.com/DouyinFE/semi-design/pull/2051)
@@ -222,6 +236,10 @@ Semi 版本号遵循 **Semver** 规范(主版本号-次版本号-修订版本
     - 修复嵌套 Dropdown 时,Item 的点击在极个别场景不生效的问题。
     - 修复 resizable Table onHeaderCell 失效问题 [#1796](https://github.com/DouyinFE/semi-design/issues/1796)
 
+#### 🎉 2.42.3 (2023-09-01)
+- 【Fix】
+    - Fix: 修复 Table baseRow onMouseLeave 报错问题 [#1794](https://github.com/DouyinFE/semi-design/pull/1794)
+
 #### 🎉 2.42.2 (2023-08-28)
 - 【Fix】
     - 修复当 Image 文件名称带 query 参数时候,图片下载后因文件名错误无法打开问题 [@nekocode](https://github.com/nekocode) [#1782](https://github.com/DouyinFE/semi-design/pull/1784)

+ 8 - 0
cypress/e2e/datePicker.spec.js

@@ -850,4 +850,12 @@ describe('DatePicker', () => {
         cy.get('.semi-input').eq(0).should('have.value', '');
         cy.get('.semi-input').eq(1).should('have.value', '');
     });
+
+    it('presets start and end support function type', () => {
+        cy.visit('http://localhost:6006/iframe.html?id=datepicker--presets-function-type&viewMode=story');
+        cy.get('.semi-input').eq(0).click();
+        cy.get('button').contains('动态时间').click();
+        cy.get('.semi-input').eq(0).should('have.value', '2024-01-24');
+        cy.get('.semi-input').eq(1).should('have.value', '2024-02-26');
+    });
 });

+ 34 - 1
cypress/e2e/table.spec.js

@@ -254,4 +254,37 @@ describe('table', () => {
         cy.get('.semi-button').eq(0).click();
         cy.get('.semi-table-column-selection').should('exist');
     });
-});
+
+    it('test renderFilterDropdown', () => {
+        cy.visit('http://localhost:6006/iframe.html?args=&id=table--feat-render-filter-dropdown&viewMode=story');
+
+        // 测试第一个筛选器
+        cy.get('.semi-table-column-filter').eq(0).click();
+        cy.get('.semi-input').should('be.focused');
+        cy.get('.semi-input').type('12');
+        cy.get('.semi-button').contains('筛选+关闭').click();
+        cy.get('.semi-table-tbody .semi-table-row').should('have.length', 1);
+        cy.get('.semi-table-column-filter').eq(0).click();
+        cy.get('.semi-input').should('be.focused');
+        cy.get('.semi-button').contains('清除+关闭').click();
+        cy.get('.semi-table-tbody .semi-table-row').should('have.length', 10);
+        cy.get('.semi-table-column-filter').eq(0).click();
+        cy.get('.semi-input').should('be.focused');
+        cy.get('.semi-button').contains('直接关闭').click();
+        cy.get('.semi-dropdown').should('not.exist');
+
+        // 测试第二个筛选器
+        cy.get('.semi-table-column-filter').eq(1).click();
+        cy.get('.semi-input').should('have.value', '姜鹏志');
+        cy.get('.semi-button').contains('清除后不关闭').click();
+        cy.get('.semi-table-pagination-info').should('contain', '显示第 1 条-第 10 条,共 46 条');
+        cy.get('.semi-dropdown').should('exist');
+        cy.get('.semi-table-column-filter').eq(1).click();
+        cy.get('.semi-input').type('郝宣');
+        cy.get('.semi-button').contains('筛选后不关闭').click();
+        cy.get('.semi-table-pagination-info').should('contain', '显示第 1 条-第 10 条,共 23 条');
+        cy.get('.semi-dropdown').should('exist');
+        cy.get('.semi-button').contains('直接关闭').click();
+        cy.get('.semi-dropdown').should('not.exist');
+    });
+});

+ 1 - 1
lerna.json

@@ -1,5 +1,5 @@
 {
     "useWorkspaces": true,
     "npmClient": "yarn",
-    "version": "2.51.4"
+    "version": "2.52.0-beta.1"
 }

+ 1 - 1
package.json

@@ -46,7 +46,7 @@
         "node": ">= 16.0.0"
     },
     "dependencies": {
-        "@douyinfe/semi-site-banner": "^0.1.0",
+        "@douyinfe/semi-site-banner": "^0.1.3",
         "@douyinfe/semi-site-doc-style": "0.0.1",
         "@douyinfe/semi-site-header": "^0.0.29",
         "@douyinfe/semi-site-markdown-blocks": "^0.0.9",

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

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

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

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

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

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

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

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

+ 19 - 0
packages/semi-foundation/avatar/animation.scss

@@ -0,0 +1,19 @@
+$animation_duration-additionalBorder: 800ms; // 边框动画持续时间
+$animation_duration-content: 1000ms; // 内容动画持续时间
+
+
+$animation_opacity-additionalBorder-start: 1; // 边框动画起始透明度
+$animation_opacity-additionalBorder-end: 0; // 边框动画结束透明度
+
+
+$animation_width-additionalBorder-end:0; // 边框动画结束宽度
+
+
+$animation_scale-additionalBorder-start: 1; // 边框动画起始缩放比例
+$animation_scale-additionalBorder-end: 1.15; // 边框动画结束缩放比例
+
+$animation_scale-content-start: 1; // 边框动画起始缩放比例
+$animation_scale-content-middle: 0.9; // 边框动画中间态缩放比例
+$animation_scale-content-end: 1; // 边框动画结束缩放比例
+
+

+ 313 - 0
packages/semi-foundation/avatar/avatar.scss

@@ -1,6 +1,8 @@
+@import "./animation";
 @import './variables.scss';
 @import './mixin.scss';
 
+
 $module: #{$prefix}-avatar;
 $colors: 'amber', 'blue', 'cyan', 'green', 'grey', 'indigo', 'light-blue', 'light-green', 'lime', 'orange', 'pink',
     'purple', 'red', 'teal', 'violet', 'yellow';
@@ -15,6 +17,12 @@ $colors: 'amber', 'blue', 'cyan', 'green', 'grey', 'indigo', 'light-blue', 'ligh
     text-align: center;
     vertical-align: middle;
 
+
+
+
+
+
+
     &:focus-visible {
         outline: $width-avatar-outline solid $color-avatar-outline-focus;
     }
@@ -149,6 +157,197 @@ $colors: 'amber', 'blue', 'cyan', 'green', 'grey', 'indigo', 'light-blue', 'ligh
     &:hover {
         cursor: pointer;
     }
+
+
+}
+
+
+.#{$module}-wrapper{
+    position: relative;
+    display: inline-flex;
+    flex-direction: column;
+    align-items: center;
+    width: fit-content;
+    .#{$module}-top_slot-bg{
+        position: absolute;
+        display: flex;
+        justify-content: center;
+        border-radius: 50%;
+        overflow: hidden;
+        
+        &-small{
+            width: $width-avatar_small;
+            height: $width-avatar_small;
+        }
+
+        &-default{
+            width: $width-avatar_default;
+            height: $width-avatar_default;
+        }
+
+        &-medium{
+            width: $width-avatar_medium;
+            height: $width-avatar_medium;
+        }
+
+        &-large{
+            width: $width-avatar_large;
+            height: $width-avatar_large;
+        }
+
+        &-extra-large{
+            width: $width-avatar_extra_large;
+            height: $width-avatar_extra_large;
+        }
+
+
+        &-svg{
+            position: absolute;
+        }
+        &-svg-small{
+            top: $spacing-avatar-top_slot_small-shift;
+            scale: $spacing-avatar-top_slot_small-scale;
+        }
+        &-svg-default{
+            top: $spacing-avatar-top_slot_default-shift;
+            scale: $spacing-avatar-top_slot_default-scale;
+        }
+        &-svg-medium{
+            top: $spacing-avatar-top_slot_medium-shift;
+            scale: $spacing-avatar-top_slot_medium-scale;
+        }
+        &-svg-large{
+            top: $spacing-avatar-top_slot_large-shift;
+            scale: $spacing-avatar-top_slot_large-scale;
+        }
+        &-svg-extra-large{
+            top: $spacing-avatar-top_slot_extra_large-shift;
+            scale: $spacing-avatar-top_slot_extra_large-scale;
+        }
+    }
+
+    .#{$module}-top_slot-bg-with_border{
+        //top: $width-avatar_additional-border;
+    }
+
+    .#{$module}-top_slot-wrapper{
+        position: absolute;
+        display: flex;
+        justify-content: center;
+        .#{$module}-top_slot{
+            color:$color-avatar-top_slot_text;
+            font-weight: $font-weight-bold;
+            &-content{
+                user-select: none;
+                position: relative;
+                line-height: normal;
+                &-small{
+                    font-size: $font-avatar_top_slot-small-fontSize;
+                    margin-top: $spacing-avatar-top_slot_small-content-marginTop;
+                }
+                &-default{
+                    font-size: $font-avatar_top_slot-default-fontSize;
+                    margin-top: $spacing-avatar-top_slot_default-content-marginTop;
+                }
+                &-medium{
+                    font-size: $font-avatar_top_slot-medium-fontSize;
+                    margin-top: $spacing-avatar-top_slot_medium-content-marginTop;
+                }
+                &-large{
+                    font-size: $font-avatar_top_slot-large-fontSize;
+                    margin-top: $spacing-avatar-top_slot_large-content-marginTop;
+                }
+                &-extra-large{
+                    font-size: $font-avatar_top_slot-extra_large-fontSize;
+                    margin-top: $spacing-avatar-top_slot_extra_large-content-marginTop;
+                }
+            }
+
+        }
+    }
+
+
+
+    .#{$module}-bottom_slot{
+        color:var(--semi-color-bg-0);
+        position: absolute;
+        cursor: pointer;
+        bottom: $spacing-avatar_additional-borderGap + $width-avatar_additional-border;
+        transform: translateY(50%);
+        user-select: none;
+        &-shape_circle{
+            display: flex;
+            justify-content: center;
+            align-items: center;
+            background: $color-avatar-bottom_slot_bg;
+            border-radius: var(--semi-border-radius-circle);
+            line-height:normal;
+        }
+        &-shape_circle-small{
+            width:$width-avatar-bottom_slot_circle_small;
+            height:$width-avatar-bottom_slot_circle_small;
+            font-size: $font-avatar_bottom_slot-small-fontSize;
+        }
+        &-shape_circle-default{
+            width:$width-avatar-bottom_slot_circle_default;
+            height:$width-avatar-bottom_slot_circle_default;
+            font-size: $font-avatar_bottom_slot-default-fontSize;
+        }
+        &-shape_circle-medium{
+            width:$width-avatar-bottom_slot_circle_medium;
+            height:$width-avatar-bottom_slot_circle_medium;
+            font-size: $font-avatar_bottom_slot-medium-fontSize;
+        }
+        &-shape_circle-large{
+            width:$width-avatar-bottom_slot_circle_large;
+            height:$width-avatar-bottom_slot_circle_large;
+            font-size: $font-avatar_bottom_slot-large-fontSize;
+        }
+
+        &-shape_circle-extra-large{
+            width:$width-avatar-bottom_slot_circle_extra_large;
+            height:$width-avatar-bottom_slot_circle_extra_large;
+            font-size: $font-avatar_bottom_slot-extra_large-fontSize;
+        }
+
+
+
+        &-shape_square{
+            display: flex;
+            justify-content: center;
+            align-items: center;
+            background: $color-avatar-bottom_slot_bg;
+            border-radius: $radius-avatar-bottom_slot_square;
+            padding: $spacing-avatar-bottom_slot_square-paddingY $spacing-avatar-bottom_slot_square-paddingX;
+            font-weight: $font-weight-bold;
+            border-style: solid;
+            border-color: $color-avatar-bottom_slot_square-border;
+        }
+
+        &-shape_square-small{
+            font-size: $font-avatar_bottom_slot-small-fontSize;
+            border-width: $width-avatar-bottom_slot_square_small-border;
+        }
+        &-shape_square-default{
+            font-size: $font-avatar_bottom_slot-default-fontSize;
+            border-width: $width-avatar-bottom_slot_square_default-border;
+
+        }
+        &-shape_square-medium{
+            font-size: $font-avatar_bottom_slot-medium-fontSize;
+            border-width: $width-avatar-bottom_slot_square_medium-border;
+
+        }
+        &-shape_square-large{
+          font-size: $font-avatar_bottom_slot-large-fontSize;
+            border-width: $width-avatar-bottom_slot_square_large-border;
+        }
+
+        &-shape_square-extra-large{
+            font-size: $font-avatar_bottom_slot-extra_large-fontSize;
+              border-width: $width-avatar-bottom_slot_square_extra_large-border;
+          }
+    }
 }
 
 .#{$module}-group {
@@ -206,6 +405,7 @@ $colors: 'amber', 'blue', 'cyan', 'green', 'grey', 'indigo', 'light-blue', 'ligh
         }
     }
 
+
     .#{$module}-item-more {
         background-color: $color-avatar_more_default-bg-default;
     }
@@ -217,4 +417,117 @@ $colors: 'amber', 'blue', 'cyan', 'green', 'grey', 'indigo', 'light-blue', 'ligh
     }
 }
 
+
+.#{$module}-additionalBorder{
+    border-style: solid;
+    border-color: $color-avatar_additional-border;
+    display: inline-block;
+    box-sizing: border-box;  
+    position: absolute;
+    border-width: $width-avatar_additional-border;
+    top: -1 *  $width-avatar_additional-border - $spacing-avatar_additional-borderGap;
+    left: -1 *  $width-avatar_additional-border - $spacing-avatar_additional-borderGap;
+
+    &-extra-extra-small{
+        width: $width-avatar_extra_extra_small + 2 * $spacing-avatar_additional-borderGap + 2 * $width-avatar_additional-border;
+        height: $width-avatar_extra_extra_small + 2 * $spacing-avatar_additional-borderGap + 2 * $width-avatar_additional-border;
+    }
+
+    &-extra-small{
+        width: $width-avatar_extra-small + 2 * $spacing-avatar_additional-borderGap + 2 * $width-avatar_additional-border;
+        height: $width-avatar_extra-small + 2 * $spacing-avatar_additional-borderGap + 2 * $width-avatar_additional-border;
+    }
+
+    &-small{
+        width: $width-avatar_small + 2 * $spacing-avatar_additional-borderGap + 2 * $width-avatar_additional-border;
+        height: $width-avatar_small + 2 * $spacing-avatar_additional-borderGap + 2 * $width-avatar_additional-border;
+    }
+
+    &-default{
+        width: $width-avatar_default + 2 * $spacing-avatar_additional-borderGap + 2 * $width-avatar_additional-border;
+        height: $width-avatar_default + 2 * $spacing-avatar_additional-borderGap + 2 * $width-avatar_additional-border;
+    }
+
+    &-medium{
+      
+        width: $width-avatar_medium + 2 * $spacing-avatar_additional-borderGap + 2 * $width-avatar_additional-border;
+        height: $width-avatar_medium + 2 * $spacing-avatar_additional-borderGap + 2 * $width-avatar_additional-border;
+    }
+
+    &-large{
+        width: $width-avatar_large + 2 * $spacing-avatar_additional-borderGap + 2 * $width-avatar_additional-border;
+        height: $width-avatar_large + 2 * $spacing-avatar_additional-borderGap + 2 * $width-avatar_additional-border;
+       
+    }
+
+    &-extra-large{
+        width: $width-avatar_extra_large + 2 * $spacing-avatar_additional-borderGap + 2 * $width-avatar_additional-border;
+        height: $width-avatar_extra_large + 2 * $spacing-avatar_additional-borderGap + 2 * $width-avatar_additional-border;
+    }
+}
+
+.#{$module}-square.#{$module}-additionalBorder-extra_extra_small {
+    border-radius: $radius-avatar-extra_extra_small;
+}
+
+.#{$module}-square.#{$module}-additionalBorder-extra_small {
+    border-radius: $radius-avatar-extra_small;
+}
+
+.#{$module}-square.#{$module}-additionalBorder-small {
+    border-radius: $radius-avatar-small;
+}
+
+.#{$module}-square.#{$module}-additionalBorder-default {
+    border-radius: $radius-avatar-default;
+}
+
+.#{$module}-square.#{$module}-additionalBorder-medium {
+    border-radius: $radius-avatar-medium;
+}
+
+.#{$module}-square.#{$module}-additionalBorder-large {
+    border-radius: $radius-avatar-large;
+}
+
+.#{$module}-additionalBorder-circle{
+    border-radius: var(--semi-border-radius-circle);
+}
+
+
+.#{$module}-additionalBorder-animated{
+    animation: $animation_duration-additionalBorder linear infinite #{$module}-additionalBorder;
+}
+
+.#{$module}-animated{
+    animation: $animation_duration-content linear infinite #{$module}-content ;
+}
+
+@keyframes #{$module}-additionalBorder {
+    0% {
+        opacity: $animation_opacity-additionalBorder-start;
+        transform: scale($animation_scale-additionalBorder-start)
+    }
+
+    to {
+        border-width: $animation_width-additionalBorder-end;
+        opacity: $animation_opacity-additionalBorder-end;
+        transform: scale($animation_scale-additionalBorder-end);
+    }
+}
+
+@keyframes #{$module}-content{
+    0% {
+        transform: scale($animation_scale-content-start)
+    }
+
+    50% {
+        transform: scale($animation_scale-content-middle)
+    }
+
+    to {
+        transform: scale($animation_scale-content-start)
+    }
+}
+
 @import './rtl.scss';

+ 66 - 10
packages/semi-foundation/avatar/variables.scss

@@ -24,29 +24,85 @@ $font-avatar_extra_large-lineHeight: 77px; // 文本行高 - 超大
 
 $radius-avatar: var(--semi-border-radius-circle); // 头像圆角
 
-$width-avatar_extra_large-border: 3px; // 头像描边尺寸 - 超大
-$spacing-avatar_extra_large-marginLeft: -32px; // 头像左侧外边距 - 超大
+$width-avatar_extra_large-border: 3px; // 头像组头像描边尺寸 - 超大
+$spacing-avatar_extra_large-marginLeft: -32px; // 头像组头像左侧外边距 - 超大
 
-$width-avatar_large-border: 3px; // 头像描边尺寸 - 大
+$width-avatar_large-border: 3px; // 头像组头像描边尺寸 - 大
 $spacing-avatar_large-marginLeft: -18px; // 头像左侧外边距 - 大
 
-$width-avatar_medium-border: 2px; // 头像描边尺寸 - 中
+$width-avatar_medium-border: 2px; // 头像组头像描边尺寸 - 中
 $spacing-avatar_medium-marginLeft: -12px; // 头像左侧外边距 - 中
 
-$width-avatar_default-border: 2px; // 头像描边尺寸 - 默认
+$width-avatar_default-border: 2px; // 头像组头像描边尺寸 - 默认
 $spacing-avatar_default-marginLeft: -12px; // 头像左侧外边距 - 默认
 
-$width-avatar_small-border: 2px; // 头像描边尺寸 - 小
+$width-avatar_small-border: 2px; // 头像组头像描边尺寸 - 小
 $spacing-avatar_small-marginLeft: -12px; // 头像左侧外边距 - 小
 
-$width-avatar_extra_small-border: 1px; // 头像描边尺寸 - 超小
+$width-avatar_extra_small-border: 1px; // 头像组头像描边尺寸 - 超小
 $spacing-avatar_extra_small-marginLeft: -10px; // 头像左侧外边距 - 超小
 
-$width-avatar_extra_extra_small-border: 1px; // 头像描边尺寸 - 极小
+$width-avatar_extra_extra_small-border: 1px; // 头像组头像描边尺寸 - 极小
 $spacing-avatar_extra_extra_small-marginLeft: -4px; // 头像左侧外边距 - 极小
-
 $width-avatar-outline: 2px; //头像聚焦轮廓宽度
 
+$width-avatar_additional-border: 1.5px; // 额外描边尺寸
+$color-avatar_additional-border: var(--semi-color-primary); // 额外描边颜色
+$spacing-avatar_additional-borderGap: 2px; // 额外描边与内侧间距
+
+$width-avatar-bottom_slot_circle_small: 12px; // small 头像底部 slot 圆形半径
+$width-avatar-bottom_slot_circle_default: 16px; // default 头像底部 slot 圆形半径
+$width-avatar-bottom_slot_circle_medium: 18px; // medium 头像底部 slot 圆形半径
+$width-avatar-bottom_slot_circle_large: 28px; // large 头像底部 slot 圆形半径
+$width-avatar-bottom_slot_circle_extra_large: 28px; // extra large 头像底部 slot 圆形半径
+$color-avatar-bottom_slot_bg:var(--semi-color-primary); // 头像底部 slot 背景色
+
+$radius-avatar-bottom_slot_square:4px;  // 底部 slot square 圆角
+$font-avatar_bottom_slot-small-fontSize: 5px; // small 底部 slot 文字大小
+$font-avatar_bottom_slot-default-fontSize: 12px; // default 底部 slot 文字大小
+$font-avatar_bottom_slot-medium-fontSize: 12px; // medium 底部 slot 文字大小
+$font-avatar_bottom_slot-large-fontSize: 12px; // large 底部 slot 文字大小
+$font-avatar_bottom_slot-extra_large-fontSize: 14px; // extra large 底部 slot 文字大小
+$spacing-avatar-bottom_slot_square-paddingX:4px; // 底部 slot square 形状左边距
+$spacing-avatar-bottom_slot_square-paddingY:1px; //底部 slot square 形状右边距
+
+$font-avatar_top_slot-small-fontSize: 5px; // small 顶部 slot 文字大小
+$font-avatar_top_slot-default-fontSize: 6px; // default 顶部 slot 文字大小
+$font-avatar_top_slot-medium-fontSize: 8px; // medium 顶部 slot 文字大小
+$font-avatar_top_slot-large-fontSize: 14px; // large 顶部 slot 文字大小
+$font-avatar_top_slot-extra_large-fontSize: 16px; // extra large 顶部 slot 文字大小
+
+$spacing-avatar-top_slot_small-content-marginTop: 0px; // small 顶部文字 marginTop
+$spacing-avatar-top_slot_default-content-marginTop: -2px; // default 顶部文字 marginTop
+$spacing-avatar-top_slot_medium-content-marginTop: 0px; // medium 顶部文字 marginTop
+$spacing-avatar-top_slot_large-content-marginTop: 0px; // large 顶部文字 marginTop
+$spacing-avatar-top_slot_extra_large-content-marginTop: 0px; // extra large 顶部文字 marginTop 
+
+$color-avatar-bottom_slot_square-border:var(--semi-color-bg-0); // 底部 square 边框颜色
+$width-avatar-bottom_slot_square_small-border:2px; // small 头像底部 square 边框宽度
+$width-avatar-bottom_slot_square_default-border:2px; // default 头像底部 square 边框宽度
+$width-avatar-bottom_slot_square_medium-border:2px; // medium 头像底部 square 边框宽度 
+$width-avatar-bottom_slot_square_large-border:2px; // large 头像底部 square 边框宽度
+$width-avatar-bottom_slot_square_extra_large-border:2px; // extra large 头像底部 square 边框宽度
+
+$color-avatar-top_slot_text:var(--semi-color-bg-0); //顶部 Slot 文字颜色
+$color-avatar-top_slot_gradient_start: var(--semi-color-primary); // 顶部 slot 渐变起始色
+$color-avatar-top_slot_gradient_end: var(--semi-color-primary); //  顶部 slot 渐变结束色
+
+
+$spacing-avatar-top_slot_small-shift: -28px; // small 顶部 slot 偏移量, 和 scale 一起控制 slot 的位置
+$spacing-avatar-top_slot_default-shift: -32px; // default 顶部 slot 偏移量, 和 scale 一起控制 slot 的位置
+$spacing-avatar-top_slot_medium-shift: -30px; // medium 顶部 slot 偏移量, 和 scale 一起控制 slot 的位置
+$spacing-avatar-top_slot_large-shift: -30px; // large 顶部 slot 偏移量, 和 scale 一起控制 slot 的位置
+$spacing-avatar-top_slot_extra_large-shift: -32px; // extra large 顶部 slot 偏移量, 和 scale 一起控制 slot 的位置
+
+$spacing-avatar-top_slot_small-scale: 0.4; // small 顶部 slot 缩放比例
+$spacing-avatar-top_slot_default-scale: 0.7; // default 顶部 slot 缩放比例
+$spacing-avatar-top_slot_medium-scale: 0.8; // medium 顶部 slot 缩放比例
+$spacing-avatar-top_slot_large-scale: 1.1; // large 顶部 slot 缩放比例
+$spacing-avatar-top_slot_extra_large-scale: 1.4; // large 顶部 slot 缩放比例 
+
+
 // radius
 $radius-avatar_extra_extra_small: 3px; // 极小尺寸头像的圆角
 $radius-avatar_extra_small: 3px; // 超小尺寸头像的圆角
@@ -54,4 +110,4 @@ $radius-avatar_small: 3px; // 小尺寸头像的圆角
 $radius-avatar_default: 3px; // 默认尺寸头像的圆角
 $radius-avatar_medium: 3px; // 中尺寸头像的圆角
 $radius-avatar_large: 6px; // 大尺寸头像的圆角
-$radius-avatar_extra_large: 12px; // 超大尺寸头像的圆角
+$radius-avatar_extra_large: 12px; // 超大尺寸头像的圆角

+ 7 - 4
packages/semi-foundation/datePicker/foundation.ts

@@ -46,9 +46,10 @@ export type DisabledDateOptions = {
      */
     rangeInputFocus?: 'rangeStart' | 'rangeEnd' | false
 };
+
 export type PresetType = {
-    start?: string | Date | number;
-    end?: string | Date | number;
+    start?: BaseValueType | (() => BaseValueType);
+    end?: BaseValueType | (() => BaseValueType);
     text?: string
 };
 
@@ -1068,18 +1069,20 @@ export default class DatePickerFoundation extends BaseFoundation<DatePickerAdapt
     handlePresetClick(item: PresetType, e: any) {
         const { type, timeZone } = this.getProps();
         const prevTimeZone = this.getState('prevTimezone');
+        const start = typeof item.start === 'function' ? item.start() : item.start;
+        const end = typeof item.end === 'function' ? item.end() : item.end;
 
         let value;
         switch (type) {
             case 'month':
             case 'dateTime':
             case 'date':
-                value = this.parseWithTimezone([item.start], timeZone, prevTimeZone);
+                value = this.parseWithTimezone([start], timeZone, prevTimeZone);
                 this.handleSelectedChange(value);
                 break;
             case 'dateTimeRange':
             case 'dateRange':
-                value = this.parseWithTimezone([item.start, item.end], timeZone, prevTimeZone);
+                value = this.parseWithTimezone([start, end], timeZone, prevTimeZone);
                 this.handleSelectedChange(value, { needCheckFocusRecord: false });
                 break;
             default:

+ 12 - 3
packages/semi-foundation/input/input.scss

@@ -85,7 +85,7 @@ $module: #{$prefix}-input;
         border: $color-input_default-border-focus solid $width-input_wrapper_focus-border;
 
         &:hover {
-            background-color: $color-input_default-bg-focus;
+            background-color: $color-input_default-bg-focus-hover;
             border-color: $color-input_default-border-focus;
         }
 
@@ -690,7 +690,18 @@ $module: #{$prefix}-input;
     }
 }
 
+.#{$module}-only_border{
+    background: transparent;
+    &:hover{
+        background: transparent;
+        border-color: $color_input-default-border-only_border-hover;
+    }
+    &:focus-within{
+        background: transparent;
+    }
+    border-color: $color_input-default-border-only_border-default;
 
+}
 
 .#{$module}-borderless{
 
@@ -713,8 +724,6 @@ $module: #{$prefix}-input;
     }
 
 
-
-
 }
 
 @import "./rtl.scss";

+ 5 - 0
packages/semi-foundation/input/variables.scss

@@ -13,6 +13,8 @@ $color-input_default-bg-focus: var(--semi-color-fill-0); // 输入框背景颜
 $color-input_default-border-focus: var(--semi-color-focus-border); // 输入框描边颜色 - 选中
 $color-input_icon-outline: var(--semi-color-primary-light-active); // 输入框 icon outline 颜色
 
+$color-input_default-bg-focus-hover: $color-input_default-bg-focus; // 输入框背景颜色 - 选中悬浮
+
 // error
 $color-input_danger-bg-default: var(--semi-color-danger-light-default); // 错误输入框背景颜色 - 默认
 $color-input_danger-border-default: var(--semi-color-danger-light-default); // 错误输入框描边颜色 - 默认
@@ -57,6 +59,9 @@ $color-input_counter_danger-text-default: var(--semi-color-danger); // 多行文
 
 $color-input_group-border-default: var(--semi-color-border); // 输入框组合分割线颜色
 
+$color_input-default-border-only_border-default: var(--semi-color-border); // 只有描边的输入框描边颜色 - 默认
+$color_input-default-border-only_border-hover: var(--semi-color-border); // 只有描边的输入框描边颜色 - 默认
+
 $height-input_large: $height-control-large - 2px; // 输入框高度 & 行高 - 大尺寸
 $height-input_small: $height-control-small - 2px; // 输入框高度 & 行高 - 小尺寸
 $height-input_default: $height-control-default - 2px; // 输入框高度 & 行高 - 默认尺寸

+ 5 - 1
packages/semi-foundation/modal/modal.scss

@@ -70,7 +70,11 @@ $module: #{$prefix}-modal;
         padding: $spacing-modal_content-paddingY $spacing-modal_content-paddingX;
         background-clip: padding-box;
         overflow: hidden;
-        @include shadow-elevated;
+        box-shadow: $shadow-modal_content;
+    }
+
+    &-footerfill{
+        display: flex;
     }
 
     &-content-fullScreen {

+ 2 - 1
packages/semi-foundation/modal/modalFoundation.ts

@@ -54,7 +54,8 @@ export interface ModalProps {
     keepDOM?: boolean;
     direction?: any;
     fullScreen?: boolean;
-    preventScroll?: boolean
+    preventScroll?: boolean;
+    footerFill?: boolean
 }
 
 export interface ModalState {

+ 4 - 0
packages/semi-foundation/modal/variables.scss

@@ -71,3 +71,7 @@ $color-modal_footer-border:transparent; // 模态框 footer 顶部描边颜色
 $width-modal_footer-border:0; // 模态框 footer 顶部描边宽度
 
 
+//shadow
+$shadow-modal_content: var(--semi-shadow-elevated);
+
+

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

@@ -1,13 +1,13 @@
 {
     "name": "@douyinfe/semi-foundation",
-    "version": "2.51.4",
+    "version": "2.52.0-beta.1",
     "description": "",
     "scripts": {
         "build:lib": "node ./scripts/compileLib.js",
         "prepublishOnly": "npm run build:lib"
     },
     "dependencies": {
-        "@douyinfe/semi-animation": "2.51.4",
+        "@douyinfe/semi-animation": "2.52.0-beta.1",
         "async-validator": "^3.5.0",
         "classnames": "^2.2.6",
         "date-fns": "^2.29.3",

+ 3 - 4
packages/semi-foundation/select/select.scss

@@ -59,12 +59,12 @@ $overflowList: #{$prefix}-overflow-list;
 
     &-open,
     &-focus {
-        border: $border-thickness-control-focus solid $color-select_default-border-focus;
+        border: $width-select-border-focus solid $color-select_default-border-focus;
         outline: 0;
 
         &:hover {
             background-color: $color-select-bg-default;
-            border: $border-thickness-control-focus solid $color-select_default-border-focus;
+            border: $width-select-border-hover solid $color-select_default-border-focus;
         }
 
         // when click the trigger, trigger get the focus state, active style should take effect
@@ -124,9 +124,8 @@ $overflowList: #{$prefix}-overflow-list;
         }
 
         &:focus {
-            // border: $border-thickness-control-focus solid $color-select_default-border-focus;
             // when select is disabled, the border should not have active color
-            border: $border-thickness-control-focus solid transparent;
+            border: $width-select-border-focus solid transparent;
         }
 
         .#{$module}-selection,

+ 7 - 6
packages/semi-foundation/select/variables.scss

@@ -6,7 +6,8 @@ $color-select-bg-focus: var(--semi-color-fill-0); // 选择器输入框背景色
 $color-select-border-default: transparent; // 选择器输入框描边颜色
 $color-select-border-hover: $color-select-border-default;  // 选择器输入框描边颜色 - 悬浮
 $color-select-border-active: var(--semi-color-focus-border); // 选择器输入框描边颜色 - 按下态
-$color-select-border-focus: $color-select-border-active;// 选择器输入框描边颜色 - 悬停态
+$color-select-border-focus: $color-select-border-active;// 选择器输入框描边颜色 - 选中态
+
 $color-select_warning-bg-default: var(--semi-color-warning-light-default); // 警示选择器输入框背景色 - 默认态
 $color-select_warning-border-default: var(--semi-color-warning-light-default); // 警示选择器输入框描边颜色 - 默认态
 $color-select_warning-bg-hover: var(--semi-color-warning-light-hover); // 警示选择器输入框背景色 - 悬停态
@@ -15,6 +16,7 @@ $color-select_warning-bg-focus: var(--semi-color-warning-light-default); // 警
 $color-select_warning-border-focus: var(--semi-color-warning); // 警示选择器输入框描边颜色 - 选中态
 $color-select_warning-bg-active: var(--semi-color-warning-light-active); // 警示选择器输入框背景色 - 按下态
 $color-select_warning-border-active: var(--semi-color-warning-light-active); // 警示选择器输入框描边颜色 - 按下态
+
 $color-select_danger-bg-default: var(--semi-color-danger-light-default); // 报错选择器输入框背景色 - 默认态
 $color-select_danger-border-default: var(--semi-color-danger-light-default); // 报错选择器输入框描边颜色 - 默认态
 $color-select_danger-bg-hover: var(--semi-color-danger-light-hover); // 报错选择器输入框背景色 - 悬停态
@@ -23,7 +25,9 @@ $color-select_danger-bg-focus: var(--semi-color-danger-light-default); // 报错
 $color-select_danger-border-focus: var(--semi-color-danger); // 报错选择器输入框描边颜色 - 选中态
 $color-select_danger-bg-active: var(--semi-color-danger-light-active); // 报错选择器输入框背景色 - 按下态
 $color-select_danger-border-active: var(--semi-color-danger-light-active); // 报错选择器输入框描边颜色 - 按下态
-$color-select_default-border-focus: var(--semi-color-focus-border); // 选择器输入框描边颜色 - 选中态
+
+$color-select_default-border-focus: var(--semi-color-focus-border); // 默认选择器输入框描边颜色 - 选中态
+
 $color-select_main-text-default: var(--semi-color-text-0); // 选择器输入框回填内容文本颜色
 $color-select-icon-default: var(--semi-color-text-2); // 选择器输入框图标颜色
 $color-select_clearBtn-text-default: var(--semi-color-text-2); // 选择器输入框清空按钮颜色 - 默认态
@@ -34,6 +38,7 @@ $color-select_input_disabled-border: var(--semi-color-border); // 禁用选择
 $color-select_input_disabled-text: var(--semi-color-disabled-text); // 禁用选择器输入框回填内容文字颜色
 $color-select_input_disabled-bg-hover: var(--semi-color-disabled-fill); // 选择器输入框回填内容文字颜色 - 悬停态
 $color-select_input_placeholder-text: var(--semi-color-text-2); // 选择器输入框占位文本文字颜色
+
 $color-select_option_main-text: var(--semi-color-text-0); // 选择器菜单选项文本颜色
 $color-select_option_keyword-text: var(--semi-color-primary); // 选择器菜单选项匹配搜索结果文本颜色
 $color-select_option-bg-default: transparent; // 选择器菜单选项背景颜色 - 默认态
@@ -88,10 +93,6 @@ $spacing-select_option-paddingTop: $spacing-tight; // 选择器菜单项顶部
 $spacing-select_option-paddingBottom: $spacing-tight; // 选择器菜单项底部内边距
 
 
-// $spacing-select_option_first-marginTop: $spacing-extra-tight; // 选择器第一个菜单项顶部外边距
-// $spacing-select_option_last-marginBottom: $spacing-extra-tight; // 选择器最后一个菜单项顶部外边距
-
-
 $spacing-select_tag-marginTop: $spacing-super-tight - 1px; // 多项选择器标签顶部外边距
 $spacing-select_tag-marginRight: $spacing-extra-tight; // 多项选择器标签右侧外边距
 $spacing-select_tag-marginBottom: $spacing-super-tight - 1px; // 多项选择器标签底部外边距

+ 1 - 0
packages/semi-foundation/slider/constants.ts

@@ -8,6 +8,7 @@ const cssClasses = {
     DOTS: `${BASE_CLASS_PREFIX}-slider-dots`,
     MARKS: `${BASE_CLASS_PREFIX}-slider-marks`,
     HANDLE: `${BASE_CLASS_PREFIX}-slider-handle`,
+    HANDLE_DOT: `${BASE_CLASS_PREFIX}-slider-handle-dot`,
 };
 
 const strings = {

+ 8 - 1
packages/semi-foundation/slider/foundation.ts

@@ -36,7 +36,14 @@ export interface SliderProps{
     'aria-label'?: string;
     'aria-labelledby'?: string;
     'aria-valuetext'?: string;
-    getAriaValueText?: (value: number, index?: number) => string
+    getAriaValueText?: (value: number, index?: number) => string;
+    handleDot?: {
+        size?: string;
+        color?: string
+    } & ({
+        size?: string;
+        color?: string
+    }[])
 }
 
 export interface SliderState {

+ 10 - 0
packages/semi-foundation/slider/slider.scss

@@ -58,9 +58,19 @@ $module: #{$prefix}-slider;
         cursor: pointer;
         transition: background-color $transition_duration_slider_handle-bg $transition_function-slider-handle-bg $transition_delay-slider_handle-bg;
         transform: $transform_scale-slider_handle translateX(-50%) translateY($spacing-slider_handle-translateY);
+        display: inline-flex;
+        justify-content: center;
+        align-items: center;
         &:focus-visible {
             outline: $width-slider_handle-focus solid $color-slider_handle-focus;
         }
+
+        &-dot{
+            background:$color-slider_handle_dot;
+            width:$width-slider_handle_dot;
+            height: $width-slider_handle_dot;
+            border-radius: var(--semi-border-radius-circle);
+        }
     }
 
     &-handle:hover {

+ 2 - 0
packages/semi-foundation/slider/variables.scss

@@ -15,6 +15,7 @@ $color-slider_rail: rgba(0, 0, 0, 0.65);
 $color-slider_track-bg-default: var(--semi-color-primary); // 滑动条轨道颜色 - 已填充
 $color-slider_track_disabled-bg: var(--semi-color-primary-disabled); // 禁用滑动条轨道颜色 - 已填充
 $color-slider_handle-focus: var(--semi-color-primary-light-active); // 圆形按钮轮廓 - 聚焦
+$color-slider_handle_dot: var(--semi-color-primary); // 圆形按钮内部圆点颜色
 
 // Spacing
 $spacing-slider-paddingX: 13px; // 滑动条整体水平内边距
@@ -57,6 +58,7 @@ $height-slider_track: 4px; // 滚动条已填充轨道高度
 $width-slider_dot: 4px; // 滚动条圆形刻度点宽度
 $width-slider_handle_border_disabled: 1px; // 禁用滚动条圆形按钮按下后描边宽度
 $width-slider_handle-focus: 2px; // 圆形按钮轮廓 - 聚焦
+$width-slider_handle_dot: 4px; // 圆形按钮内部圆点宽度
 
 // Font
 $font-slider_rail-fontSize: 14px; // 滚动条轨道文本字号

+ 2 - 0
packages/semi-foundation/treeSelect/foundation.ts

@@ -189,6 +189,7 @@ export interface TreeSelectAdapter<P = Record<string, any>, S = Record<string, a
     closeMenu: (cb?: () => void) => void;
     getTriggerWidth: () => boolean | number;
     setOptionWrapperWidth: (width: null | number) => void;
+    notifyClear: (e: any) => void;
     notifyChange: BasicOnChangeWithBasic;
     notifyChangeWithObject: BasicOnChangeWithObject;
     notifyExpand: (expandedKeys: Set<string>, expandedOtherProps: BasicExpandedOtherProps) => void;
@@ -548,6 +549,7 @@ export default class TreeSelectFoundation<P = Record<string, any>, S = Record<st
                 }
             }
         }
+        this._adapter.notifyClear(e);
     }
 
     /**

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

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

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

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

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

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

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

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

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

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

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

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

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

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

+ 3 - 1
packages/semi-ui/_utils/index.tsx

@@ -24,7 +24,9 @@ export function stopPropagation(e: React.MouseEvent | React.FocusEvent<HTMLEleme
  * 
  * skip clone function and react element
  */
-export function cloneDeep(value: any, customizer?: (value: any) => void) {
+export function cloneDeep<T>(value: T): T;
+export function cloneDeep<T>(value: T, customizer: (value: any) => any): any;
+export function cloneDeep(value: any, customizer?: (value: any) => any) {
     return cloneDeepWith(value, v => {
         if (typeof customizer === 'function') {
             return customizer(v);

+ 36 - 0
packages/semi-ui/avatar/TopSlotSvg.tsx

@@ -0,0 +1,36 @@
+import { getUuidShort } from '@douyinfe/semi-foundation/utils/uuid';
+import React from 'react';
+
+
+
+
+const TopSlotSvg = ({ gradientStart, gradientEnd }: {gradientStart: string;gradientEnd: string})=> {
+    const id = getUuidShort();
+    return <svg xmlns="http://www.w3.org/2000/svg" width="51" height="52" viewBox="0 0 51 52" fill="none">
+        <g filter="url(#filter0_d_6_2)">
+            <path
+                d="M40.4918 46.5592C44.6795 43.176 46.261 34.1333 47.5301 25.6141C49.5854 11.8168 39.6662 1 25.8097 1C11.2857 1 3 11.4279 3 25.3518C3 33.7866 6.29361 43.8947 10.4602 46.5592C12.5868 47.9192 12.5868 47.9051 25.8097 47.9192C38.3651 47.9282 38.5352 48.14 40.4918 46.5592Z"
+                fill={`url(#${id})`}/>
+        </g>
+        <defs>
+            <filter id="filter0_d_6_2" x="0.789215" y="0.447304" width="49.2216" height="51.3549"
+                filterUnits="userSpaceOnUse" colorInterpolationFilters="sRGB">
+                <feFlood floodOpacity="0" result="BackgroundImageFix"/>
+                <feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
+                    result="hardAlpha"/>
+                <feOffset dy="1.65809"/>
+                <feGaussianBlur stdDeviation="1.10539"/>
+                <feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.3 0"/>
+                <feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_6_2"/>
+                <feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_6_2" result="shape"/>
+            </filter>
+            <linearGradient id={id} x1="17.671" y1="31.7392" x2="17.671" y2="47.9333"
+                gradientUnits="userSpaceOnUse">
+                <stop stopColor={gradientStart}/>
+                <stop offset="1" stopColor={gradientEnd}/>
+            </linearGradient>
+        </defs>
+    </svg>;
+};
+
+export default TopSlotSvg;

+ 121 - 1
packages/semi-ui/avatar/_story/avatar.stories.jsx

@@ -1,6 +1,7 @@
 import React, {useState} from 'react';
 import { Avatar,Popover, AvatarGroup, RadioGroup, Radio } from '../../index';
 import { Input } from '../../input'
+import {IconPlus} from "@douyinfe/semi-icons";
 
 export default {
   title: 'Avatar',
@@ -37,6 +38,125 @@ export const Basic = () => (
   </div>
 );
 
+export const BottomSolt = () => (
+    <div>
+        <div>
+            <Avatar shape="circle" border={true} bottomSlot={{
+                shape:'circle',
+                content:<IconPlus/>
+            }}>U</Avatar>
+            <Avatar shape="circle" size={'large'} border={true} bottomSlot={{
+                shape:'circle',
+                content:<IconPlus/>
+            }}>U</Avatar>
+            <Avatar shape="circle" size={'small'} border={true} bottomSlot={{
+                shape:'circle',
+                content:<IconPlus/>
+            }}>U</Avatar>
+            <Avatar shape="circle" bottomSlot={{
+                shape:'square',
+                content: "直播中"
+            }}>U</Avatar>
+            <Avatar shape="circle" size={"large"} bottomSlot={{
+                shape:'square',
+                content: "直播中"
+            }}>U</Avatar>
+            <Avatar shape="circle" bottomSlot={{
+                shape:'rect',
+                content: "直播中",
+                render:()=>{
+                    return "test"
+                }
+            }}>U</Avatar>
+        </div>
+    </div>
+);
+
+export const TopSolt = () => (
+    <div>
+        <div>
+            <Avatar shape="circle"  size={"extra-extra-small"}  border={true} topSlot={{
+                content:"直播",
+                gradientStart:"rgb(255,23,100)",
+                gradientEnd:"rgb(237,52,148)"
+            }}>U</Avatar>
+            <Avatar shape="circle"  size={"extra-small"}  border={true} topSlot={{
+                content:"直播"
+            }}>U</Avatar>
+            <Avatar shape="square" size={"default"} border={true} topSlot={{
+                content:"直播"
+            }}>U</Avatar>
+            <Avatar shape="circle" size={"medium"} border={true} topSlot={{
+                content:"直播"
+            }}>U</Avatar>
+            <Avatar shape="circle" size={"large"} borderMotion={true} border={true} topSlot={{
+                content:"直播"
+            }} bottomSlot={{
+                content:"T",
+                shape:"circle"
+            }} contentMotion={true}>U</Avatar>
+            <br/>
+            <Avatar shape="square"  size={"extra-extra-small"}  border={true} topSlot={{
+                content:"直播"
+            }}>U</Avatar>
+            <Avatar shape="square"  size={"extra-small"}  border={true} topSlot={{
+                content:"直播"
+            }}>U</Avatar>
+            <Avatar shape="square" size={"default"} border={true} topSlot={{
+                content:"直播"
+            }}>U</Avatar>
+            <Avatar shape="square" size={"medium"} border={true} topSlot={{
+                content:"直播"
+            }}>U</Avatar>
+            <Avatar shape="square" size={"large"} borderMotion={true} border={true} topSlot={{
+                content:"直播"
+            }}  bottomSlot={{
+                content:"T",
+                shape:"circle"
+            }}>U</Avatar>
+            <br/>
+            <Avatar shape="circle"  size={"extra-extra-small"}  border={false} topSlot={{
+                content:"直播"
+            }}>U</Avatar>
+            <Avatar shape="circle"  size={"extra-small"}  border={false} topSlot={{
+                content:"直播"
+            }}>U</Avatar>
+            <Avatar shape="square" size={"default"} border={false} topSlot={{
+                content:"直播"
+            }}>U</Avatar>
+            <Avatar shape="circle" size={"medium"} border={false} topSlot={{
+                content:"直播"
+            }}>U</Avatar>
+            <Avatar shape="circle" size={"large"} borderMotion={true} border={false} topSlot={{
+                content:"直播"
+            }}  bottomSlot={{
+                content:"T",
+                shape:"circle"
+            }}>U</Avatar>
+            <br/>
+            <Avatar shape="square"  size={"extra-extra-small"}  border={false} topSlot={{
+                content:"直播"
+            }}>U</Avatar>
+            <Avatar shape="square"  size={"extra-small"}  border={false} topSlot={{
+                content:"直播"
+            }}>U</Avatar>
+            <Avatar shape="square" size={"default"} border={false} topSlot={{
+                content:"直播"
+            }}>U</Avatar>
+            <Avatar shape="square" size={"medium"} border={false} topSlot={{
+                content:"直播"
+            }}>U</Avatar>
+            <Avatar shape="square" size={"large"} borderMotion={true} border={false} topSlot={{
+                content:"直播"
+            }}  bottomSlot={{
+                content:"T",
+                shape:"circle"
+            }}>U</Avatar>
+        </div>
+    </div>
+);
+
+
 export const CustomAvatar = () => (
   <div>
     <Avatar>U</Avatar>
@@ -56,7 +176,7 @@ export const GroupSize = () => (
   <div>
     <p>medium</p>
     <AvatarGroup>
-      <Avatar color="red">LL</Avatar>
+      <Avatar color="red" topSlot={{content:"T"}} bottomSlot={{content:"T"}}>LL</Avatar>
       <Avatar>CX</Avatar>
       <Avatar size="default">CX</Avatar>
       <Avatar color="amber">RM</Avatar>

+ 177 - 24
packages/semi-ui/avatar/index.tsx

@@ -1,4 +1,4 @@
-import React from 'react';
+import React, { CSSProperties } from 'react';
 import cls from 'classnames';
 import PropTypes from 'prop-types';
 import { cssClasses, strings } from '@douyinfe/semi-foundation/avatar/constants';
@@ -8,6 +8,8 @@ import { noop } from '@douyinfe/semi-foundation/utils/function';
 import BaseComponent from '../_base/baseComponent';
 import { AvatarProps } from './interface';
 import { handlePrevent } from '@douyinfe/semi-foundation/utils/a11y';
+import TopSlotSvg from "./TopSlotSvg";
+
 
 const sizeSet = strings.SIZE;
 const shapeSet = strings.SHAPE;
@@ -15,6 +17,7 @@ const colorSet = strings.COLOR;
 const prefixCls = cssClasses.PREFIX;
 
 export * from './interface';
+
 export interface AvatarState {
     isImgExist: boolean;
     hoverContent: React.ReactNode;
@@ -51,10 +54,37 @@ export default class Avatar extends BaseComponent<AvatarProps, AvatarState> {
         onClick: PropTypes.func,
         onMouseEnter: PropTypes.func,
         onMouseLeave: PropTypes.func,
+        bottomSlot: PropTypes.shape({
+            render: PropTypes.func,
+            shape: PropTypes.oneOf(['circle', 'square']),
+            text: PropTypes.node,
+            bgColor: PropTypes.string,
+            textColor: PropTypes.string,
+            className: PropTypes.string,
+            style: PropTypes.object,
+        }),
+        topSlot: PropTypes.shape({
+            render: PropTypes.func,
+            gradientStart: PropTypes.string,
+            gradientEnd: PropTypes.string,
+            text: PropTypes.node,
+            textColor: PropTypes.string,
+            className: PropTypes.string,
+            style: PropTypes.object,
+        }),
+        border: PropTypes.oneOfType([
+            PropTypes.shape({
+                color: PropTypes.string,
+                motion: PropTypes.bool,
+            }),
+            PropTypes.bool,
+        ]),
+        contentMotion: PropTypes.bool,
     };
 
     foundation!: AvatarFoundation;
     avatarRef: React.RefObject<HTMLElement | null>;
+
     constructor(props: AvatarProps) {
         super(props);
         this.state = {
@@ -157,7 +187,7 @@ export default class Avatar extends BaseComponent<AvatarProps, AvatarState> {
                 break;
         }
     }
-    
+
     handleFocusVisible = (event: React.FocusEvent) => {
         this.foundation.handleFocusVisible(event);
     }
@@ -172,14 +202,14 @@ export default class Avatar extends BaseComponent<AvatarProps, AvatarState> {
         let content = children;
         const clickable = onClick !== noop;
         const isImg = src && isImgExist;
-        const a11yFocusProps = { 
-            tabIndex: 0, 
+        const a11yFocusProps = {
+            tabIndex: 0,
             onKeyDown: this.handleKeyDown,
             onFocus: this.handleFocusVisible,
             onBlur: this.handleBlur,
         };
         if (isImg) {
-            const finalAlt = clickable ? `clickable Avatar: ${alt}` : alt; 
+            const finalAlt = clickable ? `clickable Avatar: ${alt}` : alt;
             const imgBasicProps = {
                 src,
                 srcSet,
@@ -195,7 +225,7 @@ export default class Avatar extends BaseComponent<AvatarProps, AvatarState> {
             );
         } else if (typeof children === 'string') {
             const tempAlt = alt ?? children;
-            const finalAlt = clickable ? `clickable Avatar: ${tempAlt}` : tempAlt; 
+            const finalAlt = clickable ? `clickable Avatar: ${tempAlt}` : tempAlt;
             const props = {
                 role: 'img',
                 'aria-label': finalAlt,
@@ -218,8 +248,91 @@ export default class Avatar extends BaseComponent<AvatarProps, AvatarState> {
         return content;
     }
 
+
+    renderBottomSlot = () => {
+        if (!this.props.bottomSlot) {
+            return null;
+        }
+
+        if (this.props.bottomSlot.render) {
+            return this.props.bottomSlot.render();
+        }
+
+        const renderContent = this.props.bottomSlot.render ?? (() => {
+            const style: CSSProperties = {};
+            if (this.props.bottomSlot.bgColor) {
+                style['backgroundColor'] = this.props.bottomSlot.bgColor;
+            }
+            if (this.props.bottomSlot.textColor) {
+                style['color'] = this.props.bottomSlot.textColor;
+            }
+            return <span style={style}
+                className={cls(`${prefixCls}-bottom_slot-shape_${this.props.bottomSlot.shape}`, `${prefixCls}-bottom_slot-shape_${this.props.bottomSlot.shape}-${this.props.size}`, this.props.bottomSlot.className ?? "")}>
+                {this.props.bottomSlot.text}
+            </span>;
+        });
+
+        return <div className={cls([`${prefixCls}-bottom_slot`])} style={this.props.bottomSlot.style ?? {}}>
+            {renderContent()}
+        </div>;
+
+    }
+
+
+    renderTopSlot = () => {
+
+        if (!this.props.topSlot) {
+            return null;
+        }
+
+        if (this.props.topSlot.render) {
+            return this.props.topSlot.render();
+        }
+
+        const textStyle: CSSProperties = {};
+        if (this.props.topSlot.textColor) {
+            textStyle['color'] = this.props.topSlot.textColor;
+        } 
+        return <div style={this.props.topSlot.style ?? {}}
+            className={cls([`${prefixCls}-top_slot-wrapper`, this.props.topSlot.className ?? "", {
+                [`${prefixCls}-animated`]: this.props.contentMotion,
+            }])}>
+            <div className={cls([`${prefixCls}-top_slot-bg`, `${prefixCls}-top_slot-bg-${this.props.size}`])}>
+                <div
+                    className={cls([`${prefixCls}-top_slot-bg-svg`, `${prefixCls}-top_slot-bg-svg-${this.props.size}`])}>
+                    <TopSlotSvg gradientStart={this.props.topSlot.gradientStart ?? "var(--semi-color-primary)"}
+                        gradientEnd={this.props.topSlot.gradientEnd ?? "var(--semi-color-primary)"}/>
+                </div>
+            </div>
+            <div className={cls([`${prefixCls}-top_slot`])}>
+                <div
+                    style={textStyle}
+                    className={cls([`${prefixCls}-top_slot-content`, `${prefixCls}-top_slot-content-${this.props.size}`])}>{this.props.topSlot.text}</div>
+            </div>
+        </div>;
+    }
+
     render() {
-        const { shape, children, size, color, className, hoverMask, onClick, imgAttr, src, srcSet, style, alt, gap, ...others } = this.props;
+        const {
+            shape,
+            children,
+            size,
+            color,
+            className,
+            hoverMask,
+            onClick,
+            imgAttr,
+            src,
+            srcSet,
+            style,
+            alt,
+            gap,
+            bottomSlot,
+            topSlot,
+            border,
+            contentMotion,
+            ...others
+        } = this.props;
         const { isImgExist, hoverContent, focusVisible } = this.state;
         const isImg = src && isImgExist;
         const avatarCls = cls(
@@ -230,27 +343,67 @@ export default class Avatar extends BaseComponent<AvatarProps, AvatarState> {
                 [`${prefixCls}-${color}`]: color && !isImg,
                 [`${prefixCls}-img`]: isImg,
                 [`${prefixCls}-focus`]: focusVisible,
+                [`${prefixCls}-animated`]: contentMotion,
             },
             className
         );
 
-        const hoverRender = hoverContent ? (<div className={`${prefixCls}-hover`} x-semi-prop="hoverContent">{hoverContent}</div>) : null;
-        
-        return (
-            <span
-                {...(others as any)}
-                style={style}
-                className={avatarCls}
-                onClick={onClick as any}
-                onMouseEnter={this.onEnter as any}
-                onMouseLeave={this.onLeave as any}
-                role='listitem'
-                ref={this.avatarRef}
-            >
-                {this.getContent()}
-                {hoverRender}
-            </span>
-        );
+        const hoverRender = hoverContent ? (
+            <div className={`${prefixCls}-hover`} x-semi-prop="hoverContent">{hoverContent}</div>) : null;
+
+        let avatar = <span
+            {...(others as any)}
+            style={(border || bottomSlot || topSlot || border) ? {} : style}
+            className={avatarCls}
+            onClick={onClick as any}
+            onMouseEnter={this.onEnter as any}
+            onMouseLeave={this.onLeave as any}
+            role='listitem'
+            ref={this.avatarRef}>
+            {this.getContent()}
+            {hoverRender}
+        </span>;
+
+
+        if (border) {
+            const borderStyle: CSSProperties = {};
+            if (border?.color) {
+                borderStyle['borderColor'] = border.color;
+            }
+            avatar = <div style={{ position: "relative", ...style }}>
+                {avatar}
+                <span style={borderStyle} className={cls([
+                    `${prefixCls}-additionalBorder`,
+                    `${prefixCls}-additionalBorder-${size}`,
+                    {
+                        [`${prefixCls}-${shape}`]: shape,
+                    },
+                ])}>
+                </span>
+                {
+                    this.props.border?.motion && <span style={borderStyle} className={cls([
+                        `${prefixCls}-additionalBorder`,
+                        `${prefixCls}-additionalBorder-${size}`,
+                        {
+                            [`${prefixCls}-${shape}`]: shape,
+                            [`${prefixCls}-additionalBorder-animated`]: this.props.border?.motion,
+                        },
+                    ])}/>
+                }
+            </div>;
+
+        }
+
+
+        if (bottomSlot || topSlot || border) {
+            return <span className={cls([`${prefixCls}-wrapper`])} style={style}>
+                {avatar}
+                {topSlot && ["small", "default", "medium", "large", "extra-large"].includes(size) && shape === "circle" && this.renderTopSlot()}
+                {bottomSlot && ["small", "default", "medium", "large", "extra-large"].includes(size) && this.renderBottomSlot()}
+            </span>;
+        } else {
+            return avatar;
+        }
     }
 }
 Avatar.elementType = 'Avatar';

+ 26 - 3
packages/semi-ui/avatar/interface.ts

@@ -1,4 +1,4 @@
-import React from 'react';
+import React, { CSSProperties } from 'react';
 import { BaseProps } from '../_base/baseComponent';
 
 export type AvatarShape = 'circle' | 'square';
@@ -35,7 +35,30 @@ export interface AvatarProps extends BaseProps {
     onClick?: React.MouseEventHandler;
     onMouseEnter?: React.MouseEventHandler;
     onMouseLeave?: React.MouseEventHandler;
-    imgAttr?: React.ImgHTMLAttributes<HTMLImageElement>
+    imgAttr?: React.ImgHTMLAttributes<HTMLImageElement>;
+    bottomSlot?: {
+        render?: () => React.ReactNode;
+        shape?: "circle"|"square";
+        text: React.ReactNode;
+        bgColor: string;
+        textColor: string;
+        className: string;
+        style?: CSSProperties 
+    };
+    topSlot?: {
+        render?: () => React.ReactNode;
+        gradientStart?: string;
+        gradientEnd?: string; 
+        text: React.ReactNode;
+        textColor: string;
+        className: string;
+        style?: CSSProperties
+    };
+    border?: {
+        color?: string; 
+        motion?: boolean
+    } & boolean;
+    contentMotion?: boolean
 }
 
 export type AvatarGroupShape = 'circle' | 'square';
@@ -49,4 +72,4 @@ export interface AvatarGroupProps {
     overlapFrom?: AvatarGroupOverlapFrom;
     maxCount?: number;
     renderMore?: (restNumber?: number, restAvatars?: React.ReactNode[]) => React.ReactNode
-}
+}

+ 23 - 0
packages/semi-ui/datePicker/_story/v2/PresetsFunctionType.tsx

@@ -0,0 +1,23 @@
+import React from 'react';
+import DatePicker, { PresetsType } from '../../index';
+
+/**
+ * test with cypress, please don't modify this story
+ */
+export default function App() {
+    const presets: PresetsType = [
+        {
+            text: '动态时间',
+            start: () => new Date('2024-01-24'),
+            end: () => new Date('2024-02-26'),
+        },
+    ];
+    return (
+        <div>
+            <h4>presets start 和 end 使用函数类型</h4>
+            <div>
+                <DatePicker type="dateRange" presets={presets} />
+            </div>
+        </div>
+    );
+}

+ 1 - 0
packages/semi-ui/datePicker/_story/v2/index.js

@@ -28,4 +28,5 @@ export { default as FeatYearScrollRange } from './FeatYearScrollRange';
 export { default as FeatInsetInputShowClear } from './FeatInsetInputShowClear';
 export { default as AutoSplitInput } from './AutoSplitInput';
 export { default as FixNeedConfirmControlled } from './FixNeedConfirmControlled';
+export { default as PresetsFunctionType } from './PresetsFunctionType';
 export { default as FixedNaN } from './FixedNaN';

+ 1 - 1
packages/semi-ui/dropdown/__test__/dropdown.test.js

@@ -228,7 +228,7 @@ describe('Dropdown', () => {
                 value: 'B1',
             },
         };
-        targetItem.simulate('mousedown', event);
+        targetItem.simulate('click', event);
         expect(spyItemCLick.calledOnce).toEqual(true);
         expect(spyItemCLick.calledWithMatch(event)).toEqual(true);
     });

+ 5 - 4
packages/semi-ui/dropdown/dropdownItem.tsx

@@ -47,7 +47,7 @@ class DropdownItem extends BaseComponent<DropdownItemProps> {
         forwardRef: PropTypes.func,
         type: PropTypes.oneOf(strings.ITEM_TYPE),
         active: PropTypes.bool,
-        icon: PropTypes.node
+        icon: PropTypes.node,
     };
 
     static contextType = DropdownContext;
@@ -93,9 +93,10 @@ class DropdownItem extends BaseComponent<DropdownItemProps> {
         const events = {};
         if (!disabled) {
             ['onClick', 'onMouseEnter', 'onMouseLeave', 'onContextMenu'].forEach(eventName => {
-                if (eventName === "onClick") {
-                    events["onMouseDown"] = (e: React.MouseEvent<HTMLLIElement, MouseEvent>)=>{
-                        if (e.button===0) { 
+                const isInAnotherDropdown = this.context.level !== 1;
+                if (isInAnotherDropdown && eventName === "onClick") {
+                    events["onMouseDown"] = (e: React.MouseEvent<HTMLLIElement, MouseEvent>) => {
+                        if (e.button === 0) {
                             this.props[eventName]?.(e);
                         }
                     };

+ 2 - 2
packages/semi-ui/input/_story/input.stories.jsx

@@ -47,8 +47,8 @@ export const _Input = () => (
       width: 200,
     }}
   >
-    <Input />
-    <Input validateStatus="warning" />
+      <Input onlyBorder={2} size={"large"} />
+      <Input validateStatus="warning" />
     <Input validateStatus="error" />
     <br />
     <br />

+ 15 - 3
packages/semi-ui/input/index.tsx

@@ -66,7 +66,8 @@ export interface InputProps extends
     forwardRef?: ((instance: any) => void) | React.MutableRefObject<any> | null;
     preventScroll?: boolean;
     /** internal prop, DatePicker use it */
-    showClearIgnoreDisabled?: boolean
+    showClearIgnoreDisabled?: boolean;
+    onlyBorder?: number
 }
 
 export interface InputState {
@@ -451,6 +452,7 @@ class Input extends BaseComponent<InputProps, InputState> {
             preventScroll,
             borderless,
             showClearIgnoreDisabled,
+            onlyBorder,
             ...rest
         } = this.props;
         const { value, isFocus, minLength: stateMinLength } = this.state;
@@ -476,7 +478,8 @@ class Input extends BaseComponent<InputProps, InputState> {
             [`${wrapperPrefix}-modebtn`]: mode === 'password',
             [`${wrapperPrefix}-hidden`]: type === 'hidden',
             [`${wrapperPrefix}-${size}`]: size,
-            [`${prefixCls}-borderless`]: borderless
+            [`${prefixCls}-borderless`]: borderless,
+            [`${prefixCls}-only_border`]: onlyBorder!==undefined && onlyBorder!==null,
         });
         const inputCls = cls(prefixCls, {
             [`${prefixCls}-${size}`]: size,
@@ -511,11 +514,20 @@ class Input extends BaseComponent<InputProps, InputState> {
         if (validateStatus === 'error') {
             inputProps['aria-invalid'] = 'true';
         }
+
+        let wrapperStyle = { ...style };
+        if (onlyBorder!==undefined) {
+            wrapperStyle = {
+                borderWidth: onlyBorder,
+                ...style
+            };
+        }
+
         return (
             // eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions
             <div
                 className={wrapperCls}
-                style={style}
+                style={wrapperStyle}
                 onMouseEnter={e => this.handleMouseOver(e)}
                 onMouseLeave={e => this.handleMouseLeave(e)}
                 onClick={e => this.handleClick(e)}

+ 7 - 1
packages/semi-ui/modal/Modal.tsx

@@ -82,6 +82,7 @@ class Modal extends BaseComponent<ModalReactProps, ModalState> {
         lazyRender: PropTypes.bool,
         direction: PropTypes.oneOf(strings.directions),
         fullScreen: PropTypes.bool,
+        footerFill: PropTypes.bool,
     };
 
 
@@ -269,6 +270,7 @@ class Modal extends BaseComponent<ModalReactProps, ModalState> {
             confirmLoading,
             cancelLoading,
             hasCancel,
+            footerFill,
         } = this.props;
         const getCancelButton = (locale: Locale['Modal']) => {
             if (!hasCancel) {
@@ -280,6 +282,7 @@ class Modal extends BaseComponent<ModalReactProps, ModalState> {
                         onClick={this.handleCancel}
                         loading={cancelLoading === undefined ? this.state.onCancelReturnPromiseStatus === "pending" : cancelLoading}
                         type="tertiary"
+                        block={footerFill}
                         autoFocus={true}
                         {...this.props.cancelButtonProps}
                         x-semi-children-alias="cancelText"
@@ -293,12 +296,15 @@ class Modal extends BaseComponent<ModalReactProps, ModalState> {
         return (
             <LocaleConsumer componentName="Modal">
                 {(locale: Locale['Modal'], localeCode: Locale['code']) => (
-                    <div>
+                    <div className={cls({
+                        [`${cssClasses.DIALOG}-footerfill`]: footerFill
+                    })}>
                         {getCancelButton(locale)}
                         <Button
                             aria-label="confirm"
                             type={okType}
                             theme="solid"
+                            block={footerFill}
                             loading={confirmLoading === undefined ? this.state.onOKReturnPromiseStatus === "pending" : confirmLoading}
                             onClick={this.handleOk}
                             {...this.props.okButtonProps}

+ 1 - 1
packages/semi-ui/modal/_story/modal.stories.jsx

@@ -340,4 +340,4 @@ export const UseModalAfterClose = () => {
       </ConfigProvider>
   );
 };
-UseModalAfterClose.storyName = "useModal afterClose";
+UseModalAfterClose.storyName = "useModal afterClose";

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

@@ -1,6 +1,6 @@
 {
     "name": "@douyinfe/semi-ui",
-    "version": "2.51.4",
+    "version": "2.52.0-beta.1",
     "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.51.4",
-        "@douyinfe/semi-animation-react": "2.51.4",
-        "@douyinfe/semi-foundation": "2.51.4",
-        "@douyinfe/semi-icons": "2.51.4",
-        "@douyinfe/semi-illustrations": "2.51.4",
-        "@douyinfe/semi-theme-default": "2.51.4",
+        "@douyinfe/semi-animation": "2.52.0-beta.1",
+        "@douyinfe/semi-animation-react": "2.52.0-beta.1",
+        "@douyinfe/semi-foundation": "2.52.0-beta.1",
+        "@douyinfe/semi-icons": "2.52.0-beta.1",
+        "@douyinfe/semi-illustrations": "2.52.0-beta.1",
+        "@douyinfe/semi-theme-default": "2.52.0-beta.1",
         "async-validator": "^3.5.0",
         "classnames": "^2.2.6",
         "copy-text-to-clipboard": "^2.1.1",

+ 30 - 3
packages/semi-ui/slider/index.tsx

@@ -54,6 +54,18 @@ export default class Slider extends BaseComponent<SliderProps, SliderState> {
         railStyle: PropTypes.object,
         verticalReverse: PropTypes.bool,
         getAriaValueText: PropTypes.func,
+        handleDot: PropTypes.oneOfType([
+            PropTypes.shape({
+                size: PropTypes.string,
+                color: PropTypes.string,
+            }),
+            PropTypes.arrayOf(
+                PropTypes.shape({
+                    size: PropTypes.string,
+                    color: PropTypes.string,
+                })
+            ),
+        ]),
     } as any;
 
     static defaultProps: Partial<SliderProps> = {
@@ -371,7 +383,12 @@ export default class Slider extends BaseComponent<SliderProps, SliderState> {
                     aria-valuenow={currentValue as number}
                     aria-valuemax={max}
                     aria-valuemin={min}
-                />
+                >
+                    {this.props.handleDot && <div className={cssClasses.HANDLE_DOT} style={{
+                        ...(this.props.handleDot?.size?{ width: this.props.handleDot.size, height: this.props.handleDot.size }:{}),
+                        ...(this.props.handleDot?.color?{ backgroundColor: this.props.handleDot.color }:{}),
+                    }}/>}
+                </span>
             </Tooltip>
         ) : (
             <React.Fragment>
@@ -427,7 +444,12 @@ export default class Slider extends BaseComponent<SliderProps, SliderState> {
                         aria-valuenow={currentValue[0]}
                         aria-valuemax={currentValue[1]}
                         aria-valuemin={min}
-                    />
+                    >
+                        {this.props.handleDot?.[0] && <div className={cssClasses.HANDLE_DOT} style={{
+                            ...(this.props.handleDot[0]?.size?{ width: this.props.handleDot[0].size, height: this.props.handleDot[0].size }:{}),
+                            ...(this.props.handleDot[0]?.color?{ backgroundColor: this.props.handleDot[0].color }:{}),
+                        }}/>}
+                    </span>
                 </Tooltip>
                 <Tooltip
                     content={tipChildren.max}
@@ -481,7 +503,12 @@ export default class Slider extends BaseComponent<SliderProps, SliderState> {
                         aria-valuenow={currentValue[1]}
                         aria-valuemax={max}
                         aria-valuemin={currentValue[0]}
-                    />
+                    >
+                        {this.props.handleDot?.[1] && <div className={cssClasses.HANDLE_DOT} style={{
+                            ...(this.props.handleDot[1]?.size?{ width: this.props.handleDot[1].size, height: this.props.handleDot[1].size }:{}),
+                            ...(this.props.handleDot[1]?.color?{ backgroundColor: this.props.handleDot[1].color }:{}),
+                        }}/>}
+                    </span> 
                 </Tooltip>
             </React.Fragment>
         );

+ 187 - 109
packages/semi-ui/table/ColumnFilter.tsx

@@ -1,12 +1,11 @@
-import React, { isValidElement } from 'react';
+import React, { isValidElement, useEffect, useState } from 'react';
 import cls from 'classnames';
-import { noop } from 'lodash';
+import { isEqual, noop, pick } from 'lodash';
 import { IconFilter } from '@douyinfe/semi-icons';
 
 import { cssClasses } from '@douyinfe/semi-foundation/table/constants';
 
 import Dropdown, { DropdownProps } from '../dropdown';
-import { Trigger, Position } from '../tooltip';
 import { Radio } from '../radio';
 import { Checkbox } from '../checkbox';
 import {
@@ -16,7 +15,7 @@ import {
     RenderFilterDropdownItem
 } from './interface';
 
-function renderDropdown(props: RenderDropdownProps = {}, nestedElem: React.ReactNode = null, level = 0) {
+function renderDropdown(props: RenderDropdownProps, nestedElem: React.ReactNode = null, level = 0) {
     const {
         filterMultiple = true,
         filters = [],
@@ -26,95 +25,99 @@ function renderDropdown(props: RenderDropdownProps = {}, nestedElem: React.React
         onFilterDropdownVisibleChange = noop,
         trigger = 'click',
         position = 'bottom',
+        renderFilterDropdown,
         renderFilterDropdownItem,
-    } = props;
+    } = props ?? {};
+
+    const renderFilterDropdownProps: RenderFilterDropdownProps = pick(props, ['tempFilteredValue', 'setTempFilteredValue', 'confirm', 'clear', 'close', 'filters']);
+    const render = typeof renderFilterDropdown === 'function' ? renderFilterDropdown(renderFilterDropdownProps) : (
+        <Dropdown.Menu>
+            {Array.isArray(filters) &&
+                filters.map((filter, index) => {
+                    const changeFn = (e: React.MouseEvent<HTMLLIElement>) => {
+                        const domEvent = e && e.nativeEvent;
+                        if (domEvent) {
+                            // Block this event to prevent the pop-up layer from closing
+                            domEvent.stopImmediatePropagation();
+
+                            // Prevent bubbling and default events to prevent label click events from triggering twice
+                            domEvent.stopPropagation();
+                            domEvent.preventDefault();
+                        }
+                        let values = [...filteredValue];
+
+                        const included = values.includes(filter.value);
+                        const idx = values.indexOf(filter.value);
+
+                        if (idx > -1) {
+                            values.splice(idx, 1);
+                        } else if (filterMultiple) {
+                            values.push(filter.value);
+                        } else {
+                            values = [filter.value];
+                        }
+                        return onSelect({
+                            value: filter.value,
+                            filteredValue: values,
+                            included: !included,
+                            domEvent,
+                        });
+                    };
+
+                    const checked = filteredValue.includes(filter.value);
+                    const { text } = filter;
+                    const { value } = filter;
+                    const key = `${level}_${index}`;
+
+                    const dropdownItem =
+                        typeof renderFilterDropdownItem === 'function' ?
+                            renderFilterDropdownItem({
+                                onChange: changeFn,
+                                filterMultiple,
+                                value,
+                                text,
+                                checked,
+                                filteredValue,
+                                level,
+                            }) :
+                            null;
+
+                    let item =
+                        dropdownItem && React.isValidElement(dropdownItem) ? (
+                            React.cloneElement(dropdownItem, { key })
+                        ) : (
+                            <Dropdown.Item key={key} onClick={changeFn}>
+                                {filterMultiple ? (
+                                    <Checkbox checked={checked}>{text}</Checkbox>
+                                ) : (
+                                    <Radio checked={checked}>{text}</Radio>
+                                )}
+                            </Dropdown.Item>
+                        );
+
+                    if (Array.isArray(filter.children) && filter.children.length) {
+                        const childrenDropdownProps = {
+                            ...props,
+                            filters: filter.children,
+                            trigger: 'hover' as const,
+                            position: 'right' as const,
+                        };
+
+                        delete childrenDropdownProps.filterDropdownVisible;
+
+                        item = renderDropdown(childrenDropdownProps, item, level + 1);
+                    }
+                    return item;
+                })}
+        </Dropdown.Menu>
+    );
 
     const dropdownProps: DropdownProps = {
         ...props,
         onVisibleChange: (visible: boolean) => onFilterDropdownVisibleChange(visible),
         trigger,
         position,
-        render: (
-            <Dropdown.Menu>
-                {Array.isArray(filters) &&
-                    filters.map((filter, index) => {
-                        const changeFn = (e: React.MouseEvent<HTMLLIElement>) => {
-                            const domEvent = e && e.nativeEvent;
-                            if (domEvent) {
-                                // Block this event to prevent the pop-up layer from closing
-                                domEvent.stopImmediatePropagation();
-
-                                // Prevent bubbling and default events to prevent label click events from triggering twice
-                                domEvent.stopPropagation();
-                                domEvent.preventDefault();
-                            }
-                            let values = [...filteredValue];
-
-                            const included = values.includes(filter.value);
-                            const idx = values.indexOf(filter.value);
-
-                            if (idx > -1) {
-                                values.splice(idx, 1);
-                            } else if (filterMultiple) {
-                                values.push(filter.value);
-                            } else {
-                                values = [filter.value];
-                            }
-                            return onSelect({
-                                value: filter.value,
-                                filteredValue: values,
-                                included: !included,
-                                domEvent,
-                            });
-                        };
-
-                        const checked = filteredValue.includes(filter.value);
-                        const { text } = filter;
-                        const { value } = filter;
-                        const key = `${level}_${index}`;
-
-                        const dropdownItem =
-                            typeof renderFilterDropdownItem === 'function' ?
-                                renderFilterDropdownItem({
-                                    onChange: changeFn,
-                                    filterMultiple,
-                                    value,
-                                    text,
-                                    checked,
-                                    filteredValue,
-                                    level,
-                                }) :
-                                null;
-
-                        let item =
-                            dropdownItem && React.isValidElement(dropdownItem) ? (
-                                React.cloneElement(dropdownItem, { key })
-                            ) : (
-                                <Dropdown.Item key={key} onClick={changeFn}>
-                                    {filterMultiple ? (
-                                        <Checkbox checked={checked}>{text}</Checkbox>
-                                    ) : (
-                                        <Radio checked={checked}>{text}</Radio>
-                                    )}
-                                </Dropdown.Item>
-                            );
-
-                        if (Array.isArray(filter.children) && filter.children.length) {
-                            const childrenDropdownProps = {
-                                ...props,
-                                filters: filter.children,
-                                trigger: 'hover' as const,
-                                position: 'right' as const,
-                            };
-
-                            delete childrenDropdownProps.filterDropdownVisible;
-
-                            item = renderDropdown(childrenDropdownProps, item, level + 1);
-                        }
-                        return item;
-                    })}
-            </Dropdown.Menu>
-        ),
+        render,
     };
 
     if (filterDropdownVisible != null) {
@@ -128,27 +131,75 @@ function renderDropdown(props: RenderDropdownProps = {}, nestedElem: React.React
     );
 }
 
-export interface ColumnFilterProps {
-    prefixCls?: string;
-    filteredValue?: any[];
-    filterIcon?: FilterIcon;
-    filterDropdown?: React.ReactElement;
-    renderFilterDropdown?: (props: RenderDropdownProps, options: { iconElem: React.ReactNode }) => React.ReactElement;
-    filterDropdownProps?: DropdownProps;
-    onFilterDropdownVisibleChange?: OnFilterDropdownVisibleChange;
-    onSelect?: (data: OnSelectData) => void
-}
-
 export default function ColumnFilter(props: ColumnFilterProps = {}): React.ReactElement {
     const {
         prefixCls = cssClasses.PREFIX,
         filteredValue,
         filterIcon = 'filter',
-        renderFilterDropdown,
         filterDropdownProps,
+        onSelect,
+        filterDropdownVisible,
+        renderFilterDropdown,
+        onFilterDropdownVisibleChange
     } = props;
     let { filterDropdown = null } = props;
 
+    
+    // custom filter related status
+    const isFilterDropdownVisibleControlled = typeof filterDropdownVisible !== 'undefined';
+    const isCustomFilterDropdown = typeof renderFilterDropdown === 'function';
+    const isCustomDropdownVisible = !isFilterDropdownVisibleControlled && isCustomFilterDropdown;
+    const [tempFilteredValue, setTempFilteredValue] = useState<any[]>(filteredValue);
+    const dropdownVisibleInitValue = isCustomDropdownVisible ? false : filterDropdownVisible;
+    const [dropdownVisible, setDropdownVisible] = useState<boolean | undefined>(dropdownVisibleInitValue);
+
+    useEffect(() => {
+        if (typeof filterDropdownVisible !== 'undefined') {
+            setDropdownVisible(filterDropdownVisible);
+        }
+    }, [filterDropdownVisible]);
+
+    useEffect(() => {
+        setTempFilteredValue(filteredValue);
+    }, [filteredValue]);
+
+    const confirm: RenderFilterDropdownProps['confirm'] = (props = {}) => {
+        const newFilteredValue = props?.filteredValue || tempFilteredValue;
+        if (!isEqual(newFilteredValue, filteredValue)) {
+            onSelect({ filteredValue: newFilteredValue });
+        }
+        if (props.closeDropdown) {
+            setDropdownVisible(false);
+        }
+    };
+
+    const clear: RenderFilterDropdownProps['clear'] = (props: { closeDropdown?: boolean } = {}) => {
+        setTempFilteredValue([]);
+        onSelect({ filteredValue: [] });
+        if (props.closeDropdown) {
+            setDropdownVisible(false);
+        }
+    };
+
+    const close: RenderFilterDropdownProps['close'] = () => {
+        setDropdownVisible(false);
+    };
+
+    const handleFilterDropdownVisibleChange = (visible: boolean) => {
+        if (isCustomDropdownVisible) {
+            setDropdownVisible(visible);
+        }
+        onFilterDropdownVisibleChange(visible);
+    };
+
+    const renderFilterDropdownProps: RenderFilterDropdownProps = {
+        tempFilteredValue,
+        setTempFilteredValue,
+        confirm,
+        clear,
+        close
+    };
+
     const finalCls = cls(`${prefixCls}-column-filter`, {
         on: Array.isArray(filteredValue) && filteredValue.length,
     });
@@ -177,32 +228,59 @@ export default function ColumnFilter(props: ColumnFilterProps = {}): React.React
     const renderProps = {
         ...props,
         ...filterDropdownProps,
+        ...renderFilterDropdownProps,
+        filterDropdownVisible: isFilterDropdownVisibleControlled ? filterDropdownVisible : dropdownVisible,
+        onFilterDropdownVisibleChange: handleFilterDropdownVisibleChange,
     };
 
     filterDropdown = React.isValidElement<ColumnFilterProps>(filterDropdown) ?
         filterDropdown :
-        typeof renderFilterDropdown === 'function' ?
-            renderFilterDropdown(renderProps, { iconElem }) :
-            renderDropdown(renderProps, iconElem);
+        renderDropdown(renderProps, iconElem);
 
     return filterDropdown;
 }
 
-export interface OnSelectData {
-    value: any;
-    filteredValue: any;
-    included: boolean;
-    domEvent: React.MouseEvent<HTMLElement>
+export interface ColumnFilterProps extends Omit<RenderDropdownProps, keyof RenderFilterDropdownProps> {
+    prefixCls?: string;
+    filteredValue?: any[];
+    filterIcon?: FilterIcon;
+    filterDropdown?: React.ReactElement;
+    filterDropdownProps?: FilterDropdownProps;
+    filters?: Filter[]
 }
 
-export interface RenderDropdownProps {
+export interface RenderDropdownProps extends FilterDropdownProps, RenderFilterDropdownProps {
     filterMultiple?: boolean;
     filters?: Filter[];
     filteredValue?: any[];
     filterDropdownVisible?: boolean;
     onSelect?: (data: OnSelectData) => void;
     onFilterDropdownVisibleChange?: OnFilterDropdownVisibleChange;
-    trigger?: Trigger;
-    position?: Position;
+    renderFilterDropdown?: (props?: RenderFilterDropdownProps) => React.ReactNode;
     renderFilterDropdownItem?: RenderFilterDropdownItem
+}
+
+export interface FilterDropdownProps extends Omit<DropdownProps, 'render' | 'onVisibleChange'> {}
+
+export interface OnSelectData {
+    value?: any;
+    /** only this value is used now  */
+    filteredValue: any;
+    included?: boolean;
+    domEvent?: React.MouseEvent<HTMLElement>
+}
+
+export interface RenderFilterDropdownProps {
+    /** temporary filteredValue  */
+    tempFilteredValue: any[];
+    /** set temporary filteredValue  */
+    setTempFilteredValue: (tempFilteredValue: any[]) => void;
+    /** set tempFilteredValue to filteredValue. You can also pass filteredValue to directly set the filteredValue  */
+    confirm: (props?: { closeDropdown?: boolean; filteredValue?: any[] }) => void;
+    /** clear tempFilteredValue and filteredValue  */
+    clear: (props?: { closeDropdown?: boolean }) => void;
+    /** close dropdown  */
+    close: () => void;
+    /** column filters  */
+    filters?: RenderDropdownProps['filters']
 }

+ 59 - 16
packages/semi-ui/table/Table.tsx

@@ -693,7 +693,7 @@ class Table<RecordType extends Record<string, any>> extends BaseComponent<Normal
 
     getCurrentPageData = () => {
         const pageData = this.foundation.getCurrentPageData();
-        const retObj = ['dataSource', 'groups'].reduce((result, key) => {
+        const retObj: Pick<BasePageData<RecordType>, 'dataSource' | 'groups'> = ['dataSource', 'groups'].reduce((result, key) => {
             if (pageData[key]) {
                 result[key] = pageData[key];
             }
@@ -839,36 +839,59 @@ class Table<RecordType extends Record<string, any>> extends BaseComponent<Normal
         }
     };
 
-    renderSelection = (record = {} as any, inHeader = false): React.ReactNode => {
+    renderSelection = (record = {} as any, inHeader = false, index?: number): React.ReactNode => {
         const { rowSelection, allDisabledRowKeysSet } = this.state;
 
         if (rowSelection && typeof rowSelection === 'object') {
-            const { selectedRowKeys = [], selectedRowKeysSet = new Set(), getCheckboxProps, disabled } = rowSelection;
+            const {
+                selectedRowKeys = [],
+                selectedRowKeysSet = new Set(),
+                getCheckboxProps,
+                disabled,
+                renderCell,
+            } = rowSelection;
+
+            const allRowKeys = this.cachedFilteredSortedRowKeys;
+            const allRowKeysSet = this.cachedFilteredSortedRowKeysSet;
+            const allIsSelected = this.foundation.allIsSelected(selectedRowKeysSet, allDisabledRowKeysSet, allRowKeys);
+            const hasRowSelected = this.foundation.hasRowSelected(selectedRowKeys, allRowKeysSet);
+            const indeterminate = hasRowSelected && !allIsSelected;
 
             if (inHeader) {
                 const columnKey = get(rowSelection, 'key', strings.DEFAULT_KEY_COLUMN_SELECTION);
-                const allRowKeys = this.cachedFilteredSortedRowKeys;
-                const allRowKeysSet = this.cachedFilteredSortedRowKeysSet;
-                const allIsSelected = this.foundation.allIsSelected(selectedRowKeysSet, allDisabledRowKeysSet, allRowKeys);
-                const hasRowSelected = this.foundation.hasRowSelected(selectedRowKeys, allRowKeysSet);
-                return (
+
+                const originNode = (
                     <ColumnSelection
                         aria-label={`${allIsSelected ? 'Deselect' : 'Select'} all rows`}
                         disabled={disabled}
                         key={columnKey}
                         selected={allIsSelected}
-                        indeterminate={hasRowSelected && !allIsSelected}
+                        indeterminate={indeterminate}
                         onChange={(selected, e) => {
                             this.toggleSelectAllRow(selected, e);
                         }}
                     />
                 );
+
+                const selectAll = (selected: boolean, e: Event) =>
+                    this.toggleSelectAllRow(selected, e as TableSelectionCellEvent);
+
+                return isFunction(renderCell)
+                    ? renderCell({
+                        selected: allIsSelected,
+                        record,
+                        originNode,
+                        inHeader,
+                        disabled,
+                        indeterminate,
+                        selectAll,
+                    })
+                    : originNode;
             } else {
                 const key = this.foundation.getRecordKey(record);
                 const selected = selectedRowKeysSet.has(key);
                 const checkboxPropsFn = () => (typeof getCheckboxProps === 'function' ? getCheckboxProps(record) : {});
-
-                return (
+                const originNode = (
                     <ColumnSelection
                         aria-label={`${selected ? 'Deselect' : 'Select'} this row`}
                         getCheckboxProps={checkboxPropsFn}
@@ -876,13 +899,28 @@ class Table<RecordType extends Record<string, any>> extends BaseComponent<Normal
                         onChange={(status, e) => this.toggleSelectRow(status, key, e)}
                     />
                 );
+                const selectRow = (selected: boolean, e: Event) =>
+                    this.toggleSelectRow(selected, key, e as TableSelectionCellEvent);
+
+                return isFunction(renderCell)
+                    ? renderCell({
+                        selected,
+                        record,
+                        index,
+                        originNode,
+                        inHeader: false,
+                        disabled,
+                        indeterminate,
+                        selectRow,
+                    })
+                    : originNode;
             }
         }
         return null;
     };
 
-    renderRowSelectionCallback = (text: string, record: RecordType = {} as RecordType) => this.renderSelection(record);
-    renderTitleSelectionCallback = () => this.renderSelection(null, true);
+    renderRowSelectionCallback = (text: string, record: RecordType = {} as RecordType, index: number) => this.renderSelection(record, false, index);
+    renderTitleSelectionCallback = () => this.renderSelection(undefined, true);
 
     normalizeSelectionColumn = (props: { rowSelection?: TableStateRowSelection<RecordType>; prefixCls?: string } = {}) => {
         const { rowSelection, prefixCls } = props;
@@ -969,7 +1007,7 @@ class Table<RecordType extends Record<string, any>> extends BaseComponent<Normal
       */
     addFnsInColumn = (column: ColumnProps = {}) => {
         const { prefixCls } = this.props;
-        if (column && (column.sorter || column.filters || column.useFullRender)) {
+        if (column && (column.sorter || column.filters || column.onFilter || column.useFullRender)) {
             let hasSorterOrFilter = false;
             const { dataIndex, title: rawTitle, useFullRender } = column;
             const curQuery = this.foundation.getQuery(dataIndex);
@@ -1016,11 +1054,16 @@ class Table<RecordType extends Record<string, any>> extends BaseComponent<Normal
             const stateFilteredValue = get(curQuery, 'filteredValue');
             const defaultFilteredValue = get(curQuery, 'defaultFilteredValue');
             const filteredValue = stateFilteredValue ? stateFilteredValue : defaultFilteredValue;
-            if ((Array.isArray(column.filters) && column.filters.length) || isValidElement(column.filterDropdown)) {
+            if (
+                (Array.isArray(column.filters) && column.filters.length) ||
+                isValidElement(column.filterDropdown) ||
+                typeof column.renderFilterDropdown === 'function'
+            ) {
+
                 const filter = (
                     <ColumnFilter
                         key={strings.DEFAULT_KEY_COLUMN_FILTER}
-                        {...curQuery}
+                        {...omit(curQuery, 'children')}
                         filteredValue={filteredValue}
                         onFilterDropdownVisibleChange={(visible: boolean) =>
                             this.foundation.toggleShowFilter(dataIndex, visible)

+ 4 - 14
packages/semi-ui/table/__test__/table.test.js

@@ -560,8 +560,7 @@ describe(`Table`, () => {
         demo.find(`.${BASE_CLASS_PREFIX}-dropdown .${BASE_CLASS_PREFIX}-dropdown-item`)
             .at(0)
             .find(`.${BASE_CLASS_PREFIX}-checkbox`)
-            .simulate('mousedown', {
-                button:0,
+            .simulate('click', {
                 nativeEvent: null,
             });
         expect(onChange.callCount).toBe(++onChangeCalledCount); // click first filter again
@@ -569,8 +568,7 @@ describe(`Table`, () => {
         demo.find(`.${BASE_CLASS_PREFIX}-dropdown .${BASE_CLASS_PREFIX}-dropdown-item`)
             .at(0)
             .find(`.${BASE_CLASS_PREFIX}-checkbox`)
-            .simulate('mousedown', {
-                button:0,
+            .simulate('click', {
                 nativeEvent: null,
             });
         expect(onChange.callCount).toBe(++onChangeCalledCount); // to page 2
@@ -630,8 +628,7 @@ describe(`Table`, () => {
         demo.find(`.${BASE_CLASS_PREFIX}-dropdown .${BASE_CLASS_PREFIX}-dropdown-item`)
             .at(0)
             .find(`.${BASE_CLASS_PREFIX}-checkbox`)
-            .simulate('mousedown', {
-                button:0,
+            .simulate('click', {
                 nativeEvent: null,
             });
         const nameColList = demo.find('.semi-table-tbody .name-col');
@@ -2167,14 +2164,7 @@ describe(`Table`, () => {
         const tableNode = mount(<Table columns={columns} dataSource={data} onChange={onChange}/>);
         tableNode.find('.semi-table-column-filter').simulate('click');
         const filterNode = Array.from(document.querySelectorAll('.semi-checkbox-addon')).filter(node => node.textContent === 'Semi Design 设计稿');
-
-        const mousedownEvent = new MouseEvent('mousedown', {
-            bubbles: true,
-            cancelable: true,
-            button: 0,
-        });
-        filterNode[0].dispatchEvent(mousedownEvent);
-
+        filterNode[0].click();
         expect(onChange.calledOnce).toBe(true);
         const arg = onChange.getCall(0).args[0];
         expect(arg.sorter.defaultSortOrder).toBe(defaultSortOrder);

+ 140 - 0
packages/semi-ui/table/_story/RowSelectionRenderCell/index.jsx

@@ -0,0 +1,140 @@
+import { Table, Tooltip } from '@douyinfe/semi-ui';
+import React, { useMemo, useState } from 'react';
+
+function App() {
+    const defaultSelectedRowKeys = useMemo(() => ['3'], []);
+    const [selectedRowKeys, setSelectedRowKeys] = useState(defaultSelectedRowKeys);
+    const [headerOrigin, setHeaderOrigin] = useState(false);
+    const [rowOrigin, setRowOrigin] = useState(false);
+
+    const columns = useMemo(
+        () => [
+            {
+                title: 'Name',
+                dataIndex: 'name',
+                render: text => <span>{text}</span>,
+            },
+            {
+                title: 'Age',
+                dataIndex: 'age',
+            },
+            {
+                title: 'Address',
+                dataIndex: 'address',
+            },
+            {
+                render: () => (
+                    <input
+                        type="checkbox"
+                        onClick={(...args) => {
+                            console.log('onClick: ', ...args);
+                        }}
+                        onChange={(...args) => {
+                            console.log('onChange: ', ...args);
+                        }}
+                    />
+                ),
+            },
+        ],
+        []
+    );
+
+    const data = useMemo(() => {
+        const _data = [];
+        for (let i = 0; i < 5; i++) {
+            let age = i * 1000;
+            let name = `Edward King ${i}`;
+            _data.push({
+                key: '' + i,
+                name,
+                age,
+                address: `London, Park Lane no. ${i} Lake Park`,
+                description: `My name is ${name}, I am ${age} years old, living in New York No. ${i + 1} Lake Park.`,
+            });
+        }
+        return _data;
+    }, []);
+
+    const rowSelection = {
+        renderCell: ({ selected, record, index, originNode, inHeader, disabled, indeterminate, selectRow, selectAll }) => {
+            console.log('selected', selected);
+            console.log('index', index);
+            console.log('inHeader', inHeader);
+            console.log('disabled', disabled);
+            console.log('indeterminate', indeterminate);
+
+            if (inHeader && headerOrigin) {
+                return (
+                    <Tooltip content="自定义表头 renderCell,我是表头">
+                        <div>{originNode}</div>
+                    </Tooltip>
+                );
+            }
+
+            if (inHeader && !headerOrigin) {
+                return (
+                    <Tooltip content="自定义表头 renderCell,我是表头,不使用 originNode 控制选中">
+                        <div onClick={e => selectAll && selectAll(!selected, e)}>222</div>
+                    </Tooltip>
+                );
+            }
+
+            if (record.age === 2000 && !rowOrigin) {
+                return (
+                    <Tooltip content="自定义 renderCell, 不使用 originNode 控制选中">
+                        <div
+                            style={{ color: selected ? 'red' : 'black' }}
+                            onClick={e => selectRow && selectRow(!selected, e)}
+                        >
+                            111
+                        </div>
+                    </Tooltip>
+                );
+            }
+
+            if (record.age > 2000) {
+                return (
+                    <Tooltip content="自定义 renderCell">
+                        <div>{originNode}</div>
+                    </Tooltip>
+                );
+            }
+            return originNode;
+        },
+        onChange: (selectedRowKeys, selectedRows) => {
+            console.log(
+                `rowSelection.onChanged: selectedRowKeys: ${JSON.stringify(selectedRowKeys)}`,
+                'selectedRows: ',
+                selectedRows
+            );
+            setSelectedRowKeys(selectedRowKeys);
+        },
+        onSelectAll: (selected, selectedRows, changedRows) => {
+            console.log(
+                `rowSelection.onSelectAll: selected :${selected}, selectedRows: ${selectedRows}, changedRows: ${changedRows}`
+            );
+        },
+        getCheckboxProps: record => ({
+            // disabled: record.age < 2000,
+            name: record.name,
+            onClick: (...args) => {
+                console.log('Clicked checkbox: ', ...args);
+            },
+        }),
+        onSelect: (record, selected) => {
+            console.log('onSelect: ', record, selected);
+        },
+        selectedRowKeys,
+        defaultSelectedRowKeys,
+    };
+
+    return (
+        <div>
+            <button onClick={() => setHeaderOrigin(!headerOrigin)}>表头{headerOrigin ? '不使用' : '使用'} originNode</button>
+            <button onClick={() => setRowOrigin(!rowOrigin)}>选择行{ rowOrigin ? '不使用' : '使用' } originNode</button>
+            <Table rowKey={record => record.key} columns={columns} dataSource={data} rowSelection={rowSelection} />
+        </div>
+    );
+}
+
+export default App;

+ 10 - 0
packages/semi-ui/table/_story/table.stories.jsx

@@ -47,6 +47,7 @@ import ExpandAllGroupRows from './ExpandAllGroupRows';
 import ExpandRowByClick from './ExpandRowByClick';
 import FixAllColumnsWithoutWidth from './FixAllColumnsWithoutWidth';
 import HugeData from "./HugeData"
+import RowSelectionRenderCell from './RowSelectionRenderCell';
 
 export default {
   title: 'Table'
@@ -108,6 +109,9 @@ export {
     KeepDOM,
     SortIcon,
     FixedAllDisabledAndSelected,
+    FeatRenderFilterDropdown,
+    InputFilter
+    FixedAllDisabledAndSelected,
     FixedRowSelectionHiddenResizable
 } from './v2';
 export { default as FixSelectAll325 } from './Demos/rowSelection';
@@ -633,3 +637,9 @@ export const HugeDataDemo = ()=><HugeData/>
 HugeDataDemo.parameters = {
   chromatic: { disableSnapshot: true },
 };
+
+export const _RowSelectionRenderCell = () => <RowSelectionRenderCell />;
+
+_RowSelectionRenderCell.story = {
+  name: 'RowSelection RenderCell',
+};

+ 135 - 0
packages/semi-ui/table/_story/v2/FeatRenderFilterDropdown/index.tsx

@@ -0,0 +1,135 @@
+import React, { useState, useEffect, useRef } from 'react';
+import { Table, Avatar, Input, Button, Space } from '@douyinfe/semi-ui';
+import type { ColumnProps } from '../../../interface';
+import * as dateFns from 'date-fns';
+
+/**
+ * test with cypress, please don't modify this story
+ */
+export default function App() {
+    const [dataSource, setData] = useState([]);
+    const inputRef = useRef<HTMLInputElement>();
+
+    const DAY = 24 * 60 * 60 * 1000;
+    const figmaIconUrl = 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/figma-icon.png';
+
+    const columns: ColumnProps[] = [
+        {
+            title: '标题',
+            dataIndex: 'name',
+            width: 400,
+            render: (text, record, index) => {
+                return (
+                    <div>
+                        <Avatar size="small" shape="square" src={figmaIconUrl} style={{ marginRight: 12 }}></Avatar>
+                        {text}
+                    </div>
+                );
+            },
+            onFilter: (value, record) => record.name.includes(value),
+            renderFilterDropdown: (props) => {
+                console.log('renderFilterDropdown', props);
+                const { tempFilteredValue, setTempFilteredValue, confirm, clear, close } = props;
+
+                const handleChange = (value: any) => {
+                    const filteredValue = value ? [value] : [];
+                    setTempFilteredValue(filteredValue);
+                    // 你也可以在 input value 变化时直接筛选
+                    // confirm({ filteredValue });
+                };
+
+                return (
+                    <Space vertical align='start' style={{ padding: 8 }}>
+                        <Input ref={inputRef} value={tempFilteredValue[0]} onChange={handleChange}/>
+                        <Space>
+                            <Button onClick={() => confirm({ closeDropdown: true })}>筛选+关闭</Button>
+                            <Button onClick={() => clear({ closeDropdown: true })}>清除+关闭</Button>
+                            <Button onClick={() => close()}>直接关闭</Button>
+                        </Space>
+                    </Space>
+                );
+            },
+            onFilterDropdownVisibleChange: (visible) => {
+                console.log('inputRef', visible, inputRef);
+                inputRef.current?.focus?.();
+            }
+        },
+        {
+            title: '大小',
+            dataIndex: 'size',
+            sorter: (a, b) => (a.size - b.size > 0 ? 1 : -1),
+            render: text => `${text} KB`,
+        },
+        {
+            title: '所有者',
+            dataIndex: 'owner',
+            render: (text, record, index) => {
+                return (
+                    <div>
+                        <Avatar size="small" color={record.avatarBg} style={{ marginRight: 4 }}>
+                            {typeof text === 'string' && text.slice(0, 1)}
+                        </Avatar>
+                        {text}
+                    </div>
+                );
+            },
+            onFilter: (value, record) => record.owner.includes(value),
+            defaultFilteredValue: ['姜鹏志'],
+            renderFilterDropdown: (props) => {
+                console.log('renderFilterDropdown', props);
+                const { tempFilteredValue, setTempFilteredValue, confirm, clear, close } = props;
+
+                const handleChange = (value: any) => {
+                    if (value) {
+                        setTempFilteredValue([value]);
+                    } else {
+                        setTempFilteredValue([]);
+                    }
+                };
+
+                return (
+                    <Space vertical align='start' style={{ padding: 8 }}>
+                        <Input value={tempFilteredValue[0]} onChange={handleChange}/>
+                        <Space>
+                            <Button onClick={() => confirm({ closeDropdown: false })}>筛选后不关闭</Button>
+                            <Button onClick={() => clear({ closeDropdown: false })}>清除后不关闭</Button>
+                            <Button onClick={() => close()}>直接关闭</Button>
+                        </Space>
+                    </Space>
+                );
+            },
+        },
+        {
+            title: '更新日期',
+            dataIndex: 'updateTime',
+            sorter: (a, b) => (a.updateTime - b.updateTime > 0 ? 1 : -1),
+            render: value => {
+                return dateFns.format(new Date(value), 'yyyy-MM-dd');
+            },
+        },
+    ];
+
+    const getData = () => {
+        const data = [];
+        for (let i = 0; i < 46; i++) {
+            const isSemiDesign = i % 2 === 0;
+            const randomNumber = (i * 1000) % 199;
+            data.push({
+                key: '' + i,
+                name: isSemiDesign ? `Semi Design 设计稿${i}.fig` : `Semi D2C 首页${i}.fig`,
+                owner: isSemiDesign ? '姜鹏志' : '郝宣',
+                size: randomNumber,
+                updateTime: new Date('2024-01-25').valueOf() + randomNumber * DAY,
+                avatarBg: isSemiDesign ? 'grey' : 'red',
+            });
+        }
+        return data;
+    };
+
+    useEffect(() => {
+        const data = getData();
+        setData(data);
+    }, []);
+
+    return <Table columns={columns} dataSource={dataSource} />;
+}

+ 117 - 0
packages/semi-ui/table/_story/v2/InputFilter/index.tsx

@@ -0,0 +1,117 @@
+import React, { useState, useEffect, useRef } from 'react';
+import { Table, Avatar, Input, Space } from '@douyinfe/semi-ui';
+import type { ColumnProps } from '../../../interface';
+import * as dateFns from 'date-fns';
+
+/**
+ * test with cypress, please don't modify this story
+ */
+export default function App() {
+    const [dataSource, setData] = useState([]);
+    const [filteredValue, setFilteredValue] = useState(['设计稿']);
+    const compositionRef = useRef({ isComposition: false });
+
+    const DAY = 24 * 60 * 60 * 1000;
+    const figmaIconUrl = 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/figma-icon.png';
+
+    const handleChange = (value: string) => {
+        if (compositionRef.current?.isComposition) {
+            return;
+        }
+        const newFilteredValue = value ? [value] : [];
+        setFilteredValue(newFilteredValue);
+    };
+    const handleCompositionStart = () => {
+        compositionRef.current.isComposition = true;
+    };
+
+    const handleCompositionEnd = (event: React.CompositionEvent) => {
+        compositionRef.current.isComposition = false;
+        const value = event.target?.value;
+        const newFilteredValue = value ? [value] : [];
+        setFilteredValue(newFilteredValue);
+    };
+
+
+    const columns: ColumnProps[] = [
+        {
+            title: (
+                <Space>
+                    <span>标题</span>
+                    <Input
+                        style={{ width: 200 }}
+                        defaultValue={filteredValue[0]}
+                        onCompositionStart={handleCompositionStart}
+                        onCompositionEnd={handleCompositionEnd}
+                        onChange={handleChange}
+                        showClear 
+                    />
+                </Space>
+            ),
+            dataIndex: 'name',
+            width: 400,
+            render: (text, record, index) => {
+                return (
+                    <div>
+                        <Avatar size="small" shape="square" src={figmaIconUrl} style={{ marginRight: 12 }}></Avatar>
+                        {text}
+                    </div>
+                );
+            },
+            onFilter: (value, record) => record.name.includes(value),
+            filteredValue,
+        },
+        {
+            title: '大小',
+            dataIndex: 'size',
+            sorter: (a, b) => (a.size - b.size > 0 ? 1 : -1),
+            render: text => `${text} KB`,
+        },
+        {
+            title: '所有者',
+            dataIndex: 'owner',
+            render: (text, record, index) => {
+                return (
+                    <div>
+                        <Avatar size="small" color={record.avatarBg} style={{ marginRight: 4 }}>
+                            {typeof text === 'string' && text.slice(0, 1)}
+                        </Avatar>
+                        {text}
+                    </div>
+                );
+            },
+        },
+        {
+            title: '更新日期',
+            dataIndex: 'updateTime',
+            sorter: (a, b) => (a.updateTime - b.updateTime > 0 ? 1 : -1),
+            render: value => {
+                return dateFns.format(new Date(value), 'yyyy-MM-dd');
+            },
+        },
+    ];
+
+    const getData = () => {
+        const data = [];
+        for (let i = 0; i < 46; i++) {
+            const isSemiDesign = i % 2 === 0;
+            const randomNumber = (i * 1000) % 199;
+            data.push({
+                key: '' + i,
+                name: isSemiDesign ? `Semi Design 设计稿${i}.fig` : `Semi D2C 首页${i}.fig`,
+                owner: isSemiDesign ? '姜鹏志' : '郝宣',
+                size: randomNumber,
+                updateTime: new Date('2024-01-25').valueOf() + randomNumber * DAY,
+                avatarBg: isSemiDesign ? 'grey' : 'red',
+            });
+        }
+        return data;
+    };
+
+    useEffect(() => {
+        const data = getData();
+        setData(data);
+    }, []);
+
+    return <Table columns={columns} dataSource={dataSource} />;
+}

+ 2 - 0
packages/semi-ui/table/_story/v2/index.js

@@ -29,3 +29,5 @@ export { default as KeepDOM } from './KeepDOM';
 export { default as SortIcon } from './SortIcon';
 export { default as FixedAllDisabledAndSelected } from './FixedAllDisabledAndSelected';
 export { default as FixedRowSelectionHiddenResizable } from './FixedRowSelectionHiddenResizable';
+export { default as FeatRenderFilterDropdown } from './FeatRenderFilterDropdown';
+export { default as InputFilter } from './InputFilter';

+ 31 - 11
packages/semi-ui/table/interface.ts

@@ -1,13 +1,12 @@
 import React, { ReactNode, MutableRefObject } from 'react';
 
-import { BaseProps } from '../_base/baseComponent';
-import { PaginationProps } from '../pagination';
-import { CheckboxProps } from '../checkbox';
-import { DropdownProps } from '../dropdown';
-import { Locale } from '../locale/interface';
-import { ArrayElement } from '../_base/base';
+import type { BaseProps } from '../_base/baseComponent';
+import type { PaginationProps } from '../pagination';
+import type { CheckboxProps } from '../checkbox';
+import type { Locale } from '../locale/interface';
+import type { ArrayElement } from '../_base/base';
 import { strings } from '@douyinfe/semi-foundation/table/constants';
-import {
+import type {
     BaseRowKeyType,
     BaseSortOrder,
     BaseGroupBy,
@@ -21,7 +20,8 @@ import {
     BaseIncludeGroupRecord,
     BaseEllipsis
 } from '@douyinfe/semi-foundation/table/foundation';
-import { ScrollDirection, CSSDirection } from 'react-window';
+import type { ScrollDirection, CSSDirection } from 'react-window';
+import type { ColumnFilterProps } from './ColumnFilter';
 
 export interface TableProps<RecordType extends Record<string, any> = any> extends BaseProps {
     bordered?: boolean;
@@ -81,29 +81,37 @@ export interface ColumnProps<RecordType extends Record<string, any> = any> {
     children?: Array<ColumnProps<RecordType>>;
     className?: string;
     colSpan?: number;
+    /** use `dataIndex` to get current column data item from record. If you use `sorter` or `onFilter`, a unique `dataIndex` is required  */
     dataIndex?: string;
     defaultFilteredValue?: any[];
     defaultSortOrder?: SortOrder;
     filterChildrenRecord?: boolean;
-    filterDropdown?: React.ReactNode;
-    filterDropdownProps?: DropdownProps;
+    filterDropdown?: ColumnFilterProps['filterDropdown'];
+    /** render filter Dropdown panel content  */
+    renderFilterDropdown?: ColumnFilterProps['renderFilterDropdown'];
+    /** filter Dropdown props  */
+    filterDropdownProps?: ColumnFilterProps['filterDropdownProps'];
     filterDropdownVisible?: boolean;
     filterIcon?: FilterIcon;
     filterMultiple?: boolean;
     filteredValue?: any[];
+    /** `filters` is not required if you use `renderFilterDropdown`  */
     filters?: Filter[];
     fixed?: Fixed;
+    /** the key required by React. If you have already set the `dataIndex`, the key does not need to be set again.  */
     key?: string | number;
     render?: ColumnRender<RecordType>;
     renderFilterDropdownItem?: RenderFilterDropdownItem;
     sortChildrenRecord?: boolean;
     sortOrder?: SortOrder;
+    /** enable sorting, `dataIndex` is required at the same time  */
     sorter?: Sorter<RecordType>;
     sortIcon?: SortIcon;
     title?: ColumnTitle;
     useFullRender?: boolean;
     width?: string | number;
     onCell?: OnCell<RecordType>;
+    /** enable filtering, `dataIndex` is required at the same time  */
     onFilter?: OnFilter<RecordType>;
     onFilterDropdownVisibleChange?: OnFilterDropdownVisibleChange;
     onHeaderCell?: OnHeaderCell<RecordType>;
@@ -237,9 +245,21 @@ export interface RowSelectionProps<RecordType> {
     width?: string | number;
     onChange?: RowSelectionOnChange<RecordType>;
     onSelect?: RowSelectionOnSelect<RecordType>;
-    onSelectAll?: RowSelectionOnSelectAll<RecordType>
+    onSelectAll?: RowSelectionOnSelectAll<RecordType>;
+    renderCell?: RowSelectionRenderCell<RecordType>
 }
 
+export type RowSelectionRenderCell<RecordType> = (renderCellArgs: {
+    selected: boolean;
+    record: RecordType;
+    originNode: JSX.Element;
+    inHeader: boolean;
+    disabled: boolean;
+    indeterminate: boolean;
+    index?: number;
+    selectRow?: (selected: boolean, e: Event) => void;
+    selectAll?: (selected: boolean, e: Event) => void
+}) => ReactNode;
 export type GetCheckboxProps<RecordType> = (record: RecordType) => CheckboxProps;
 export type RowSelectionOnChange<RecordType> = (selectedRowKeys?: (string | number)[], selectedRows?: RecordType[]) => void;
 export type RowSelectionOnSelect<RecordType> = (

+ 21 - 0
packages/semi-ui/treeSelect/__test__/treeSelect.test.js

@@ -595,6 +595,27 @@ describe('TreeSelect', () => {
         expect(treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-select-selection`).getDOMNode().textContent).toEqual('亚洲');
     });
 
+    it('onClear', () => {
+        let spyOnClear = sinon.spy(() => { });
+        let treeSelect = getTreeSelect({
+            defaultExpandAll: true,
+            onClear: spyOnClear,
+            showClear: true,
+        });
+
+        let nodeBeijing = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-3`).at(0);
+        // select beijing
+        nodeBeijing.simulate('click');
+
+        let nodeSelectTree = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-select.${BASE_CLASS_PREFIX}-tree-select-single`).at(0);
+        nodeSelectTree.simulate('mouseenter');
+
+        let nodeClearIcon = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-select-clearbtn`).at(0);
+        nodeClearIcon.simulate('click');
+
+        expect(spyOnClear.calledOnce).toBe(true);
+    })
+
     it('onChange + value not changed', () => {
         let spyOnSelect = sinon.spy(() => { });
         let spyOnChange = sinon.spy(() => { });

+ 7 - 1
packages/semi-ui/treeSelect/index.tsx

@@ -149,7 +149,8 @@ export interface TreeSelectProps extends Omit<BasicTreeSelectProps, OverrideComm
     onBlur?: (e: React.MouseEvent) => void;
     onChange?: OnChange;
     onFocus?: (e: React.MouseEvent) => void;
-    onVisibleChange?: (isVisible: boolean) => void
+    onVisibleChange?: (isVisible: boolean) => void;
+    onClear?: (e: React.MouseEvent | React.KeyboardEvent<HTMLDivElement>) => void
 }
 
 export type OverrideCommonState =
@@ -204,6 +205,7 @@ class TreeSelect extends BaseComponent<TreeSelectProps, TreeSelectState> {
         virtualize: PropTypes.object,
         treeNodeFilterProp: PropTypes.string,
         onChange: PropTypes.func,
+        onClear: PropTypes.func,
         onSearch: PropTypes.func,
         onSelect: PropTypes.func,
         onExpand: PropTypes.func,
@@ -667,6 +669,7 @@ class TreeSelect extends BaseComponent<TreeSelectProps, TreeSelectState> {
         | 'notifySearch'
         | 'cacheFlattenNodes'
         | 'notifyLoad'
+        | 'notifyClear'
         > = {
             updateState: states => {
                 this.setState({ ...states } as TreeSelectState);
@@ -683,6 +686,9 @@ class TreeSelect extends BaseComponent<TreeSelectProps, TreeSelectState> {
             notifyLoad: (newLoadedKeys, data) => {
                 const { onLoad } = this.props;
                 isFunction(onLoad) && onLoad(newLoadedKeys, data);
+            },
+            notifyClear: (e: React.MouseEvent | React.KeyboardEvent<HTMLDivElement>) => {
+                this.props.onClear && this.props.onClear(e);
             }
         };
         return {

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

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

+ 202 - 202
sitemap.xml

@@ -2,333 +2,333 @@
 <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-01-31T12:21:50.080Z</lastmod>
+        <lastmod>2024-01-31T08:49:44.764Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://medium.com/front-end-weekly/how-we-test-semi-design-component-libraries-64b854f63b65</loc>
-        <lastmod>2024-01-31T12:21:48.975Z</lastmod>
+        <lastmod>2024-01-31T08:49:44.277Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://mp.weixin.qq.com/s/noHoWRuA25PgqFNcurhIUA</loc>
-        <lastmod>2024-01-31T12:21:51.558Z</lastmod>
+        <lastmod>2024-01-31T08:49:46.965Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://mp.weixin.qq.com/s/O3js-SZDNPEOjGxh-aAkbw</loc>
-        <lastmod>2024-01-31T12:21:51.652Z</lastmod>
+        <lastmod>2024-01-31T08:49:46.575Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/code/en-US</loc>
-        <lastmod>2024-01-31T12:21:50.212Z</lastmod>
+        <lastmod>2024-01-31T08:49:44.936Z</lastmod>
         <changefreq>weekly</changefreq>
         <scm>1.0.0.87</scm>
     </url>
     <url>
         <loc>https://semi.design/code/en-US/about/contact</loc>
-        <lastmod>2024-01-31T12:21:50.328Z</lastmod>
+        <lastmod>2024-01-31T08:49:45.243Z</lastmod>
         <changefreq>weekly</changefreq>
         <scm>1.0.0.87</scm>
     </url>
     <url>
         <loc>https://semi.design/code/en-US/about/known-issues</loc>
-        <lastmod>2024-01-31T12:21:50.399Z</lastmod>
+        <lastmod>2024-01-31T08:49:45.325Z</lastmod>
         <changefreq>weekly</changefreq>
         <scm>1.0.0.87</scm>
     </url>
     <url>
         <loc>https://semi.design/code/en-US/about/roadmap</loc>
-        <lastmod>2024-01-31T12:21:50.613Z</lastmod>
+        <lastmod>2024-01-31T08:49:45.644Z</lastmod>
         <changefreq>weekly</changefreq>
         <scm>1.0.0.87</scm>
     </url>
     <url>
         <loc>https://semi.design/code/en-US/about/schema</loc>
-        <lastmod>2024-01-31T12:21:50.759Z</lastmod>
+        <lastmod>2024-01-31T08:49:45.709Z</lastmod>
         <changefreq>weekly</changefreq>
         <scm>1.0.0.87</scm>
     </url>
     <url>
         <loc>https://semi.design/code/en-US/d2c/inspect</loc>
-        <lastmod>2024-01-31T12:21:50.849Z</lastmod>
+        <lastmod>2024-01-31T08:49:45.861Z</lastmod>
         <changefreq>weekly</changefreq>
         <scm>1.0.0.87</scm>
     </url>
     <url>
         <loc>https://semi.design/code/en-US/d2c/mark</loc>
-        <lastmod>2024-01-31T12:21:50.840Z</lastmod>
+        <lastmod>2024-01-31T08:49:45.875Z</lastmod>
         <changefreq>weekly</changefreq>
         <scm>1.0.0.87</scm>
     </url>
     <url>
         <loc>https://semi.design/code/en-US/d2c/mark-icon</loc>
-        <lastmod>2024-01-31T12:21:51.688Z</lastmod>
+        <lastmod>2024-01-31T08:49:46.041Z</lastmod>
         <changefreq>weekly</changefreq>
         <scm>1.0.0.87</scm>
     </url>
     <url>
         <loc>https://semi.design/code/en-US/d2c/mark-library</loc>
-        <lastmod>2024-01-31T12:21:51.011Z</lastmod>
+        <lastmod>2024-01-31T08:49:46.015Z</lastmod>
         <changefreq>weekly</changefreq>
         <scm>1.0.0.87</scm>
     </url>
     <url>
         <loc>https://semi.design/code/en-US/d2c/mark-table</loc>
-        <lastmod>2024-01-31T12:21:51.044Z</lastmod>
+        <lastmod>2024-01-31T08:49:46.084Z</lastmod>
         <changefreq>weekly</changefreq>
         <scm>1.0.0.87</scm>
     </url>
     <url>
         <loc>https://semi.design/code/en-US/d2c/settings</loc>
-        <lastmod>2024-01-31T12:21:51.052Z</lastmod>
+        <lastmod>2024-01-31T08:49:46.060Z</lastmod>
         <changefreq>weekly</changefreq>
         <scm>1.0.0.87</scm>
     </url>
     <url>
         <loc>https://semi.design/code/en-US/d2c/support-list</loc>
-        <lastmod>2024-01-31T12:21:51.490Z</lastmod>
+        <lastmod>2024-01-31T08:49:46.271Z</lastmod>
         <changefreq>weekly</changefreq>
         <scm>1.0.0.87</scm>
     </url>
     <url>
         <loc>https://semi.design/code/en-US/d2c/transform-plugin</loc>
-        <lastmod>2024-01-31T12:21:51.320Z</lastmod>
+        <lastmod>2024-01-31T08:49:46.310Z</lastmod>
         <changefreq>weekly</changefreq>
         <scm>1.0.0.87</scm>
     </url>
     <url>
         <loc>https://semi.design/code/en-US/d2c/translate-logic</loc>
-        <lastmod>2024-01-31T12:21:51.529Z</lastmod>
+        <lastmod>2024-01-31T08:49:46.521Z</lastmod>
         <changefreq>weekly</changefreq>
         <scm>1.0.0.87</scm>
     </url>
     <url>
         <loc>https://semi.design/code/en-US/d2c/translate-page</loc>
-        <lastmod>2024-01-31T12:21:51.496Z</lastmod>
+        <lastmod>2024-01-31T08:49:46.240Z</lastmod>
         <changefreq>weekly</changefreq>
         <scm>1.0.0.87</scm>
     </url>
     <url>
         <loc>https://semi.design/code/en-US/start/changelog</loc>
-        <lastmod>2024-01-31T12:21:51.718Z</lastmod>
+        <lastmod>2024-01-31T08:49:46.464Z</lastmod>
         <changefreq>weekly</changefreq>
         <scm>1.0.0.87</scm>
     </url>
     <url>
         <loc>https://semi.design/code/en-US/start/faq</loc>
-        <lastmod>2024-01-31T12:21:51.776Z</lastmod>
+        <lastmod>2024-01-31T08:49:46.524Z</lastmod>
         <changefreq>weekly</changefreq>
         <scm>1.0.0.87</scm>
     </url>
     <url>
         <loc>https://semi.design/code/en-US/start/introduction</loc>
-        <lastmod>2024-01-31T12:21:51.997Z</lastmod>
+        <lastmod>2024-01-31T08:49:46.694Z</lastmod>
         <changefreq>weekly</changefreq>
         <scm>1.0.0.87</scm>
     </url>
     <url>
         <loc>https://semi.design/code/en-US/start/quick-start</loc>
-        <lastmod>2024-01-31T12:21:51.991Z</lastmod>
+        <lastmod>2024-01-31T08:49:46.882Z</lastmod>
         <changefreq>weekly</changefreq>
         <scm>1.0.0.87</scm>
     </url>
     <url>
         <loc>https://semi.design/code/en-US/start/terms</loc>
-        <lastmod>2024-01-31T12:21:52.271Z</lastmod>
+        <lastmod>2024-01-31T08:49:46.782Z</lastmod>
         <changefreq>weekly</changefreq>
         <scm>1.0.0.87</scm>
     </url>
     <url>
         <loc>https://semi.design/code/en-US/uikit/create</loc>
-        <lastmod>2024-01-31T12:21:52.246Z</lastmod>
+        <lastmod>2024-01-31T08:49:46.657Z</lastmod>
         <changefreq>weekly</changefreq>
         <scm>1.0.0.87</scm>
     </url>
     <url>
         <loc>https://semi.design/code/en-US/uikit/figma-usage</loc>
-        <lastmod>2024-01-31T12:21:52.497Z</lastmod>
+        <lastmod>2024-01-31T08:49:46.916Z</lastmod>
         <changefreq>weekly</changefreq>
         <scm>1.0.0.87</scm>
     </url>
     <url>
         <loc>https://semi.design/code/en-US/uikit/form-usage</loc>
-        <lastmod>2024-01-31T12:21:52.463Z</lastmod>
+        <lastmod>2024-01-31T08:49:46.843Z</lastmod>
         <changefreq>weekly</changefreq>
         <scm>1.0.0.87</scm>
     </url>
     <url>
         <loc>https://semi.design/code/en-US/uikit/migrate</loc>
-        <lastmod>2024-01-31T12:21:52.711Z</lastmod>
+        <lastmod>2024-01-31T08:49:47.091Z</lastmod>
         <changefreq>weekly</changefreq>
         <scm>1.0.0.87</scm>
     </url>
     <url>
         <loc>https://semi.design/code/en-US/uikit/rules</loc>
-        <lastmod>2024-01-31T12:21:52.738Z</lastmod>
+        <lastmod>2024-01-31T08:49:47.284Z</lastmod>
         <changefreq>weekly</changefreq>
         <scm>1.0.0.87</scm>
     </url>
     <url>
         <loc>https://semi.design/code/en-US/uikit/table-usage</loc>
-        <lastmod>2024-01-31T12:21:52.970Z</lastmod>
+        <lastmod>2024-01-31T08:49:47.089Z</lastmod>
         <changefreq>weekly</changefreq>
         <scm>1.0.0.87</scm>
     </url>
     <url>
         <loc>https://semi.design/code/zh-CN</loc>
-        <lastmod>2024-01-31T12:21:52.976Z</lastmod>
+        <lastmod>2024-01-31T08:49:47.567Z</lastmod>
         <changefreq>weekly</changefreq>
         <scm>1.0.0.87</scm>
     </url>
     <url>
         <loc>https://semi.design/code/zh-CN/about/contact</loc>
-        <lastmod>2024-01-31T12:21:53.139Z</lastmod>
+        <lastmod>2024-01-31T08:49:47.037Z</lastmod>
         <changefreq>weekly</changefreq>
         <scm>1.0.0.87</scm>
     </url>
     <url>
         <loc>https://semi.design/code/zh-CN/about/known-issues</loc>
-        <lastmod>2024-01-31T12:21:53.139Z</lastmod>
+        <lastmod>2024-01-31T08:49:47.061Z</lastmod>
         <changefreq>weekly</changefreq>
         <scm>1.0.0.87</scm>
     </url>
     <url>
         <loc>https://semi.design/code/zh-CN/about/roadmap</loc>
-        <lastmod>2024-01-31T12:21:53.141Z</lastmod>
+        <lastmod>2024-01-31T08:49:47.242Z</lastmod>
         <changefreq>weekly</changefreq>
         <scm>1.0.0.87</scm>
     </url>
     <url>
         <loc>https://semi.design/code/zh-CN/about/schema</loc>
-        <lastmod>2024-01-31T12:21:53.242Z</lastmod>
+        <lastmod>2024-01-31T08:49:47.270Z</lastmod>
         <changefreq>weekly</changefreq>
         <scm>1.0.0.87</scm>
     </url>
     <url>
         <loc>https://semi.design/code/zh-CN/d2c/inspect</loc>
-        <lastmod>2024-01-31T12:21:53.449Z</lastmod>
+        <lastmod>2024-01-31T08:49:47.483Z</lastmod>
         <changefreq>weekly</changefreq>
         <scm>1.0.0.87</scm>
     </url>
     <url>
         <loc>https://semi.design/code/zh-CN/d2c/mark</loc>
-        <lastmod>2024-01-31T12:21:53.453Z</lastmod>
+        <lastmod>2024-01-31T08:49:47.541Z</lastmod>
         <changefreq>weekly</changefreq>
         <scm>1.0.0.87</scm>
     </url>
     <url>
         <loc>https://semi.design/code/zh-CN/d2c/mark-icon</loc>
-        <lastmod>2024-01-31T12:21:53.679Z</lastmod>
+        <lastmod>2024-01-31T08:49:47.669Z</lastmod>
         <changefreq>weekly</changefreq>
         <scm>1.0.0.87</scm>
     </url>
     <url>
         <loc>https://semi.design/code/zh-CN/d2c/mark-library</loc>
-        <lastmod>2024-01-31T12:21:53.635Z</lastmod>
+        <lastmod>2024-01-31T08:49:47.576Z</lastmod>
         <changefreq>weekly</changefreq>
         <scm>1.0.0.87</scm>
     </url>
     <url>
         <loc>https://semi.design/code/zh-CN/d2c/mark-table</loc>
-        <lastmod>2024-01-31T12:21:53.703Z</lastmod>
+        <lastmod>2024-01-31T08:49:47.492Z</lastmod>
         <changefreq>weekly</changefreq>
         <scm>1.0.0.87</scm>
     </url>
     <url>
         <loc>https://semi.design/code/zh-CN/d2c/settings</loc>
-        <lastmod>2024-01-31T12:21:53.679Z</lastmod>
+        <lastmod>2024-01-31T08:49:47.472Z</lastmod>
         <changefreq>weekly</changefreq>
         <scm>1.0.0.87</scm>
     </url>
     <url>
         <loc>https://semi.design/code/zh-CN/d2c/support-list</loc>
-        <lastmod>2024-01-31T12:21:53.924Z</lastmod>
+        <lastmod>2024-01-31T08:49:47.721Z</lastmod>
         <changefreq>weekly</changefreq>
         <scm>1.0.0.87</scm>
     </url>
     <url>
         <loc>https://semi.design/code/zh-CN/d2c/transform-plugin</loc>
-        <lastmod>2024-01-31T12:21:53.937Z</lastmod>
+        <lastmod>2024-01-31T08:49:47.665Z</lastmod>
         <changefreq>weekly</changefreq>
         <scm>1.0.0.87</scm>
     </url>
     <url>
         <loc>https://semi.design/code/zh-CN/d2c/translate-logic</loc>
-        <lastmod>2024-01-31T12:21:54.217Z</lastmod>
+        <lastmod>2024-01-31T08:49:47.664Z</lastmod>
         <changefreq>weekly</changefreq>
         <scm>1.0.0.87</scm>
     </url>
     <url>
         <loc>https://semi.design/code/zh-CN/d2c/translate-page</loc>
-        <lastmod>2024-01-31T12:21:54.185Z</lastmod>
+        <lastmod>2024-01-31T08:49:47.650Z</lastmod>
         <changefreq>weekly</changefreq>
         <scm>1.0.0.87</scm>
     </url>
     <url>
         <loc>https://semi.design/code/zh-CN/start/changelog</loc>
-        <lastmod>2024-01-31T12:21:54.401Z</lastmod>
+        <lastmod>2024-01-31T08:49:47.826Z</lastmod>
         <changefreq>weekly</changefreq>
         <scm>1.0.0.87</scm>
     </url>
     <url>
         <loc>https://semi.design/code/zh-CN/start/faq</loc>
-        <lastmod>2024-01-31T12:21:54.445Z</lastmod>
+        <lastmod>2024-01-31T08:49:47.911Z</lastmod>
         <changefreq>weekly</changefreq>
         <scm>1.0.0.87</scm>
     </url>
     <url>
         <loc>https://semi.design/code/zh-CN/start/introduction</loc>
-        <lastmod>2024-01-31T12:21:54.696Z</lastmod>
+        <lastmod>2024-01-31T08:49:47.879Z</lastmod>
         <changefreq>weekly</changefreq>
         <scm>1.0.0.87</scm>
     </url>
     <url>
         <loc>https://semi.design/code/zh-CN/start/quick-start</loc>
-        <lastmod>2024-01-31T12:21:54.687Z</lastmod>
+        <lastmod>2024-01-31T08:49:48.109Z</lastmod>
         <changefreq>weekly</changefreq>
         <scm>1.0.0.87</scm>
     </url>
     <url>
         <loc>https://semi.design/code/zh-CN/start/terms</loc>
-        <lastmod>2024-01-31T12:21:54.873Z</lastmod>
+        <lastmod>2024-01-31T08:49:47.882Z</lastmod>
         <changefreq>weekly</changefreq>
         <scm>1.0.0.87</scm>
     </url>
     <url>
         <loc>https://semi.design/code/zh-CN/uikit/create</loc>
-        <lastmod>2024-01-31T12:21:54.827Z</lastmod>
+        <lastmod>2024-01-31T08:49:48.075Z</lastmod>
         <changefreq>weekly</changefreq>
         <scm>1.0.0.87</scm>
     </url>
     <url>
         <loc>https://semi.design/code/zh-CN/uikit/figma-usage</loc>
-        <lastmod>2024-01-31T12:21:55.237Z</lastmod>
+        <lastmod>2024-01-31T08:49:48.060Z</lastmod>
         <changefreq>weekly</changefreq>
         <scm>1.0.0.87</scm>
     </url>
     <url>
         <loc>https://semi.design/code/zh-CN/uikit/form-usage</loc>
-        <lastmod>2024-01-31T12:21:55.183Z</lastmod>
+        <lastmod>2024-01-31T08:49:48.040Z</lastmod>
         <changefreq>weekly</changefreq>
         <scm>1.0.0.87</scm>
     </url>
     <url>
         <loc>https://semi.design/code/zh-CN/uikit/migrate</loc>
-        <lastmod>2024-01-31T12:21:55.458Z</lastmod>
+        <lastmod>2024-01-31T08:49:48.481Z</lastmod>
         <changefreq>weekly</changefreq>
         <scm>1.0.0.87</scm>
     </url>
     <url>
         <loc>https://semi.design/code/zh-CN/uikit/rules</loc>
-        <lastmod>2024-01-31T12:21:55.464Z</lastmod>
+        <lastmod>2024-01-31T08:49:48.275Z</lastmod>
         <changefreq>weekly</changefreq>
         <scm>1.0.0.87</scm>
     </url>
     <url>
         <loc>https://semi.design/code/zh-CN/uikit/table-usage</loc>
-        <lastmod>2024-01-31T12:21:55.520Z</lastmod>
+        <lastmod>2024-01-31T08:49:48.472Z</lastmod>
         <changefreq>weekly</changefreq>
         <scm>1.0.0.87</scm>
     </url>
@@ -790,732 +790,732 @@
     </url>
     <url>
         <loc>https://semi.design/en-US/basic/divider</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/basic/grid</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/basic/icon</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/basic/layout</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/basic/space</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/basic/tokens</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/basic/typography</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/feedback/banner</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/feedback/notification</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/feedback/popconfirm</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/feedback/progress</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/feedback/skeleton</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/feedback/spin</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/feedback/toast</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/input/autocomplete</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/input/button</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/input/cascader</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/input/checkbox</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/input/datepicker</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/input/form</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/input/input</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/input/inputnumber</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/input/radio</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/input/rating</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/input/select</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/input/slider</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/input/switch</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/input/taginput</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/input/timepicker</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/input/transfer</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/input/treeselect</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/input/upload</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/navigation/anchor</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/navigation/backtop</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/navigation/breadcrumb</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/navigation/navigation</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/navigation/pagination</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/navigation/steps</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/navigation/tabs</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/navigation/tree</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/other/configprovider</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/other/locale</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/show/avatar</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/show/badge</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/show/calendar</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/show/card</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/show/carousel</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/show/collapse</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/show/collapsible</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/show/descriptions</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/show/dropdown</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/show/empty</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/show/highlight</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/show/image</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/show/list</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/show/modal</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/show/overflowlist</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/show/popover</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/show/scrolllist</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/show/sidesheet</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/show/table</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/show/tag</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/show/timeline</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/show/tooltip</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/start/accessibility</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/start/changelog</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/start/customize-theme</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/start/dark-mode</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/start/faq</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/start/getting-started</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/start/introduction</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/start/overview</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/en-US/start/update-to-v2</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/basic/divider</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/basic/grid</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/basic/icon</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/basic/layout</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/basic/space</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/basic/tokens</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/basic/typography</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/feedback/banner</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/feedback/notification</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/feedback/popconfirm</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/feedback/progress</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/feedback/skeleton</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/feedback/spin</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/feedback/toast</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/input/autocomplete</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/input/button</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/input/cascader</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/input/checkbox</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/input/datepicker</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/input/form</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/input/input</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/input/inputnumber</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/input/radio</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/input/rating</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/input/select</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/input/slider</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/input/switch</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/input/taginput</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/input/timepicker</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/input/transfer</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/input/treeselect</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/input/upload</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/navigation/anchor</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/navigation/backtop</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/navigation/breadcrumb</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/navigation/navigation</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/navigation/pagination</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/navigation/steps</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/navigation/tabs</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/navigation/tree</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/other/configprovider</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/other/locale</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/show/avatar</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/show/badge</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/show/calendar</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/show/card</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/show/carousel</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/show/collapse</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/show/collapsible</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/show/descriptions</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/show/dropdown</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/show/empty</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/show/highlight</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/show/image</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/show/list</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/show/modal</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/show/overflowlist</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/show/popover</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/show/scrolllist</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/show/sidesheet</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/show/table</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/show/tag</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/show/timeline</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/show/tooltip</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/start/accessibility</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/start/changelog</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/start/customize-theme</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/start/dark-mode</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/start/faq</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/start/getting-started</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/start/introduction</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/start/overview</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
     <url>
         <loc>https://semi.design/zh-CN/start/update-to-v2</loc>
-        <lastmod>2024-01-31T12:18:01.000Z</lastmod>
+        <lastmod>2024-01-31T08:14:38.000Z</lastmod>
         <changefreq>weekly</changefreq>
     </url>
 </urlset>

+ 5 - 3
src/templates/postTemplate.js

@@ -4,7 +4,7 @@ import { graphql, Link } from 'gatsby';
 import Blocks from '@douyinfe/semi-site-markdown-blocks';
 import '@douyinfe/semi-site-markdown-blocks/dist/index.css';
 import SearchAllInOne from '../components/SearchAllInOne';
-import { Icon, Row, Col, Tag, Tooltip, Popover, Checkbox, Button, Radio, Skeleton, Toast, Table, CheckboxGroup, Descriptions, Dropdown, Form, Typography, Empty, Image, Card, Space } from '@douyinfe/semi-ui';
+import { Icon, Row, Col, Tag, Tooltip, Popover, Checkbox, Button, Radio, Avatar,Skeleton, Toast, Table, CheckboxGroup, Descriptions, Dropdown, Form, Typography, Empty, Image, Card, Space } from '@douyinfe/semi-ui';
 import { IllustrationNoAccess, IllustrationNoAccessDark } from '@douyinfe/semi-illustrations';
 import NotificationCard from '../../packages/semi-ui/notification/notice';
 import ToastCard from '../../packages/semi-ui/toast/toast';
@@ -44,7 +44,7 @@ import '../styles/docDemo.scss';
 import '../styles/index.scss';
 import '../styles/doc.scss';
 import cls from 'classnames';
-import { IconLink, IconFile, IconHelpCircle } from '@douyinfe/semi-icons';
+import { IconLink, IconFile, IconHelpCircle,IconPlus } from '@douyinfe/semi-icons';
 import { Switch, TabPane, Tabs } from '../../packages/semi-ui';
 import DesignPageAnchor from 'components/DesignPageAnchor';
 import transContent, { getAnotherSideUrl, isHaveUedDocs, isJumpToDesignSite } from './toUEDUtils/toUED';
@@ -115,7 +115,9 @@ const SemiComponents = {
     Button,
     Image,
     Card,
-    Space
+    Space,
+    Avatar,
+    IconPlus
 };
 
 const pre = ({ ...props }) => {

+ 90 - 4
yarn.lock

@@ -1519,11 +1519,25 @@
     "@douyinfe/semi-animation-styled" "2.23.2"
     classnames "^2.2.6"
 
+"@douyinfe/[email protected]":
+  version "2.51.4"
+  resolved "https://registry.npmjs.org/@douyinfe/semi-animation-react/-/semi-animation-react-2.51.4.tgz#89c2ece14e3677a7aaa756eaab0f57078e16631a"
+  integrity sha512-NGWMQ2f3+zzPBacSzIPvHpSg9jVcpyEj6tT938YNhL2raqmEOFZhjpOVXuFU0bhYnOgIR/fR9b1WObdes/Di2g==
+  dependencies:
+    "@douyinfe/semi-animation" "2.51.4"
+    "@douyinfe/semi-animation-styled" "2.51.4"
+    classnames "^2.2.6"
+
 "@douyinfe/[email protected]":
   version "2.23.2"
   resolved "https://registry.npmjs.org/@douyinfe/semi-animation-styled/-/semi-animation-styled-2.23.2.tgz#f18bc074515441c297cc636ed98521e249d093c9"
   integrity sha512-cKaA1yGHPF76Rx7EZDZicj+1oX1su2wnqb/UGFOTquAwqWmkTfgQ+EKxCd/N704WH+RtmGf4xbrJKpBvvcEdSQ==
 
+"@douyinfe/[email protected]":
+  version "2.51.4"
+  resolved "https://registry.npmjs.org/@douyinfe/semi-animation-styled/-/semi-animation-styled-2.51.4.tgz#c281c91ac6fe8a8dd6bbdc4180e95782acb5ab4a"
+  integrity sha512-PccxY7gX43H3cnzj0gqOR4d1Tqn6G3L+0j1GkKuDuWBaiB1XQcPe9SOpQLzo3TSTNTKJzgZPE2Wj/JAJ0SMNlg==
+
 "@douyinfe/[email protected]":
   version "2.12.0"
   resolved "https://registry.npmjs.org/@douyinfe/semi-animation/-/semi-animation-2.12.0.tgz#51fe52d3911c2591a80a6e9fe96e6809c1511f13"
@@ -1539,6 +1553,13 @@
   dependencies:
     bezier-easing "^2.1.0"
 
+"@douyinfe/[email protected]":
+  version "2.51.4"
+  resolved "https://registry.npmjs.org/@douyinfe/semi-animation/-/semi-animation-2.51.4.tgz#8a11d6432f045d482267983d3951d2c61a8e89ed"
+  integrity sha512-jwnQQchD/0Rp5lDXoaKhRkjdfp7qcyh9dON0KYK9q5l0gdVM9IAgEUoFvR4HfzWu9smRQFv03ls+gHG84nBN+Q==
+  dependencies:
+    bezier-easing "^2.1.0"
+
 "@douyinfe/[email protected]":
   version "2.33.1"
   resolved "https://registry.npmjs.org/@douyinfe/semi-foundation/-/semi-foundation-2.33.1.tgz#1dfe6233e35a4ed768cb580b0c9a677d1c34ffba"
@@ -1553,6 +1574,20 @@
     memoize-one "^5.2.1"
     scroll-into-view-if-needed "^2.2.24"
 
+"@douyinfe/[email protected]":
+  version "2.51.4"
+  resolved "https://registry.npmjs.org/@douyinfe/semi-foundation/-/semi-foundation-2.51.4.tgz#98105ebc77470d6e8f3abe8445967ae400975599"
+  integrity sha512-ACZodJdpHxvrDrwxsoX3eUYrB6vqsW55Dej980aqEH+0/5YAoNEamit5ntEZEDNGSr7N4e7DUF4SoKYeMl200w==
+  dependencies:
+    "@douyinfe/semi-animation" "2.51.4"
+    async-validator "^3.5.0"
+    classnames "^2.2.6"
+    date-fns "^2.29.3"
+    date-fns-tz "^1.3.8"
+    lodash "^4.17.21"
+    memoize-one "^5.2.1"
+    scroll-into-view-if-needed "^2.2.24"
+
 "@douyinfe/[email protected]", "@douyinfe/semi-icons@latest":
   version "2.33.1"
   resolved "https://registry.yarnpkg.com/@douyinfe/semi-icons/-/semi-icons-2.33.1.tgz#8e2871d9bc0ab7e12df74e3c71802d53d69b7425"
@@ -1560,11 +1595,23 @@
   dependencies:
     classnames "^2.2.6"
 
+"@douyinfe/[email protected]", "@douyinfe/semi-icons@^2.0.0":
+  version "2.51.4"
+  resolved "https://registry.npmjs.org/@douyinfe/semi-icons/-/semi-icons-2.51.4.tgz#441cc6907aa11a457bfd9da81b1eb2e8a511c757"
+  integrity sha512-o372lQrHWQ2bG3z0gLjgt4rImm5BU3m34uOeqOimyiqlrzWAHgOJ+dKGvmMSO7AW0fl+B+os8o7tmZDbgNwSSg==
+  dependencies:
+    classnames "^2.2.6"
+
 "@douyinfe/[email protected]":
   version "2.33.1"
   resolved "https://registry.npmjs.org/@douyinfe/semi-illustrations/-/semi-illustrations-2.33.1.tgz#530ab851f4dc32a52221c4067c778c800b9b55d7"
   integrity sha512-tTTUN8QwnQiF++sk4VBNzfkG87aYZ4iUeqk2ys8/ymVUmCZQ7y46ys020GO1MfPHRR47OMFPI82FVcH1WQtE3g==
 
+"@douyinfe/[email protected]":
+  version "2.51.4"
+  resolved "https://registry.npmjs.org/@douyinfe/semi-illustrations/-/semi-illustrations-2.51.4.tgz#27ddc72aec58835f0ca4a7252c8bc767f15d6398"
+  integrity sha512-vlf8wI9ulNRPU2SfRs7l7PeUPuON2sro+7BgVA/z/XIiOrR+u4GHIn+Li66/REp+z+N91Fj/61feJHCtAd4jAg==
+
 "@douyinfe/[email protected]":
   version "2.23.2"
   resolved "https://registry.npmjs.org/@douyinfe/semi-scss-compile/-/semi-scss-compile-2.23.2.tgz#30884bb194ee9ae1e81877985e5663c3297c1ced"
@@ -1575,10 +1622,10 @@
     lodash "^4.17.21"
     sass "^1.54.9"
 
-"@douyinfe/semi-site-banner@^0.1.0":
-  version "0.1.0"
-  resolved "https://registry.npmjs.org/@douyinfe/semi-site-banner/-/semi-site-banner-0.1.0.tgz#d6fbffb71a5c3ba88f8148ac6eab0cbfadbc12bd"
-  integrity sha512-/eN6vwo8scZkYFdK0jOdh74IEHq1a0YWWlg2vNVgCEnq978fOYL14jKtJdXvVcOG9+GbESU25c9lQIgk8OfIPQ==
+"@douyinfe/semi-site-banner@^0.1.3":
+  version "0.1.3"
+  resolved "https://registry.npmjs.org/@douyinfe/semi-site-banner/-/semi-site-banner-0.1.3.tgz#0d7e26d93431db29475e3c456f36f6fdd60e5362"
+  integrity sha512-Sju1cRqeQPnbzpHYan4CyxsXBPgduvIyEZGBs2xVajCbwKWoJdbScBzrWPlyyMvQGcibqu5hmptw4GHZLrn22w==
   dependencies:
     "@douyinfe/semi-icons" latest
     "@douyinfe/semi-ui" latest
@@ -1638,6 +1685,40 @@
   dependencies:
     glob "^7.1.6"
 
+"@douyinfe/[email protected]":
+  version "2.51.4"
+  resolved "https://registry.npmjs.org/@douyinfe/semi-theme-default/-/semi-theme-default-2.51.4.tgz#4a3edba58fa303b4180fd4de86d287b4ca6916cf"
+  integrity sha512-87LiPLRO6DcusVRtIV+pQy5c7bbFx6I8kP2W6vsgJBsPGUkNj5ZG2wSGe2wxdg480Jjjb9wUQdxvwdYk5YtEzQ==
+  dependencies:
+    glob "^7.1.6"
+
+"@douyinfe/semi-ui@^2.0.0":
+  version "2.51.4"
+  resolved "https://registry.npmjs.org/@douyinfe/semi-ui/-/semi-ui-2.51.4.tgz#0f608744b73ab0344d9a8cfcb5e548da7db1199c"
+  integrity sha512-1HdkX7dREoAYsoKCnnQMi85aqdOywKkNmdz6WKqioByf3MfR8jzT2UhxSKtRo0OWAQDxJROC5kY/psULq1WPrw==
+  dependencies:
+    "@dnd-kit/core" "^6.0.8"
+    "@dnd-kit/sortable" "^7.0.2"
+    "@dnd-kit/utilities" "^3.2.1"
+    "@douyinfe/semi-animation" "2.51.4"
+    "@douyinfe/semi-animation-react" "2.51.4"
+    "@douyinfe/semi-foundation" "2.51.4"
+    "@douyinfe/semi-icons" "2.51.4"
+    "@douyinfe/semi-illustrations" "2.51.4"
+    "@douyinfe/semi-theme-default" "2.51.4"
+    async-validator "^3.5.0"
+    classnames "^2.2.6"
+    copy-text-to-clipboard "^2.1.1"
+    date-fns "^2.29.3"
+    date-fns-tz "^1.3.8"
+    lodash "^4.17.21"
+    prop-types "^15.7.2"
+    react-resizable "^3.0.5"
+    react-window "^1.8.2"
+    resize-observer-polyfill "^1.5.1"
+    scroll-into-view-if-needed "^2.2.24"
+    utility-types "^3.10.0"
+
 "@douyinfe/semi-ui@latest":
   version "2.33.1"
   resolved "https://registry.yarnpkg.com/@douyinfe/semi-ui/-/semi-ui-2.33.1.tgz#3234ca96eb3560b8299bc9750fbe59446522d9bb"
@@ -11584,6 +11665,11 @@ eslint-plugin-react@^7.20.6, eslint-plugin-react@^7.24.0:
     semver "^6.3.0"
     string.prototype.matchall "^4.0.8"
 
+eslint-plugin-semi-design@^2.33.0:
+  version "2.51.4"
+  resolved "https://registry.npmjs.org/eslint-plugin-semi-design/-/eslint-plugin-semi-design-2.51.4.tgz#573027d101238966bccee22440923d996e359eff"
+  integrity sha512-9ePpkFwmXZA1hkEbY2entVg8Ywb0ticegYGtd5tpizaL9HBVDDno/1I5n5uEG1KYzYNb2FEvmuo40XTCvr3laA==
+
 eslint-rule-composer@^0.3.0:
   version "0.3.0"
   resolved "https://registry.npmjs.org/eslint-rule-composer/-/eslint-rule-composer-0.3.0.tgz#79320c927b0c5c0d3d3d2b76c8b4a488f25bbaf9"