From 3265d387c235437fa6143c4833f8d03d626f70fe Mon Sep 17 00:00:00 2001 From: DaiQiangReal Date: Mon, 31 Jul 2023 17:36:17 +0800 Subject: [PATCH 01/29] fix: fix audoFocus autofocus in Input and TextArea #1608 --- packages/semi-ui/input/index.tsx | 11 ++-- packages/semi-ui/input/textarea.tsx | 4 +- yarn.lock | 84 ----------------------------- 3 files changed, 8 insertions(+), 91 deletions(-) diff --git a/packages/semi-ui/input/index.tsx b/packages/semi-ui/input/index.tsx index 170a540245..15a4a68952 100644 --- a/packages/semi-ui/input/index.tsx +++ b/packages/semi-ui/input/index.tsx @@ -24,7 +24,7 @@ export type InputMode = 'password'; export type ValidateStatus = "default" | "error" | "warning" | "success"; export interface InputProps extends - Omit, 'onChange' | 'prefix' | 'size' | 'autoFocus' | 'placeholder' | 'onFocus' | 'onBlur'> { + Omit, 'onChange' | 'prefix' | 'size' | 'placeholder' | 'onFocus' | 'onBlur'> { 'aria-label'?: React.AriaAttributes['aria-label']; 'aria-describedby'?: React.AriaAttributes['aria-describedby']; 'aria-errormessage'?: React.AriaAttributes['aria-errormessage']; @@ -41,7 +41,6 @@ export interface InputProps extends defaultValue?: React.ReactText; disabled?: boolean; readonly?: boolean; - autofocus?: boolean; type?: string; showClear?: boolean; hideSuffix?: boolean; @@ -99,7 +98,7 @@ class Input extends BaseComponent { defaultValue: PropTypes.any, disabled: PropTypes.bool, readonly: PropTypes.bool, - autofocus: PropTypes.bool, + autoFocus: PropTypes.bool, type: PropTypes.string, showClear: PropTypes.bool, hideSuffix: PropTypes.bool, @@ -224,8 +223,8 @@ class Input extends BaseComponent { // autofocus is changed from the original support of input to the support of manually calling the focus method, // so that preventScroll can still take effect under the setting of autofocus this.foundation.init(); - const { disabled, autofocus, preventScroll } = this.props; - if (!disabled && autofocus) { + const { disabled, autoFocus, preventScroll } = this.props; + if (!disabled && (autoFocus || this.props['autofocus'])) { this.inputRef.current.focus({ preventScroll }); } } @@ -425,7 +424,7 @@ class Input extends BaseComponent { const { addonAfter, addonBefore, - autofocus, + autoFocus, clearIcon, className, disabled, diff --git a/packages/semi-ui/input/textarea.tsx b/packages/semi-ui/input/textarea.tsx index 5a833e2218..d5fca8a9b5 100644 --- a/packages/semi-ui/input/textarea.tsx +++ b/packages/semi-ui/input/textarea.tsx @@ -35,7 +35,7 @@ export interface TextAreaProps extends defaultValue?: string; disabled?: boolean; readonly?: boolean; - autofocus?: boolean; + autoFocus?: boolean; showCounter?: boolean; showClear?: boolean; onClear?: (e: React.MouseEvent) => void; @@ -280,6 +280,7 @@ class TextArea extends BaseComponent { minLength, showClear, borderless, + autoFocus, ...rest } = this.props; const { isFocus, value, minLength: stateMinLength } = this.state; @@ -307,6 +308,7 @@ class TextArea extends BaseComponent { ); const itemProps = { ...omit(rest, 'insetLabel', 'insetLabelId', 'getValueLength', 'onClear', 'showClear'), + autoFocus: autoFocus || this.props['autofocus'], className: itemCls, disabled, readOnly: readonly, diff --git a/yarn.lock b/yarn.lock index 14ec2c17e5..9d40369c0b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1488,25 +1488,11 @@ "@douyinfe/semi-animation-styled" "2.23.2" classnames "^2.2.6" -"@douyinfe/semi-animation-react@2.39.3": - version "2.39.3" - resolved "https://registry.yarnpkg.com/@douyinfe/semi-animation-react/-/semi-animation-react-2.39.3.tgz#b46cc2a9db9f489e52f62965bb9857708f37f73e" - integrity sha512-sMf2cKmFIMVWFdQlTyMXO917oOvjDq+KOTGLyO9rVIZDK0mFU9VM/jToYngKaUU+f6kvNZcLdx+PUxKQEfZ7hQ== - dependencies: - "@douyinfe/semi-animation" "2.39.3" - "@douyinfe/semi-animation-styled" "2.39.3" - classnames "^2.2.6" - "@douyinfe/semi-animation-styled@2.23.2": 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/semi-animation-styled@2.39.3": - version "2.39.3" - resolved "https://registry.yarnpkg.com/@douyinfe/semi-animation-styled/-/semi-animation-styled-2.39.3.tgz#4818e43b9fc646e9a3304ec2081f50c84a168aa1" - integrity sha512-mMExH5PXvCW2D8rtbG8pk53L9pYyBa8QNDoB2nNMrFlGSvHU+o/1UJ0Y504rUZ0LMsi2QJChP8Ry4mqzINN2sg== - "@douyinfe/semi-animation@2.12.0": version "2.12.0" resolved "https://registry.npmjs.org/@douyinfe/semi-animation/-/semi-animation-2.12.0.tgz#51fe52d3911c2591a80a6e9fe96e6809c1511f13" @@ -1522,13 +1508,6 @@ dependencies: bezier-easing "^2.1.0" -"@douyinfe/semi-animation@2.39.3": - version "2.39.3" - resolved "https://registry.yarnpkg.com/@douyinfe/semi-animation/-/semi-animation-2.39.3.tgz#d8c21be360431b48a8ea8856920cf4d534e68c93" - integrity sha512-KI8O8mvuZiZPNwiK+OUSO/DjPcXLs7sdopPdN3g9WSR7ipPJKmorOZzAG2OTUDH0b4diQYd8gs/YIiFfU+UoOw== - dependencies: - bezier-easing "^2.1.0" - "@douyinfe/semi-foundation@2.33.1": version "2.33.1" resolved "https://registry.npmjs.org/@douyinfe/semi-foundation/-/semi-foundation-2.33.1.tgz#1dfe6233e35a4ed768cb580b0c9a677d1c34ffba" @@ -1543,20 +1522,6 @@ memoize-one "^5.2.1" scroll-into-view-if-needed "^2.2.24" -"@douyinfe/semi-foundation@2.39.3": - version "2.39.3" - resolved "https://registry.yarnpkg.com/@douyinfe/semi-foundation/-/semi-foundation-2.39.3.tgz#6490340494d8ea40981c41123b02fd4ab64cbe2c" - integrity sha512-yTjJYd4BiTdbxt0tCLPJCe3IDCdOEuMjaslDU2TLE3oVs5aTfEcnS2HjioSFgsLPSqEgk8jCdwQDD7eaf+pruA== - dependencies: - "@douyinfe/semi-animation" "2.39.3" - 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/semi-icons@2.33.1", "@douyinfe/semi-icons@latest": version "2.33.1" resolved "https://registry.yarnpkg.com/@douyinfe/semi-icons/-/semi-icons-2.33.1.tgz#8e2871d9bc0ab7e12df74e3c71802d53d69b7425" @@ -1564,23 +1529,11 @@ dependencies: classnames "^2.2.6" -"@douyinfe/semi-icons@2.39.3", "@douyinfe/semi-icons@^2.0.0": - version "2.39.3" - resolved "https://registry.yarnpkg.com/@douyinfe/semi-icons/-/semi-icons-2.39.3.tgz#0e21bbcdd3705b8f1570935b0096ee3847bed34f" - integrity sha512-l/Wq0ytYecSO1AbNIuLgDdlJfi1nOMLm5aZoPCJRLU6qRASPjQhpgV1inf050FlVFVfK1ocIiyOyjkTP9sEpNg== - dependencies: - classnames "^2.2.6" - "@douyinfe/semi-illustrations@2.33.1": 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/semi-illustrations@2.39.3": - version "2.39.3" - resolved "https://registry.yarnpkg.com/@douyinfe/semi-illustrations/-/semi-illustrations-2.39.3.tgz#1a0d7bd523e16244efa08004ad6169994cd13bf2" - integrity sha512-/bZNcAMRKk4cigH+ltAmTIxltR8aWrsiVUXdvBkf0txzv/NSXMRFNGehE3JFxiw728iE5P6B6AbJdDi64dKYqA== - "@douyinfe/semi-scss-compile@2.23.2": version "2.23.2" resolved "https://registry.npmjs.org/@douyinfe/semi-scss-compile/-/semi-scss-compile-2.23.2.tgz#30884bb194ee9ae1e81877985e5663c3297c1ced" @@ -1654,38 +1607,6 @@ dependencies: glob "^7.1.6" -"@douyinfe/semi-theme-default@2.39.3": - version "2.39.3" - resolved "https://registry.yarnpkg.com/@douyinfe/semi-theme-default/-/semi-theme-default-2.39.3.tgz#a02a5b20890587c674eb7c3b2550551f42b933a0" - integrity sha512-dTTD8nkzM0ad1Lli9cFYLqvmTsSvKp5NSIc35UQBZcvi7OvmUA7qaSMentEMgl15bVWKInwCvp+mSFJsDtDPlg== - dependencies: - glob "^7.1.6" - -"@douyinfe/semi-ui@^2.0.0": - version "2.39.3" - resolved "https://registry.yarnpkg.com/@douyinfe/semi-ui/-/semi-ui-2.39.3.tgz#081297781163882882e501686c76356804bd9555" - integrity sha512-xrQ9Xd1B4vhDK41RjN4AFxDD/ILuR9HTctJZ0Be+mio8xIifINtD2jD5xXB1pV+DE/43jtu30VzNlvLm/0TQbw== - dependencies: - "@douyinfe/semi-animation" "2.39.3" - "@douyinfe/semi-animation-react" "2.39.3" - "@douyinfe/semi-foundation" "2.39.3" - "@douyinfe/semi-icons" "2.39.3" - "@douyinfe/semi-illustrations" "2.39.3" - "@douyinfe/semi-theme-default" "2.39.3" - 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 "^1.8.0" - react-sortable-hoc "^2.0.0" - react-window "^1.8.2" - resize-observer-polyfill "^1.5.1" - scroll-into-view-if-needed "^2.2.24" - utility-types "^3.10.0" - "@douyinfe/semi-ui@latest": version "2.33.1" resolved "https://registry.yarnpkg.com/@douyinfe/semi-ui/-/semi-ui-2.33.1.tgz#3234ca96eb3560b8299bc9750fbe59446522d9bb" @@ -11253,11 +11174,6 @@ 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.39.3" - resolved "https://registry.yarnpkg.com/eslint-plugin-semi-design/-/eslint-plugin-semi-design-2.39.3.tgz#ceab48928648acd0fef41ea5ef97b17268aec70b" - integrity sha512-9oX8xdmLR9IZPZ4JpMd/1V+e2ebQ7gcqax2kgzl0ICY0iWvb40WrF+tvnkI92OVlD7OLqMlxv//Q83vkKoZ2fA== - 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" From b6c1d3ca0854cd2530b1c5aa3ecbb8036c6cf6a9 Mon Sep 17 00:00:00 2001 From: linyan Date: Wed, 2 Aug 2023 16:21:17 +0800 Subject: [PATCH 02/29] fix: add calc scrollBarWidth logic into sidesheet open --- packages/semi-ui/sideSheet/index.tsx | 26 ++++++++++++++++++++++---- src/styles/content.scss | 5 ----- src/styles/index.scss | 4 ---- 3 files changed, 22 insertions(+), 13 deletions(-) diff --git a/packages/semi-ui/sideSheet/index.tsx b/packages/semi-ui/sideSheet/index.tsx index feeeb432b4..3e5293a978 100644 --- a/packages/semi-ui/sideSheet/index.tsx +++ b/packages/semi-ui/sideSheet/index.tsx @@ -87,23 +87,32 @@ export default class SideSheet extends BaseComponent { const { getPopupContainer } = this.props; - if (!getPopupContainer && document) { + this.bodyOverflow = document.body.style.overflow || ''; + if (!getPopupContainer && this.bodyOverflow !== 'hidden') { document.body.style.overflow = 'hidden'; + document.body.style.width = `calc(${this.originBodyWidth || '100%'} - ${this.scrollBarWidth}px)`; } }, enabledBodyScroll: () => { const { getPopupContainer } = this.props; - if (!getPopupContainer && document) { - document.body.style.overflow = ''; + if (!getPopupContainer && this.bodyOverflow !== 'hidden') { + document.body.style.overflow = this.bodyOverflow; + document.body.style.width = this.originBodyWidth; } }, notifyCancel: (e: React.MouseEvent | React.KeyboardEvent) => { @@ -143,7 +152,16 @@ export default class SideSheet extends BaseComponent Date: Wed, 2 Aug 2023 18:26:08 +0800 Subject: [PATCH 03/29] feat: slider add on MouseUp --- content/input/slider/index-en-US.md | 15 +++--- content/input/slider/index.md | 47 ++++++++++--------- packages/semi-foundation/slider/foundation.ts | 1 + packages/semi-ui/slider/index.tsx | 2 + 4 files changed, 35 insertions(+), 30 deletions(-) diff --git a/content/input/slider/index-en-US.md b/content/input/slider/index-en-US.md index db2e19fe42..3c98d6cdce 100644 --- a/content/input/slider/index-en-US.md +++ b/content/input/slider/index-en-US.md @@ -241,17 +241,17 @@ import { Slider } from '@douyinfe/semi-ui'; ## 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 |-|-| +| -------------- |-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| ------------- |---------|------ | +| 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 |- | | 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 | - |- | | 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| +| railStyle | Style for slide rail | CSSProperties | - |0.31.0| | range | Toggle whether it is allow to move slider from both sides | boolean | false |- | | showBoundary | Toggle whether show max/min value when hover | boolean | false |- | | step | Increment between successive values | number | 1 |- | @@ -259,10 +259,11 @@ import { Slider } from '@douyinfe/semi-ui'; | 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 |-| +| 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 | - |- | -| 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 |-|-| +| onMouseUp | Trigged when mouse up on handle | (e: React.MouseEvent) => 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 diff --git a/content/input/slider/index.md b/content/input/slider/index.md index 543dd76a3f..b8a17d6e7e 100644 --- a/content/input/slider/index.md +++ b/content/input/slider/index.md @@ -227,29 +227,30 @@ import { Slider } from '@douyinfe/semi-ui'; ``` ## 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 |-| -| included | `marks` 不为空对象时有效,值为 true 时表示值为包含关系,false 表示并列 | boolean | true |-| -| marks | 刻度,key 的类型必须为 `number` 且取值在闭区间 \[min, max] 内 | Record | 无 |-| -| max | 最大值 | number | 100 |-| -| min | 最小值 | number | 0 |-| -| railStyle | 滑块轨道的样式 | CSSProperties | - |0.31.0| -| range | 是否支持两边同时可滑动 | boolean | false |-| -| showBoundary | 是否在 hover 时展示最大值最小值 | boolean | false |-| -| step | 步长 | number | 1 |-| -| tipFormatter | 设置Tooltip的展示格式,默认显示当前选值 | (value: string \| number \| boolean \| (string \| number \| boolean)[]) => any | v => v |-| -| 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 | 无 |-| -| getAriaValueText | 用于给滑块的当前值提供一个用户友好的名称,对屏幕阅读器用户很重要,参数value为当前滑块的值,index为当前滑块的顺序 | (value: number, index?: number) => string |-|-| +| 属性 | 说明 | 类型 | 默认值 | 版本 | +|-------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------|--------|--------| +| 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 | - | +| included | `marks` 不为空对象时有效,值为 true 时表示值为包含关系,false 表示并列 | boolean | true | - | +| marks | 刻度,key 的类型必须为 `number` 且取值在闭区间 \[min, max] 内 | Record | 无 | - | +| max | 最大值 | number | 100 | - | +| min | 最小值 | number | 0 | - | +| railStyle | 滑块轨道的样式 | CSSProperties | - | 0.31.0 | +| range | 是否支持两边同时可滑动 | boolean | false | - | +| showBoundary | 是否在 hover 时展示最大值最小值 | boolean | false | - | +| step | 步长 | number | 1 | - | +| tipFormatter | 设置Tooltip的展示格式,默认显示当前选值 | (value: string \| number \| boolean \| (string \| number \| boolean)[]) => any | v => v | - | +| 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 | 鼠标松开 handle 时触发 | (e: React.MouseEvent) => void | 无 | 2.41.0 | +| getAriaValueText | 用于给滑块的当前值提供一个用户友好的名称,对屏幕阅读器用户很重要,参数value为当前滑块的值,index为当前滑块的顺序 | (value: number, index?: number) => string |-| - | ## Accessibility diff --git a/packages/semi-foundation/slider/foundation.ts b/packages/semi-foundation/slider/foundation.ts index 33449d3314..64d4c4b45c 100644 --- a/packages/semi-foundation/slider/foundation.ts +++ b/packages/semi-foundation/slider/foundation.ts @@ -23,6 +23,7 @@ export interface SliderProps{ vertical?: boolean; onAfterChange?: (value: SliderProps['value']) => void; // triggered when mouse up and clicked onChange?: (value: SliderProps['value']) => void; + onMouseUp?: (e: any) => void; tooltipVisible?: boolean; style?: Record; className?: string; diff --git a/packages/semi-ui/slider/index.tsx b/packages/semi-ui/slider/index.tsx index 82d06e7230..012d97e57b 100644 --- a/packages/semi-ui/slider/index.tsx +++ b/packages/semi-ui/slider/index.tsx @@ -43,6 +43,7 @@ export default class Slider extends BaseComponent { vertical: PropTypes.bool, onAfterChange: PropTypes.func, // OnmouseUp and triggered when clicked onChange: PropTypes.func, + onMouseUp: PropTypes.func, tooltipVisible: PropTypes.bool, style: PropTypes.object, className: PropTypes.string, @@ -240,6 +241,7 @@ export default class Slider extends BaseComponent { this.setState({ focusPos: '' }); }, onHandleUpBefore: (e: React.MouseEvent) => { + this.props.onMouseUp?.(e); e.stopPropagation(); e.preventDefault(); document.body.removeEventListener('mousemove', this.foundation.onHandleMove, false); From 144c04fbe76307201d64f585ea0e5d45fc1a4031 Mon Sep 17 00:00:00 2001 From: linyan Date: Fri, 4 Aug 2023 11:09:36 +0800 Subject: [PATCH 04/29] fix: preserve the scroll bar width for the aesthetics of the windows system --- src/styles/content.scss | 5 +++++ src/styles/index.scss | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/src/styles/content.scss b/src/styles/content.scss index 9a0516a28c..4fa666a04f 100644 --- a/src/styles/content.scss +++ b/src/styles/content.scss @@ -112,6 +112,11 @@ .light-scrollbar { + // light scrollbar + &::-webkit-scrollbar { + width: 8px; + height: 8px; + } &::-webkit-scrollbar-track { background: rgba(0, 0, 0, 0); diff --git a/src/styles/index.scss b/src/styles/index.scss index 3093290439..bf4025e88f 100644 --- a/src/styles/index.scss +++ b/src/styles/index.scss @@ -20,6 +20,10 @@ body { margin: 0; background: var(--semi-color-bg-0); + &::-webkit-scrollbar { + width: 8px; + height: 8px; + } &::-webkit-scrollbar-track { background: rgba(0, 0, 0, 0); From 9b82b7e001b8d245e89601af3b10fcffa9f7561f Mon Sep 17 00:00:00 2001 From: SyMind Date: Sat, 5 Aug 2023 17:11:42 +0800 Subject: [PATCH 05/29] chore: eslint fix --- .../semi-foundation/carousel/foundation.ts | 13 +++-- .../dropdown/menuFoundation.ts | 6 +-- .../image/previewFoundation.ts | 2 +- .../modal/modalContentFoundation.ts | 6 +-- .../sideSheet/sideSheetFoundation.ts | 4 +- packages/semi-foundation/tabs/foundation.ts | 4 +- packages/semi-foundation/utils/a11y.ts | 12 ++--- packages/semi-icons/webpack.config.js | 2 +- packages/semi-illustrations/webpack.config.js | 2 +- packages/semi-ui/carousel/interface.ts | 2 +- packages/semi-ui/datePicker/quickControl.tsx | 2 +- .../_story/DynamicField/nestArrayField.jsx | 7 +-- packages/semi-ui/layout/Sider.tsx | 2 +- packages/semi-ui/slider/_story/Demo.tsx | 2 +- packages/semi-ui/typography/numeral.tsx | 2 +- src/components/ComponentOverview/index.jsx | 2 +- src/components/DesignPageAnchor/index.jsx | 4 +- src/components/DesignToken/index.tsx | 22 ++++----- src/components/IconList/IconCategory.jsx | 4 +- src/components/example.js | 6 +-- src/components/header.js | 2 +- src/pages/en-US/index.js | 4 +- src/pages/zh-CN/index.js | 4 +- .../theme/components/topBar/index.jsx | 2 +- .../components/theme/cutsomCssVariable.js | 2 +- src/sitePages/newHome/utils/compileScss.js | 48 +++++++++---------- .../newHome/utils/componentsScssContent.js | 30 ++++++------ .../newHome/utils/loadSassCompiler.js | 12 ++--- .../newHome/utils/themeDefaultScssContent.js | 10 ++-- src/templates/toUEDUtils/toUED.ts | 48 +++++++++---------- 30 files changed, 132 insertions(+), 136 deletions(-) diff --git a/packages/semi-foundation/carousel/foundation.ts b/packages/semi-foundation/carousel/foundation.ts index 37bc641965..544afb483d 100644 --- a/packages/semi-foundation/carousel/foundation.ts +++ b/packages/semi-foundation/carousel/foundation.ts @@ -1,7 +1,6 @@ import { isObject, get } from 'lodash'; import BaseFoundation, { DefaultAdapter } from '../base/foundation'; import { numbers } from './constants'; -import { throttle } from 'lodash'; export interface CarouselAdapter

, S = Record> extends DefaultAdapter { notifyChange: (activeIndex: number, preIndex: number) => void; @@ -34,7 +33,7 @@ class CarouselFoundation

, S = Record> exten } stop(): void { - if (this._interval){ + if (this._interval) { clearInterval(this._interval); } } @@ -93,7 +92,7 @@ class CarouselFoundation

, S = Record> exten _notifyChange(activeIndex: number): void { const { activeIndex: stateActiveIndex, isInit } = this.getStates(); - if (isInit){ + if (isInit) { this._adapter.setIsInit(false); } if (stateActiveIndex !== activeIndex) { @@ -110,10 +109,10 @@ class CarouselFoundation

, S = Record> exten getSwitchingTime(): number { const { autoPlay, speed } = this.getProps(); const autoPlayType = typeof autoPlay; - if (autoPlayType === 'boolean'){ + if (autoPlayType === 'boolean') { return numbers.DEFAULT_INTERVAL + speed; } - if (isObject(autoPlay)){ + if (isObject(autoPlay)) { return get(autoPlay, 'interval', numbers.DEFAULT_INTERVAL) + speed; } return speed; @@ -127,12 +126,12 @@ class CarouselFoundation

, S = Record> exten const { autoPlay } = this.getProps(); const autoPlayType = typeof autoPlay; // when user manually call the play function, force play - if ((autoPlayType === 'boolean' && autoPlay) || isObject(autoPlay) || this._forcePlay){ + if ((autoPlayType === 'boolean' && autoPlay) || isObject(autoPlay) || this._forcePlay) { this.play(this.getSwitchingTime()); } } - handleKeyDown(event: any): void{ + handleKeyDown(event: any): void { if (event.key === 'ArrowLeft') { this.prev(); } diff --git a/packages/semi-foundation/dropdown/menuFoundation.ts b/packages/semi-foundation/dropdown/menuFoundation.ts index 80fef8a46d..3515081d87 100644 --- a/packages/semi-foundation/dropdown/menuFoundation.ts +++ b/packages/semi-foundation/dropdown/menuFoundation.ts @@ -8,7 +8,7 @@ export default class DropdownMenuFoundation extends BaseFoundation item.ariaDisabled !== "true"); } - if (this.firstChars.length === 0){ + if (this.firstChars.length === 0) { this.menuItemNodes.forEach((item: Element) => { // the menuItemNodes can be an component and not exit textContent this.firstChars.push(item.textContent.trim()[0]?.toLowerCase()); diff --git a/packages/semi-foundation/image/previewFoundation.ts b/packages/semi-foundation/image/previewFoundation.ts index 6d8e165e7f..454e8e293c 100644 --- a/packages/semi-foundation/image/previewFoundation.ts +++ b/packages/semi-foundation/image/previewFoundation.ts @@ -2,7 +2,7 @@ import BaseFoundation, { DefaultAdapter } from "../base/foundation"; export default class PreviewFoundation

, S = Record> extends BaseFoundation> { - handleVisibleChange = (newVisible : boolean) => { + handleVisibleChange = (newVisible: boolean) => { const { visible, onVisibleChange } = this.getProps(); if (!(visible in this.getProps())) { this.setState({ diff --git a/packages/semi-foundation/modal/modalContentFoundation.ts b/packages/semi-foundation/modal/modalContentFoundation.ts index 3977caa12e..744e46f660 100644 --- a/packages/semi-foundation/modal/modalContentFoundation.ts +++ b/packages/semi-foundation/modal/modalContentFoundation.ts @@ -8,9 +8,9 @@ export interface ModalContentProps extends ModalProps { isFullScreen?: boolean; contentClassName?: string; maskClassName?: string; - onAnimationEnd?: (e:any) => void; - maskExtraProps?:Record; - contentExtraProps?:Record + onAnimationEnd?: (e: any) => void; + maskExtraProps?: Record; + contentExtraProps?: Record } export interface ModalContentState { diff --git a/packages/semi-foundation/sideSheet/sideSheetFoundation.ts b/packages/semi-foundation/sideSheet/sideSheetFoundation.ts index c502df0df1..208899bf5a 100644 --- a/packages/semi-foundation/sideSheet/sideSheetFoundation.ts +++ b/packages/semi-foundation/sideSheet/sideSheetFoundation.ts @@ -1,5 +1,5 @@ import BaseFoundation, { DefaultAdapter } from '../base/foundation'; -import { get, noop } from 'lodash'; +import { noop } from 'lodash'; import KeyCode from '../utils/keyCode'; @@ -95,7 +95,7 @@ export default class SideSheetFoundation extends BaseFoundation{ + toggleDisplayNone = (displayNone: boolean)=>{ this._adapter.toggleDisplayNone(displayNone); } diff --git a/packages/semi-foundation/tabs/foundation.ts b/packages/semi-foundation/tabs/foundation.ts index a3d8d6b04d..010ab4e9bf 100644 --- a/packages/semi-foundation/tabs/foundation.ts +++ b/packages/semi-foundation/tabs/foundation.ts @@ -128,14 +128,14 @@ class TabsFoundation

, S = Record> extends B } } - handleDeleteKeyDown(event:any, tabs: HTMLElement[], itemKey: string, closable: boolean): void { + handleDeleteKeyDown(event: any, tabs: HTMLElement[], itemKey: string, closable: boolean): void { const { preventScroll } = this.getProps(); if (closable) { this.handleTabDelete(itemKey); const index = tabs.indexOf(event.target); // Move focus to next element after deletion // If the element is the last removable tab, focus to its previous tab - if (tabs.length !== 1 ){ + if (tabs.length !== 1 ) { tabs[index + 1 >= tabs.length ? index - 1 : index + 1].focus({ preventScroll }); } } diff --git a/packages/semi-foundation/utils/a11y.ts b/packages/semi-foundation/utils/a11y.ts index 22491ac2a3..5b6081ee1b 100644 --- a/packages/semi-foundation/utils/a11y.ts +++ b/packages/semi-foundation/utils/a11y.ts @@ -35,7 +35,7 @@ export function setFocusToLastItem(itemNodes: HTMLElement[]): void { export function setFocusToPreviousMenuItem (itemNodes: HTMLElement[], currentItem: HTMLElement): void { let newMenuItem: HTMLElement, index: number; - if (itemNodes.length > 0){ + if (itemNodes.length > 0) { if (currentItem === itemNodes[0]) { newMenuItem = itemNodes[itemNodes.length-1]; } else { @@ -50,7 +50,7 @@ export function setFocusToPreviousMenuItem (itemNodes: HTMLElement[], currentIte export function setFocusToNextMenuitem (itemNodes: HTMLElement[], currentItem: HTMLElement): void { let newMenuItem: HTMLElement, index: number; - if (itemNodes.length > 0){ + if (itemNodes.length > 0) { if (currentItem === itemNodes[itemNodes.length-1]) { newMenuItem = itemNodes[0]; } else { @@ -91,17 +91,17 @@ export function getAncestorNodeByRole(curElement: Element, role: string): Elemen if (!curElement) { return null; } - while (curElement.parentElement && get(curElement.parentElement, 'attributes.role.value', '') !== role){ + while (curElement.parentElement && get(curElement.parentElement, 'attributes.role.value', '') !== role) { curElement = curElement.parentElement; } return curElement.parentElement; } // According to the Id, find the corresponding data-popupid element -export function getMenuButton(focusableEle: NodeListOf, Id: string): HTMLElement{ - for (let i = 0; i < focusableEle.length; i++){ +export function getMenuButton(focusableEle: NodeListOf, Id: string): HTMLElement { + for (let i = 0; i < focusableEle.length; i++) { const curAriDescribedby = focusableEle[i].attributes['data-popupid']; - if (curAriDescribedby && curAriDescribedby.value === Id){ + if (curAriDescribedby && curAriDescribedby.value === Id) { return focusableEle[i]; } } diff --git a/packages/semi-icons/webpack.config.js b/packages/semi-icons/webpack.config.js index 3e2622bf2c..a143713759 100644 --- a/packages/semi-icons/webpack.config.js +++ b/packages/semi-icons/webpack.config.js @@ -4,7 +4,7 @@ const TerserPlugin = require('terser-webpack-plugin'); const MiniCssExtractPlugin = require("mini-css-extract-plugin"); const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin'); -module.exports = function getWebpackConfig({ minimize }){ +module.exports = function getWebpackConfig({ minimize }) { return { mode: 'production', bail: true, diff --git a/packages/semi-illustrations/webpack.config.js b/packages/semi-illustrations/webpack.config.js index acf59af175..f6fe274167 100644 --- a/packages/semi-illustrations/webpack.config.js +++ b/packages/semi-illustrations/webpack.config.js @@ -3,7 +3,7 @@ const webpack = require('webpack'); const TerserPlugin = require('terser-webpack-plugin'); const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin'); -module.exports = function getWebpackConfig({ minimize }){ +module.exports = function getWebpackConfig({ minimize }) { return { mode: 'production', bail: true, diff --git a/packages/semi-ui/carousel/interface.ts b/packages/semi-ui/carousel/interface.ts index ae2fcb3ed9..14224f3e27 100644 --- a/packages/semi-ui/carousel/interface.ts +++ b/packages/semi-ui/carousel/interface.ts @@ -37,7 +37,7 @@ export interface CarouselIndicatorProps { defaultActiveIndex?: number; position?: typeof strings.POSITION_MAP[number]; size?: typeof strings.SIZE[number]; - total?:number; + total?: number; theme?: typeof strings.THEME_MAP[number]; type?: typeof strings.TYPE_MAP[number]; onIndicatorChange?: (activeIndex: number) => void; diff --git a/packages/semi-ui/datePicker/quickControl.tsx b/packages/semi-ui/datePicker/quickControl.tsx index 361206de95..979b7be9d4 100644 --- a/packages/semi-ui/datePicker/quickControl.tsx +++ b/packages/semi-ui/datePicker/quickControl.tsx @@ -17,7 +17,7 @@ export interface QuickControlProps { presetPosition: typeof strings.PRESET_POSITION_SET[number]; onPresetClick: (preset: PresetType, e: React.MouseEvent) => void; type: string; - insetInput: DateInputFoundationProps['insetInput'] + insetInput: DateInputFoundationProps['insetInput']; locale: any } diff --git a/packages/semi-ui/form/_story/DynamicField/nestArrayField.jsx b/packages/semi-ui/form/_story/DynamicField/nestArrayField.jsx index 49d84f8b1e..26a00890fd 100644 --- a/packages/semi-ui/form/_story/DynamicField/nestArrayField.jsx +++ b/packages/semi-ui/form/_story/DynamicField/nestArrayField.jsx @@ -10,9 +10,6 @@ import { Button, Modal, TreeSelect, Row, Col, Avatar, Select as BasicSelect, withFormApi, withField, ArrayField, - AutoComplete, - Collapse, - Icon, } from '../../../index'; import { format } from 'date-fns'; import { ComponentUsingFormState } from '../Hook/hookDemo'; @@ -120,7 +117,7 @@ class NestArrayField extends React.Component { class Child extends React.Component { - constructor(props){ + constructor(props) { super(props); this.state = { ts: format(new Date(), 'yyyy-MM-dd HH:mm:ss') @@ -134,7 +131,7 @@ class Child extends React.Component { } class Parent extends React.Component { - constructor(props){ + constructor(props) { super(props); this.click = this.click.bind(this); } diff --git a/packages/semi-ui/layout/Sider.tsx b/packages/semi-ui/layout/Sider.tsx index 653f5e1aa1..7e55bd0fb5 100644 --- a/packages/semi-ui/layout/Sider.tsx +++ b/packages/semi-ui/layout/Sider.tsx @@ -42,7 +42,7 @@ export interface SiderProps { breakpoint?: Array; onBreakpoint?: (screen: keyof ResponsiveMap, match: boolean) => void; 'aria-label'?: React.AriaAttributes['aria-label']; - 'role'?:React.AriaRole + 'role'?: React.AriaRole } class Sider extends React.PureComponent { diff --git a/packages/semi-ui/slider/_story/Demo.tsx b/packages/semi-ui/slider/_story/Demo.tsx index c2dc513a42..7bfd6d50e6 100644 --- a/packages/semi-ui/slider/_story/Demo.tsx +++ b/packages/semi-ui/slider/_story/Demo.tsx @@ -7,7 +7,7 @@ const Demo = () => {

tipFormatter
- `=====${val}=====` }> + `=====${val}=====` }>


diff --git a/packages/semi-ui/typography/numeral.tsx b/packages/semi-ui/typography/numeral.tsx index e3ed83e9de..cafc051fa0 100644 --- a/packages/semi-ui/typography/numeral.tsx +++ b/packages/semi-ui/typography/numeral.tsx @@ -33,7 +33,7 @@ export interface NumeralProps extends Omit strong?: boolean; style?: React.CSSProperties; type?: TypographyBaseType; - underline?: boolean; + underline?: boolean } export default class Numeral extends PureComponent { diff --git a/src/components/ComponentOverview/index.jsx b/src/components/ComponentOverview/index.jsx index 5a7ba5ec4e..4c0d5190aa 100644 --- a/src/components/ComponentOverview/index.jsx +++ b/src/components/ComponentOverview/index.jsx @@ -4,7 +4,7 @@ import Card from './card'; const ComponentList = props => { const list = props.code.split(','); return ( -
+
{list.map((item, index) => ( ))} diff --git a/src/components/DesignPageAnchor/index.jsx b/src/components/DesignPageAnchor/index.jsx index 4674784ef6..4e295dd063 100644 --- a/src/components/DesignPageAnchor/index.jsx +++ b/src/components/DesignPageAnchor/index.jsx @@ -34,7 +34,7 @@ const PageAnchor = props => { {getAnchorLink(item.items, currentLayer + 1)} - + ; } else { return { @@ -45,7 +45,7 @@ const PageAnchor = props => { dom?.scrollIntoView(); }}> - + ; } } ); diff --git a/src/components/DesignToken/index.tsx b/src/components/DesignToken/index.tsx index 26861f3b96..f3d96d09b5 100644 --- a/src/components/DesignToken/index.tsx +++ b/src/components/DesignToken/index.tsx @@ -15,7 +15,7 @@ interface Token { key: string; value: string; category: string; - raw: string; + raw: string } interface DesignToken { @@ -24,22 +24,22 @@ interface DesignToken { global: { global: { light: Token[]; - dark: Token[]; + dark: Token[] }; palette: { light: Token[]; - dark: Token[]; + dark: Token[] }; normal: Token[]; - animation: Token[]; + animation: Token[] }; - [key: string]: Token[]; + [key: string]: Token[] } interface TokenMayWithColor extends Token { - color?: string; + color?: string } @@ -59,7 +59,7 @@ const JumpLink = ({ value, availableKeySet }: { value: string; availableKeySet: } }; -const TokenTable = ({ tokenList, designToken, currentTab, mode = 'light' }: { mode?: 'light' | 'dark', tokenList: TokenMayWithColor[]; designToken: DesignToken; currentTab?: string; }): React.ReactElement => { +const TokenTable = ({ tokenList, designToken, currentTab, mode = 'light' }: { mode?: 'light' | 'dark'; tokenList: TokenMayWithColor[]; designToken: DesignToken; currentTab?: string }): React.ReactElement => { const intl = useIntl(); const globalTokenJumpAvailableSet = useMemo(() => { const global = designToken?.global; @@ -169,7 +169,7 @@ const GlobalAnimationToken = ({ designToken }: { designToken: DesignToken }) => animationList.forEach(token => { const tab = token['key'].match(/--semi-transition_([\w\W]+)-/)?.[1] ?? "other"; tokenMap[tab] = [...(tokenMap[tab] ?? []), token]; - }) + }); return tokenMap; }, [animationList]); @@ -180,15 +180,15 @@ const GlobalAnimationToken = ({ designToken }: { designToken: DesignToken }) => {Object.entries(tokenMap).map(([category, tokenList]) => { return - + ; })} - + ; -} +}; const DesignToken = (props: Props): React.ReactElement => { diff --git a/src/components/IconList/IconCategory.jsx b/src/components/IconList/IconCategory.jsx index c1f28f7323..e24c98dcfd 100644 --- a/src/components/IconList/IconCategory.jsx +++ b/src/components/IconList/IconCategory.jsx @@ -16,13 +16,13 @@ const IconCategory = props => { const handleToggle = (i) => { $categorySet((c)=>{ - if(c.has(i)){ + if (c.has(i)) { c.delete(i); } else { c.add(i); } return new Set(Array.from(c)); - }) + }); }; return groups.map((g, i) => (
diff --git a/src/components/example.js b/src/components/example.js index 3f35c200dd..ae76aa7a4a 100644 --- a/src/components/example.js +++ b/src/components/example.js @@ -1,7 +1,7 @@ -import React from 'react' +import React from 'react'; const ExampleContainer = ({ children }) => { return
{ children }
; -} +}; -export default ExampleContainer \ No newline at end of file +export default ExampleContainer; \ No newline at end of file diff --git a/src/components/header.js b/src/components/header.js index b7c2ddf050..d1304dca0c 100644 --- a/src/components/header.js +++ b/src/components/header.js @@ -12,7 +12,7 @@ const Header = ({ location, localeCode, style }) => ( const iframeDOM=document.querySelector('iframe'); try { iframeDOM?.contentWindow?.semidoc?.setDarkmode(mode==='dark'); - } catch (e){ + } catch (e) { } }} diff --git a/src/pages/en-US/index.js b/src/pages/en-US/index.js index 75276405c8..8c8d427956 100644 --- a/src/pages/en-US/index.js +++ b/src/pages/en-US/index.js @@ -14,8 +14,8 @@ const IndexPage = ({ location }) => { useEffect(() => { setTimeout(()=>{ window?.__semi__?.Tea?.userVisited(); - window?.__semi__?.Tea?.eventHappened("refer",document?.referrer ?? 'empty'); - },3000); + window?.__semi__?.Tea?.eventHappened("refer", document?.referrer ?? 'empty'); + }, 3000); }, []); diff --git a/src/pages/zh-CN/index.js b/src/pages/zh-CN/index.js index ceded6a193..967c63cbd9 100644 --- a/src/pages/zh-CN/index.js +++ b/src/pages/zh-CN/index.js @@ -7,8 +7,8 @@ const IndexPage = ({ location }) => { useEffect(() => { setTimeout(()=>{ window?.__semi__?.Tea?.userVisited(); - window?.__semi__?.Tea?.eventHappened("refer",document?.referrer ?? 'empty'); - },3000); + window?.__semi__?.Tea?.eventHappened("refer", document?.referrer ?? 'empty'); + }, 3000); }, []); return ( diff --git a/src/sitePages/newHome/components/theme/components/topBar/index.jsx b/src/sitePages/newHome/components/theme/components/topBar/index.jsx index b55171ceaf..31ce5a1725 100644 --- a/src/sitePages/newHome/components/theme/components/topBar/index.jsx +++ b/src/sitePages/newHome/components/theme/components/topBar/index.jsx @@ -1,5 +1,5 @@ import React from 'react'; -import styles from './index.module.scss' +import styles from './index.module.scss'; function TopBar() { return ( diff --git a/src/sitePages/newHome/components/theme/cutsomCssVariable.js b/src/sitePages/newHome/components/theme/cutsomCssVariable.js index 1a13006ce2..ca8dd59650 100644 --- a/src/sitePages/newHome/components/theme/cutsomCssVariable.js +++ b/src/sitePages/newHome/components/theme/cutsomCssVariable.js @@ -38,5 +38,5 @@ export const customCssVariables = { 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'Helvetica Neue', Helvetica, Arial, sans-serif` } -} +}; diff --git a/src/sitePages/newHome/utils/compileScss.js b/src/sitePages/newHome/utils/compileScss.js index 8fea95aed4..1b599e81a3 100644 --- a/src/sitePages/newHome/utils/compileScss.js +++ b/src/sitePages/newHome/utils/compileScss.js @@ -1,30 +1,30 @@ import loadSassCompiler from "./loadSassCompiler"; -import {themeScssContent} from './themeDefaultScssContent' +import { themeScssContent } from './themeDefaultScssContent'; import { componentsScssContent } from "./componentsScssContent"; export async function compile(customVariables) { if (!customVariables) { - return '' + return ''; } - const compiler = await loadSassCompiler() + const compiler = await loadSassCompiler(); - const customVariablesString = Object.entries(customVariables).reduce((acc, cur) => { + const customVariablesString = Object.entries(customVariables).reduce((acc, cur) => { const [key, value] = cur; - acc += `${key}: ${value};\n` + acc += `${key}: ${value};\n`; return acc; - }, '') + }, ''); await compiler.writeFilePromisify({ 'custom.scss': customVariablesString, - }) + }); - const modifiedComponentScssFiles = insertCustomVariables('../custom.scss') + const modifiedComponentScssFiles = insertCustomVariables('../custom.scss'); await compiler.writeFilePromisify({ ...themeScssContent, ...componentsScssContent, ...modifiedComponentScssFiles - }) + }); return new Promise(resolve => { // hack sass.js write file bug @@ -32,20 +32,20 @@ export async function compile(customVariables) { const componentScssEntry = Object.keys(componentsScssContent).filter(path => path.includes('index.scss')); const entryString = componentScssEntry.reduce((acc, path) => { - acc += `@import '${path}';` + acc += `@import '${path}';`; return acc; - }, '') + }, ''); compiler.compile(`@import 'theme/index.scss';${entryString}`, (res) => { if (res.status === 0) { - console.log(res) + console.log(res); resolve(res.text); } else { console.dir(res); resolve(""); } - }) - }) + }); + }); }).finally(() => { compiler.clearFiles(); }); @@ -67,7 +67,7 @@ function insertCustomVariablesTo(source, customVariablesPath) { fileStr = fileSplit.join(''); } } catch (error) {} - return fileStr + return fileStr; } export function insertCustomVariables(customVariablesPath) { @@ -76,13 +76,13 @@ export function insertCustomVariables(customVariablesPath) { const modifiedFiles = componentScssEntry.reduce((acc, cur) => { const content = componentsScssContent[cur]; - const newContent = insertCustomVariablesTo(content, customVariablesPath) - acc[cur] = newContent + const newContent = insertCustomVariablesTo(content, customVariablesPath); + acc[cur] = newContent; return acc; - }, {}) + }, {}); - const themeVariableContent = themeScssContent['theme/variables.scss'] - const newThemeVariableContent = themeVariableContent + `\n@import "${customVariablesPath}";` + const themeVariableContent = themeScssContent['theme/variables.scss']; + const newThemeVariableContent = themeVariableContent + `\n@import "${customVariablesPath}";`; return { ...modifiedFiles, @@ -91,16 +91,16 @@ export function insertCustomVariables(customVariablesPath) { } export function insertStyleToDocument(css) { - let styleEle = document.querySelector('#customStyle') + let styleEle = document.querySelector('#customStyle'); if (!styleEle) { styleEle = document.createElement("style"); styleEle.setAttribute('id', 'customStyle'); document.head.appendChild(styleEle); } - styleEle.textContent = `${css}` + styleEle.textContent = `${css}`; } export function removeStyleFromDocument() { - let styleEle = document.querySelector('#customStyle') - styleEle && styleEle.remove() + let styleEle = document.querySelector('#customStyle'); + styleEle && styleEle.remove(); } \ No newline at end of file diff --git a/src/sitePages/newHome/utils/componentsScssContent.js b/src/sitePages/newHome/utils/componentsScssContent.js index a83cd352fb..03f0afb53d 100644 --- a/src/sitePages/newHome/utils/componentsScssContent.js +++ b/src/sitePages/newHome/utils/componentsScssContent.js @@ -146,7 +146,7 @@ $module: #{$prefix}-descriptions; } } } -` +`; const DESCRIPTIONS_VARIABLES = `$font-descriptions-lineHeight: 20px; // 文字行高 $font-descriptions_value-fontWeight: $font-weight-bold; // 双行显示 value 文字字重 @@ -163,7 +163,7 @@ $color-descriptions_value-text-default: var(--semi-color-text-0); // value 文 $spacing-descriptions_value_plain-paddingLeft: 8px; // 普通显示 plain 模式下 value 左侧内边距 $spacing-descriptions_item_double-padding: 0; // 双行显示右侧 item 内边距 -` +`; export const TYPOGRAPHY_CONTENT = `@import "./variables.scss"; @@ -381,7 +381,7 @@ p.#{$module}-extended, .#{$module}-paragraph.#{$module}-extended { line-height: $font-typography_paragraph_extended-lineHeight; } -` +`; const TYPOGRAPHY_VARIABLES = `$color-typography_default-text-default: var(--semi-color-text-0); // 默认文本颜色 $color-typography_secondary-text-default: var(--semi-color-text-1); // 稍次要文本颜色 @@ -428,7 +428,7 @@ $width-typography_code-border: 1px; // 代码文本描边宽度 $width-typography_link-border: 1px; // 链接文本下划线宽度 $radius-typography_code: 2px; // 代码文本圆角 -` +`; const INPUT_CONTENT = `@import "./variables.scss"; @@ -616,7 +616,7 @@ $module: #{$prefix}-input; } } } -` +`; const INPUT_VARIABLES = `$color-input_default-border-default: transparent; // 输入框描边颜色 - 默认 @@ -727,7 +727,7 @@ $width-textarea-icon: $width-icon-medium + $spacing-tight; // clear 图标最小 $height-textarea-default: 32px; // 多行文本 clear 图标的高度 $spacing-textarea_withShowClear-paddingRight: 36px; // 多行文本设置 showClear 后的右内边距 $spacing-textarea-icon-right: $spacing-extra-tight;// 多行文本 clear 图标的右边距 -` +`; const SELECT_CONTENT = `//@import '../theme/variables.scss'; @import './variables.scss'; @@ -1149,7 +1149,7 @@ $multiple: #{$module}-multiple; cursor: not-allowed; } -` +`; const SELECT_VARIABLES = `// Color $color-select-bg-default: var(--semi-color-fill-0); // 选择器输入框背景色 - 默认态 @@ -1251,14 +1251,14 @@ $font-select_keyword-fontWeight: 600; // 选择器搜索结果命关键词中文 // Other $opacity-select_selection_text_inactive: .4; -` +`; const SELECT_MIXIN = `// Mixin @mixin select-tag-margin { margin-top: $spacing-select_tag-marginTop; margin-right: $spacing-select_tag-marginRight; margin-bottom: $spacing-select_tag-marginBottom; -}` +}`; const TABLE_CONTENT = `@import "./variables.scss"; @import "./mixin.scss"; @@ -1787,7 +1787,7 @@ $module: #{$prefix}-table; justify-content: center; } } -` +`; const TABLE_VARIABLES = `// Spacing $spacing-table-paddingY: $spacing-base; // 表格单元格垂直内边距 @@ -1872,7 +1872,7 @@ $shadow-table_left: -3px 0 0 0 $color-table_shadow-bg-default; // 表格滚动 $shadow-table_right: 3px 0 0 0 $color-table_shadow-bg-default; // 表格滚动阴影 - 右侧 $border-table: #{$width-table_base_border} #{$border-table_base-borderStyle} $color-table-border-default; // 表格默认描边 $border-table_resizer: $width-table_resizer_border solid $color-table_resizer-bg-default; // 表格拉伸标识描边 -` +`; const TABLE_MIXIN = `@mixin genResizing() { border-right: $border-table_resizer; @@ -1883,7 +1883,7 @@ const TABLE_MIXIN = `@mixin genResizing() { background-color: unset; } } -}` +}`; const PAGINATION_CONTENT = `//@import '../theme/variables.scss'; @import "./variables.scss"; @@ -2041,7 +2041,7 @@ $module: #{$prefix}-page; } } } -` +`; const PAGINATION_VARIABLES = `// Color $color-pagination-text-default: var(--semi-color-text-2); // 翻页器总页数文本颜色 @@ -2094,7 +2094,7 @@ $font-pagination_small-fontWeight: $font-weight-regular; // 迷你翻页器字 $font-pagination_item-fontWeight: $font-weight-regular; // 翻页器页码字重 $font-pagination_item_active-fontWeight: $font-weight-bold; // 翻页器页码选中态字重 $font-pagination_quickjump_fontWeight: $font-weight-regular; // 快速跳转输入框字重 -` +`; export const componentsScssContent= { 'descriptions/index.scss': DESCRIPTIONS_CONTENT, @@ -2111,4 +2111,4 @@ export const componentsScssContent= { 'table/mixin.scss': TABLE_MIXIN, 'pagination/index.scss': PAGINATION_CONTENT, 'pagination/variables.scss': PAGINATION_VARIABLES -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/sitePages/newHome/utils/loadSassCompiler.js b/src/sitePages/newHome/utils/loadSassCompiler.js index 4aa127e6ac..6608c92fb8 100644 --- a/src/sitePages/newHome/utils/loadSassCompiler.js +++ b/src/sitePages/newHome/utils/loadSassCompiler.js @@ -10,22 +10,22 @@ const loadSassCompiler = () => new Promise((resolve) => { scriptEle.src = "/sass.js"; scriptEle.onload = () => { // @ts-ignore - const {Sass} = window; + const { Sass } = window; compiler = new Sass(); compiler.writeFilePromisify = (...args) => { return new Promise((resolve, reject) => { compiler.writeFile(...args, (result) => { if (result) { - console.log("writed", args) + console.log("writed", args); resolve(); } else { reject(); } - }) - }) - } + }); + }); + }; resolve(compiler); - } + }; document.head.appendChild(scriptEle); }); diff --git a/src/sitePages/newHome/utils/themeDefaultScssContent.js b/src/sitePages/newHome/utils/themeDefaultScssContent.js index 5f9a97f877..0b751621ef 100644 --- a/src/sitePages/newHome/utils/themeDefaultScssContent.js +++ b/src/sitePages/newHome/utils/themeDefaultScssContent.js @@ -1,6 +1,6 @@ const ENTRY_CONTENT = `@import './mixin.scss'; @import './variables.scss'; -@import './_font.scss';` +@import './_font.scss';`; const MIXIN_CONTENT = `/* shadow */ @mixin shadow-elevated { @@ -75,7 +75,7 @@ const MIXIN_CONTENT = `/* shadow */ } } } -` +`; const VARIABLES_CONTENT = `$prefix: 'semi'; @@ -137,7 +137,7 @@ $font-size-header-1: 32px; // 一级标题字号 $font-weight-light: 200; // 字重 - 轻 $font-weight-regular: 400; // 字重 - 常规 $font-weight-bold: 600; // 字重 - 加粗 -` +`; const FONT_CONTENT = `// font-size line-height绑定 @mixin font-size-small { @@ -187,11 +187,11 @@ const FONT_CONTENT = `// font-size line-height绑定 line-height: 44px; font-family: $font-family-regular; } -` +`; export const themeScssContent = { 'theme/index.scss': ENTRY_CONTENT, 'theme/variables.scss': VARIABLES_CONTENT, 'theme/_font.scss': FONT_CONTENT, 'theme/mixin.scss': MIXIN_CONTENT -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/templates/toUEDUtils/toUED.ts b/src/templates/toUEDUtils/toUED.ts index 925c71675a..76f69b8e96 100644 --- a/src/templates/toUEDUtils/toUED.ts +++ b/src/templates/toUEDUtils/toUED.ts @@ -8,11 +8,11 @@ const getSite=()=>{ -const getAnotherSideUrl=(site:'design'|'main')=>{ +const getAnotherSideUrl=(site: 'design'|'main')=>{ const currentUrlSplit=window.location.pathname.split('/').filter(s=>s); const url=currentUrlSplit.slice(currentUrlSplit.length-2); const locale=/zh-CN/.test(window.location.pathname)?'zh-CN':'en-US'; - if (site==='main'){ + if (site==='main') { return `${window.location.origin}/${locale}/${url[0]}/${url[1]}`; } else { return `${window.location.origin}/design/${locale}/${url[0]}/${url[1]}`; @@ -20,48 +20,48 @@ const getAnotherSideUrl=(site:'design'|'main')=>{ }; -const cache={ scrollHeight:null }; +const cache={ scrollHeight: null }; -const transContent=(site:'main'|'design')=>{ +const transContent=(site: 'main'|'design')=>{ const url=`${getAnotherSideUrl('design')}?concisemode=true`; const mainSiteContentDOM= document.querySelector('.main-article') as HTMLDivElement; - if (site==='design'){ + if (site==='design') { mainSiteContentDOM.style['display']='none'; let iframeContainer=document.querySelector('#iframeContainer') as HTMLDivElement; - if (iframeContainer){ + if (iframeContainer) { iframeContainer.style['display']='block'; iframeContainer.style['margin-bottom']='120px'; const iframeDOM=iframeContainer.querySelector('iframe'); - if (iframeDOM.getAttribute('src')!==url){ - iframeDOM.setAttribute('src',url); + if (iframeDOM.getAttribute('src')!==url) { + iframeDOM.setAttribute('src', url); } - if (cache.scrollHeight){ + if (cache.scrollHeight) { iframeContainer.style['height']=cache['scrollHeight']; iframeDOM.style['height']=cache['scrollHeight']; } } else { iframeContainer=document.createElement('div') as HTMLDivElement; - iframeContainer.setAttribute('class','iframeContainer'); - iframeContainer.setAttribute('id','iframeContainer'); + iframeContainer.setAttribute('class', 'iframeContainer'); + iframeContainer.setAttribute('id', 'iframeContainer'); const iframeDOM=document.createElement('iframe'); - iframeDOM.setAttribute('src',url); - iframeDOM.setAttribute('scrolling','no'); - window.addEventListener('message',e=>{ - console.log('message',e.data); + iframeDOM.setAttribute('src', url); + iframeDOM.setAttribute('scrolling', 'no'); + window.addEventListener('message', e=>{ + console.log('message', e.data); try { const data=JSON.parse(e.data); - if (data['scrollHeight']){ + if (data['scrollHeight']) { // @ts-ignore window.syncThemeToIframe && window.syncThemeToIframe(); iframeDOM.style['height']=`${data['scrollHeight']}px`; iframeContainer.style['height']=`${data['scrollHeight']}px`; - console.log('height===>',data['scrollHeight']); + console.log('height===>', data['scrollHeight']); cache['scrollHeight']=`${data['scrollHeight']}px`; // @ts-ignore iframeDOM?.contentWindow?.semidoc?.setDarkmode(document.body.getAttribute('theme-mode')==='dark'); } - } catch (e){ - console.log('getMessage ====>',e); + } catch (e) { + console.log('getMessage ====>', e); } }); iframeContainer.prepend(iframeDOM); @@ -80,9 +80,9 @@ const transContent=(site:'main'|'design')=>{ } }; -const isHaveUedDocs=(pathName:string)=>{ +const isHaveUedDocs=(pathName: string)=>{ - if (pathName){ + if (pathName) { const urlSplitArray=pathName.split('/').filter(v=>v); const componentName=urlSplitArray[urlSplitArray.length-1]; return haveUedDocComponents.includes(componentName); @@ -90,9 +90,9 @@ const isHaveUedDocs=(pathName:string)=>{ return false; }; -const isJumpToDesignSite=(pathName:string)=>{ - const components=['toast','popconfirm','scrolllist','popover','select','dropdown','treeselect']; - if (pathName){ +const isJumpToDesignSite=(pathName: string)=>{ + const components=['toast', 'popconfirm', 'scrolllist', 'popover', 'select', 'dropdown', 'treeselect']; + if (pathName) { const urlSplitArray=pathName.split('/').filter(v=>v); const componentName=urlSplitArray[urlSplitArray.length-1]; return components.includes(componentName); From ef375fb64e6d0d508cf7fb1c817c9e56ab890c3a Mon Sep 17 00:00:00 2001 From: YyumeiZhang <101110131+YyumeiZhang@users.noreply.github.com> Date: Mon, 7 Aug 2023 14:38:57 +0800 Subject: [PATCH 06/29] =?UTF-8?q?refactor:=20change=20react-sortable-hoc?= =?UTF-8?q?=20to=20dnd-kit=20for=20Transfer/Taginput=20=E2=80=A6=20(#1738)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: change react-sortable-hoc to dnd-kit for Transfer/Taginput drag & drop * chore: update yarn.lock file --------- Co-authored-by: pointhalo <88709023+pointhalo@users.noreply.github.com> --- content/input/transfer/index-en-US.md | 285 +++++++++++- content/input/transfer/index.md | 289 ++++++++++++- content/show/list/index-en-US.md | 78 ---- content/show/list/index.md | 77 ---- .../semi-foundation/tagInput/tagInput.scss | 21 + .../semi-foundation/tagInput/variables.scss | 2 + .../semi-foundation/transfer/transfer.scss | 7 + packages/semi-ui/_sortable/index.tsx | 255 +++++++++++ packages/semi-ui/package.json | 16 +- .../tagInput/_story/tagInput.stories.jsx | 51 ++- packages/semi-ui/tagInput/index.tsx | 110 ++--- .../transfer/_story/transfer.stories.jsx | 408 +++++++++++------- packages/semi-ui/transfer/index.tsx | 54 ++- src/templates/scope.js | 21 + yarn.lock | 31 ++ 15 files changed, 1295 insertions(+), 410 deletions(-) create mode 100644 packages/semi-ui/_sortable/index.tsx diff --git a/content/input/transfer/index-en-US.md b/content/input/transfer/index-en-US.md index 176f626b72..87ee398c85 100644 --- a/content/input/transfer/index-en-US.md +++ b/content/input/transfer/index-en-US.md @@ -710,8 +710,15 @@ class CustomRenderDemo extends React.Component { ### Fully custom rendering, drag and drop sorting In a completely custom rendering scene, since the rendering of the drag area has also been completely taken over by you, you do not need to declare draggable. -But you need to implement the drag and drop logic yourself, we recommend using `react-sortable-hoc` directly -To support drag sorting, you need to call onSortEnd with oldIndex and newIndex as the input parameters after the drag sorting is over +But you need to implement the drag and drop logic yourself, You can use the drag-and-drop tool library [dnd-kit](https://github.com/clauderic/dnd-kit) or [react-sortable-hoc](https://github.com/clauderic/react-sortable-hoc), quickly realize the function. Regarding the selection of the two, here are some of our suggestions. + +- Both are maintained by the same author, dnd-kit is the successor of react-sortable-hoc +- The API design of react-sortable-hoc is more cohesive, and the code is more concise in simple scenarios. But it strongly relies on the findDOMNode API, which will be deprecated in future React versions. At the same time, the library has not been maintained for the past two years. +- Relatively speaking, dnd-kit has a certain threshold for getting started, but it has a higher degree of freedom, stronger scalability, and is still under maintenance. we recommend it. + +Besides, To support drag sorting, you need to call onSortEnd with oldIndex and newIndex as the input parameters after the drag sorting is over + +Example using react-sortable-hoc: ```jsx live=true dir="column" import React from 'react'; @@ -874,6 +881,280 @@ class CustomRenderDragDemo extends React.Component { } ``` +Example using dnd-kit,The core dependencies that need to be used are @dnd-kit/sortable, @dnd-kit/core. The core hooks are useSortable, and the usage instructions of useSortable are as follows + +``` +1. Function: Obtain the necessary information during the drag and drop process through the unique id +2. Core input parameters: + - id: unique identifier, which can be a number or a string, but cannot be a number 0 +3. Core return value description: + - setNodeRef: Associate the dom node to make it a draggable item + - listeners: Contains onKeyDown, onPointerDown and other methods, mainly to allow nodes to be dragged + - transform: the movement change value when the node is dragged + - transition: transition effect + - active: information about the dragged node, including id +``` + +```jsx live=true dir="column" noInline=true +import React from 'react'; +import ReactDOM from 'react-dom'; +import { Transfer, Input, Spin, Button } from '@douyinfe/semi-ui'; +import { IconSearch, IconHandle } from '@douyinfe/semi-icons'; +import { useSortable, SortableContext, sortableKeyboardCoordinates, verticalListSortingStrategy } from '@dnd-kit/sortable'; +import { CSS as cssDndKit } from '@dnd-kit/utilities'; +import { closestCenter, DragOverlay, DndContext, MouseSensor, TouchSensor, useSensor, useSensors, KeyboardSensor, TraversalOrder } from '@dnd-kit/core'; + +function SortableList({ + items, + onSortEnd, + renderItem, +}) { + const [activeId, setActiveId] = useState(null); + // sensors determine which external input is affected by the drag operation (such as mouse, keyboard, touchpad) + const sensors = useSensors( + useSensor(MouseSensor), + useSensor(TouchSensor), + useSensor(KeyboardSensor, { + coordinateGetter: sortableKeyboardCoordinates, + }) + ); + const getIndex = useCallback((id) => items.indexOf(id), [items]); + const activeIndex = useMemo(() => activeId ? getIndex(activeId) : -1, [getIndex, activeId]); + + const onDragStart = useCallback(({ active }) => { + if (!active) { return; } + setActiveId(active.id); + }, []); + + // Drag end callback + const onDragEnd = useCallback(({ over }) => { + setActiveId(null); + if (over) { + const overIndex = getIndex(over.id); + if (activeIndex !== overIndex) { + onSortEnd({ oldIndex: activeIndex, newIndex: overIndex }); + } + } + }, [activeIndex, getIndex, onSortEnd]); + + const onDragCancel = useCallback(() => { + setActiveId(null); + }, []); + + return ( + + +
+ {items.map((value, index) => ( + + ))} +
+ {ReactDOM.createPortal( + + {activeId ? ( + renderItem({ + id: activeId, + sortableHandle: (WrapperComponent) => WrapperComponent + }) + ) : null} + , + document.body + )} +
+
+ ); +} + +function SortableItem({ id, renderItem }) { + const { + listeners, + setNodeRef, + transform, + transition, + active, + } = useSortable({ + id, + }); + + const sortableHandle = useCallback((WrapperComponent) => { + return () => ; + }, [listeners]); + + const wrapperStyle = { + transform: cssDndKit.Transform.toString({ + ...transform, + scaleX: 1, + scaleY: 1, + }), + transition: transition, + opacity: active && active.id === id ? 0 : undefined, + }; + + return
+ {renderItem({ id, sortableHandle })} +
; +} + +class CustomRenderDragDemo extends React.Component { + constructor(props) { + super(props); + this.state = { + dataSource: Array.from({ length: 100 }, (v, i) => ({ + label: `Hdl Store ${i}`, + value: i, + disabled: false, + key: `key-${i}`, + })), + }; + this.renderSourcePanel = this.renderSourcePanel.bind(this); + this.renderSelectedPanel = this.renderSelectedPanel.bind(this); + this.renderItem = this.renderItem.bind(this); + } + + renderItem(type, item, onItemAction, selectedItems, sortableHandle) { + let buttonText = 'delete'; + + if (type === 'source') { + let checked = selectedItems.has(item.key); + buttonText = checked ? 'delete' : 'add'; + } + + const DragHandle = (sortableHandle && sortableHandle(() => )); + + return ( +
+ {type === 'source' ? null : ( DragHandle ? : null) } +
+

{item.label}

+ +
+
+ ); + } + + renderSourcePanel(props) { + const { + loading, + noMatch, + filterData, + selectedItems, + allChecked, + onAllClick, + inputValue, + onSearch, + onSelectOrRemove, + } = props; + let content; + switch (true) { + case loading: + content = ; + break; + case noMatch: + content =
{inputValue ? 'No search results' : 'No content yet'}
; + break; + case !noMatch: + content = filterData.map(item => this.renderItem('source', item, onSelectOrRemove, selectedItems)); + break; + default: + content = null; + break; + } + return ( +
+
Store list
+
+ } + onChange={onSearch} + showClear + /> +
+ Store to be selected: {filterData.length} + +
+
{content}
+
+
+ ); + } + + renderSelectedPanel(props) { + const { selectedData, onClear, clearText, onRemove, onSortEnd } = props; + let mainContent = null; + + if (!selectedData.length) { + mainContent =
No data, please filter from the left
; + } + + const renderSelectItem = ({ id, sortableHandle }) => { + const item = selectedData.find(item => id === item.key); + return this.renderItem('selected', item, onRemove, null, sortableHandle); + }; + + const sortData = selectedData.map(item => item.key); + + mainContent =
+ +
; + + return ( +
+
+
Selected: {selectedData.length}
+ +
+ {mainContent} +
+ ); + } + + render() { + const { dataSource } = this.state; + return ( + console.log(values)} + className="component-transfer-demo-custom-panel" + renderSourcePanel={this.renderSourcePanel} + renderSelectedPanel={this.renderSelectedPanel} + dataSource={dataSource} + /> + ); + } +} + +render(CustomRenderDragDemo); +``` + ### Tree Transfer The input type is `treeList`, and the [`Tree`](/en-US/navigation/tree) component is used as a custom rendering list. **v1.20.0 available** diff --git a/content/input/transfer/index.md b/content/input/transfer/index.md index 60268fb8b2..4f7b5182ae 100644 --- a/content/input/transfer/index.md +++ b/content/input/transfer/index.md @@ -711,9 +711,18 @@ class CustomRenderDemo extends React.Component { ### 完全自定义渲染 、 拖拽排序 -在完全自定义渲染的场景下,由于拖拽区的渲染也已由你完全接管,因此你不声明 draggable 亦可。 -但你需要自行实现拖拽逻辑,我们推荐直接使用`react-sortable-hoc` -要支持拖拽排序,你需要在拖拽排序结束后,将 oldIndex、newIndex 作为入参,调用 onSortEnd +在完全自定义渲染的场景下,由于拖拽区的渲染也已由你完全接管,因此你不声明 draggable 亦可。 +但你需要自行实现拖拽逻辑,你可以借助社区中拖拽类工具库 [dnd-kit](https://github.com/clauderic/dnd-kit) 或者 [react-sortable-hoc](https://github.com/clauderic/react-sortable-hoc),快速实现功能。关于两者选型,这是我们的一些建议 + +- 两者均由同一作者维护, dnd-kit 是 react-sortable-hoc 的接任产品 +- react-sortable-hoc 的 API 设计更加高内聚,在简单场景上代码更加简洁。但它强依赖了 findDOMNode API,在未来的 React 版本中会被废弃。同时该库最近两年已经处于不维护的状态。 +- dnd-kit 相对而言,有一定上手门槛,但它的自由度更高,扩展性更强,并且仍处于维护状态。我们更推荐使用 + +更多 DIff 信息可查阅 [react-sortable-hoc](https://github.com/clauderic/react-sortable-hoc) 的 Github 主页 + +另外,要支持拖拽排序,你需要在拖拽排序结束后,将 oldIndex、newIndex 作为入参,调用 onSortEnd + +使用 react-sortable-hoc 的示例: ```jsx live=true dir="column" import React from 'react'; @@ -876,6 +885,280 @@ class CustomRenderDragDemo extends React.Component { } ``` +使用 dnd-kit 的示例如下,需要用到的核心依赖有 @dnd-kit/sortable, @dnd-kit/core,其中核心 hooks 为 useSortable,使用说明如下 + +``` +1. 作用:通过唯一标志 id 获取拖拽过程中必要信息 +2. 核心输入参数: + - id: 唯一标识, 以为数字或者字符串,但是不能为数字 0 +3. 核心返回值说明: + - setNodeRef: 关联 dom 节点,使其成为一个可拖拽的项 + - listeners: 包含 onKeyDown,onPointerDown 等方法,主要让节点可以进行拖拽 + - transform:该节点被拖动时候的移动变化值 + - transition:过渡效果 + - active: 被拖拽节点的相关信息,包括 id +``` + +```jsx live=true dir="column" noInline=true +import React from 'react'; +import ReactDOM from 'react-dom'; +import { Transfer, Input, Spin, Button } from '@douyinfe/semi-ui'; +import { IconSearch, IconHandle } from '@douyinfe/semi-icons'; +import { useSortable, SortableContext, sortableKeyboardCoordinates, verticalListSortingStrategy } from '@dnd-kit/sortable'; +import { CSS as cssDndKit } from '@dnd-kit/utilities'; +import { closestCenter, DragOverlay, DndContext, MouseSensor, TouchSensor, useSensor, useSensors, KeyboardSensor, TraversalOrder } from '@dnd-kit/core'; + +function SortableList({ + items, + onSortEnd, + renderItem, +}) { + const [activeId, setActiveId] = useState(null); + // sensors 确定拖拽操作受哪些外部输入影响(如鼠标,键盘,触摸板) + const sensors = useSensors( + useSensor(MouseSensor), + useSensor(TouchSensor), + useSensor(KeyboardSensor, { + coordinateGetter: sortableKeyboardCoordinates, + }) + ); + const getIndex = useCallback((id) => items.indexOf(id), [items]); + const activeIndex = useMemo(() => activeId ? getIndex(activeId) : -1, [getIndex, activeId]); + + const onDragStart = useCallback(({ active }) => { + if (!active) { return; } + setActiveId(active.id); + }, []); + + // 拖拽结束回调 + const onDragEnd = useCallback(({ over }) => { + setActiveId(null); + if (over) { + const overIndex = getIndex(over.id); + if (activeIndex !== overIndex) { + onSortEnd({ oldIndex: activeIndex, newIndex: overIndex }); + } + } + }, [activeIndex, getIndex, onSortEnd]); + + const onDragCancel = useCallback(() => { + setActiveId(null); + }, []); + + return ( + + +
+ {items.map((value, index) => ( + + ))} +
+ {ReactDOM.createPortal( + + {activeId ? ( + renderItem({ + id: activeId, + sortableHandle: (WrapperComponent) => WrapperComponent + }) + ) : null} + , + document.body + )} +
+
+ ); +} + +function SortableItem({ id, renderItem }) { + const { + listeners, + setNodeRef, + transform, + transition, + active, + } = useSortable({ + id, + }); + + const sortableHandle = useCallback((WrapperComponent) => { + return () => ; + }, [listeners]); + + const wrapperStyle = { + transform: cssDndKit.Transform.toString({ + ...transform, + scaleX: 1, + scaleY: 1, + }), + transition: transition, + opacity: active && active.id === id ? 0 : undefined, + }; + + return
+ {renderItem({ id, sortableHandle })} +
; +} + +class CustomRenderDragDemo extends React.Component { + constructor(props) { + super(props); + this.state = { + dataSource: Array.from({ length: 100 }, (v, i) => ({ + label: `海底捞门店 ${i}`, + value: i, + disabled: false, + key: `key-${i}`, + })), + }; + this.renderSourcePanel = this.renderSourcePanel.bind(this); + this.renderSelectedPanel = this.renderSelectedPanel.bind(this); + this.renderItem = this.renderItem.bind(this); + } + + renderItem(type, item, onItemAction, selectedItems, sortableHandle) { + let buttonText = '删除'; + + if (type === 'source') { + let checked = selectedItems.has(item.key); + buttonText = checked ? '删除' : '添加'; + } + + const DragHandle = (sortableHandle && sortableHandle(() => )); + + return ( +
+ {type === 'source' ? null : ( DragHandle ? : null) } +
+

{item.label}

+ +
+
+ ); + } + + renderSourcePanel(props) { + const { + loading, + noMatch, + filterData, + selectedItems, + allChecked, + onAllClick, + inputValue, + onSearch, + onSelectOrRemove, + } = props; + let content; + switch (true) { + case loading: + content = ; + break; + case noMatch: + content =
{inputValue ? '无搜索结果' : '暂无内容'}
; + break; + case !noMatch: + content = filterData.map(item => this.renderItem('source', item, onSelectOrRemove, selectedItems)); + break; + default: + content = null; + break; + } + return ( +
+
门店列表
+
+ } + onChange={onSearch} + showClear + /> +
+ 待选门店: {filterData.length} + +
+
{content}
+
+
+ ); + } + + renderSelectedPanel(props) { + const { selectedData, onClear, clearText, onRemove, onSortEnd } = props; + let mainContent = null; + + if (!selectedData.length) { + mainContent =
暂无数据,请从左侧筛选
; + } + + const renderSelectItem = ({ id, sortableHandle }) => { + const item = selectedData.find(item => id === item.key); + return this.renderItem('selected', item, onRemove, null, sortableHandle); + }; + + const sortData = selectedData.map(item => item.key); + + mainContent =
+ +
; + + return ( +
+
+
已选同步门店: {selectedData.length}
+ +
+ {mainContent} +
+ ); + } + + render() { + const { dataSource } = this.state; + return ( + console.log(values)} + className="component-transfer-demo-custom-panel" + renderSourcePanel={this.renderSourcePanel} + renderSelectedPanel={this.renderSelectedPanel} + dataSource={dataSource} + /> + ); + } +} + +render(CustomRenderDragDemo); +``` + ### 树穿梭框 传入 type 为`treeList`,使用[`Tree`](/zh-CN/navigation/tree)组件作为自定义渲染列表。**v1.20.0 提供** diff --git a/content/show/list/index-en-US.md b/content/show/list/index-en-US.md index c20281ff5f..3de0edb4af 100644 --- a/content/show/list/index-en-US.md +++ b/content/show/list/index-en-US.md @@ -916,84 +916,6 @@ class DraggableList extends React.Component { render(DraggableList); ``` - -If you use [react-sortable-hoc](https://github.com/clauderic/react-sortable-hoc), here is also an example - -```jsx live=true dir="column" hideInDSM -import React, { useState } from 'react'; -import { List } from '@douyinfe/semi-ui'; -import { IconHandle } from '@douyinfe/semi-icons'; -import { SortableContainer, SortableElement, sortableHandle } from 'react-sortable-hoc'; - -() => { - const data = [ - 'Siege', - 'The ordinary world', - 'Three Body', - 'Snow in the Snow', - 'Saharan story', - 'Those things', - 'A little monk of Zen', - 'Dune', - 'The courage to be hated', - 'Crime and Punishment', - 'Moon and sixpence', - 'The silent majority', - 'First person singular', - ]; - - const [list, setList] = useState(data.slice(0, 6)); - - const renderItem = (props) => { - const { item } = props; - const DragHandle = sortableHandle(() => ); - return ( - - - {item} - - ); - }; - - const arrayMove = (array, from, to) => { - let newArray = array.slice(); - newArray.splice(to < 0 ? newArray.length + to : to, 0, newArray.splice(from, 1)[0]); - return newArray; - }; - - const onSortEnd = (callbackProps) => { - let { oldIndex, newIndex } = callbackProps; - let newList = arrayMove(list, oldIndex, newIndex); - setList(newList); - }; - - const SortableItem = SortableElement(props => renderItem(props)); - const SortableList = SortableContainer( - ({ items }) => { - return ( -
- {items.map((item, index) => ( - - ))} -
- ); - }, - { distance: 10 } - ); - - return ( -
-
- - - -
- -
- ); -}; -``` - ### With Pagination You can use Pagination in combination to achieve a paged List diff --git a/content/show/list/index.md b/content/show/list/index.md index 8fd6c89c0b..82d0b0b80d 100644 --- a/content/show/list/index.md +++ b/content/show/list/index.md @@ -919,83 +919,6 @@ class DraggableList extends React.Component { render(DraggableList); ``` -如果你使用 [react-sortable-hoc](https://github.com/clauderic/react-sortable-hoc),这里也有一个例子 - -```jsx live=true dir="column" hideInDSM -import React, { useState } from 'react'; -import { List } from '@douyinfe/semi-ui'; -import { IconHandle } from '@douyinfe/semi-icons'; -import { SortableContainer, SortableElement, sortableHandle } from 'react-sortable-hoc'; - - -() => { - const data = [ - '围城', - '平凡的世界(全三册)', - '三体(全集)', - '雪中悍刀行(全集)', - '撒哈拉的故事', - '明朝那些事', - '一禅小和尚', - '沙丘', - '被讨厌的勇气', - '罪与罚', - '月亮与六便士', - '沉默的大多数', - '第一人称单数', - ]; - - const [list, setList] = useState(data.slice(0, 6)); - - const renderItem = (props) => { - const { item } = props; - const DragHandle = sortableHandle(() => ); - return ( - - - {item} - - ); - }; - - const arrayMove = (array, from, to) => { - let newArray = array.slice(); - newArray.splice(to < 0 ? newArray.length + to : to, 0, newArray.splice(from, 1)[0]); - return newArray; - }; - - const onSortEnd = (callbackProps) => { - let { oldIndex, newIndex } = callbackProps; - let newList = arrayMove(list, oldIndex, newIndex); - setList(newList); - }; - - const SortableItem = SortableElement(props => renderItem(props)); - const SortableList = SortableContainer( - ({ items }) => { - return ( -
- {items.map((item, index) => ( - - ))} -
- ); - }, - { distance: 10 } - ); - - return ( -
-
- - - -
- -
- ); -}; -``` ### 带分页器 diff --git a/packages/semi-foundation/tagInput/tagInput.scss b/packages/semi-foundation/tagInput/tagInput.scss index d98e3a42db..191d5f3115 100644 --- a/packages/semi-foundation/tagInput/tagInput.scss +++ b/packages/semi-foundation/tagInput/tagInput.scss @@ -42,6 +42,27 @@ $module: #{$prefix}-tagInput; } } + &-sortable-item { + position: relative; + &-over { + overflow: visible; + &::before { + content: ""; + display: block; + height: 100%; + width: $width-tagInput_sortable_item_over; + background-color: $color-tagInput_sortable_item_over-bg; + position: absolute; + left: -$width-tagInput_sortable_item_over; + top: 0; + } + } + + &-active { + opacity: 0.5; + } + } + &-hover { background-color: $color-tagInput_default-bg-hover; border: $width-tagInput-border-hover $color-tagInput-border-hover solid; diff --git a/packages/semi-foundation/tagInput/variables.scss b/packages/semi-foundation/tagInput/variables.scss index ba345388d8..bf5196bdbb 100644 --- a/packages/semi-foundation/tagInput/variables.scss +++ b/packages/semi-foundation/tagInput/variables.scss @@ -27,6 +27,7 @@ $color-tagInput_danger-bg-hover: var(--semi-color-danger-light-hover); // 危险 $color-tagInput_danger-border-hover: var(--semi-color-danger-light-hover); // 危险标签输入框描边颜色 - 悬浮 $color-tagInput_danger-bg-focus: var(--semi-color-danger-light-default); // 危险标签输入框背景颜色 - 选中 $color-tagInput_danger-border-focus: var(--semi-color-danger); // 危险标签输入框描边颜色 - 选中 +$color-tagInput_sortable_item_over-bg: var(--semi-color-primary); // 拖拽经过的元素前竖线背景色 $color-tagInput_handler-icon-default: var(--semi-color-text-2); // 可拖拽的标签拖拽按钮颜色 @@ -48,6 +49,7 @@ $width-tagInput-clear-medium: $width-icon-medium * 2; // 标签输入框清空 $width-tagInput-border-default: $border-thickness-control; // 标签输入框描边描边宽度 - 默认 $width-tagInput-border-hover: $width-tagInput-border-default; // 标签输入框描边描边宽度 - 悬浮 $width-tagInput-border-focus: $border-thickness-control-focus; // 标签输入框描边宽度 - 选中态 +$width-tagInput_sortable_item_over: 2px; // 拖拽经过的元素前竖线宽度 $radius-tagInput: var(--semi-border-radius-small); // 标签输入框圆角 diff --git a/packages/semi-foundation/transfer/transfer.scss b/packages/semi-foundation/transfer/transfer.scss index 25f4c8fc6a..13c7f08ec3 100644 --- a/packages/semi-foundation/transfer/transfer.scss +++ b/packages/semi-foundation/transfer/transfer.scss @@ -169,12 +169,19 @@ $module: #{$prefix}-transfer; &-handler { margin-right: $spacing-transfer_right_item_drag_handler-marginRight; flex-shrink: 0; + cursor: move; } &-item-move { z-index: $z-transfer_right_item_drag_item_move; } } + + &-sortable-item { + &-active { + opacity: 0; + } + } } &-empty { diff --git a/packages/semi-ui/_sortable/index.tsx b/packages/semi-ui/_sortable/index.tsx new file mode 100644 index 0000000000..6bbdbc0a47 --- /dev/null +++ b/packages/semi-ui/_sortable/index.tsx @@ -0,0 +1,255 @@ +import React, { ReactNode, useState, useCallback, useMemo } from 'react'; +import { createPortal } from 'react-dom'; +import { CSS as cssDndKit } from '@dnd-kit/utilities'; +import cls from 'classnames'; + +import { + closestCenter, + DragOverlay, + DndContext, + MouseSensor, + TouchSensor, + useSensor, + useSensors, + KeyboardSensor, + TraversalOrder, +} from '@dnd-kit/core'; +import type { + UniqueIdentifier, + PointerActivationConstraint, + CollisionDetection, +} from '@dnd-kit/core'; +import { + useSortable, + SortableContext, + rectSortingStrategy, + sortableKeyboardCoordinates, +} from '@dnd-kit/sortable'; +import type { + SortingStrategy, + AnimateLayoutChanges, + NewIndexGetter, +} from '@dnd-kit/sortable'; +import type { SortableTransition } from '@dnd-kit/sortable/dist/hooks/types'; +import { isNull } from 'lodash'; + +const defaultPrefix = 'semi-sortable'; +const defaultConstraint = { + delay: 150, + tolerance: 5, +}; + +interface OnSortEndProps { + oldIndex: number; + newIndex: number +} +export type OnSortEnd = (props: OnSortEndProps) => void; + +export interface RenderItemProps { + id?: string | number; + sortableHandle?: any; + [x: string]: any +} +export interface SortableProps { + onSortEnd?: OnSortEnd; + // Set drag and drop trigger conditions + activationConstraint?: PointerActivationConstraint; + // Collision detection algorithm, for drag and drop sorting, use closestCenter to meet most scenarios + collisionDetection?: CollisionDetection; + // the dragged items,The content in items cannot be the number 0 + items?: any[]; + // Function that renders the item that is allowed to be dragged + renderItem?: (props: RenderItemProps) => React.ReactNode; + // Drag and drop strategy + strategy?: SortingStrategy; + // Whether to use a separate drag layer for items that move with the mouse + useDragOverlay?: boolean; + // A container for all elements that are allowed to be dragged + container?: any; + // Whether to change the size of the item being dragged + adjustScale?: boolean; + // Whether to use animation during dragging + transition?: SortableTransition | null; + // prefix + prefix?: string; + // The className of the item that moves with the mouse during the drag + dragOverlayCls?: string +} + +interface SortableItemProps { + animateLayoutChanges?: AnimateLayoutChanges; + getNewIndex?: NewIndexGetter; + id: UniqueIdentifier; + index: number; + useDragOverlay?: boolean; + renderItem?: (props: RenderItemProps) => ReactNode; + prefix?: string; + transition?: SortableTransition | null +} + +function DefaultContainer(props) { + return
; +} + +export function Sortable({ + items, + onSortEnd, + adjustScale, + renderItem, + transition, + activationConstraint = defaultConstraint, + collisionDetection = closestCenter, + strategy = rectSortingStrategy, + useDragOverlay = true, + dragOverlayCls, + container: Container = DefaultContainer, + prefix = defaultPrefix, +}: SortableProps) { + + const [activeId, setActiveId] = useState(null); + const sensors = useSensors( + useSensor(MouseSensor, { + activationConstraint, + }), + useSensor(TouchSensor, { + activationConstraint, + }), + useSensor(KeyboardSensor, { + coordinateGetter: sortableKeyboardCoordinates, + }) + ); + const getIndex = useCallback((id: UniqueIdentifier) => items.indexOf(id), [items]); + const activeIndex = useMemo(() => activeId ? getIndex(activeId) : -1, [getIndex, activeId]); + + const onDragStart = useCallback(({ active }) => { + if (!active) { return; } + setActiveId(active.id); + }, []); + + const onDragEnd = useCallback(({ over }) => { + setActiveId(null); + if (over) { + const overIndex = getIndex(over.id); + if (activeIndex !== overIndex) { + onSortEnd({ oldIndex: activeIndex, newIndex: overIndex }); + } + } + }, [activeIndex, getIndex, onSortEnd]); + + const onDragCancel = useCallback(() => { + setActiveId(null); + }, []); + + return ( + + + + {items.map((value, index) => ( + + ))} + + + {useDragOverlay + ? createPortal( + + {activeId ? ( + renderItem({ + id: activeId, + sortableHandle: (WrapperComponent) => WrapperComponent + }) + ) : null} + , + document.body + ) + : null} + + ); +} + +export function SortableItem({ + animateLayoutChanges, + id, + renderItem, + prefix, + transition: animation, +}: SortableItemProps) { + const { + listeners, + setNodeRef, + transform, + transition, + active, + isOver, + attributes, + } = useSortable({ + id, + animateLayoutChanges, + transition: animation, + }); + + const sortableHandle = useCallback((WrapperComponent) => { + // console.log('listeners', listeners); + // 保证给出的接口的一致性,使用 span 包一层,保证用户能够通过同样的方式使用 handler + // To ensure the consistency of the given interface + // use a span package layer to ensure that users can use the handler in the same way + // eslint-disable-next-line jsx-a11y/no-static-element-interactions + return () => { + listeners.onMouseDown(e); + // 阻止onMousedown的事件传递, + // 防止元素在点击后被卸载导致tooltip/popover的弹出层意外关闭 + // Prevent the onMousedown event from being delivered, + // preventing the element from being unloaded after being clicked, + // causing the tooltip/popover pop-up layer to close unexpectedly + e.preventDefault(); + e.stopPropagation(); + }} + >; + }, [listeners]); + + const itemCls = cls( + `${prefix}-sortable-item`, + { + [`${prefix}-sortable-item-over`]: isOver, + [`${prefix}-sortable-item-active`]: active?.id === id, + } + ); + + const wrapperStyle = (!isNull(animation)) ? { + transform: cssDndKit.Transform.toString({ + ...transform, + scaleX: 1, + scaleY: 1, + }), + transition: transition, + } : undefined; + + return
+ {renderItem({ id, sortableHandle }) as JSX.Element} +
; +} diff --git a/packages/semi-ui/package.json b/packages/semi-ui/package.json index 3ccf6ff9ee..f29b7adf21 100644 --- a/packages/semi-ui/package.json +++ b/packages/semi-ui/package.json @@ -17,12 +17,15 @@ "lib/*" ], "dependencies": { - "@douyinfe/semi-animation": "2.40.0", - "@douyinfe/semi-animation-react": "2.40.0", - "@douyinfe/semi-foundation": "2.40.0", - "@douyinfe/semi-icons": "2.40.0", - "@douyinfe/semi-illustrations": "2.40.0", - "@douyinfe/semi-theme-default": "2.40.0", + "@douyinfe/semi-animation": "2.40.0-beta.0", + "@douyinfe/semi-animation-react": "2.40.0-beta.0", + "@douyinfe/semi-foundation": "2.40.0-beta.0", + "@douyinfe/semi-icons": "2.40.0-beta.0", + "@douyinfe/semi-illustrations": "2.40.0-beta.0", + "@douyinfe/semi-theme-default": "2.40.0-beta.0", + "@dnd-kit/core": "^6.0.8", + "@dnd-kit/sortable": "^7.0.2", + "@dnd-kit/utilities": "^3.2.1", "async-validator": "^3.5.0", "classnames": "^2.2.6", "copy-text-to-clipboard": "^2.1.1", @@ -31,7 +34,6 @@ "lodash": "^4.17.21", "prop-types": "^15.7.2", "react-resizable": "^1.8.0", - "react-sortable-hoc": "^2.0.0", "react-window": "^1.8.2", "resize-observer-polyfill": "^1.5.1", "scroll-into-view-if-needed": "^2.2.24", diff --git a/packages/semi-ui/tagInput/_story/tagInput.stories.jsx b/packages/semi-ui/tagInput/_story/tagInput.stories.jsx index 774a6cc6c7..223988aa82 100644 --- a/packages/semi-ui/tagInput/_story/tagInput.stories.jsx +++ b/packages/semi-ui/tagInput/_story/tagInput.stories.jsx @@ -77,19 +77,44 @@ ShowClear.story = { name: 'showClear', }; -export const Draggable = () => ( - <> - -
- - -); +export const Draggable = () => { + const renderTagItem = useCallback((value, index, onClose) => ( +
+ + {`${value}`} + + { + onClose(e); + e.stopPropagation(); + e.nativeEvent.stopImmediatePropagation(); + }} /> +
), []); + + return ( + <> + +
+ +
+ + ); +}; Draggable.story = { name: 'draggable', diff --git a/packages/semi-ui/tagInput/index.tsx b/packages/semi-ui/tagInput/index.tsx index f693829a3f..bf1e673b6b 100644 --- a/packages/semi-ui/tagInput/index.tsx +++ b/packages/semi-ui/tagInput/index.tsx @@ -20,8 +20,8 @@ import Input from '../input'; import Popover, { PopoverProps } from '../popover'; import Paragraph from '../typography/paragraph'; import { IconClear, IconHandle } from '@douyinfe/semi-icons'; -import { SortableContainer, SortableElement, SortableHandle } from 'react-sortable-hoc'; import { ShowTooltip } from '../typography'; +import { RenderItemProps, Sortable } from '../_sortable'; const prefixCls = cssClasses.PREFIX; @@ -29,19 +29,9 @@ export type Size = ArrayElement; export type RestTagsPopoverProps = PopoverProps; type ValidateStatus = "default" | "error" | "warning"; -const SortableItem = SortableElement(props => props.item); - -const SortableList = SortableContainer( - ({ items }) => { - return ( -
- {items.map((item, index) => ( - // @ts-ignore skip SortableItem type check - - ))} -
- ); - }); +function SortContainer(props) { + return
; +} export interface TagInputProps { className?: string; @@ -406,6 +396,11 @@ class TagInput extends BaseComponent { } getAllTags = () => { + const { tagsArray } = this.state; + return tagsArray.map((value, index) => this.renderTag(value, index)); + } + + renderTag = (value: any, index: number, sortableHandle?: any) => { const { size, disabled, @@ -413,7 +408,7 @@ class TagInput extends BaseComponent { showContentTooltip, draggable, } = this.props; - const { tagsArray, active } = this.state; + const { active } = this.state; const showIconHandler = active && draggable; const tagCls = cls(`${prefixCls}-wrapper-tag`, { [`${prefixCls}-wrapper-tag-size-${size}`]: size, @@ -426,41 +421,46 @@ class TagInput extends BaseComponent { [`${prefixCls}-drag-item`]: showIconHandler, [`${prefixCls}-wrapper-tag-icon`]: showIconHandler, }); - const DragHandle = SortableHandle(() => ); - return tagsArray.map((value, index) => { - const elementKey = showIconHandler ? value : `${index}${value}`; - const onClose = () => { - !disabled && this.handleTagClose(index); - }; - if (isFunction(renderTagItem)) { - return showIconHandler? (
- - {renderTagItem(value, index, onClose)} -
) : renderTagItem(value, index, onClose); - } else { - return ( - ); + const elementKey = showIconHandler ? value : `${index}${value}`; + const onClose = () => { + !disabled && this.handleTagClose(index); + }; + if (isFunction(renderTagItem)) { + return (
+ {showIconHandler && sortableHandle ? : null} + {renderTagItem(value, index, onClose)} +
); + } else { + return ( + + {showIconHandler && sortableHandle ? : null} + - {showIconHandler && } - - {value} - - - ); - } - }); + {value} + +
+ ); + } + } + + renderSortTag = (props: RenderItemProps) => { + const { id: item, sortableHandle } = props; + const { tagsArray } = this.state; + const index = tagsArray.indexOf(item as string); + return this.renderTag(item, index, sortableHandle); } onSortEnd = (callbackProps: OnSortEndProps) => { @@ -498,9 +498,15 @@ class TagInput extends BaseComponent { })); if (active && draggable && sortableListItems.length > 0) { - // helperClass:add styles to the helper(item being dragged) https://github.com/clauderic/react-sortable-hoc/issues/87 - // @ts-ignore skip SortableItem type check - return ; + return ; } return ( <> diff --git a/packages/semi-ui/transfer/_story/transfer.stories.jsx b/packages/semi-ui/transfer/_story/transfer.stories.jsx index e426d69f61..8e4e208e45 100644 --- a/packages/semi-ui/transfer/_story/transfer.stories.jsx +++ b/packages/semi-ui/transfer/_story/transfer.stories.jsx @@ -1,9 +1,29 @@ -import React, { useState, useRef } from 'react'; +import React, { useState, useRef, useCallback, useEffect, useMemo } from 'react'; +import { createPortal } from 'react-dom'; import { Transfer, Button, Popover, SideSheet, Avatar, Checkbox, Tree, Input, Tag } from '../../index'; -import { omit, values } from 'lodash'; +import { omit, values, isNull } from 'lodash'; import './transfer.scss'; -import { SortableContainer, SortableElement, sortableHandle } from 'react-sortable-hoc'; import { IconClose, IconSearch, IconHandle } from '@douyinfe/semi-icons'; +import { + useSortable, + SortableContext, + sortableKeyboardCoordinates, + verticalListSortingStrategy, +} from '@dnd-kit/sortable'; + +import { CSS as cssDndKit } from '@dnd-kit/utilities'; + +import { + closestCenter, + DragOverlay, + DndContext, + MouseSensor, + TouchSensor, + useSensor, + useSensors, + KeyboardSensor, + TraversalOrder +} from '@dnd-kit/core'; export default { title: 'Transfer' @@ -28,12 +48,12 @@ const commonProps = { }, }; -const data = Array.from({ length: 100 }, (v, i) => { +const data = Array.from({ length: 20 }, (v, i) => { return { label: `选项名称${i}`, value: i, disabled: false, - key: i, + key: `key-${i}`, }; }); @@ -165,7 +185,7 @@ export const TransferDraggableAndDisabled = () => { return { label: `选项名称 ${i}`, value: i, - key: i, + key: `key-${i}`, disabled: true, }; }); @@ -306,8 +326,11 @@ export const CustomFilterRenderSourceItemRenderSelectedItem = () => { ); }; const renderSelectedItem = item => { + const { sortableHandle } = item; + const DragHandle = sortableHandle(() => ); return (
+ {item.abbr} @@ -322,6 +345,7 @@ export const CustomFilterRenderSourceItemRenderSelectedItem = () => { return (
items.indexOf(id), [items]); + const activeIndex = useMemo(() => activeId ? getIndex(activeId) : -1, [getIndex, activeId]); + + const onDragStart = useCallback(({ active }) => { + if (!active) { return; } + setActiveId(active.id); + }, []); + + const onDragEnd = useCallback(({ over }) => { + setActiveId(null); + if (over) { + const overIndex = getIndex(over.id); + if (activeIndex !== overIndex) { + onSortEnd({ oldIndex: activeIndex, newIndex: overIndex }); + } + } + }, [activeIndex, getIndex, onSortEnd]); + + const onDragCancel = useCallback(() => { + setActiveId(null); + }, []); + + return ( + + +
+ {items.map((value, index) => ( + + ))} +
+ {createPortal( + + {activeId ? ( + renderItem({ + id: activeId, + sortableHandle: (WrapperComponent) => WrapperComponent + }) + ) : null} + , + document.body + )} +
+
+ ); +} + +function SortableItem({ getNewIndex, id, renderItem }) { + const { + listeners, + setNodeRef, + transform, + transition, + active, + isOver, + attributes, + } = useSortable({ + id, + getNewIndex, + }); + + const sortableHandle = useCallback((WrapperComponent) => { + return () => ; + }, [listeners]); + + const wrapperStyle = { + transform: cssDndKit.Transform.toString({ + ...transform, + scaleX: 1, + scaleY: 1, + }), + transition: transition, + opacity: active && active.id === id ? 0 : undefined, + }; + + return
+ {renderItem({ id, sortableHandle })} +
; +} + class CustomRenderDragDemo extends React.Component { constructor(props) { - super(props); - this.state = { - dataSource: Array.from({ length: 100 }, (v, i) => ({ - label: `海底捞门店 ${i}`, - value: i, - disabled: false, - key: i, - })), - }; - this.renderSourcePanel = this.renderSourcePanel.bind(this); - this.renderSelectedPanel = this.renderSelectedPanel.bind(this); - this.renderItem = this.renderItem.bind(this); + super(props); + this.state = { + dataSource: Array.from({ length: 10 }, (v, i) => ({ + label: `海底捞门店 ${i}`, + value: i, + disabled: false, + key: `key-${i}`, + })), + }; + this.renderSourcePanel = this.renderSourcePanel.bind(this); + this.renderSelectedPanel = this.renderSelectedPanel.bind(this); + this.renderItem = this.renderItem.bind(this); } - renderItem(type, item, onItemAction, selectedItems) { - let buttonText = '删除'; - let newItem = item; + renderItem(type, item, onItemAction, selectedItems, sortableHandle) { + let buttonText = '删除'; - if (type === 'source') { - let checked = selectedItems.has(item.key); - buttonText = checked ? '删除' : '添加'; - } else { - // delete newItem._optionKey; - newItem = { ...item, key: item._optionKey }; - delete newItem._optionKey; - } - - const DragHandle = sortableHandle(() => ); + if (type === 'source') { + let checked = selectedItems.has(item.key); + buttonText = checked ? '删除' : '添加'; + } - return ( -
- {type === 'source' ? null : } -
-

{item.label}

- -
-
- ); + const DragHandle = (sortableHandle && sortableHandle(() => )); + + return ( +
+ {type === 'source' ? null : ( DragHandle ? : null) } +
+

{item.label}

+ +
+
+ ); } renderSourcePanel(props) { - const { - loading, - noMatch, - filterData, - selectedItems, - allChecked, - onAllClick, - inputValue, - onSearch, - onSelectOrRemove, - } = props; - let content; - switch (true) { - case loading: - content = ; - break; - case noMatch: - content =
{inputValue ? '无搜索结果' : '暂无内容'}
; - break; - case !noMatch: - content = filterData.map(item => - this.renderItem('source', item, onSelectOrRemove, selectedItems) - ); - break; - default: - content = null; - break; - } - return ( -
-
门店列表
-
- } - onChange={onSearch} - showClear - /> -
- 待选门店: {filterData.length} - -
-
{content}
-
-
- ); + const { + loading, + noMatch, + filterData, + selectedItems, + allChecked, + onAllClick, + inputValue, + onSearch, + onSelectOrRemove, + } = props; + let content; + switch (true) { + case loading: + content = ; + break; + case noMatch: + content =
{inputValue ? '无搜索结果' : '暂无内容'}
; + break; + case !noMatch: + content = filterData.map(item => this.renderItem('source', item, onSelectOrRemove, selectedItems)); + break; + default: + content = null; + break; + } + return ( +
+
门店列表
+
+ } + onChange={onSearch} + showClear + /> +
+ 待选门店: {filterData.length} + +
+
{content}
+
+
+ ); } renderSelectedPanel(props) { - const { selectedData, onClear, clearText, onRemove, onSortEnd } = props; - - let mainContent = null; - - if (!selectedData.length) { - mainContent =
暂无数据,请从左侧筛选
; - } + const { selectedData, onClear, clearText, onRemove, onSortEnd } = props; + let mainContent = null; - const SortableItem = SortableElement(item => this.renderItem('selected', item, onRemove)); - const SortableList = SortableContainer( - ({ items }) => { - return ( -
- {items.map((item, index) => ( - // sortableElement will take over the property 'key', so use another '_optionKey' to pass - // otherwise you can't get `key` property in this.renderItem - - ))} -
- ); - }, - { distance: 10 } - ); + if (!selectedData.length) { + mainContent =
暂无数据,请从左侧筛选
; + } - mainContent = ( - - ); + const renderSelectItem = ({ id, sortableHandle }) => { + const item = selectedData.find(item => id === item.key); + return this.renderItem('selected', item, onRemove, null, sortableHandle); + }; - return ( -
-
-
已选同步门店: {selectedData.length}
- -
- {mainContent} -
- ); + const sortData = selectedData.map(item => item.key); + + mainContent =
+ +
; + + return ( +
+
+
已选同步门店: {selectedData.length}
+ +
+ {mainContent} +
+ ); } render() { - const { dataSource } = this.state; - return ( - console.log(values)} - className="component-transfer-demo-custom-panel" - renderSourcePanel={this.renderSourcePanel} - renderSelectedPanel={this.renderSelectedPanel} - dataSource={dataSource} - /> - ); + const { dataSource } = this.state; + return ( + console.log(values)} + className="component-transfer-demo-custom-panel" + renderSourcePanel={this.renderSourcePanel} + renderSelectedPanel={this.renderSelectedPanel} + dataSource={dataSource} + /> + ); } } diff --git a/packages/semi-ui/transfer/index.tsx b/packages/semi-ui/transfer/index.tsx index ee1dc2bf46..46dc2f79d6 100644 --- a/packages/semi-ui/transfer/index.tsx +++ b/packages/semi-ui/transfer/index.tsx @@ -1,6 +1,5 @@ import React from 'react'; import cls from 'classnames'; -import { SortableContainer, SortableElement, SortableHandle } from 'react-sortable-hoc'; import PropTypes from 'prop-types'; import { isEqual, noop, omit, isEmpty, isArray, pick } from 'lodash'; import TransferFoundation, { TransferAdapter, BasicDataItem, OnSortEndProps } from '@douyinfe/semi-foundation/transfer/foundation'; @@ -17,6 +16,8 @@ import Button from '../button'; import Tree from '../tree'; import { IconClose, IconSearch, IconHandle } from '@douyinfe/semi-icons'; import { Value as TreeValue, TreeProps } from '../tree/interface'; +import { RenderItemProps, Sortable } from '../_sortable'; +import { verticalListSortingStrategy } from '@dnd-kit/sortable'; export interface DataItem extends BasicDataItem { label?: React.ReactNode; @@ -39,7 +40,7 @@ export interface RenderSourceItemProps extends DataItem { export interface RenderSelectedItemProps extends DataItem { onRemove?: () => void; - sortableHandle?: typeof SortableHandle + sortableHandle?: any } export interface EmptyContent { @@ -168,22 +169,6 @@ export interface TransferProps { } const prefixCls = cssClasses.PREFIX; - -// SortableItem & SortableList should not be assigned inside of the render function -const SortableItem = SortableElement(( - (props: DraggableResolvedDataItem) => (props.item.node as React.FC) -)); - -const SortableList = SortableContainer(({ items }: { items: Array }) => ( -
- {items.map((item, index: number) => ( - // @ts-ignore skip SortableItem type check - - ))} -
- // @ts-ignore see reasons: https://github.com/clauderic/react-sortable-hoc/issues/206 -), { distance: 10 }); - class Transfer extends BaseComponent { static propTypes = { style: PropTypes.object, @@ -569,7 +554,7 @@ class Transfer extends BaseComponent { return
{content}
; } - renderRightItem(item: ResolvedDataItem): React.ReactNode { + renderRightItem = (item: ResolvedDataItem, sortableHandle?: any): React.ReactNode => { const { renderSelectedItem, draggable, type, showPath } = this.props; const onRemove = () => this.foundation.handleSelectOrRemove(item); const rightItemCls = cls({ @@ -582,17 +567,17 @@ class Transfer extends BaseComponent { const label = shouldShowPath ? this.foundation._generatePath(item) : item.label; if (renderSelectedItem) { - return renderSelectedItem({ ...item, onRemove, sortableHandle: SortableHandle }); + return renderSelectedItem({ ...item, onRemove, sortableHandle }); } - const DragHandle = SortableHandle(() => ( + const DragHandle = sortableHandle && sortableHandle(() => ( )); return ( // https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex
- {draggable ? : null} + {draggable && sortableHandle ? : null}
{label}
{ ); } + renderSortItem = (props: RenderItemProps): React.ReactNode => { + const { id, sortableHandle } = props; + const { selectedItems } = this.state; + const selectedData = [...selectedItems.values()]; + const item = selectedData.find(item => item.key === id); + return this.renderRightItem(item, sortableHandle); + } + renderEmpty(type: string, emptyText: React.ReactNode) { const emptyCls = cls({ [`${prefixCls}-empty`]: true, @@ -615,14 +608,15 @@ class Transfer extends BaseComponent { } renderRightSortableList(selectedData: Array) { - const sortableListItems = selectedData.map(item => ({ - ...item, - node: this.renderRightItem(item) - })); - - // helperClass:add styles to the helper(item being dragged) https://github.com/clauderic/react-sortable-hoc/issues/87 - // @ts-ignore skip SortableItem type check - const sortList = ; + const sortItems = selectedData.map(item => item.key); + const sortList = ; return sortList; } diff --git a/src/templates/scope.js b/src/templates/scope.js index 60848ab4b3..89810c4334 100644 --- a/src/templates/scope.js +++ b/src/templates/scope.js @@ -126,3 +126,24 @@ export { export { debounce, throttle, range, get, filter, map, some }; export { zh_CN, en_GB, en_US, ko_KR, ja_JP, ar, vi_VN, ru_RU, id_ID, ms_MY, th_TH, tr_TR, pt_BR, zh_TW, nl_NL, pl_PL, sv_SE, es, de, it, fr, ro }; + +export { + useSortable, + SortableContext, + sortableKeyboardCoordinates, + verticalListSortingStrategy, +} from '@dnd-kit/sortable'; + +export { CSS as cssDndKit } from '@dnd-kit/utilities'; + +export { + closestCenter, + DragOverlay, + DndContext, + MouseSensor, + TouchSensor, + useSensor, + useSensors, + KeyboardSensor, + TraversalOrder +} from '@dnd-kit/core'; diff --git a/yarn.lock b/yarn.lock index 14ec2c17e5..0b64b7ee24 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1479,6 +1479,37 @@ resolved "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70" integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw== +"@dnd-kit/accessibility@^3.0.0": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@dnd-kit/accessibility/-/accessibility-3.0.1.tgz#3ccbefdfca595b0a23a5dc57d3de96bc6935641c" + integrity sha512-HXRrwS9YUYQO9lFRc/49uO/VICbM+O+ZRpFDe9Pd1rwVv2PCNkRiTZRdxrDgng/UkvdC3Re9r2vwPpXXrWeFzg== + dependencies: + tslib "^2.0.0" + +"@dnd-kit/core@^6.0.8": + version "6.0.8" + resolved "https://registry.yarnpkg.com/@dnd-kit/core/-/core-6.0.8.tgz#040ae13fea9787ee078e5f0361f3b49b07f3f005" + integrity sha512-lYaoP8yHTQSLlZe6Rr9qogouGUz9oRUj4AHhDQGQzq/hqaJRpFo65X+JKsdHf8oUFBzx5A+SJPUvxAwTF2OabA== + dependencies: + "@dnd-kit/accessibility" "^3.0.0" + "@dnd-kit/utilities" "^3.2.1" + tslib "^2.0.0" + +"@dnd-kit/sortable@^7.0.2": + version "7.0.2" + resolved "https://registry.yarnpkg.com/@dnd-kit/sortable/-/sortable-7.0.2.tgz#791d550872457f3f3c843e00d159b640f982011c" + integrity sha512-wDkBHHf9iCi1veM834Gbk1429bd4lHX4RpAwT0y2cHLf246GAvU2sVw/oxWNpPKQNQRQaeGXhAVgrOl1IT+iyA== + dependencies: + "@dnd-kit/utilities" "^3.2.0" + tslib "^2.0.0" + +"@dnd-kit/utilities@^3.2.0", "@dnd-kit/utilities@^3.2.1": + version "3.2.1" + resolved "https://registry.yarnpkg.com/@dnd-kit/utilities/-/utilities-3.2.1.tgz#53f9e2016fd2506ec49e404c289392cfff30332a" + integrity sha512-OOXqISfvBw/1REtkSK2N3Fi2EQiLMlWUlqnOK/UpOISqBZPWpE6TqL+jcPtMOkE8TqYGiURvRdPSI9hltNUjEA== + dependencies: + tslib "^2.0.0" + "@douyinfe/semi-animation-react@2.33.1": version "2.33.1" resolved "https://registry.npmjs.org/@douyinfe/semi-animation-react/-/semi-animation-react-2.33.1.tgz#353ce23968f27d4443bb2529cfd210f84d424034" From 50557124f9f191a4759440d0860365211b34e99e Mon Sep 17 00:00:00 2001 From: linyan Date: Mon, 7 Aug 2023 14:54:56 +0800 Subject: [PATCH 07/29] docs(changelog): v2.41.0-beta.0 update --- content/start/changelog/index-en-US.md | 9 +++ content/start/changelog/index.md | 9 +++ yarn.lock | 92 +++++++++----------------- 3 files changed, 49 insertions(+), 61 deletions(-) diff --git a/content/start/changelog/index-en-US.md b/content/start/changelog/index-en-US.md index 1a9dcdc232..115614d233 100644 --- a/content/start/changelog/index-en-US.md +++ b/content/start/changelog/index-en-US.md @@ -16,6 +16,15 @@ Version:Major.Minor.Patch (follow the **Semver** specification) --- +#### 🎉 2.41.0-beta.0 (2023-08-07) +- 【Refactor】 + - change react-sortable-hoc to @dnd-kit/sortable for Transfer/Taginput drag & drop [#1683](https://github.com/DouyinFE/semi-design/issues/1683) +- 【Style】 + - The interaction of the Taginput dragging process has been modified, from the change of the tag position in the original dragging to the vertical line in front of the tag to mark the position where the tag in the dragging can be dropped. TagInput adds drag-related tokens, $width-tagInput_sortable_item_over, $color-tagInput_sortable_item_over-bg [#1738](https://github.com/DouyinFE/semi-design/pull/1738) +- 【Fix】 + - fix wrong type definition for defaultCurrentIndex in ImagePreview + - fix document is not defined error [@nekocode](https://github.com/nekocode) + #### 🎉 2.40.0 (2023-07-28) - 【Style】 - Remove unnecessary margin in button component [#1732](https://github.com/DouyinFE/semi-design/pull/1732) diff --git a/content/start/changelog/index.md b/content/start/changelog/index.md index 7b430e1592..a43aa3e568 100644 --- a/content/start/changelog/index.md +++ b/content/start/changelog/index.md @@ -13,6 +13,15 @@ Semi 版本号遵循 **Semver** 规范(主版本号-次版本号-修订版本 - 修订版本号(patch):仅会进行 bugfix,发布时间不限 - 不同版本间的详细关系,可查阅 [FAQ](/zh-CN/start/faq) +#### 🎉 2.41.0-beta.0 (2023-08-07) +- 【Refactor】 + - 使用 @dnd-kit/sortable 替换 react-sortable-hoc 实现 Transfer/Taginput 中拖拽 [#1683](https://github.com/DouyinFE/semi-design/issues/1683) +- 【Style】 + - Taginput 拖拽过程交互有修改,从原来的拖拽中 tag 位置发生变化修改为通过 tag 前的竖线标识拖拽中的 tag 可被放下的位置。TagInput 新增和拖拽相关的 token,$width-tagInput_sortable_item_over,$color-tagInput_sortable_item_over-bg [#1738](https://github.com/DouyinFE/semi-design/pull/1738) +- 【Fix】 + - 修复 ImagePreview 中 defaultCurrentIndex 错误的类型定义 + - 修复 document is not defined 错误 [@nekocode](https://github.com/nekocode) + #### 🎉 2.40.0 (2023-07-28) - 【Style】 - 删除 Button 组件中的不必要的 margin [#1732](https://github.com/DouyinFE/semi-design/pull/1732) diff --git a/yarn.lock b/yarn.lock index 0b64b7ee24..682e15226a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1519,13 +1519,13 @@ "@douyinfe/semi-animation-styled" "2.23.2" classnames "^2.2.6" -"@douyinfe/semi-animation-react@2.39.3": - version "2.39.3" - resolved "https://registry.yarnpkg.com/@douyinfe/semi-animation-react/-/semi-animation-react-2.39.3.tgz#b46cc2a9db9f489e52f62965bb9857708f37f73e" - integrity sha512-sMf2cKmFIMVWFdQlTyMXO917oOvjDq+KOTGLyO9rVIZDK0mFU9VM/jToYngKaUU+f6kvNZcLdx+PUxKQEfZ7hQ== +"@douyinfe/semi-animation-react@2.40.0-beta.0": + version "2.40.0-beta.0" + resolved "https://registry.yarnpkg.com/@douyinfe/semi-animation-react/-/semi-animation-react-2.40.0-beta.0.tgz#c42c2248c0468cb477df3d92ac14573bfb65f0bb" + integrity sha512-b68hGH8JqMGlGRwn0UNTx8zTSXb2oRgERyVziisVSlco6nhnp29CtAOLZuTxQrgHX9OEfA/Jz07ancg1ebqqUw== dependencies: - "@douyinfe/semi-animation" "2.39.3" - "@douyinfe/semi-animation-styled" "2.39.3" + "@douyinfe/semi-animation" "2.40.0-beta.0" + "@douyinfe/semi-animation-styled" "2.40.0-beta.0" classnames "^2.2.6" "@douyinfe/semi-animation-styled@2.23.2": @@ -1533,10 +1533,10 @@ 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/semi-animation-styled@2.39.3": - version "2.39.3" - resolved "https://registry.yarnpkg.com/@douyinfe/semi-animation-styled/-/semi-animation-styled-2.39.3.tgz#4818e43b9fc646e9a3304ec2081f50c84a168aa1" - integrity sha512-mMExH5PXvCW2D8rtbG8pk53L9pYyBa8QNDoB2nNMrFlGSvHU+o/1UJ0Y504rUZ0LMsi2QJChP8Ry4mqzINN2sg== +"@douyinfe/semi-animation-styled@2.40.0-beta.0": + version "2.40.0-beta.0" + resolved "https://registry.yarnpkg.com/@douyinfe/semi-animation-styled/-/semi-animation-styled-2.40.0-beta.0.tgz#8907a9bbdba1f77aecd46a276eae001249a3aaee" + integrity sha512-+ez2aIIGnjMYr5u7mM747GqISBFnC2Zby/njMm+AL90gg7JTPU9jmIocaKF38W23DbDocdl/iGop1FNAq3fbvA== "@douyinfe/semi-animation@2.12.0": version "2.12.0" @@ -1553,10 +1553,10 @@ dependencies: bezier-easing "^2.1.0" -"@douyinfe/semi-animation@2.39.3": - version "2.39.3" - resolved "https://registry.yarnpkg.com/@douyinfe/semi-animation/-/semi-animation-2.39.3.tgz#d8c21be360431b48a8ea8856920cf4d534e68c93" - integrity sha512-KI8O8mvuZiZPNwiK+OUSO/DjPcXLs7sdopPdN3g9WSR7ipPJKmorOZzAG2OTUDH0b4diQYd8gs/YIiFfU+UoOw== +"@douyinfe/semi-animation@2.40.0-beta.0": + version "2.40.0-beta.0" + resolved "https://registry.yarnpkg.com/@douyinfe/semi-animation/-/semi-animation-2.40.0-beta.0.tgz#c8cfa769550fc6dc146956b37804b6be331625a3" + integrity sha512-YJhZalmBpo2BOAILasMgJnn7ybzKHSfGFVmbManuA1yP9GW4J3mF/HWthml5PVqNmeXGkLjjHJyrGJ7d9OZizQ== dependencies: bezier-easing "^2.1.0" @@ -1574,12 +1574,12 @@ memoize-one "^5.2.1" scroll-into-view-if-needed "^2.2.24" -"@douyinfe/semi-foundation@2.39.3": - version "2.39.3" - resolved "https://registry.yarnpkg.com/@douyinfe/semi-foundation/-/semi-foundation-2.39.3.tgz#6490340494d8ea40981c41123b02fd4ab64cbe2c" - integrity sha512-yTjJYd4BiTdbxt0tCLPJCe3IDCdOEuMjaslDU2TLE3oVs5aTfEcnS2HjioSFgsLPSqEgk8jCdwQDD7eaf+pruA== +"@douyinfe/semi-foundation@2.40.0-beta.0": + version "2.40.0-beta.0" + resolved "https://registry.yarnpkg.com/@douyinfe/semi-foundation/-/semi-foundation-2.40.0-beta.0.tgz#dfaced34afa05cead1cb09d344239b8344755ca1" + integrity sha512-7tGu97gosYo5mCuPXqm9z8bYTuaAXt5U+6mq4VSrHcqpllOfGed3YvHPRDTz6JRKT7/PR+1yzK01VMzwy8P4zw== dependencies: - "@douyinfe/semi-animation" "2.39.3" + "@douyinfe/semi-animation" "2.40.0-beta.0" async-validator "^3.5.0" classnames "^2.2.6" date-fns "^2.29.3" @@ -1595,10 +1595,10 @@ dependencies: classnames "^2.2.6" -"@douyinfe/semi-icons@2.39.3", "@douyinfe/semi-icons@^2.0.0": - version "2.39.3" - resolved "https://registry.yarnpkg.com/@douyinfe/semi-icons/-/semi-icons-2.39.3.tgz#0e21bbcdd3705b8f1570935b0096ee3847bed34f" - integrity sha512-l/Wq0ytYecSO1AbNIuLgDdlJfi1nOMLm5aZoPCJRLU6qRASPjQhpgV1inf050FlVFVfK1ocIiyOyjkTP9sEpNg== +"@douyinfe/semi-icons@2.40.0-beta.0": + version "2.40.0-beta.0" + resolved "https://registry.yarnpkg.com/@douyinfe/semi-icons/-/semi-icons-2.40.0-beta.0.tgz#456505d15a35380bdcb4b25a2d075223b574e68a" + integrity sha512-J4BLLG1ShXoZ9wJaKhJ8b0fKHgPNUfzy2t+/FkWIfw9FF5Y14TMA51YzLKR6DY+s8ZKpikzO7PG/xmu3qqdrkg== dependencies: classnames "^2.2.6" @@ -1607,10 +1607,10 @@ resolved "https://registry.npmjs.org/@douyinfe/semi-illustrations/-/semi-illustrations-2.33.1.tgz#530ab851f4dc32a52221c4067c778c800b9b55d7" integrity sha512-tTTUN8QwnQiF++sk4VBNzfkG87aYZ4iUeqk2ys8/ymVUmCZQ7y46ys020GO1MfPHRR47OMFPI82FVcH1WQtE3g== -"@douyinfe/semi-illustrations@2.39.3": - version "2.39.3" - resolved "https://registry.yarnpkg.com/@douyinfe/semi-illustrations/-/semi-illustrations-2.39.3.tgz#1a0d7bd523e16244efa08004ad6169994cd13bf2" - integrity sha512-/bZNcAMRKk4cigH+ltAmTIxltR8aWrsiVUXdvBkf0txzv/NSXMRFNGehE3JFxiw728iE5P6B6AbJdDi64dKYqA== +"@douyinfe/semi-illustrations@2.40.0-beta.0": + version "2.40.0-beta.0" + resolved "https://registry.yarnpkg.com/@douyinfe/semi-illustrations/-/semi-illustrations-2.40.0-beta.0.tgz#1fb83134d67c06425eb85e65a527c37806cc397d" + integrity sha512-/JHPg8lX80a1L9qzF0Vf7vBkQ6n9fy2EcDAJDF1qx1+Eh3GaFi4Wi9ngbRPrla9cVdmsHyTTAUMoypxwoHMHVg== "@douyinfe/semi-scss-compile@2.23.2": version "2.23.2" @@ -1685,38 +1685,13 @@ dependencies: glob "^7.1.6" -"@douyinfe/semi-theme-default@2.39.3": - version "2.39.3" - resolved "https://registry.yarnpkg.com/@douyinfe/semi-theme-default/-/semi-theme-default-2.39.3.tgz#a02a5b20890587c674eb7c3b2550551f42b933a0" - integrity sha512-dTTD8nkzM0ad1Lli9cFYLqvmTsSvKp5NSIc35UQBZcvi7OvmUA7qaSMentEMgl15bVWKInwCvp+mSFJsDtDPlg== +"@douyinfe/semi-theme-default@2.40.0-beta.0": + version "2.40.0-beta.0" + resolved "https://registry.yarnpkg.com/@douyinfe/semi-theme-default/-/semi-theme-default-2.40.0-beta.0.tgz#f0f3e04870b24d229fcb89fcc9ffcb6fee1eb964" + integrity sha512-fi9OCHVG3kY+bntiTfLkUz0BzC3xnzFFrvp+Wqg68OC11osLZMR5kKuAUFj/mskTsuUyikGI0lx/dIi0IMNNFw== dependencies: glob "^7.1.6" -"@douyinfe/semi-ui@^2.0.0": - version "2.39.3" - resolved "https://registry.yarnpkg.com/@douyinfe/semi-ui/-/semi-ui-2.39.3.tgz#081297781163882882e501686c76356804bd9555" - integrity sha512-xrQ9Xd1B4vhDK41RjN4AFxDD/ILuR9HTctJZ0Be+mio8xIifINtD2jD5xXB1pV+DE/43jtu30VzNlvLm/0TQbw== - dependencies: - "@douyinfe/semi-animation" "2.39.3" - "@douyinfe/semi-animation-react" "2.39.3" - "@douyinfe/semi-foundation" "2.39.3" - "@douyinfe/semi-icons" "2.39.3" - "@douyinfe/semi-illustrations" "2.39.3" - "@douyinfe/semi-theme-default" "2.39.3" - 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 "^1.8.0" - react-sortable-hoc "^2.0.0" - react-window "^1.8.2" - resize-observer-polyfill "^1.5.1" - scroll-into-view-if-needed "^2.2.24" - utility-types "^3.10.0" - "@douyinfe/semi-ui@latest": version "2.33.1" resolved "https://registry.yarnpkg.com/@douyinfe/semi-ui/-/semi-ui-2.33.1.tgz#3234ca96eb3560b8299bc9750fbe59446522d9bb" @@ -11284,11 +11259,6 @@ 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.39.3" - resolved "https://registry.yarnpkg.com/eslint-plugin-semi-design/-/eslint-plugin-semi-design-2.39.3.tgz#ceab48928648acd0fef41ea5ef97b17268aec70b" - integrity sha512-9oX8xdmLR9IZPZ4JpMd/1V+e2ebQ7gcqax2kgzl0ICY0iWvb40WrF+tvnkI92OVlD7OLqMlxv//Q83vkKoZ2fA== - 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" From f83f6076d1c6f3b64c1d9359a335a7182d991fb6 Mon Sep 17 00:00:00 2001 From: semi-bot Date: Mon, 7 Aug 2023 07:00:32 +0000 Subject: [PATCH 08/29] v2.41.0-beta.0 --- lerna.json | 2 +- packages/semi-animation-react/package.json | 6 +++--- packages/semi-animation-styled/package.json | 2 +- packages/semi-animation/package.json | 2 +- packages/semi-eslint-plugin/package.json | 2 +- packages/semi-foundation/package.json | 4 ++-- packages/semi-icons/package.json | 2 +- packages/semi-illustrations/package.json | 2 +- packages/semi-next/package.json | 4 ++-- packages/semi-rspack/package.json | 2 +- packages/semi-scss-compile/package.json | 2 +- packages/semi-theme-default/package.json | 2 +- packages/semi-ui/package.json | 8 ++++---- packages/semi-webpack/package.json | 2 +- 14 files changed, 21 insertions(+), 21 deletions(-) diff --git a/lerna.json b/lerna.json index f4ca41f2b6..ddc9784c5f 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { "useWorkspaces": true, "npmClient": "yarn", - "version": "2.40.0" + "version": "2.41.0-beta.0" } diff --git a/packages/semi-animation-react/package.json b/packages/semi-animation-react/package.json index 795dbc162f..fea3dbb7b3 100644 --- a/packages/semi-animation-react/package.json +++ b/packages/semi-animation-react/package.json @@ -1,6 +1,6 @@ { "name": "@douyinfe/semi-animation-react", - "version": "2.40.0", + "version": "2.41.0-beta.0", "description": "motion library for semi-ui-react", "keywords": [ "motion", @@ -25,8 +25,8 @@ "prepublishOnly": "npm run build:lib" }, "dependencies": { - "@douyinfe/semi-animation": "2.40.0", - "@douyinfe/semi-animation-styled": "2.40.0", + "@douyinfe/semi-animation": "2.41.0-beta.0", + "@douyinfe/semi-animation-styled": "2.41.0-beta.0", "classnames": "^2.2.6" }, "devDependencies": { diff --git a/packages/semi-animation-styled/package.json b/packages/semi-animation-styled/package.json index 4b98b1c447..b90add74ba 100644 --- a/packages/semi-animation-styled/package.json +++ b/packages/semi-animation-styled/package.json @@ -1,6 +1,6 @@ { "name": "@douyinfe/semi-animation-styled", - "version": "2.40.0", + "version": "2.41.0-beta.0", "description": "semi styled animation", "keywords": [ "semi", diff --git a/packages/semi-animation/package.json b/packages/semi-animation/package.json index 42d84ab8d5..bb9413f041 100644 --- a/packages/semi-animation/package.json +++ b/packages/semi-animation/package.json @@ -1,6 +1,6 @@ { "name": "@douyinfe/semi-animation", - "version": "2.40.0", + "version": "2.41.0-beta.0", "description": "animation base library for semi-ui", "keywords": [ "animation", diff --git a/packages/semi-eslint-plugin/package.json b/packages/semi-eslint-plugin/package.json index a6d9424cfe..a6a7c825ff 100644 --- a/packages/semi-eslint-plugin/package.json +++ b/packages/semi-eslint-plugin/package.json @@ -1,6 +1,6 @@ { "name": "eslint-plugin-semi-design", - "version": "2.40.0", + "version": "2.41.0-beta.0", "description": "semi ui eslint plugin", "keywords": [ "semi", diff --git a/packages/semi-foundation/package.json b/packages/semi-foundation/package.json index 75e1b2f41d..31c4dbd326 100644 --- a/packages/semi-foundation/package.json +++ b/packages/semi-foundation/package.json @@ -1,13 +1,13 @@ { "name": "@douyinfe/semi-foundation", - "version": "2.40.0", + "version": "2.41.0-beta.0", "description": "", "scripts": { "build:lib": "node ./scripts/compileLib.js", "prepublishOnly": "npm run build:lib" }, "dependencies": { - "@douyinfe/semi-animation": "2.40.0", + "@douyinfe/semi-animation": "2.41.0-beta.0", "async-validator": "^3.5.0", "classnames": "^2.2.6", "date-fns": "^2.29.3", diff --git a/packages/semi-icons/package.json b/packages/semi-icons/package.json index 280a0ec6d7..3b1247e73a 100644 --- a/packages/semi-icons/package.json +++ b/packages/semi-icons/package.json @@ -1,6 +1,6 @@ { "name": "@douyinfe/semi-icons", - "version": "2.40.0", + "version": "2.41.0-beta.0", "description": "semi icons", "keywords": [ "semi", diff --git a/packages/semi-illustrations/package.json b/packages/semi-illustrations/package.json index 154c7c7ed1..86c0c26cc1 100644 --- a/packages/semi-illustrations/package.json +++ b/packages/semi-illustrations/package.json @@ -1,6 +1,6 @@ { "name": "@douyinfe/semi-illustrations", - "version": "2.40.0", + "version": "2.41.0-beta.0", "description": "semi illustrations", "keywords": [ "semi", diff --git a/packages/semi-next/package.json b/packages/semi-next/package.json index cfde877b79..3b5c674f74 100644 --- a/packages/semi-next/package.json +++ b/packages/semi-next/package.json @@ -1,6 +1,6 @@ { "name": "@douyinfe/semi-next", - "version": "2.40.0", + "version": "2.41.0-beta.0", "description": "Plugin that support Semi Design in Next.js", "author": "伍浩威 ", "homepage": "", @@ -23,7 +23,7 @@ "typescript": "^4" }, "dependencies": { - "@douyinfe/semi-webpack-plugin": "2.40.0" + "@douyinfe/semi-webpack-plugin": "2.41.0-beta.0" }, "gitHead": "eb34a4f25f002bb4cbcfa51f3df93bed868c831a" } diff --git a/packages/semi-rspack/package.json b/packages/semi-rspack/package.json index ce99565fcd..f544b63b40 100644 --- a/packages/semi-rspack/package.json +++ b/packages/semi-rspack/package.json @@ -1,6 +1,6 @@ { "name": "@douyinfe/semi-rspack-plugin", - "version": "2.40.0", + "version": "2.41.0-beta.0", "description": "", "homepage": "", "license": "MIT", diff --git a/packages/semi-scss-compile/package.json b/packages/semi-scss-compile/package.json index 624b38cb55..bc6636723d 100644 --- a/packages/semi-scss-compile/package.json +++ b/packages/semi-scss-compile/package.json @@ -1,6 +1,6 @@ { "name": "@douyinfe/semi-scss-compile", - "version": "2.40.0", + "version": "2.41.0-beta.0", "description": "compile semi scss to css", "author": "daiqiang@bytedance.com", "license": "MIT", diff --git a/packages/semi-theme-default/package.json b/packages/semi-theme-default/package.json index 5621991b9b..fecaf2bfde 100644 --- a/packages/semi-theme-default/package.json +++ b/packages/semi-theme-default/package.json @@ -1,6 +1,6 @@ { "name": "@douyinfe/semi-theme-default", - "version": "2.40.0", + "version": "2.41.0-beta.0", "description": "semi-theme-default", "keywords": [ "semi-theme", diff --git a/packages/semi-ui/package.json b/packages/semi-ui/package.json index f29b7adf21..70dc564f41 100644 --- a/packages/semi-ui/package.json +++ b/packages/semi-ui/package.json @@ -1,6 +1,6 @@ { "name": "@douyinfe/semi-ui", - "version": "2.40.0", + "version": "2.41.0-beta.0", "description": "", "main": "lib/cjs/index.js", "module": "lib/es/index.js", @@ -17,15 +17,15 @@ "lib/*" ], "dependencies": { + "@dnd-kit/core": "^6.0.8", + "@dnd-kit/sortable": "^7.0.2", + "@dnd-kit/utilities": "^3.2.1", "@douyinfe/semi-animation": "2.40.0-beta.0", "@douyinfe/semi-animation-react": "2.40.0-beta.0", "@douyinfe/semi-foundation": "2.40.0-beta.0", "@douyinfe/semi-icons": "2.40.0-beta.0", "@douyinfe/semi-illustrations": "2.40.0-beta.0", "@douyinfe/semi-theme-default": "2.40.0-beta.0", - "@dnd-kit/core": "^6.0.8", - "@dnd-kit/sortable": "^7.0.2", - "@dnd-kit/utilities": "^3.2.1", "async-validator": "^3.5.0", "classnames": "^2.2.6", "copy-text-to-clipboard": "^2.1.1", diff --git a/packages/semi-webpack/package.json b/packages/semi-webpack/package.json index ed1d266eba..5f2090bcf3 100644 --- a/packages/semi-webpack/package.json +++ b/packages/semi-webpack/package.json @@ -1,6 +1,6 @@ { "name": "@douyinfe/semi-webpack-plugin", - "version": "2.40.0", + "version": "2.41.0-beta.0", "description": "", "author": "伍浩威 ", "homepage": "", From f28dbe65c94d987fc12243bb952ff20b7ce0cff5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BB=A3=E5=BC=BA?= Date: Mon, 7 Aug 2023 17:38:14 +0800 Subject: [PATCH 09/29] Feat: add sitemap && generate script (#1754) * feat: add sitemap && generate script * chore: update sitemap * chore: update sitemap --- package.json | 4 +- scripts/sitemap_update.js | 77 ++ sitemap.xml | 1501 +++++++++++++++++++++++++++++++++++++ yarn.lock | 126 +--- 4 files changed, 1608 insertions(+), 100 deletions(-) create mode 100644 scripts/sitemap_update.js create mode 100644 sitemap.xml diff --git a/package.json b/package.json index 9f0cf421f7..25cbb20990 100644 --- a/package.json +++ b/package.json @@ -101,7 +101,9 @@ "unist-util-remove": "^1.0.3", "unist-util-visit": "^2.0.3", "wait-on": "^6.0.1", - "wcag-color": "^1.1.1" + "wcag-color": "^1.1.1", + "fast-xml-parser": "^4.2.7", + "execa": "5" }, "devDependencies": { "@actions/core": "^1.6.0", diff --git a/scripts/sitemap_update.js b/scripts/sitemap_update.js new file mode 100644 index 0000000000..1544bf10d2 --- /dev/null +++ b/scripts/sitemap_update.js @@ -0,0 +1,77 @@ +const axios = require("axios"); +const fastXML = require("fast-xml-parser"); +const fs = require("fs/promises"); +const execa = require("execa"); +const xmlPath = "./sitemap.xml"; + + +const getData = async ()=>{ + const xmlRaw = await fs.readFile(xmlPath, "utf8"); + const { XMLParser, XMLBuilder, XMLValidator } = fastXML; + const parser = new XMLParser({ + ignoreAttributes: false, + ignoreNameSpace: false, + }); + let jsObj = parser.parse(xmlRaw); + + return jsObj; +}; + +const writeData = async (jsObj)=>{ + const { XMLBuilder } = fastXML; + const builder = new XMLBuilder({ + indentBy: " ", + format: true, + ignoreAttributes: false, + ignoreNameSpace: false, + }); + const xmlContent = builder.build(jsObj); + await fs.writeFile(xmlPath, xmlContent); +}; + + +const main = async ()=>{ + const data = await getData(); + const urlMap = {}; + data['urlset'].url.forEach(item=>{ + urlMap[item.loc] = item; + }); + const promiseList = []; + let count = 0; + const urls = Object.keys(urlMap); + const updatedArr = []; + urls.forEach((url)=>{ + const item = urlMap[url]; + promiseList.push(new Promise(async resolve=>{ + const res = await axios.get(url); + if (url.startsWith("https://semi.design/zh-CN") || url.startsWith("https://semi.design/en-US")) { + const lang = url.startsWith("https://semi.design/zh-CN") ? "zh-CN" : "en-US"; + const mdRelativePath = url.replace(`https://semi.design/${lang}/`, ""); + const mdPath = `./content/${mdRelativePath}/${lang==="zh-CN"?"index.md":"index-en-US.md"}`; + const seconds = execa.commandSync(`echo $(git log -1 --pretty="format:%ct" ${mdPath})`, { shell: true }).stdout; + item.lastmod = new Date(seconds * 1000).toISOString(); + } else { + const scm = res.headers['X-Deploy-Scm-Version'] || res.headers['X-Deploy-Scm-Version'.toLowerCase()] || res.headers['X-Deploy-Scm-Version'.toUpperCase()]; + if (item['scm'] && item['scm']!==scm || !item['scm']) { + item['scm'] = scm; + item.lastmod = new Date().toISOString(); + } + } + count++; + console.log(`SiteMap processed ${url} ${count}/${urls.length}`); + resolve(); + }).catch(e=>{ + console.log("error", e, url); + }).finally(()=>{ + updatedArr.push(item); + })); + }); + await Promise.all(promiseList); + updatedArr.sort((itemA, itemB)=>{ + return itemA.loc.localeCompare(itemB.loc); + }); + data['urlset'].url = updatedArr; + await writeData(data); +}; + +main(); diff --git a/sitemap.xml b/sitemap.xml new file mode 100644 index 0000000000..6b2420589b --- /dev/null +++ b/sitemap.xml @@ -0,0 +1,1501 @@ + + + + https://semi.design/code/en-US + 2023-08-07T07:46:38.267Z + weekly + 1.0.0.53 + + + https://semi.design/code/en-US/about/contact + 2023-08-07T07:46:38.259Z + weekly + 1.0.0.53 + + + https://semi.design/code/en-US/about/known-issues + 2023-08-07T07:46:38.260Z + weekly + 1.0.0.53 + + + https://semi.design/code/en-US/about/roadmap + 2023-08-07T07:46:38.254Z + weekly + 1.0.0.53 + + + https://semi.design/code/en-US/about/schema + 2023-08-07T07:46:38.274Z + weekly + 1.0.0.53 + + + https://semi.design/code/en-US/d2c/inspect + 2023-08-07T07:46:38.300Z + weekly + 1.0.0.53 + + + https://semi.design/code/en-US/d2c/mark + 2023-08-07T07:46:38.297Z + weekly + 1.0.0.53 + + + https://semi.design/code/en-US/d2c/mark-icon + 2023-08-07T07:46:38.263Z + weekly + 1.0.0.53 + + + https://semi.design/code/en-US/d2c/mark-library + 2023-08-07T07:46:38.271Z + weekly + 1.0.0.53 + + + https://semi.design/code/en-US/d2c/mark-table + 2023-08-07T07:46:38.294Z + weekly + 1.0.0.53 + + + https://semi.design/code/en-US/d2c/settings + 2023-08-07T07:46:38.284Z + weekly + 1.0.0.53 + + + https://semi.design/code/en-US/d2c/support-list + 2023-08-07T07:46:38.314Z + weekly + 1.0.0.53 + + + https://semi.design/code/en-US/d2c/transform-plugin + 2023-08-07T07:46:38.294Z + weekly + 1.0.0.53 + + + https://semi.design/code/en-US/d2c/translate-logic + 2023-08-07T07:46:38.277Z + weekly + 1.0.0.53 + + + https://semi.design/code/en-US/d2c/translate-page + 2023-08-07T07:46:38.258Z + weekly + 1.0.0.53 + + + https://semi.design/code/en-US/start/changelog + 2023-08-07T07:46:38.299Z + weekly + 1.0.0.53 + + + https://semi.design/code/en-US/start/faq + 2023-08-07T07:46:38.285Z + weekly + 1.0.0.53 + + + https://semi.design/code/en-US/start/introduction + 2023-08-07T07:46:38.267Z + weekly + 1.0.0.53 + + + https://semi.design/code/en-US/start/quick-start + 2023-08-07T07:46:38.276Z + weekly + 1.0.0.53 + + + https://semi.design/code/en-US/start/terms + 2023-08-07T07:46:38.295Z + weekly + 1.0.0.53 + + + https://semi.design/code/en-US/uikit/create + 2023-08-07T07:46:38.279Z + weekly + 1.0.0.53 + + + https://semi.design/code/en-US/uikit/figma-usage + 2023-08-07T07:46:38.259Z + weekly + 1.0.0.53 + + + https://semi.design/code/en-US/uikit/form-usage + 2023-08-07T07:46:38.283Z + weekly + 1.0.0.53 + + + https://semi.design/code/en-US/uikit/migrate + 2023-08-07T07:46:38.291Z + weekly + 1.0.0.53 + + + https://semi.design/code/en-US/uikit/rules + 2023-08-07T07:46:38.263Z + weekly + 1.0.0.53 + + + https://semi.design/code/en-US/uikit/table-usage + 2023-08-07T07:46:38.299Z + weekly + 1.0.0.53 + + + https://semi.design/code/zh-CN + 2023-08-07T07:46:38.277Z + weekly + 1.0.0.53 + + + https://semi.design/code/zh-CN/about/contact + 2023-08-07T07:46:38.270Z + weekly + 1.0.0.53 + + + https://semi.design/code/zh-CN/about/known-issues + 2023-08-07T07:46:38.276Z + weekly + 1.0.0.53 + + + https://semi.design/code/zh-CN/about/roadmap + 2023-08-07T07:46:38.266Z + weekly + 1.0.0.53 + + + https://semi.design/code/zh-CN/about/schema + 2023-08-07T07:46:38.275Z + weekly + 1.0.0.53 + + + https://semi.design/code/zh-CN/d2c/inspect + 2023-08-07T07:46:38.268Z + weekly + 1.0.0.53 + + + https://semi.design/code/zh-CN/d2c/mark + 2023-08-07T07:46:38.277Z + weekly + 1.0.0.53 + + + https://semi.design/code/zh-CN/d2c/mark-icon + 2023-08-07T07:46:38.272Z + weekly + 1.0.0.53 + + + https://semi.design/code/zh-CN/d2c/mark-library + 2023-08-07T07:46:38.278Z + weekly + 1.0.0.53 + + + https://semi.design/code/zh-CN/d2c/mark-table + 2023-08-07T07:46:38.284Z + weekly + 1.0.0.53 + + + https://semi.design/code/zh-CN/d2c/settings + 2023-08-07T07:46:38.261Z + weekly + 1.0.0.53 + + + https://semi.design/code/zh-CN/d2c/support-list + 2023-08-07T07:46:38.263Z + weekly + 1.0.0.53 + + + https://semi.design/code/zh-CN/d2c/transform-plugin + 2023-08-07T07:46:38.248Z + weekly + 1.0.0.53 + + + https://semi.design/code/zh-CN/d2c/translate-logic + 2023-08-07T07:46:38.288Z + weekly + 1.0.0.53 + + + https://semi.design/code/zh-CN/d2c/translate-page + 2023-08-07T07:46:38.284Z + weekly + 1.0.0.53 + + + https://semi.design/code/zh-CN/start/changelog + 2023-08-07T07:46:38.287Z + weekly + 1.0.0.53 + + + https://semi.design/code/zh-CN/start/faq + 2023-08-07T07:46:38.307Z + weekly + 1.0.0.53 + + + https://semi.design/code/zh-CN/start/introduction + 2023-08-07T07:46:38.368Z + weekly + 1.0.0.53 + + + https://semi.design/code/zh-CN/start/quick-start + 2023-08-07T07:46:38.288Z + weekly + 1.0.0.53 + + + https://semi.design/code/zh-CN/start/terms + 2023-08-07T07:46:38.290Z + weekly + 1.0.0.53 + + + https://semi.design/code/zh-CN/uikit/create + 2023-08-07T07:46:38.339Z + weekly + 1.0.0.53 + + + https://semi.design/code/zh-CN/uikit/figma-usage + 2023-08-07T07:46:43.843Z + weekly + 1.0.0.53 + + + https://semi.design/code/zh-CN/uikit/form-usage + 2023-08-07T07:46:38.276Z + weekly + 1.0.0.53 + + + https://semi.design/code/zh-CN/uikit/migrate + 2023-08-07T07:46:38.282Z + weekly + 1.0.0.53 + + + https://semi.design/code/zh-CN/uikit/rules + 2023-08-07T07:46:38.295Z + weekly + 1.0.0.53 + + + https://semi.design/code/zh-CN/uikit/table-usage + 2023-08-07T07:46:38.292Z + weekly + 1.0.0.53 + + + https://semi.design/design/zh-CN/feedback/banner + 2023-08-07T07:46:38.201Z + weekly + 1.0.0.125 + + + https://semi.design/design/zh-CN/feedback/notification + 2023-08-07T07:46:38.212Z + weekly + 1.0.0.125 + + + https://semi.design/design/zh-CN/feedback/popconfirm + 2023-08-07T07:46:38.186Z + weekly + 1.0.0.125 + + + https://semi.design/design/zh-CN/feedback/progress + 2023-08-07T07:46:38.240Z + weekly + 1.0.0.125 + + + https://semi.design/design/zh-CN/feedback/skeleton + 2023-08-07T07:46:38.196Z + weekly + 1.0.0.125 + + + https://semi.design/design/zh-CN/feedback/spin + 2023-08-07T07:46:38.196Z + weekly + 1.0.0.125 + + + https://semi.design/design/zh-CN/feedback/toast + 2023-08-07T07:46:38.213Z + weekly + 1.0.0.125 + + + https://semi.design/design/zh-CN/handbook/intro + 2023-08-07T07:46:38.208Z + weekly + 1.0.0.125 + + + https://semi.design/design/zh-CN/handbook/tools + 2023-08-07T07:46:38.215Z + weekly + 1.0.0.125 + + + https://semi.design/design/zh-CN/input/button + 2023-08-07T07:46:38.255Z + weekly + 1.0.0.125 + + + https://semi.design/design/zh-CN/input/cascader + 2023-08-07T07:46:38.242Z + weekly + 1.0.0.125 + + + https://semi.design/design/zh-CN/input/checkbox + 2023-08-07T07:46:38.242Z + weekly + 1.0.0.125 + + + https://semi.design/design/zh-CN/input/datepicker + 2023-08-07T07:46:38.227Z + weekly + 1.0.0.125 + + + https://semi.design/design/zh-CN/input/form + 2023-08-07T07:46:38.248Z + weekly + 1.0.0.125 + + + https://semi.design/design/zh-CN/input/input + 2023-08-07T07:46:38.255Z + weekly + 1.0.0.125 + + + https://semi.design/design/zh-CN/input/inputnumber + 2023-08-07T07:46:38.239Z + weekly + 1.0.0.125 + + + https://semi.design/design/zh-CN/input/radio + 2023-08-07T07:46:38.270Z + weekly + 1.0.0.125 + + + https://semi.design/design/zh-CN/input/rating + 2023-08-07T07:46:38.249Z + weekly + 1.0.0.125 + + + https://semi.design/design/zh-CN/input/select + 2023-08-07T07:46:38.272Z + weekly + 1.0.0.125 + + + https://semi.design/design/zh-CN/input/slider + 2023-08-07T07:46:38.254Z + weekly + 1.0.0.125 + + + https://semi.design/design/zh-CN/input/switch + 2023-08-07T07:46:38.274Z + weekly + 1.0.0.125 + + + https://semi.design/design/zh-CN/input/taginput + 2023-08-07T07:46:38.280Z + weekly + 1.0.0.125 + + + https://semi.design/design/zh-CN/input/timepicker + 2023-08-07T07:46:38.275Z + weekly + 1.0.0.125 + + + https://semi.design/design/zh-CN/input/transfer + 2023-08-07T07:46:38.292Z + weekly + 1.0.0.125 + + + https://semi.design/design/zh-CN/input/treeselect + 2023-08-07T07:46:38.282Z + weekly + 1.0.0.125 + + + https://semi.design/design/zh-CN/input/upload + 2023-08-07T07:46:38.289Z + weekly + 1.0.0.125 + + + https://semi.design/design/zh-CN/navigation/anchor + 2023-08-07T07:46:38.289Z + weekly + 1.0.0.125 + + + https://semi.design/design/zh-CN/navigation/breadcrumb + 2023-08-07T07:46:38.323Z + weekly + 1.0.0.125 + + + https://semi.design/design/zh-CN/navigation/navigation + 2023-08-07T07:46:38.310Z + weekly + 1.0.0.125 + + + https://semi.design/design/zh-CN/navigation/pagination + 2023-08-07T07:46:38.329Z + weekly + 1.0.0.125 + + + https://semi.design/design/zh-CN/navigation/steps + 2023-08-07T07:46:38.323Z + weekly + 1.0.0.125 + + + https://semi.design/design/zh-CN/navigation/tabs + 2023-08-07T07:46:38.351Z + weekly + 1.0.0.125 + + + https://semi.design/design/zh-CN/navigation/tree + 2023-08-07T07:46:38.334Z + weekly + 1.0.0.125 + + + https://semi.design/design/zh-CN/show/avatar + 2023-08-07T07:46:38.332Z + weekly + 1.0.0.125 + + + https://semi.design/design/zh-CN/show/badge + 2023-08-07T07:46:38.341Z + weekly + 1.0.0.125 + + + https://semi.design/design/zh-CN/show/calendar + 2023-08-07T07:46:38.404Z + weekly + 1.0.0.125 + + + https://semi.design/design/zh-CN/show/card + 2023-08-07T07:46:38.367Z + weekly + 1.0.0.125 + + + https://semi.design/design/zh-CN/show/collapse + 2023-08-07T07:46:38.389Z + weekly + 1.0.0.125 + + + https://semi.design/design/zh-CN/show/descriptions + 2023-08-07T07:46:38.406Z + weekly + 1.0.0.125 + + + https://semi.design/design/zh-CN/show/dropdown + 2023-08-07T07:46:38.383Z + weekly + 1.0.0.125 + + + https://semi.design/design/zh-CN/show/list + 2023-08-07T07:46:38.391Z + weekly + 1.0.0.125 + + + https://semi.design/design/zh-CN/show/modal + 2023-08-07T07:46:38.427Z + weekly + 1.0.0.125 + + + https://semi.design/design/zh-CN/show/popover + 2023-08-07T07:46:38.410Z + weekly + 1.0.0.125 + + + https://semi.design/design/zh-CN/show/scrolllist + 2023-08-07T07:46:38.394Z + weekly + 1.0.0.125 + + + https://semi.design/design/zh-CN/show/table + 2023-08-07T07:46:38.435Z + weekly + 1.0.0.125 + + + https://semi.design/design/zh-CN/show/tag + 2023-08-07T07:46:38.395Z + weekly + 1.0.0.125 + + + https://semi.design/design/zh-CN/show/timeline + 2023-08-07T07:46:38.413Z + weekly + 1.0.0.125 + + + https://semi.design/design/zh-CN/show/tooltip + 2023-08-07T07:46:38.410Z + weekly + 1.0.0.125 + + + https://semi.design/design/zh-CN/visual/colors + 2023-08-07T07:46:38.502Z + weekly + 1.0.0.125 + + + https://semi.design/design/zh-CN/visual/dark-mode + 2023-08-07T07:46:38.444Z + weekly + 1.0.0.125 + + + https://semi.design/design/zh-CN/visual/data-format + 2023-08-07T07:46:38.417Z + weekly + 1.0.0.125 + + + https://semi.design/design/zh-CN/visual/grid + 2023-08-07T07:46:38.486Z + weekly + 1.0.0.125 + + + https://semi.design/design/zh-CN/visual/iconography + 2023-08-07T07:46:38.469Z + weekly + 1.0.0.125 + + + https://semi.design/design/zh-CN/visual/layout + 2023-08-07T07:46:38.461Z + weekly + 1.0.0.125 + + + https://semi.design/design/zh-CN/visual/spacings + 2023-08-07T07:46:38.451Z + weekly + 1.0.0.125 + + + https://semi.design/design/zh-CN/visual/typography + 2023-08-07T07:46:38.473Z + weekly + 1.0.0.125 + + + https://semi.design/dsm_manual/zh-CN/introduction/case + 2023-08-07T07:46:38.495Z + weekly + 1.0.0.59 + + + https://semi.design/dsm_manual/zh-CN/introduction/changelog + 2023-08-07T07:46:38.501Z + weekly + 1.0.0.59 + + + https://semi.design/dsm_manual/zh-CN/introduction/faq + 2023-08-07T07:46:38.992Z + weekly + 1.0.0.59 + + + https://semi.design/dsm_manual/zh-CN/introduction/roadmap + 2023-08-07T07:46:38.503Z + weekly + 1.0.0.59 + + + https://semi.design/dsm_manual/zh-CN/introduction/start + 2023-08-07T07:46:38.516Z + weekly + 1.0.0.59 + + + https://semi.design/dsm_manual/zh-CN/plugin/changeThemeModel + 2023-08-07T07:46:38.855Z + weekly + 1.0.0.59 + + + https://semi.design/dsm_manual/zh-CN/plugin/genDocs + 2023-08-07T07:46:38.531Z + weekly + 1.0.0.59 + + + https://semi.design/dsm_manual/zh-CN/plugin/intallPlugin + 2023-08-07T07:46:38.544Z + weekly + 1.0.0.59 + + + https://semi.design/dsm_manual/zh-CN/plugin/syncInFigma + 2023-08-07T07:46:38.533Z + weekly + 1.0.0.59 + + + https://semi.design/dsm_manual/zh-CN/plugin/writeTheme + 2023-08-07T07:46:38.539Z + weekly + 1.0.0.59 + + + https://semi.design/dsm_manual/zh-CN/themeStore/fork + 2023-08-07T07:46:38.537Z + weekly + 1.0.0.59 + + + https://semi.design/dsm_manual/zh-CN/themeStore/preview + 2023-08-07T07:46:38.551Z + weekly + 1.0.0.59 + + + https://semi.design/dsm_manual/zh-CN/themeStore/publish + 2023-08-07T07:46:38.561Z + weekly + 1.0.0.59 + + + https://semi.design/dsm_manual/zh-CN/web/addPartner + 2023-08-07T07:46:38.579Z + weekly + 1.0.0.59 + + + https://semi.design/dsm_manual/zh-CN/web/componentToken + 2023-08-07T07:46:38.570Z + weekly + 1.0.0.59 + + + https://semi.design/dsm_manual/zh-CN/web/globalToken + 2023-08-07T07:46:38.578Z + weekly + 1.0.0.59 + + + https://semi.design/dsm_manual/zh-CN/web/use + 2023-08-07T07:46:38.585Z + weekly + 1.0.0.59 + + + https://semi.design/dsm_manual/zh-CN/web/web_publish + 2023-08-07T07:46:38.577Z + weekly + 1.0.0.59 + + + https://semi.design/dsm_manual/zh-CN/web/web_start + 2023-08-07T07:46:38.591Z + weekly + 1.0.0.59 + + + https://semi.design/dsm/landing + 2023-08-07T07:46:38.585Z + weekly + 1.0.0.140 + + + https://semi.design/en-US/basic/divider + 2023-02-17T06:27:12.000Z + weekly + + + https://semi.design/en-US/basic/grid + 2023-02-17T06:27:12.000Z + weekly + + + https://semi.design/en-US/basic/icon + 2023-02-17T06:27:12.000Z + weekly + + + https://semi.design/en-US/basic/layout + 2023-03-02T05:59:35.000Z + weekly + + + https://semi.design/en-US/basic/space + 2023-02-17T06:27:12.000Z + weekly + + + https://semi.design/en-US/basic/tokens + 2023-02-17T06:27:12.000Z + weekly + + + https://semi.design/en-US/basic/typography + 2023-07-11T03:28:16.000Z + weekly + + + https://semi.design/en-US/feedback/banner + 2023-02-17T06:27:12.000Z + weekly + + + https://semi.design/en-US/feedback/notification + 2023-06-25T11:59:57.000Z + weekly + + + https://semi.design/en-US/feedback/popconfirm + 2023-07-10T02:54:52.000Z + weekly + + + https://semi.design/en-US/feedback/progress + 2023-02-17T06:27:12.000Z + weekly + + + https://semi.design/en-US/feedback/skeleton + 2023-02-17T06:27:12.000Z + weekly + + + https://semi.design/en-US/feedback/spin + 2023-02-17T06:27:12.000Z + weekly + + + https://semi.design/en-US/feedback/toast + 2023-06-25T11:59:57.000Z + weekly + + + https://semi.design/en-US/input/autocomplete + 2023-06-25T11:59:57.000Z + weekly + + + https://semi.design/en-US/input/button + 2023-03-02T05:59:35.000Z + weekly + + + https://semi.design/en-US/input/cascader + 2023-07-03T11:18:54.000Z + weekly + + + https://semi.design/en-US/input/checkbox + 2023-07-06T05:04:36.000Z + weekly + + + https://semi.design/en-US/input/datepicker + 2023-06-25T11:59:57.000Z + weekly + + + https://semi.design/en-US/input/form + 2023-07-25T12:08:58.000Z + weekly + + + https://semi.design/en-US/input/input + 2023-05-26T08:02:32.000Z + weekly + + + https://semi.design/en-US/input/inputnumber + 2023-04-11T06:10:36.000Z + weekly + + + https://semi.design/en-US/input/radio + 2023-03-02T05:59:35.000Z + weekly + + + https://semi.design/en-US/input/rating + 2023-02-17T06:27:12.000Z + weekly + + + https://semi.design/en-US/input/select + 2023-07-10T13:04:38.000Z + weekly + + + https://semi.design/en-US/input/slider + 2023-05-24T06:42:41.000Z + weekly + + + https://semi.design/en-US/input/switch + 2023-02-17T06:27:12.000Z + weekly + + + https://semi.design/en-US/input/taginput + 2023-02-17T06:27:12.000Z + weekly + + + https://semi.design/en-US/input/timepicker + 2023-06-25T11:59:57.000Z + weekly + + + https://semi.design/en-US/input/transfer + 2023-04-11T08:04:27.000Z + weekly + + + https://semi.design/en-US/input/treeselect + 2023-06-25T11:59:57.000Z + weekly + + + https://semi.design/en-US/input/upload + 2023-07-03T09:26:00.000Z + weekly + + + https://semi.design/en-US/navigation/anchor + 2023-07-31T03:36:42.000Z + weekly + + + https://semi.design/en-US/navigation/backtop + 2023-02-17T06:27:12.000Z + weekly + + + https://semi.design/en-US/navigation/breadcrumb + 2023-02-17T06:27:12.000Z + weekly + + + https://semi.design/en-US/navigation/navigation + 2023-05-19T09:31:13.000Z + weekly + + + https://semi.design/en-US/navigation/pagination + 2023-06-05T07:00:17.000Z + weekly + + + https://semi.design/en-US/navigation/steps + 2023-04-21T08:47:17.000Z + weekly + + + https://semi.design/en-US/navigation/tabs + 2023-05-24T06:40:59.000Z + weekly + + + https://semi.design/en-US/navigation/tree + 2023-06-26T06:30:26.000Z + weekly + + + https://semi.design/en-US/other/configprovider + 2023-06-25T11:59:57.000Z + weekly + + + https://semi.design/en-US/other/locale + 2023-02-17T06:27:12.000Z + weekly + + + https://semi.design/en-US/show/avatar + 2023-02-17T06:27:12.000Z + weekly + + + https://semi.design/en-US/show/badge + 2023-06-26T03:12:28.000Z + weekly + + + https://semi.design/en-US/show/calendar + 2023-05-24T06:40:59.000Z + weekly + + + https://semi.design/en-US/show/card + 2023-03-02T05:59:35.000Z + weekly + + + https://semi.design/en-US/show/carousel + 2023-07-27T02:39:50.000Z + weekly + + + https://semi.design/en-US/show/collapse + 2023-04-04T13:01:23.000Z + weekly + + + https://semi.design/en-US/show/collapsible + 2023-02-17T06:27:12.000Z + weekly + + + https://semi.design/en-US/show/descriptions + 2023-02-17T06:27:12.000Z + weekly + + + https://semi.design/en-US/show/dropdown + 2023-07-18T10:49:54.000Z + weekly + + + https://semi.design/en-US/show/empty + 2023-02-17T06:27:12.000Z + weekly + + + https://semi.design/en-US/show/highlight + 2023-02-17T06:27:12.000Z + weekly + + + https://semi.design/en-US/show/image + 2023-07-24T07:16:09.000Z + weekly + + + https://semi.design/en-US/show/list + 2023-02-17T06:27:12.000Z + weekly + + + https://semi.design/en-US/show/modal + 2023-06-25T11:59:57.000Z + weekly + + + https://semi.design/en-US/show/overflowlist + 2023-02-17T06:27:12.000Z + weekly + + + https://semi.design/en-US/show/popover + 2023-07-18T10:49:54.000Z + weekly + + + https://semi.design/en-US/show/scrolllist + 2023-02-17T06:27:12.000Z + weekly + + + https://semi.design/en-US/show/sidesheet + 2023-06-25T11:59:57.000Z + weekly + + + https://semi.design/en-US/show/table + 2023-07-27T02:39:50.000Z + weekly + + + https://semi.design/en-US/show/tag + 2023-02-17T06:27:12.000Z + weekly + + + https://semi.design/en-US/show/timeline + 2023-02-17T06:27:12.000Z + weekly + + + https://semi.design/en-US/show/tooltip + 2023-06-25T11:59:57.000Z + weekly + + + https://semi.design/en-US/start/accessibility + 2023-02-17T06:27:12.000Z + weekly + + + https://semi.design/en-US/start/changelog + 2023-07-28T09:56:14.000Z + weekly + + + https://semi.design/en-US/start/customize-theme + 2022-02-22T03:49:01.000Z + weekly + + + https://semi.design/en-US/start/dark-mode + 2023-02-17T06:27:12.000Z + weekly + + + https://semi.design/en-US/start/faq + 2023-07-10T02:54:52.000Z + weekly + + + https://semi.design/en-US/start/getting-started + 2023-01-19T08:41:09.000Z + weekly + + + https://semi.design/en-US/start/introduction + 2023-07-27T02:39:50.000Z + weekly + + + https://semi.design/en-US/start/overview + 2023-06-07T03:46:37.000Z + weekly + + + https://semi.design/en-US/start/update-to-v2 + 2023-06-07T03:46:37.000Z + weekly + + + https://semi.design/zh-CN/basic/divider + 2023-02-17T06:27:12.000Z + weekly + + + https://semi.design/zh-CN/basic/grid + 2023-02-17T06:27:12.000Z + weekly + + + https://semi.design/zh-CN/basic/icon + 2023-02-17T06:27:12.000Z + weekly + + + https://semi.design/zh-CN/basic/layout + 2023-03-02T05:59:35.000Z + weekly + + + https://semi.design/zh-CN/basic/space + 2023-02-17T06:27:12.000Z + weekly + + + https://semi.design/zh-CN/basic/tokens + 2023-02-17T06:27:12.000Z + weekly + + + https://semi.design/zh-CN/basic/typography + 2023-07-11T03:28:16.000Z + weekly + + + https://semi.design/zh-CN/feedback/banner + 2023-02-17T06:27:12.000Z + weekly + + + https://semi.design/zh-CN/feedback/notification + 2023-06-25T11:59:57.000Z + weekly + + + https://semi.design/zh-CN/feedback/popconfirm + 2023-06-25T11:59:57.000Z + weekly + + + https://semi.design/zh-CN/feedback/progress + 2023-02-17T06:27:12.000Z + weekly + + + https://semi.design/zh-CN/feedback/skeleton + 2023-02-17T06:27:12.000Z + weekly + + + https://semi.design/zh-CN/feedback/spin + 2023-02-17T06:27:12.000Z + weekly + + + https://semi.design/zh-CN/feedback/toast + 2023-06-25T11:59:57.000Z + weekly + + + https://semi.design/zh-CN/input/autocomplete + 2023-06-25T11:59:57.000Z + weekly + + + https://semi.design/zh-CN/input/button + 2023-03-02T05:59:35.000Z + weekly + + + https://semi.design/zh-CN/input/cascader + 2023-07-03T11:18:54.000Z + weekly + + + https://semi.design/zh-CN/input/checkbox + 2023-07-06T05:04:36.000Z + weekly + + + https://semi.design/zh-CN/input/datepicker + 2023-06-25T11:59:57.000Z + weekly + + + https://semi.design/zh-CN/input/form + 2023-07-25T12:08:58.000Z + weekly + + + https://semi.design/zh-CN/input/input + 2023-05-26T08:02:32.000Z + weekly + + + https://semi.design/zh-CN/input/inputnumber + 2023-04-11T06:10:36.000Z + weekly + + + https://semi.design/zh-CN/input/radio + 2023-03-02T05:59:35.000Z + weekly + + + https://semi.design/zh-CN/input/rating + 2023-02-17T06:27:12.000Z + weekly + + + https://semi.design/zh-CN/input/select + 2023-07-10T13:04:38.000Z + weekly + + + https://semi.design/zh-CN/input/slider + 2023-05-24T06:42:41.000Z + weekly + + + https://semi.design/zh-CN/input/switch + 2023-02-17T06:27:12.000Z + weekly + + + https://semi.design/zh-CN/input/taginput + 2023-02-17T06:27:12.000Z + weekly + + + https://semi.design/zh-CN/input/timepicker + 2023-06-25T11:59:57.000Z + weekly + + + https://semi.design/zh-CN/input/transfer + 2023-04-11T08:04:27.000Z + weekly + + + https://semi.design/zh-CN/input/treeselect + 2023-06-25T11:59:57.000Z + weekly + + + https://semi.design/zh-CN/input/upload + 2023-07-03T09:26:00.000Z + weekly + + + https://semi.design/zh-CN/navigation/anchor + 2023-05-18T12:46:19.000Z + weekly + + + https://semi.design/zh-CN/navigation/backtop + 2023-02-17T06:27:12.000Z + weekly + + + https://semi.design/zh-CN/navigation/breadcrumb + 2023-02-17T06:27:12.000Z + weekly + + + https://semi.design/zh-CN/navigation/navigation + 2023-06-25T11:59:57.000Z + weekly + + + https://semi.design/zh-CN/navigation/pagination + 2023-06-05T07:00:17.000Z + weekly + + + https://semi.design/zh-CN/navigation/steps + 2023-04-21T08:47:17.000Z + weekly + + + https://semi.design/zh-CN/navigation/tabs + 2023-05-24T06:40:59.000Z + weekly + + + https://semi.design/zh-CN/navigation/tree + 2023-06-26T06:30:26.000Z + weekly + + + https://semi.design/zh-CN/other/configprovider + 2023-06-25T11:59:57.000Z + weekly + + + https://semi.design/zh-CN/other/locale + 2023-02-20T11:40:22.000Z + weekly + + + https://semi.design/zh-CN/show/avatar + 2023-02-17T06:27:12.000Z + weekly + + + https://semi.design/zh-CN/show/badge + 2023-06-26T03:12:28.000Z + weekly + + + https://semi.design/zh-CN/show/calendar + 2023-05-24T06:40:59.000Z + weekly + + + https://semi.design/zh-CN/show/card + 2023-03-02T05:59:35.000Z + weekly + + + https://semi.design/zh-CN/show/carousel + 2023-07-27T02:39:50.000Z + weekly + + + https://semi.design/zh-CN/show/collapse + 2023-04-04T13:01:23.000Z + weekly + + + https://semi.design/zh-CN/show/collapsible + 2023-02-17T06:27:12.000Z + weekly + + + https://semi.design/zh-CN/show/descriptions + 2023-02-17T06:27:12.000Z + weekly + + + https://semi.design/zh-CN/show/dropdown + 2023-07-18T10:49:54.000Z + weekly + + + https://semi.design/zh-CN/show/empty + 2023-02-17T06:27:12.000Z + weekly + + + https://semi.design/zh-CN/show/highlight + 2023-02-17T06:27:12.000Z + weekly + + + https://semi.design/zh-CN/show/image + 2023-07-24T07:16:09.000Z + weekly + + + https://semi.design/zh-CN/show/list + 2023-02-17T06:27:12.000Z + weekly + + + https://semi.design/zh-CN/show/modal + 2023-06-25T11:59:57.000Z + weekly + + + https://semi.design/zh-CN/show/overflowlist + 2023-02-17T06:27:12.000Z + weekly + + + https://semi.design/zh-CN/show/popover + 2023-07-18T10:49:54.000Z + weekly + + + https://semi.design/zh-CN/show/scrolllist + 2023-02-17T06:27:12.000Z + weekly + + + https://semi.design/zh-CN/show/sidesheet + 2023-06-25T11:59:57.000Z + weekly + + + https://semi.design/zh-CN/show/table + 2023-07-27T02:39:50.000Z + weekly + + + https://semi.design/zh-CN/show/tag + 2023-02-17T06:27:12.000Z + weekly + + + https://semi.design/zh-CN/show/timeline + 2023-02-17T06:27:12.000Z + weekly + + + https://semi.design/zh-CN/show/tooltip + 2023-06-25T11:59:57.000Z + weekly + + + https://semi.design/zh-CN/start/accessibility + 2023-02-17T06:27:12.000Z + weekly + + + https://semi.design/zh-CN/start/changelog + 2023-07-28T09:56:14.000Z + weekly + + + https://semi.design/zh-CN/start/customize-theme + 2022-08-23T09:27:55.000Z + weekly + + + https://semi.design/zh-CN/start/dark-mode + 2023-02-17T06:27:12.000Z + weekly + + + https://semi.design/zh-CN/start/faq + 2023-06-07T03:46:37.000Z + weekly + + + https://semi.design/zh-CN/start/getting-started + 2023-01-19T08:41:09.000Z + weekly + + + https://semi.design/zh-CN/start/introduction + 2023-07-27T02:39:50.000Z + weekly + + + https://semi.design/zh-CN/start/overview + 2023-06-07T03:46:37.000Z + weekly + + + https://semi.design/zh-CN/start/update-to-v2 + 2023-06-07T03:46:37.000Z + weekly + + diff --git a/yarn.lock b/yarn.lock index 14ec2c17e5..147077ab7f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1488,25 +1488,11 @@ "@douyinfe/semi-animation-styled" "2.23.2" classnames "^2.2.6" -"@douyinfe/semi-animation-react@2.39.3": - version "2.39.3" - resolved "https://registry.yarnpkg.com/@douyinfe/semi-animation-react/-/semi-animation-react-2.39.3.tgz#b46cc2a9db9f489e52f62965bb9857708f37f73e" - integrity sha512-sMf2cKmFIMVWFdQlTyMXO917oOvjDq+KOTGLyO9rVIZDK0mFU9VM/jToYngKaUU+f6kvNZcLdx+PUxKQEfZ7hQ== - dependencies: - "@douyinfe/semi-animation" "2.39.3" - "@douyinfe/semi-animation-styled" "2.39.3" - classnames "^2.2.6" - "@douyinfe/semi-animation-styled@2.23.2": 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/semi-animation-styled@2.39.3": - version "2.39.3" - resolved "https://registry.yarnpkg.com/@douyinfe/semi-animation-styled/-/semi-animation-styled-2.39.3.tgz#4818e43b9fc646e9a3304ec2081f50c84a168aa1" - integrity sha512-mMExH5PXvCW2D8rtbG8pk53L9pYyBa8QNDoB2nNMrFlGSvHU+o/1UJ0Y504rUZ0LMsi2QJChP8Ry4mqzINN2sg== - "@douyinfe/semi-animation@2.12.0": version "2.12.0" resolved "https://registry.npmjs.org/@douyinfe/semi-animation/-/semi-animation-2.12.0.tgz#51fe52d3911c2591a80a6e9fe96e6809c1511f13" @@ -1522,13 +1508,6 @@ dependencies: bezier-easing "^2.1.0" -"@douyinfe/semi-animation@2.39.3": - version "2.39.3" - resolved "https://registry.yarnpkg.com/@douyinfe/semi-animation/-/semi-animation-2.39.3.tgz#d8c21be360431b48a8ea8856920cf4d534e68c93" - integrity sha512-KI8O8mvuZiZPNwiK+OUSO/DjPcXLs7sdopPdN3g9WSR7ipPJKmorOZzAG2OTUDH0b4diQYd8gs/YIiFfU+UoOw== - dependencies: - bezier-easing "^2.1.0" - "@douyinfe/semi-foundation@2.33.1": version "2.33.1" resolved "https://registry.npmjs.org/@douyinfe/semi-foundation/-/semi-foundation-2.33.1.tgz#1dfe6233e35a4ed768cb580b0c9a677d1c34ffba" @@ -1543,20 +1522,6 @@ memoize-one "^5.2.1" scroll-into-view-if-needed "^2.2.24" -"@douyinfe/semi-foundation@2.39.3": - version "2.39.3" - resolved "https://registry.yarnpkg.com/@douyinfe/semi-foundation/-/semi-foundation-2.39.3.tgz#6490340494d8ea40981c41123b02fd4ab64cbe2c" - integrity sha512-yTjJYd4BiTdbxt0tCLPJCe3IDCdOEuMjaslDU2TLE3oVs5aTfEcnS2HjioSFgsLPSqEgk8jCdwQDD7eaf+pruA== - dependencies: - "@douyinfe/semi-animation" "2.39.3" - 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/semi-icons@2.33.1", "@douyinfe/semi-icons@latest": version "2.33.1" resolved "https://registry.yarnpkg.com/@douyinfe/semi-icons/-/semi-icons-2.33.1.tgz#8e2871d9bc0ab7e12df74e3c71802d53d69b7425" @@ -1564,23 +1529,11 @@ dependencies: classnames "^2.2.6" -"@douyinfe/semi-icons@2.39.3", "@douyinfe/semi-icons@^2.0.0": - version "2.39.3" - resolved "https://registry.yarnpkg.com/@douyinfe/semi-icons/-/semi-icons-2.39.3.tgz#0e21bbcdd3705b8f1570935b0096ee3847bed34f" - integrity sha512-l/Wq0ytYecSO1AbNIuLgDdlJfi1nOMLm5aZoPCJRLU6qRASPjQhpgV1inf050FlVFVfK1ocIiyOyjkTP9sEpNg== - dependencies: - classnames "^2.2.6" - "@douyinfe/semi-illustrations@2.33.1": 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/semi-illustrations@2.39.3": - version "2.39.3" - resolved "https://registry.yarnpkg.com/@douyinfe/semi-illustrations/-/semi-illustrations-2.39.3.tgz#1a0d7bd523e16244efa08004ad6169994cd13bf2" - integrity sha512-/bZNcAMRKk4cigH+ltAmTIxltR8aWrsiVUXdvBkf0txzv/NSXMRFNGehE3JFxiw728iE5P6B6AbJdDi64dKYqA== - "@douyinfe/semi-scss-compile@2.23.2": version "2.23.2" resolved "https://registry.npmjs.org/@douyinfe/semi-scss-compile/-/semi-scss-compile-2.23.2.tgz#30884bb194ee9ae1e81877985e5663c3297c1ced" @@ -1654,38 +1607,6 @@ dependencies: glob "^7.1.6" -"@douyinfe/semi-theme-default@2.39.3": - version "2.39.3" - resolved "https://registry.yarnpkg.com/@douyinfe/semi-theme-default/-/semi-theme-default-2.39.3.tgz#a02a5b20890587c674eb7c3b2550551f42b933a0" - integrity sha512-dTTD8nkzM0ad1Lli9cFYLqvmTsSvKp5NSIc35UQBZcvi7OvmUA7qaSMentEMgl15bVWKInwCvp+mSFJsDtDPlg== - dependencies: - glob "^7.1.6" - -"@douyinfe/semi-ui@^2.0.0": - version "2.39.3" - resolved "https://registry.yarnpkg.com/@douyinfe/semi-ui/-/semi-ui-2.39.3.tgz#081297781163882882e501686c76356804bd9555" - integrity sha512-xrQ9Xd1B4vhDK41RjN4AFxDD/ILuR9HTctJZ0Be+mio8xIifINtD2jD5xXB1pV+DE/43jtu30VzNlvLm/0TQbw== - dependencies: - "@douyinfe/semi-animation" "2.39.3" - "@douyinfe/semi-animation-react" "2.39.3" - "@douyinfe/semi-foundation" "2.39.3" - "@douyinfe/semi-icons" "2.39.3" - "@douyinfe/semi-illustrations" "2.39.3" - "@douyinfe/semi-theme-default" "2.39.3" - 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 "^1.8.0" - react-sortable-hoc "^2.0.0" - react-window "^1.8.2" - resize-observer-polyfill "^1.5.1" - scroll-into-view-if-needed "^2.2.24" - utility-types "^3.10.0" - "@douyinfe/semi-ui@latest": version "2.33.1" resolved "https://registry.yarnpkg.com/@douyinfe/semi-ui/-/semi-ui-2.33.1.tgz#3234ca96eb3560b8299bc9750fbe59446522d9bb" @@ -11253,11 +11174,6 @@ 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.39.3" - resolved "https://registry.yarnpkg.com/eslint-plugin-semi-design/-/eslint-plugin-semi-design-2.39.3.tgz#ceab48928648acd0fef41ea5ef97b17268aec70b" - integrity sha512-9oX8xdmLR9IZPZ4JpMd/1V+e2ebQ7gcqax2kgzl0ICY0iWvb40WrF+tvnkI92OVlD7OLqMlxv//Q83vkKoZ2fA== - 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" @@ -11571,6 +11487,21 @@ execa@4.1.0, execa@^4.0.2, execa@^4.0.3, execa@^4.1.0: signal-exit "^3.0.2" strip-final-newline "^2.0.0" +execa@5, execa@^5.0.0, execa@^5.1.1: + version "5.1.1" + resolved "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" + integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== + dependencies: + cross-spawn "^7.0.3" + get-stream "^6.0.0" + human-signals "^2.1.0" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.1" + onetime "^5.1.2" + signal-exit "^3.0.3" + strip-final-newline "^2.0.0" + execa@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" @@ -11600,21 +11531,6 @@ execa@^3.4.0: signal-exit "^3.0.2" strip-final-newline "^2.0.0" -execa@^5.0.0, execa@^5.1.1: - version "5.1.1" - resolved "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" - integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== - dependencies: - cross-spawn "^7.0.3" - get-stream "^6.0.0" - human-signals "^2.1.0" - is-stream "^2.0.0" - merge-stream "^2.0.0" - npm-run-path "^4.0.1" - onetime "^5.1.2" - signal-exit "^3.0.3" - strip-final-newline "^2.0.0" - execall@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/execall/-/execall-2.0.0.tgz#16a06b5fe5099df7d00be5d9c06eecded1663b45" @@ -11869,6 +11785,13 @@ fast-plist@^0.1.2: resolved "https://registry.npmjs.org/fast-plist/-/fast-plist-0.1.3.tgz#328cd9335e93a2479ac90814a1302437574ea925" integrity sha512-d9cEfo/WcOezgPLAC/8t8wGb6YOD6JTCPMw2QcG2nAdFmyY+9rTUizCTaGjIZAloWENTEUMAPpkUAIJJJ0i96A== +fast-xml-parser@^4.2.7: + version "4.2.7" + resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-4.2.7.tgz#871f2ca299dc4334b29f8da3658c164e68395167" + integrity sha512-J8r6BriSLO1uj2miOk1NW0YVm8AGOOu3Si2HQp/cSmo6EA4m3fcwu2WKjJ4RK9wMLBtg69y1kS8baDiQBR41Ig== + dependencies: + strnum "^1.0.5" + fastest-levenshtein@^1.0.12: version "1.0.16" resolved "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz#210e61b6ff181de91ea9b3d1b84fdedd47e034e5" @@ -23781,6 +23704,11 @@ strip-json-comments@~2.0.1: resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== +strnum@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/strnum/-/strnum-1.0.5.tgz#5c4e829fe15ad4ff0d20c3db5ac97b73c9b072db" + integrity sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA== + strong-log-transformer@^2.1.0: version "2.1.0" resolved "https://registry.npmjs.org/strong-log-transformer/-/strong-log-transformer-2.1.0.tgz#0f5ed78d325e0421ac6f90f7f10e691d6ae3ae10" From 7d72163a340add2d3988174703af75926821a6cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BB=A3=E5=BC=BA?= Date: Tue, 8 Aug 2023 11:58:21 +0800 Subject: [PATCH 10/29] chore: add sitemap url to robots.txt --- static/robots.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/static/robots.txt b/static/robots.txt index eb0536286f..d55645fcfd 100644 --- a/static/robots.txt +++ b/static/robots.txt @@ -1,2 +1,4 @@ User-agent: * Disallow: + +Sitemap: https://semi.design/sitemap.xml From 274714dd3ab0d08490919c6e46d52664b0261719 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BB=A3=E5=BC=BA?= Date: Tue, 8 Aug 2023 14:57:15 +0800 Subject: [PATCH 11/29] chore: add description keywords --- src/html.js | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/html.js b/src/html.js index fb3a77e7bb..ce41fa85c0 100644 --- a/src/html.js +++ b/src/html.js @@ -156,6 +156,28 @@ export default function HTML(props) { + +