From 9d437e8d11fc63118966c1f105af0f7c16c9c0c6 Mon Sep 17 00:00:00 2001 From: Carbon Serio <79406469+CoderSerio@users.noreply.github.com> Date: Fri, 9 Jun 2023 18:26:30 +0800 Subject: [PATCH 01/25] site: enable the path to be resolved correctly on windows (#128) Co-authored-by: CoderSerio --- .../DemoGeneratePlugin/generate-demo.js | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/scripts/sites/plugins/DemoGeneratePlugin/generate-demo.js b/scripts/sites/plugins/DemoGeneratePlugin/generate-demo.js index 36a01ccb..5368907f 100644 --- a/scripts/sites/plugins/DemoGeneratePlugin/generate-demo.js +++ b/scripts/sites/plugins/DemoGeneratePlugin/generate-demo.js @@ -11,7 +11,7 @@ const compositeCompFolder = 'sites/mobile/pages/composite-comp'; const compositeFolder = 'sites/composite-comp'; const srcFolder = 'packages/arcodesign'; const packageName = '@arco-design/mobile-react'; -const compFolder = path.join(srcFolder, 'components'); +const compFolder = path.posix.join(srcFolder, 'components'); const compPath = path.join(rootPath, compFolder); const sitePath = path.join(rootPath, siteFolder); const compositeCompPath = path.join(rootPath, compositeCompFolder); @@ -25,7 +25,7 @@ function renderSource({ comp, demoName, depsCompSet, language, compileEnv, demoP const reg = new RegExp(packageName, 'g'); let order = 0; - + renderer.code = code => { const filename = `_${utils.getCompName(demoName)}`; const content = `import React from 'react'; @@ -165,9 +165,9 @@ function generateSiteDemo({ return new Promise((resolve) => { // 内部工具js不处理 if (/^_/.test(comp)) { - return resolve() + return resolve(); } - + depsCompSet.add(comp); const docPath = path.join(sitePath, comp); @@ -181,7 +181,7 @@ function generateSiteDemo({ } const demoSource = []; let importStr = `import React from 'react';\n`; - + demos.forEach(name => { if (name.indexOf('.md') < 0) { return resolve(); @@ -256,7 +256,7 @@ function generateSiteDemo({ }); Promise.all(promises).then(() => { - console.log(`>>> Generate ${language} demo files finished`); + console.log(`>>> Generate ${language} demo files finished`); }); if (!compileComps.length) { @@ -343,9 +343,9 @@ function generateSiteCompositeDemo({ demoCompSet.add(comp); } }); - + demoSource.sort((a, b) => a.order - b.order); - + const demoStylePath = path.join(demoPath, 'style'); if (fs.existsSync(demoStylePath)) { const styles = fs.readdirSync(demoStylePath); @@ -379,7 +379,7 @@ function generateSiteCompositeDemo({ }); Promise.all(promises).then(() => { - console.log(`>>> Generate ${language} composite demo files finished`) + console.log(`>>> Generate ${language} composite demo files finished`); }); [...demoCompSet].map(e => { @@ -389,7 +389,7 @@ function generateSiteCompositeDemo({ compDocsImportStr += `import ${importName} from './${e}${tsxFileSuffix ? `/index${tsxFileSuffix}` : ''}';\n`; compDocsStr += ` '${route}': ${importName},\n`; }); -const docEntryStr = `${compDocsImportStr} + const docEntryStr = `${compDocsImportStr} const docs = {\n${compDocsStr}}; export default docs; @@ -431,4 +431,4 @@ function generateDemo({ } } -module.exports = generateDemo; \ No newline at end of file +module.exports = generateDemo; From daa8f67961d9d2751a14c0c3f7759b54fe0579cb Mon Sep 17 00:00:00 2001 From: Yiyue Tao <106640896+TinaPeach@users.noreply.github.com> Date: Mon, 3 Jul 2023 20:03:31 +0800 Subject: [PATCH 02/25] fix: error caught when using "getComputedStyle" (#129) --- packages/arcodesign/components/_helpers/hooks.ts | 4 ++-- packages/common-widgets/package-lock.json | 2 +- packages/common-widgets/utils/dom.ts | 8 ++++++++ 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/packages/arcodesign/components/_helpers/hooks.ts b/packages/arcodesign/components/_helpers/hooks.ts index e127efc8..83cd1834 100644 --- a/packages/arcodesign/components/_helpers/hooks.ts +++ b/packages/arcodesign/components/_helpers/hooks.ts @@ -4,7 +4,7 @@ * @name_en General Hooks */ import React, { useState, useRef, useEffect, useCallback, useContext } from 'react'; -import { getSystem, scrollWithAnimation } from '@arco-design/mobile-utils'; +import { getSystem, scrollWithAnimation, safeGetComputedStyle } from '@arco-design/mobile-utils'; import { GlobalContext } from '../context-provider'; import { BezierType } from '../progress'; @@ -163,7 +163,7 @@ export function usePopupScroll( scrollRef.current = actualEle.reduce( (acc, nowEle) => [ ...acc, - ...(nowEle && window.getComputedStyle(nowEle).overflow !== 'hidden' + ...(nowEle && safeGetComputedStyle(nowEle).overflow !== 'hidden' ? [ { ele: nowEle, diff --git a/packages/common-widgets/package-lock.json b/packages/common-widgets/package-lock.json index 2eff737e..4764a776 100644 --- a/packages/common-widgets/package-lock.json +++ b/packages/common-widgets/package-lock.json @@ -6,7 +6,7 @@ "packages": { "": { "name": "@arco-design/mobile-utils", - "version": "2.14.0", + "version": "2.15.4", "license": "ISC", "dependencies": { "es6-promise": "^4.2.8" diff --git a/packages/common-widgets/utils/dom.ts b/packages/common-widgets/utils/dom.ts index b9a2079c..cb0a11c4 100644 --- a/packages/common-widgets/utils/dom.ts +++ b/packages/common-widgets/utils/dom.ts @@ -429,3 +429,11 @@ export function convertCssDuration(ele: HTMLElement, property: string) { } return 0; } + +export function safeGetComputedStyle(element: HTMLElement) { + try { + return window.getComputedStyle(element); + } catch (e) { + return {} as CSSStyleDeclaration; + } +} From 3df1f71a8b1f63ed5e1986284f2746438de59d70 Mon Sep 17 00:00:00 2001 From: Yiyue Tao <106640896+TinaPeach@users.noreply.github.com> Date: Mon, 3 Jul 2023 20:51:55 +0800 Subject: [PATCH 03/25] fix: `ImagePreview` fix long picture display problem (#137) --- packages/arcodesign/components/image-preview/style/index.less | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/arcodesign/components/image-preview/style/index.less b/packages/arcodesign/components/image-preview/style/index.less index 2ddd4c54..82fd144d 100644 --- a/packages/arcodesign/components/image-preview/style/index.less +++ b/packages/arcodesign/components/image-preview/style/index.less @@ -41,6 +41,10 @@ height: 100%; will-change: transform; + .image-container { + overflow: visible; + } + &.preview-hidden { pointer-events: none; From da76f125734579a1921a3ace0964d5ff845cd545 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E9=BB=84=E6=B1=AA?= <50308467+huangguang1999@users.noreply.github.com> Date: Mon, 3 Jul 2023 21:13:20 +0800 Subject: [PATCH 04/25] fix: `LoadMore` fix the inaccurate scrollheight when using multiple loadmore (#130) --- packages/arcodesign/components/index.ts | 24 ++++++++--------- .../components/load-more/README.en-US.md | 1 + .../arcodesign/components/load-more/README.md | 1 + .../load-more/__ast__/index.ast.json | 17 ++++++++++++ .../arcodesign/components/load-more/index.tsx | 11 +++++++- packages/arcodesign/components/style.ts | 26 +++++++++---------- packages/arcodesign/package.json | 2 +- 7 files changed, 55 insertions(+), 27 deletions(-) diff --git a/packages/arcodesign/components/index.ts b/packages/arcodesign/components/index.ts index ea9ecc74..2131facf 100644 --- a/packages/arcodesign/components/index.ts +++ b/packages/arcodesign/components/index.ts @@ -1,34 +1,31 @@ -export { default as Button } from './button'; +export { default as Tabs } from './tabs'; +export { default as Sticky } from './sticky'; +export { default as LoadMore } from './load-more'; +export { default as Cell } from './cell'; export { default as ActionSheet } from './action-sheet'; export { default as Avatar } from './avatar'; export { default as Badge } from './badge'; +export { default as Button } from './button'; export { default as Carousel } from './carousel'; -export { default as Cell } from './cell'; export { default as Checkbox } from './checkbox'; export { default as CircleProgress } from './circle-progress'; export { default as Collapse } from './collapse'; export { default as ContextProvider } from './context-provider'; export { default as CountDown } from './count-down'; export { default as DatePicker } from './date-picker'; -export { default as Divider } from './divider'; export { default as Dialog } from './dialog'; +export { default as Divider } from './divider'; export { default as Dropdown } from './dropdown'; export { default as DropdownMenu } from './dropdown-menu'; export { default as Ellipsis } from './ellipsis'; export { default as Form } from './form'; -export { default as Input } from './input'; -export { default as Textarea } from './textarea'; -export { default as Radio } from './radio'; -export { default as Rate } from './rate'; -export { default as Slider } from './slider'; export { default as Grid } from './grid'; export { default as Image } from './image'; -export { default as ShowMonitor } from './show-monitor'; export { default as ImagePicker } from './image-picker'; export { default as ImagePreview } from './image-preview'; export { default as IndexBar } from './index-bar'; +export { default as Input } from './input'; export { default as Keyboard } from './keyboard'; -export { default as LoadMore } from './load-more'; export { default as Loading } from './loading'; export { default as Masking } from './masking'; export { default as NavBar } from './nav-bar'; @@ -43,15 +40,18 @@ export { default as PopupSwiper } from './popup-swiper'; export { default as Portal } from './portal'; export { default as Progress } from './progress'; export { default as PullRefresh } from './pull-refresh'; +export { default as Radio } from './radio'; +export { default as Rate } from './rate'; export { default as SearchBar } from './search-bar'; +export { default as ShowMonitor } from './show-monitor'; +export { default as Slider } from './slider'; export { default as Stepper } from './stepper'; export { default as Steps } from './steps'; -export { default as Sticky } from './sticky'; export { default as SwipeAction } from './swipe-action'; export { default as SwipeLoad } from './swipe-load'; export { default as Switch } from './switch'; export { default as TabBar } from './tab-bar'; -export { default as Tabs } from './tabs'; export { default as Tag } from './tag'; +export { default as Textarea } from './textarea'; export { default as Toast } from './toast'; export { default as Transition } from './transition'; diff --git a/packages/arcodesign/components/load-more/README.en-US.md b/packages/arcodesign/components/load-more/README.en-US.md index 3de9ca20..12ad0253 100644 --- a/packages/arcodesign/components/load-more/README.en-US.md +++ b/packages/arcodesign/components/load-more/README.en-US.md @@ -20,6 +20,7 @@ Pull-up loading component, supports `scroll` and `click` two trigger loading met |defaultStatus|The component is loaded in the initial state\. Inputing in "before\-ready" will load the component first without requesting data|"before\-ready" \| "prepare"|"prepare"| |status|Current state, the component is controlledc when it is input|"before\-ready" \| "prepare" \| "loading" \| "nomore" \| "retry"|-| |getScrollContainer|Scrolling container to be calculated|() =\> HTMLElement \| Window|() => window| +|getOffsetNode|When multiple loadmores are on the same page, pass in the offsetHeight \+ offsetTop of the node instead of scrollHeight|() =\> HTMLElement \| Window|-| |trigger|The timing of triggering loading, when it is click, getData will be triggered after clicking|"scroll" \| "click"|"scroll"| |threshold|Scroll to how far from the bottom of the list to trigger getData, valid when the trigger state timing is 'scroll'|number|200| |getData|The request data method, after the asynchronous task ends, the callback can be called according to the task result to modify the internal state of loadmore|(callback: (status: LoadMoreStatus) =\> void) =\> void|-| diff --git a/packages/arcodesign/components/load-more/README.md b/packages/arcodesign/components/load-more/README.md index 5697de9b..c9c95858 100644 --- a/packages/arcodesign/components/load-more/README.md +++ b/packages/arcodesign/components/load-more/README.md @@ -20,6 +20,7 @@ |defaultStatus|组件加载初始状态,传入 "before\-ready" 则先加载组件但不请求数据|"before\-ready" \| "prepare"|"prepare"| |status|当前状态,传入则受控|"before\-ready" \| "prepare" \| "loading" \| "nomore" \| "retry"|-| |getScrollContainer|待计算滚动容器|() =\> HTMLElement \| Window|() => window| +|getOffsetNode|当多个 loadmore 在同一页面时,通过传入节点的 offsetHeight \+ offsetTop 代替 scrollHeight|() =\> HTMLElement \| Window|-| |trigger|触发loading的时机,当为click时,点击后将触发getData|"scroll" \| "click"|"scroll"| |threshold|滚动到离列表底部多远的位置触发getData,触发状态时机为'scroll'时有效|number|200| |getData|请求数据方法,可在异步任务结束后根据任务结果调用callback修改loadmore内部状态|(callback: (status: LoadMoreStatus) =\> void) =\> void|-| diff --git a/packages/arcodesign/components/load-more/__ast__/index.ast.json b/packages/arcodesign/components/load-more/__ast__/index.ast.json index b271d23b..856757a4 100644 --- a/packages/arcodesign/components/load-more/__ast__/index.ast.json +++ b/packages/arcodesign/components/load-more/__ast__/index.ast.json @@ -232,6 +232,23 @@ "name": "() => HTMLElement | Window" } }, + "getOffsetNode": { + "defaultValue": null, + "description": "当多个 loadmore 在同一页面时,通过传入节点的 offsetHeight + offsetTop 代替 scrollHeight\n@en When multiple loadmores are on the same page, pass in the offsetHeight + offsetTop of the node instead of scrollHeight", + "name": "getOffsetNode", + "tags": { + "en": "When multiple loadmores are on the same page, pass in the offsetHeight + offsetTop of the node instead of scrollHeight" + }, + "descWithTags": "当多个 loadmore 在同一页面时,通过传入节点的 offsetHeight + offsetTop 代替 scrollHeight", + "parent": { + "fileName": "arcom-github/packages/arcodesign/components/load-more/index.tsx", + "name": "LoadMoreProps" + }, + "required": false, + "type": { + "name": "() => HTMLElement | Window" + } + }, "trigger": { "defaultValue": { "value": "\"scroll\"" diff --git a/packages/arcodesign/components/load-more/index.tsx b/packages/arcodesign/components/load-more/index.tsx index cff20786..3678fe75 100644 --- a/packages/arcodesign/components/load-more/index.tsx +++ b/packages/arcodesign/components/load-more/index.tsx @@ -82,6 +82,11 @@ export interface LoadMoreProps { * @default () => window */ getScrollContainer?: () => HTMLElement | Window | null; + /** + * 当多个 loadmore 在同一页面时,通过传入节点的 offsetHeight + offsetTop 代替 scrollHeight + * @en When multiple loadmores are on the same page, pass in the offsetHeight + offsetTop of the node instead of scrollHeight + */ + getOffsetNode?: () => HTMLElement | Window | null; /** * 触发loading的时机,当为click时,点击后将触发getData * @en The timing of triggering loading, when it is click, getData will be triggered after clicking @@ -167,6 +172,7 @@ const LoadMore = forwardRef((props: LoadMoreProps, ref: Ref) => { defaultStatus = 'prepare', status, getScrollContainer, + getOffsetNode, trigger = 'scroll', threshold = 200, throttle = 0, @@ -272,7 +278,10 @@ const LoadMore = forwardRef((props: LoadMoreProps, ref: Ref) => { ); function checkNeedTrigger(top: number, ths: number) { - const scrollHeight = getScrollContainerAttribute('scrollHeight', getScrollContainer); + const scrollHeight = getOffsetNode + ? getScrollContainerAttribute('offsetHeight', getOffsetNode) + + getScrollContainerAttribute('offsetTop', getOffsetNode) + : getScrollContainerAttribute('scrollHeight', getScrollContainer); const clientHeight = getScrollContainerAttribute('clientHeight', getScrollContainer); return scrollHeight - top - clientHeight <= ths; } diff --git a/packages/arcodesign/components/style.ts b/packages/arcodesign/components/style.ts index b486c534..40740798 100644 --- a/packages/arcodesign/components/style.ts +++ b/packages/arcodesign/components/style.ts @@ -1,35 +1,32 @@ import '../style/public.less'; -import './button/style'; +import './tabs/style'; +import './sticky/style'; +import './load-more/style'; +import './cell/style'; import './action-sheet/style'; import './avatar/style'; import './badge/style'; +import './button/style'; import './carousel/style'; -import './cell/style'; import './checkbox/style'; import './circle-progress/style'; import './collapse/style'; import './context-provider/style'; import './count-down/style'; import './date-picker/style'; -import './divider/style'; import './dialog/style'; +import './divider/style'; import './dropdown/style'; import './dropdown-menu/style'; import './ellipsis/style'; import './form/style'; -import './input/style'; -import './textarea/style'; -import './radio/style'; -import './image-picker/style'; -import './rate/style'; -import './slider/style'; import './grid/style'; import './image/style'; -import './show-monitor/style'; +import './image-picker/style'; import './image-preview/style'; import './index-bar/style'; +import './input/style'; import './keyboard/style'; -import './load-more/style'; import './loading/style'; import './masking/style'; import './nav-bar/style'; @@ -44,15 +41,18 @@ import './popup-swiper/style'; import './portal/style'; import './progress/style'; import './pull-refresh/style'; +import './radio/style'; +import './rate/style'; import './search-bar/style'; +import './show-monitor/style'; +import './slider/style'; import './stepper/style'; import './steps/style'; -import './sticky/style'; import './swipe-action/style'; import './swipe-load/style'; import './switch/style'; import './tab-bar/style'; -import './tabs/style'; import './tag/style'; +import './textarea/style'; import './toast/style'; import './transition/style'; diff --git a/packages/arcodesign/package.json b/packages/arcodesign/package.json index dfbf6444..64d87d6c 100644 --- a/packages/arcodesign/package.json +++ b/packages/arcodesign/package.json @@ -35,5 +35,5 @@ "publishConfig": { "access": "public" }, - "gitHead": "1ae5c477f0f78e51fd883214b25923a4dcfea8bb" + "gitHead": "e648561be24f2152a4e3c5ca8f6450c2fbaadca1" } From 084448b0e4b43ea7d8632e232c1665ce00449c3d Mon Sep 17 00:00:00 2001 From: Sia <125020500+ziqisia@users.noreply.github.com> Date: Mon, 3 Jul 2023 21:17:31 +0800 Subject: [PATCH 05/25] fix: transition in StrictMode (#131) --- packages/arcodesign/components/badge/index.tsx | 2 +- .../components/image-preview/index.tsx | 1 + .../arcodesign/components/masking/index.tsx | 2 ++ .../arcodesign/components/popover/popover.tsx | 15 +++++++++++++-- .../arcodesign/components/slider/popover.tsx | 17 ++++++++++++++--- packages/arcodesign/components/toast/index.tsx | 9 ++++++++- .../components/transition/demo/index.md | 3 +++ 7 files changed, 42 insertions(+), 7 deletions(-) diff --git a/packages/arcodesign/components/badge/index.tsx b/packages/arcodesign/components/badge/index.tsx index e29056c4..b560659c 100644 --- a/packages/arcodesign/components/badge/index.tsx +++ b/packages/arcodesign/components/badge/index.tsx @@ -106,7 +106,7 @@ const Badge = forwardRef((props: BadgeProps, ref: Ref) => { return ( {({ prefixCls }) => ( - +
) => { type={maskTransitionType} mountOnEnter={mountOnEnter} unmountOnExit={unmountOnExit} + nodeRef={maskRef} >
) => { type={contentTransitionType} mountOnEnter={mountOnEnter} unmountOnExit={unmountOnExit} + nodeRef={contentRef} >
) => const wrapperRef = useRef(null); const childRef = useRef(null); const popoverRef = useRef(null); + const transitionNodeRef = useRef(null); + const maskRef = useRef(null); const { direction, position, @@ -176,7 +178,10 @@ export const Popover = forwardRef((props: PopoverProps, ref: Ref) => className={cls(`${theme}-theme`, innerPopoverClassName, { bordered, })} - ref={popoverRef} + ref={ele => { + popoverRef.current = ele; + transitionNodeRef.current = ele?.dom!; + }} direction={direction} minWidth={minWidth} maxWidth={maxWidth} @@ -207,6 +212,7 @@ export const Popover = forwardRef((props: PopoverProps, ref: Ref) => in={visibleState && !isCalcPosition} timeout={transitionTimeout} type={transitionName} + nodeRef={transitionNodeRef} mountOnEnter unmountOnExit > @@ -223,11 +229,16 @@ export const Popover = forwardRef((props: PopoverProps, ref: Ref) => -
+
)} diff --git a/packages/arcodesign/components/slider/popover.tsx b/packages/arcodesign/components/slider/popover.tsx index 2c566e5b..07c79594 100644 --- a/packages/arcodesign/components/slider/popover.tsx +++ b/packages/arcodesign/components/slider/popover.tsx @@ -1,4 +1,4 @@ -import React, { useContext, ReactNode } from 'react'; +import React, { useContext, ReactNode, useRef } from 'react'; import Transition from '../transition'; import { GlobalContext } from '../context-provider'; @@ -12,11 +12,22 @@ export function Popover({ children: ReactNode; }) { const { prefixCls = '' } = useContext(GlobalContext); + const domRef = useRef(null); return (
- -
+ +
{content}
diff --git a/packages/arcodesign/components/toast/index.tsx b/packages/arcodesign/components/toast/index.tsx index 45bb0324..e02922b1 100644 --- a/packages/arcodesign/components/toast/index.tsx +++ b/packages/arcodesign/components/toast/index.tsx @@ -147,6 +147,7 @@ const Toast = forwardRef((props: ToastProps, ref: Ref) => { } = props; const closeTimerRef = useRef(); const domRef = useRef(null); + const wrapDomRef = useRef(null); const isInitialMount = useRef(false); const hasType = type && type !== 'info'; @@ -214,6 +215,7 @@ const Toast = forwardRef((props: ToastProps, ref: Ref) => { 'no-event': !disableBodyTouch, })} onClick={handleClickMask} + ref={wrapDomRef} >
) => { className={cls(`${prefixCls}-toast`, 'all-border-box', className)} ref={domRef} > - + {renderComponent(`${prefixCls}-toast`)}
diff --git a/packages/arcodesign/components/transition/demo/index.md b/packages/arcodesign/components/transition/demo/index.md index fab332b5..e43f2ba1 100644 --- a/packages/arcodesign/components/transition/demo/index.md +++ b/packages/arcodesign/components/transition/demo/index.md @@ -7,6 +7,7 @@ import { Transition, Cell } from '@arco-design/mobile-react'; export default function TransitionDemo() { const [visible, setVisible] = React.useState(false); + const domRef = React.useRef(); return (<> setVisible(true)} /> @@ -17,10 +18,12 @@ export default function TransitionDemo() { type="fade" mountOnEnter={true} unmountOnExit={true} + nodeRef={domRef} >
setVisible(false)} + ref={domRef} >
); From 71dabe71f3508ac8cb9a800d8ac1be01df509f28 Mon Sep 17 00:00:00 2001 From: Sia <125020500+ziqisia@users.noreply.github.com> Date: Tue, 4 Jul 2023 17:31:24 +0800 Subject: [PATCH 06/25] fix: `Stepper` disable status (#134) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: 吴霞玉 --- .../components/stepper/demo/default.md | 2 +- .../components/stepper/hooks/useButtonClick.tsx | 16 +++++++--------- .../tokens/app/arcodesign/default/index.js | 2 +- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/packages/arcodesign/components/stepper/demo/default.md b/packages/arcodesign/components/stepper/demo/default.md index 59ccd4e3..b09bbc50 100644 --- a/packages/arcodesign/components/stepper/demo/default.md +++ b/packages/arcodesign/components/stepper/demo/default.md @@ -15,7 +15,7 @@ export default function StepperDemo() {
- +
); diff --git a/packages/arcodesign/components/stepper/hooks/useButtonClick.tsx b/packages/arcodesign/components/stepper/hooks/useButtonClick.tsx index 625c71f2..a9d97a81 100644 --- a/packages/arcodesign/components/stepper/hooks/useButtonClick.tsx +++ b/packages/arcodesign/components/stepper/hooks/useButtonClick.tsx @@ -31,12 +31,10 @@ export default function useButtonClick( onAddButtonClick, onMinusButtonClick, } = params; - const [minusButtonDisable, setMinusButtonDisable] = useState( - () => actualInputValue === min || disabled, - ); - const [addButtonDisable, setAddButtonDisable] = useState( - () => actualInputValue === max || disabled, - ); + const minusDisable = actualInputValue <= min || disabled; + const [minusButtonDisable, setMinusButtonDisable] = useState(minusDisable); + const addDisable = actualInputValue >= max || disabled; + const [addButtonDisable, setAddButtonDisable] = useState(addDisable); const handleMinusButtonClick = (e: React.MouseEvent) => { if (minusButtonDisable) { @@ -63,9 +61,9 @@ export default function useButtonClick( // 当前值改变时,更新按钮状态 // Changes button status when value changed useEffect(() => { - setMinusButtonDisable(actualInputValue <= min); - setAddButtonDisable(actualInputValue >= max); - }, [actualInputValue]); + setMinusButtonDisable(minusDisable); + setAddButtonDisable(addDisable); + }, [minusDisable, addDisable]); return { minusButtonDisable, diff --git a/packages/arcodesign/tokens/app/arcodesign/default/index.js b/packages/arcodesign/tokens/app/arcodesign/default/index.js index f48a7f69..9e246d7f 100644 --- a/packages/arcodesign/tokens/app/arcodesign/default/index.js +++ b/packages/arcodesign/tokens/app/arcodesign/default/index.js @@ -7,7 +7,7 @@ exports["default"] = void 0; exports.getRem = getRem; function getRem(px, baseFontSize) { - var num = Math.round(px / Number(baseFontSize) * 1000000) / 1000000; + var num = Math.round(px / Number(baseFontSize) * 1e6) / 1e6; return num ? "".concat(num, "rem") : num; } From 0f41863cde2457384778f80ec7a7f78bf2e8fe47 Mon Sep 17 00:00:00 2001 From: taoyiyue Date: Tue, 4 Jul 2023 17:57:26 +0800 Subject: [PATCH 07/25] build: release version - @arco-design/mobile-react@2.27.5 - @arco-design/mobile-utils@2.15.5 --- packages/arcodesign/CHANGELOG.md | 15 +++++++++++++++ packages/arcodesign/package-lock.json | 2 +- packages/arcodesign/package.json | 4 ++-- packages/common-widgets/CHANGELOG.md | 11 +++++++++++ packages/common-widgets/package-lock.json | 2 +- packages/common-widgets/package.json | 2 +- 6 files changed, 31 insertions(+), 5 deletions(-) diff --git a/packages/arcodesign/CHANGELOG.md b/packages/arcodesign/CHANGELOG.md index fb7a0b7e..9ac74bfb 100644 --- a/packages/arcodesign/CHANGELOG.md +++ b/packages/arcodesign/CHANGELOG.md @@ -3,6 +3,21 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [2.27.5](https://github.com/arco-design/arco-design-mobile/compare/@arco-design/mobile-react@2.27.4...@arco-design/mobile-react@2.27.5) (2023-07-04) + + +### Bug Fixes + +* `ImagePreview` fix long picture display problem ([#137](https://github.com/arco-design/arco-design-mobile/issues/137)) ([3df1f71](https://github.com/arco-design/arco-design-mobile/commit/3df1f71a8b1f63ed5e1986284f2746438de59d70)) +* `LoadMore` fix the inaccurate scrollheight when using multiple loadmore ([#130](https://github.com/arco-design/arco-design-mobile/issues/130)) ([da76f12](https://github.com/arco-design/arco-design-mobile/commit/da76f125734579a1921a3ace0964d5ff845cd545)) +* `Stepper` disable status ([#134](https://github.com/arco-design/arco-design-mobile/issues/134)) ([71dabe7](https://github.com/arco-design/arco-design-mobile/commit/71dabe71f3508ac8cb9a800d8ac1be01df509f28)) +* error caught when using "getComputedStyle" ([#129](https://github.com/arco-design/arco-design-mobile/issues/129)) ([daa8f67](https://github.com/arco-design/arco-design-mobile/commit/daa8f67961d9d2751a14c0c3f7759b54fe0579cb)) +* transition in StrictMode ([#131](https://github.com/arco-design/arco-design-mobile/issues/131)) ([084448b](https://github.com/arco-design/arco-design-mobile/commit/084448b0e4b43ea7d8632e232c1665ce00449c3d)) + + + + + ## [2.27.4](https://github.com/arco-design/arco-design-mobile/compare/@arco-design/mobile-react@2.27.3...@arco-design/mobile-react@2.27.4) (2023-05-19) diff --git a/packages/arcodesign/package-lock.json b/packages/arcodesign/package-lock.json index 274c5e7b..599f3fd8 100644 --- a/packages/arcodesign/package-lock.json +++ b/packages/arcodesign/package-lock.json @@ -1,6 +1,6 @@ { "name": "@arco-design/mobile-react", - "version": "2.27.4", + "version": "2.27.5", "lockfileVersion": 2, "requires": true, "packages": { diff --git a/packages/arcodesign/package.json b/packages/arcodesign/package.json index 64d87d6c..aa23ba81 100644 --- a/packages/arcodesign/package.json +++ b/packages/arcodesign/package.json @@ -1,6 +1,6 @@ { "name": "@arco-design/mobile-react", - "version": "2.27.4", + "version": "2.27.5", "description": "", "main": "cjs/index.js", "module": "esm/index.js", @@ -15,7 +15,7 @@ "author": "taoyiyue@bytedance.com", "license": "ISC", "dependencies": { - "@arco-design/mobile-utils": "2.15.4", + "@arco-design/mobile-utils": "2.15.5", "@arco-design/transformable": "^1.0.0", "lodash.throttle": "^4.1.1", "resize-observer-polyfill": "^1.5.1" diff --git a/packages/common-widgets/CHANGELOG.md b/packages/common-widgets/CHANGELOG.md index 10860c5e..0c45a130 100644 --- a/packages/common-widgets/CHANGELOG.md +++ b/packages/common-widgets/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [2.15.5](https://github.com/arco-design/arco-design-mobile/compare/@arco-design/mobile-utils@2.15.4...@arco-design/mobile-utils@2.15.5) (2023-07-04) + + +### Bug Fixes + +* error caught when using "getComputedStyle" ([#129](https://github.com/arco-design/arco-design-mobile/issues/129)) ([daa8f67](https://github.com/arco-design/arco-design-mobile/commit/daa8f67961d9d2751a14c0c3f7759b54fe0579cb)) + + + + + ## [2.15.4](https://github.com/arco-design/arco-design-mobile/compare/@arco-design/mobile-utils@2.15.3...@arco-design/mobile-utils@2.15.4) (2023-05-19) **Note:** Version bump only for package @arco-design/mobile-utils diff --git a/packages/common-widgets/package-lock.json b/packages/common-widgets/package-lock.json index 4764a776..3ac5e297 100644 --- a/packages/common-widgets/package-lock.json +++ b/packages/common-widgets/package-lock.json @@ -1,6 +1,6 @@ { "name": "@arco-design/mobile-utils", - "version": "2.15.4", + "version": "2.15.5", "lockfileVersion": 2, "requires": true, "packages": { diff --git a/packages/common-widgets/package.json b/packages/common-widgets/package.json index 849d17a5..67bebdc5 100644 --- a/packages/common-widgets/package.json +++ b/packages/common-widgets/package.json @@ -1,6 +1,6 @@ { "name": "@arco-design/mobile-utils", - "version": "2.15.4", + "version": "2.15.5", "description": "", "main": "cjs/index.js", "module": "esm/index.js", From c63a32aa78875a3c89cd7df8992a284674a5f4c7 Mon Sep 17 00:00:00 2001 From: taoyiyue Date: Tue, 4 Jul 2023 18:00:31 +0800 Subject: [PATCH 08/25] build: update readme --- packages/arcodesign/README.en-US.md | 4 ++-- packages/arcodesign/README.md | 4 ++-- packages/arcodesign/package.json | 2 +- packages/arcodesign/tokens/app/arcodesign/default/index.js | 2 +- packages/common-widgets/package.json | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/arcodesign/README.en-US.md b/packages/arcodesign/README.en-US.md index 3946b040..c5c345db 100644 --- a/packages/arcodesign/README.en-US.md +++ b/packages/arcodesign/README.en-US.md @@ -59,8 +59,8 @@ React & ReactDOM: **Click here** ``` - - + + ``` ## Full import diff --git a/packages/arcodesign/README.md b/packages/arcodesign/README.md index 2a87342c..3e5e629a 100644 --- a/packages/arcodesign/README.md +++ b/packages/arcodesign/README.md @@ -59,8 +59,8 @@ React & ReactDOM: **戳这里获取** ``` - - + + ``` ## 引入全部 diff --git a/packages/arcodesign/package.json b/packages/arcodesign/package.json index aa23ba81..c8d5bdf0 100644 --- a/packages/arcodesign/package.json +++ b/packages/arcodesign/package.json @@ -35,5 +35,5 @@ "publishConfig": { "access": "public" }, - "gitHead": "e648561be24f2152a4e3c5ca8f6450c2fbaadca1" + "gitHead": "0f41863cde2457384778f80ec7a7f78bf2e8fe47" } diff --git a/packages/arcodesign/tokens/app/arcodesign/default/index.js b/packages/arcodesign/tokens/app/arcodesign/default/index.js index 9e246d7f..f48a7f69 100644 --- a/packages/arcodesign/tokens/app/arcodesign/default/index.js +++ b/packages/arcodesign/tokens/app/arcodesign/default/index.js @@ -7,7 +7,7 @@ exports["default"] = void 0; exports.getRem = getRem; function getRem(px, baseFontSize) { - var num = Math.round(px / Number(baseFontSize) * 1e6) / 1e6; + var num = Math.round(px / Number(baseFontSize) * 1000000) / 1000000; return num ? "".concat(num, "rem") : num; } diff --git a/packages/common-widgets/package.json b/packages/common-widgets/package.json index 67bebdc5..a8813995 100644 --- a/packages/common-widgets/package.json +++ b/packages/common-widgets/package.json @@ -13,7 +13,7 @@ "publishConfig": { "access": "public" }, - "gitHead": "1ae5c477f0f78e51fd883214b25923a4dcfea8bb", + "gitHead": "0f41863cde2457384778f80ec7a7f78bf2e8fe47", "dependencies": { "es6-promise": "^4.2.8" } From 97de976ba514ec0f48103bd4f0c535ebceb8981a Mon Sep 17 00:00:00 2001 From: Sia <125020500+ziqisia@users.noreply.github.com> Date: Mon, 10 Jul 2023 21:40:03 +0800 Subject: [PATCH 09/25] feat: RTL support for `Badge`, `Button`, `Cell`, `Checkbox`, `Form`, `Radio`, `Rate`, `Switch` and `Tabs` (#135) --- .../components/badge/style/index.less | 6 ++--- .../components/button/style/index.less | 2 +- .../components/cell/style/index.less | 5 +++- .../components/checkbox/style/index.less | 6 ++--- .../components/form/style/index.less | 8 +++--- .../components/radio/style/index.less | 4 +-- packages/arcodesign/components/rate/index.tsx | 9 ++++--- .../components/rate/style/index.less | 4 +++ .../arcodesign/components/switch/index.tsx | 19 +++++++++++--- .../components/switch/style/index.less | 26 ++++++++++++++----- .../components/tabs/demo/style/mobile.less | 6 ++++- packages/arcodesign/components/tabs/index.tsx | 19 +++++++++----- .../components/tabs/style/index.less | 23 +++++++--------- .../components/tabs/tab-cell-underline.tsx | 16 ++++++++---- .../arcodesign/components/tabs/tab-cell.tsx | 11 +++++--- .../arcodesign/components/tabs/tab-pane.tsx | 5 ++-- packages/arcodesign/components/tabs/type.ts | 1 + packages/arcodesign/package-lock.json | 2 +- packages/common-widgets/style/mixin.less | 6 +++++ packages/common-widgets/utils/dom.ts | 2 +- 20 files changed, 119 insertions(+), 61 deletions(-) diff --git a/packages/arcodesign/components/badge/style/index.less b/packages/arcodesign/components/badge/style/index.less index 30a1bf08..4ee3e0d6 100644 --- a/packages/arcodesign/components/badge/style/index.less +++ b/packages/arcodesign/components/badge/style/index.less @@ -60,13 +60,13 @@ &-absolute { position: absolute; top: 0; - left: 100%; - .use-var(margin-left, badge-text-deviation); + .set-prop-with-rtl(left, 100%); + .use-var-with-rtl(margin-left, badge-text-deviation); .use-var(margin-top, badge-text-deviation); } &-absolute&-dot { - .use-var(margin-left, badge-dot-deviation); + .use-var-with-rtl(margin-left, badge-dot-deviation); .use-var(margin-top, badge-dot-deviation); } } diff --git a/packages/arcodesign/components/button/style/index.less b/packages/arcodesign/components/button/style/index.less index b35c2d53..8d8befa2 100644 --- a/packages/arcodesign/components/button/style/index.less +++ b/packages/arcodesign/components/button/style/index.less @@ -84,7 +84,7 @@ vertical-align: middle; } &-text-has-icon { - .use-var(margin-left, button-icon-text-gutter); + .use-var-with-rtl(margin-left, button-icon-text-gutter); } &-loading-icon { diff --git a/packages/arcodesign/components/cell/style/index.less b/packages/arcodesign/components/cell/style/index.less index 1a2076ca..1ad96a4f 100644 --- a/packages/arcodesign/components/cell/style/index.less +++ b/packages/arcodesign/components/cell/style/index.less @@ -54,7 +54,7 @@ .cell-text { width: 100%; - text-align: right; + .set-value-with-rtl(text-align, right); .use-var(font-size, cell-content-font-size); .text-overflow(2); } @@ -71,6 +71,9 @@ } .cell-arrow-icon { + [dir="rtl"] & { + transform: scale(-1); + } .use-var-with-rtl(margin-left, cell-arrow-gutter); font-size: 0; .@{prefix}-icon { diff --git a/packages/arcodesign/components/checkbox/style/index.less b/packages/arcodesign/components/checkbox/style/index.less index a98f7c25..6fb56cb5 100644 --- a/packages/arcodesign/components/checkbox/style/index.less +++ b/packages/arcodesign/components/checkbox/style/index.less @@ -29,7 +29,7 @@ } .checkbox-icon + .checkbox-text { - .use-var(margin-left, checkbox-icon-margin-right); + .use-var-with-rtl(margin-left, checkbox-icon-margin-right); } &.disabled .checkbox-text { @@ -48,11 +48,11 @@ .@{prefix}-checkbox-group { .@{prefix}-checkbox:not(:last-child) { - .use-var(margin-right, checkbox-group-gutter); + .use-var-with-rtl(margin-right, checkbox-group-gutter); &.block, &.justify { - margin-right: 0; + .set-prop-with-rtl(margin-right, 0); } } } diff --git a/packages/arcodesign/components/form/style/index.less b/packages/arcodesign/components/form/style/index.less index a7b4ac23..a0e07f65 100644 --- a/packages/arcodesign/components/form/style/index.less +++ b/packages/arcodesign/components/form/style/index.less @@ -20,12 +20,12 @@ .use-var(font-size, form-item-label-item-font-size); .use-var(line-height, form-item-label-item-line-height); .use-var(color, form-item-label-item-color); - .use-var(padding-right, form-item-label-item-gutter); + .use-var-with-rtl(padding-right, form-item-label-item-gutter); .use-var(width, form-item-label-item-width); &-required-asterisk { position: absolute; - left: -0.6em; + .set-prop-with-rtl(left, -0.6em); top: 0; .use-var(font-size, form-item-label-item-font-size); @@ -60,7 +60,7 @@ } svg { - .rem(margin-right, 4); + .rem-with-rtl(margin-right, 4); } margin-bottom: 16px; } @@ -75,7 +75,7 @@ &-item.@{prefix}-form-item-vertical { display: block; .arco-input-wrap { - padding-left: 0; + .set-prop-with-rtl(padding-left, 0); } .@{prefix}-form-label-item { width: auto; diff --git a/packages/arcodesign/components/radio/style/index.less b/packages/arcodesign/components/radio/style/index.less index c496fb9e..555e1842 100644 --- a/packages/arcodesign/components/radio/style/index.less +++ b/packages/arcodesign/components/radio/style/index.less @@ -29,7 +29,7 @@ } .radio-icon + .radio-text { - .use-var(margin-left, checkbox-icon-margin-right); + .use-var-with-rtl(margin-left, checkbox-icon-margin-right); } &.disabled .radio-text { @@ -48,6 +48,6 @@ .@{prefix}-radio-group { .@{prefix}-radio:not(:last-child, .block) { - .use-var(margin-right, checkbox-group-gutter); + .use-var-with-rtl(margin-right, checkbox-group-gutter); } } diff --git a/packages/arcodesign/components/rate/index.tsx b/packages/arcodesign/components/rate/index.tsx index e8d68f56..b40ec6d2 100644 --- a/packages/arcodesign/components/rate/index.tsx +++ b/packages/arcodesign/components/rate/index.tsx @@ -224,7 +224,7 @@ const Rate = forwardRef((props: RateProps, ref: Ref) => { return ( - {({ prefixCls }) => ( + {({ prefixCls, useRtl }) => (
) => { // 对内的index从1开始,方便计算 // @en The index of the pair starts from 1, which is convenient for calculation const index = i + 1; + const halfIndex = allowHalf ? index - 0.5 : index; const status = getIconStatus(index); return (
) => {
- handleStarIndexChange(allowHalf ? index - 0.5 : index) + handleStarIndexChange(useRtl ? index : halfIndex) } />
handleStarIndexChange(index)} + onClick={() => + handleStarIndexChange(useRtl ? halfIndex : index) + } />
); diff --git a/packages/arcodesign/components/rate/style/index.less b/packages/arcodesign/components/rate/style/index.less index 43cdf6e8..a2d55c71 100644 --- a/packages/arcodesign/components/rate/style/index.less +++ b/packages/arcodesign/components/rate/style/index.less @@ -38,6 +38,10 @@ &.half-active { position: absolute; z-index: 1; + + [dir="rtl"] & { + transform: scaleX(-1); + } } } diff --git a/packages/arcodesign/components/switch/index.tsx b/packages/arcodesign/components/switch/index.tsx index f38de812..60517fa2 100644 --- a/packages/arcodesign/components/switch/index.tsx +++ b/packages/arcodesign/components/switch/index.tsx @@ -1,6 +1,14 @@ -import React, { useState, useEffect, forwardRef, Ref, useImperativeHandle, useRef } from 'react'; +import React, { + useState, + useEffect, + forwardRef, + Ref, + useImperativeHandle, + useRef, + useContext, +} from 'react'; import { cls, componentWrapper } from '@arco-design/mobile-utils'; -import { ContextLayout } from '../context-provider'; +import { ContextLayout, GlobalContext } from '../context-provider'; import { useSystem } from '../_helpers'; interface SwitchText { @@ -98,6 +106,7 @@ export interface SwitchRef { } const Switch = forwardRef((props: SwitchProps, ref: Ref) => { + const { useRtl } = useContext(GlobalContext); const system = useSystem(); const { className, @@ -153,15 +162,17 @@ const Switch = forwardRef((props: SwitchProps, ref: Ref) => { } const touchEndX = e.changedTouches && e.changedTouches[0] ? e.changedTouches[0].clientX : 0; const distance = touchEndX - touchStartX; + const swipeRight = useRtl ? distance < 0 : distance > 0; + const swipeLeft = useRtl ? distance > 0 : distance < 0; let newChecked = false; // 右滑打开 // @en Swipe right to open - if (distance > 0) { + if (swipeRight) { newChecked = true; // 左滑关闭 // @en Swipe left to close - } else if (distance < 0) { + } else if (swipeLeft) { newChecked = false; // 点击时取反 // @en Invert on clicking diff --git a/packages/arcodesign/components/switch/style/index.less b/packages/arcodesign/components/switch/style/index.less index a4e62cdf..54bc4d15 100644 --- a/packages/arcodesign/components/switch/style/index.less +++ b/packages/arcodesign/components/switch/style/index.less @@ -33,17 +33,23 @@ &.checked { .use-var(background-color, switch-android-checked-background); .@{prefix}-switch-text { - right: auto; - .use-var(left, switch-android-text-gap-size); + .set-prop-with-rtl(right, auto); + .use-var-with-rtl(left, switch-android-text-gap-size); } .@{prefix}-switch-inner { .use-var(transform, switch-android-checked-inner-transform); + [dir="rtl"] & { + .use-var(transform, switch-android-checked-inner-transform, "rotate(180deg)"); + } } } .@{prefix}-switch-inner { .use-var(width, switch-android-inner-diameter-size); .use-var(height, switch-android-inner-diameter-size); .use-var(box-shadow, switch-android-inner-box-shadow); + [dir="rtl"] & { + transform: rotate(180deg); + } } &.disabled { @@ -58,7 +64,7 @@ } .@{prefix}-switch-text { .use-var(font-size, switch-android-text-font-size); - .use-var(right, switch-android-text-gap-size); + .use-var-with-rtl(right, switch-android-text-gap-size); } } @@ -80,12 +86,15 @@ &.checked { .use-var(background-color, switch-ios-checked-background); .@{prefix}-switch-text { - right: auto; - .use-var(left, switch-ios-text-gap-size); + .set-prop-with-rtl(right, auto); + .use-var-with-rtl(left, switch-ios-text-gap-size); } .@{prefix}-switch-inner { .use-var(transform, switch-ios-checked-inner-transform); .use-var(box-shadow, switch-ios-inner-box-shadow); + [dir="rtl"] & { + .use-var(transform, switch-ios-checked-inner-transform, "rotate(180deg)"); + } } } @@ -94,12 +103,15 @@ } .@{prefix}-switch-text { .use-var(font-size, switch-ios-text-font-size); - .use-var(right, switch-ios-text-gap-size); + .use-var-with-rtl(right, switch-ios-text-gap-size); } .@{prefix}-switch-inner { .use-var(width, switch-ios-inner-diameter-size); .use-var(height, switch-ios-inner-diameter-size); .onepx-border-var(all, switch-ios-inner-border-color, 50%); + [dir="rtl"] & { + transform: rotate(180deg); + } } &.disabled { @@ -127,7 +139,7 @@ &-inner { position: relative; - left: 0; + .set-prop-with-rtl(left, 0); top: 0; display: flex; align-items: center; diff --git a/packages/arcodesign/components/tabs/demo/style/mobile.less b/packages/arcodesign/components/tabs/demo/style/mobile.less index dd2cd57d..4af7084d 100644 --- a/packages/arcodesign/components/tabs/demo/style/mobile.less +++ b/packages/arcodesign/components/tabs/demo/style/mobile.less @@ -24,7 +24,7 @@ .demo-tabs-add-extra { position: absolute; - right: 0; + .set-prop-with-rtl(right, 0); top: 0; background: linear-gradient(270deg, #fff 66.04%, rgba(255, 255, 255, 0) 105%); .rem(width, 64); @@ -36,6 +36,10 @@ align-items: center; justify-content: flex-end; font-weight: bold; + [dir="rtl"] & { + justify-content: flex-start; + transform: rotate(180deg); + } } .demo-tab-custom-bar { diff --git a/packages/arcodesign/components/tabs/index.tsx b/packages/arcodesign/components/tabs/index.tsx index e90b9860..5b61d312 100644 --- a/packages/arcodesign/components/tabs/index.tsx +++ b/packages/arcodesign/components/tabs/index.tsx @@ -7,9 +7,10 @@ import React, { useState, useEffect, useCallback, + useContext, } from 'react'; import { cls, nextTick } from '@arco-design/mobile-utils'; -import { ContextLayout } from '../context-provider'; +import { ContextLayout, GlobalContext } from '../context-provider'; import TabCell from './tab-cell'; import TabPane from './tab-pane'; import { @@ -110,6 +111,7 @@ const Tabs = forwardRef((props: TabsProps, ref: Ref) => { tabBarStopPropagation = true, swipeEnergySaving = false, } = props; + const { useRtl } = useContext(GlobalContext); const domRef = useRef(null); const cellRef = useRef(null); const paneRef = useRef(null); @@ -142,6 +144,8 @@ const Tabs = forwardRef((props: TabsProps, ref: Ref) => { swipeable && tabDirection === 'vertical' && tabs.length > 1; + const horizontalUseRtl = tabDirection === 'vertical' && useRtl; + const rtlRatio = horizontalUseRtl ? -1 : 1; useImperativeHandle(ref, () => ({ dom: domRef.current, @@ -264,6 +268,7 @@ const Tabs = forwardRef((props: TabsProps, ref: Ref) => { const posDisY = touchMoveY - touchStartYRef.current; const absDisX = Math.abs(posDisX); const absDisY = Math.abs(posDisY); + const comparedDis = posDisX * rtlRatio; if (scrollingRef.current === null) { scrollingRef.current = absDisX < absDisY; } @@ -278,12 +283,12 @@ const Tabs = forwardRef((props: TabsProps, ref: Ref) => { return; } if ( - (activeIndexRef.current === 0 && posDisX > 0) || - (activeIndexRef.current === tabs.length - 1 && posDisX < 0) + (activeIndexRef.current === 0 && comparedDis > 0) || + (activeIndexRef.current === tabs.length - 1 && comparedDis < 0) ) { if (!touchStoppedRef.current && absDisX > stopTouchThreshold) { touchStoppedRef.current = true; - onTouchStopped && onTouchStopped(posDisX >= 0 ? -1 : 1); + onTouchStopped && onTouchStopped(comparedDis >= 0 ? -1 : 1); } setDistance(0); return; @@ -339,9 +344,10 @@ const Tabs = forwardRef((props: TabsProps, ref: Ref) => { (Math.abs(dis) > maxSlice && Math.abs(dis) > distanceToChangeTab) || Math.abs(speed) > speedToChangeTab; let newIndex = index; - if (dis > 0 && needJump) { + const comparedDis = dis * rtlRatio; + if (comparedDis > 0 && needJump) { newIndex = index - 1; - } else if (dis < 0 && needJump) { + } else if (comparedDis < 0 && needJump) { newIndex = index + 1; } nextTick(() => { @@ -483,6 +489,7 @@ const Tabs = forwardRef((props: TabsProps, ref: Ref) => { autoHeight={autoHeight} onScroll={onScroll} swipeEnergySaving={swipeEnergySaving} + rtlRatio={rtlRatio} {...commonProps} />
diff --git a/packages/arcodesign/components/tabs/style/index.less b/packages/arcodesign/components/tabs/style/index.less index f964f72b..440c68d5 100644 --- a/packages/arcodesign/components/tabs/style/index.less +++ b/packages/arcodesign/components/tabs/style/index.less @@ -310,12 +310,8 @@ &:not(.custom) { - &.line { - .use-var(margin-right, tabs-tab-bar-line-gutter); - - &.last { - margin-right: 0; - } + &.line:not(.last) { + .use-var-with-rtl(margin-right, tabs-tab-bar-line-gutter); } &.line, @@ -337,17 +333,17 @@ } &:not(:last-child) { - .use-var(border-right, tabs-tab-bar-card-color, 1PX solid); + .use-var-with-rtl(border-right, tabs-tab-bar-card-color, 1PX solid); } &:first-of-type { - .use-var(border-top-left-radius, tabs-tab-bar-card-border-radius); - .use-var(border-bottom-left-radius, tabs-tab-bar-card-border-radius); + .use-var-with-rtl(border-top-left-radius, tabs-tab-bar-card-border-radius); + .use-var-with-rtl(border-bottom-left-radius, tabs-tab-bar-card-border-radius); } &:last-of-type { - .use-var(border-top-right-radius, tabs-tab-bar-card-border-radius); - .use-var(border-bottom-right-radius, tabs-tab-bar-card-border-radius); + .use-var-with-rtl(border-top-right-radius, tabs-tab-bar-card-border-radius); + .use-var-with-rtl(border-bottom-right-radius, tabs-tab-bar-card-border-radius); } } @@ -361,14 +357,13 @@ &.tag, &.tag-divide { - .use-var(margin-right, tabs-tab-bar-tag-gutter); .use-var(padding, tabs-tab-bar-tag-padding); .rem(border-radius, 100); .use-var(background, tabs-tab-bar-tag-background); .use-var(color, tabs-tab-bar-tag-text-color); - &.last { - margin-right: 0; + &:not(.last) { + .use-var-with-rtl(margin-right, tabs-tab-bar-tag-gutter); } &.active { diff --git a/packages/arcodesign/components/tabs/tab-cell-underline.tsx b/packages/arcodesign/components/tabs/tab-cell-underline.tsx index c448b3c0..9ca31fe5 100644 --- a/packages/arcodesign/components/tabs/tab-cell-underline.tsx +++ b/packages/arcodesign/components/tabs/tab-cell-underline.tsx @@ -2,6 +2,7 @@ import React, { CSSProperties, forwardRef, Ref, + useContext, useEffect, useImperativeHandle, useMemo, @@ -11,6 +12,7 @@ import React, { import { addCssKeyframes, cls, nextTick, removeCssStyleDom } from '@arco-design/mobile-utils'; import { TabCellUnderlineProps, TabCellUnderlineRef, UnderlineStyle } from './type'; import { getStyleWithVendor, useRefState, useSystem } from '../_helpers'; +import { GlobalContext } from '../context-provider'; const TabCellUnderline = forwardRef( (props: TabCellUnderlineProps, ref: Ref) => { @@ -37,6 +39,7 @@ const TabCellUnderline = forwardRef( getTabRect, getTabCenterLeft, } = props; + const { useRtl } = useContext(GlobalContext); const [underlineStyle, setUnderlineStyle] = useState({}); const [caterpillar, caterpillarRef, setCaterpillar] = useRefState(false); const [caterpillarDelay, setCaterpillarDelay] = useState(0); @@ -46,6 +49,7 @@ const TabCellUnderline = forwardRef( const isVertical = tabDirection === 'vertical'; const maxScaleWithDefault = caterpillarMaxScale || 2; const translateZStr = translateZ ? ' translateZ(0)' : ''; + const rtlRatio = isVertical && useRtl ? -1 : 1; useImperativeHandle( ref, @@ -159,10 +163,11 @@ const TabCellUnderline = forwardRef( } function getDescIndex() { - if (distance > 0) { + const comparedDis = distance * rtlRatio; + if (comparedDis > 0) { return activeIndex - 1; } - if (distance < 0) { + if (comparedDis < 0) { return activeIndex + 1; } return activeIndex; @@ -182,7 +187,8 @@ const TabCellUnderline = forwardRef( const currentLeft = getLineLeft(activeIndex); const descIndex = getDescIndex(); const descLeft = getLineLeft(descIndex); - const moveRatio = wrapWidth ? distance / wrapWidth : 0; + const comparedDis = distance * rtlRatio; + const moveRatio = wrapWidth ? comparedDis / wrapWidth : 0; const leftOffset = moveRatio * (currentLeft - descLeft); const direc = isVertical ? 'X' : 'Y'; const transStyle: CSSProperties = @@ -206,7 +212,7 @@ const TabCellUnderline = forwardRef( const widthOffset = moveRatio * (currentWidth - descWidth); adaptiveStyle = { [isVertical ? 'width' : 'height']: - distance > 0 ? currentWidth - widthOffset : currentWidth + widthOffset, + comparedDis > 0 ? currentWidth - widthOffset : currentWidth + widthOffset, willChange: 'width', }; adaptiveOuterStyle = isVertical ? { width: 'auto' } : { height: 'auto' }; @@ -223,7 +229,7 @@ const TabCellUnderline = forwardRef( return { outer: { transform: `translate${direc}(${ - distance > 0 ? currentLeft - leftOffset : currentLeft + leftOffset + comparedDis > 0 ? currentLeft - leftOffset : currentLeft + leftOffset }px)${translateZStr}`, ...outerSize, ...adaptiveOuterStyle, diff --git a/packages/arcodesign/components/tabs/tab-cell.tsx b/packages/arcodesign/components/tabs/tab-cell.tsx index f9ad1da9..e8052c4b 100644 --- a/packages/arcodesign/components/tabs/tab-cell.tsx +++ b/packages/arcodesign/components/tabs/tab-cell.tsx @@ -6,11 +6,13 @@ import React, { useState, useEffect, CSSProperties, + useContext, } from 'react'; import { cls, scrollWithAnimation, nextTick } from '@arco-design/mobile-utils'; import { TabData, TabCellProps, TabCellRef, TabCellUnderlineRef, OffsetRect } from './type'; import { useSystem } from '../_helpers'; import TabCellUnderline from './tab-cell-underline'; +import { GlobalContext } from '../context-provider'; const TabCell = forwardRef((props: TabCellProps, ref: Ref) => { const { @@ -62,6 +64,7 @@ const TabCell = forwardRef((props: TabCellProps, ref: Ref) => { tabBarStopPropagation, } = props; const prefix = `${prefixCls}-tab-cell`; + const { useRtl } = useContext(GlobalContext); const domRef = useRef(null); const underlineRef = useRef(null); const allCellRectRef = useRef([]); @@ -252,14 +255,16 @@ const TabCell = forwardRef((props: TabCellProps, ref: Ref) => { if (!isVertical) { return {}; } + const marginStart = useRtl ? 'marginRight' : 'marginLeft'; + const marginEnd = useRtl ? 'marginLeft' : 'marginRight'; if (index === 0) { return { - marginRight: cellGutter, - marginLeft: getCellPadding('left'), + [marginEnd]: cellGutter, + [marginStart]: getCellPadding('left'), }; } return { - marginRight: index === tabs.length - 1 ? void 0 : cellGutter, + [marginEnd]: index === tabs.length - 1 ? void 0 : cellGutter, }; } diff --git a/packages/arcodesign/components/tabs/tab-pane.tsx b/packages/arcodesign/components/tabs/tab-pane.tsx index 6befab76..5369213b 100644 --- a/packages/arcodesign/components/tabs/tab-pane.tsx +++ b/packages/arcodesign/components/tabs/tab-pane.tsx @@ -45,6 +45,7 @@ const TabPane = forwardRef((props: TabPaneProps, ref: Ref) => { swipeEnergySaving, changeIndex, onScroll, + rtlRatio, } = props; const domRef = useRef(null); const panesRef = useRef<(HTMLDivElement | null)[]>([]); @@ -224,7 +225,7 @@ const TabPane = forwardRef((props: TabPaneProps, ref: Ref) => { ? { width: `${100 * panes.length}%`, transform: `translateX(${ - distance - wrapWidth * activeIndex + distance - wrapWidth * activeIndex * rtlRatio }px)${translateStr}`, } : { @@ -263,7 +264,7 @@ const TabPane = forwardRef((props: TabPaneProps, ref: Ref) => { tabDirection === 'vertical' ? { transform: `translateX(${ - distance - wrapWidth * (activeIndex - index) + distance - wrapWidth * (activeIndex - index) * rtlRatio }px)${translateStr}`, } : { diff --git a/packages/arcodesign/components/tabs/type.ts b/packages/arcodesign/components/tabs/type.ts index 9c86f124..a801f50d 100644 --- a/packages/arcodesign/components/tabs/type.ts +++ b/packages/arcodesign/components/tabs/type.ts @@ -654,6 +654,7 @@ export interface TabPaneProps paneTrans: boolean; swipeable: boolean; changeIndex: (newIndex: number, from?: string) => void; + rtlRatio: number; } export interface TabPaneRef { diff --git a/packages/arcodesign/package-lock.json b/packages/arcodesign/package-lock.json index 599f3fd8..c5987387 100644 --- a/packages/arcodesign/package-lock.json +++ b/packages/arcodesign/package-lock.json @@ -6,7 +6,7 @@ "packages": { "": { "name": "@arco-design/mobile-react", - "version": "2.25.3", + "version": "2.27.4", "license": "ISC", "dependencies": { "@arco-design/transformable": "^1.0.0", diff --git a/packages/common-widgets/style/mixin.less b/packages/common-widgets/style/mixin.less index b36cee72..e478f643 100644 --- a/packages/common-widgets/style/mixin.less +++ b/packages/common-widgets/style/mixin.less @@ -258,6 +258,12 @@ @margin-right: margin-left; @padding-left: padding-right; @padding-right: padding-left; + @border-right: border-left; + @border-left: border-right; + @border-top-left-radius: border-top-right-radius; + @border-bottom-left-radius: border-bottom-right-radius; + @border-top-right-radius: border-top-left-radius; + @border-bottom-right-radius: border-bottom-left-radius; } @property-name: @property-map[@@origin-property]; } diff --git a/packages/common-widgets/utils/dom.ts b/packages/common-widgets/utils/dom.ts index cb0a11c4..097b29d4 100644 --- a/packages/common-widgets/utils/dom.ts +++ b/packages/common-widgets/utils/dom.ts @@ -74,7 +74,7 @@ export function scrollWithAnimation( bezier: [number, number, number, number] = [0.34, 0.69, 0.1, 1], type: 'by' | 'to' = 'to', ) { - const targetTop = Math.max(0, type === 'by' ? initTop + target : target); + const targetTop = type === 'by' ? initTop + target : target; const start = Date.now(); const fn = () => { const p = (Date.now() - start) / duration; From 842b4fe6084b3ae282bd54850e381fbe34bd826f Mon Sep 17 00:00:00 2001 From: taoyiyue Date: Fri, 14 Jul 2023 14:58:35 +0800 Subject: [PATCH 10/25] fix: `Sticky` support the method "updatePlaceholderLayout" --- .../components/sticky/README.en-US.md | 1 + .../arcodesign/components/sticky/README.md | 1 + .../components/sticky/__ast__/index.ast.json | 13 ++++++++ .../arcodesign/components/sticky/index.tsx | 33 ++++++++++++++----- 4 files changed, 40 insertions(+), 8 deletions(-) diff --git a/packages/arcodesign/components/sticky/README.en-US.md b/packages/arcodesign/components/sticky/README.en-US.md index 4ddf0679..20379aeb 100644 --- a/packages/arcodesign/components/sticky/README.en-US.md +++ b/packages/arcodesign/components/sticky/README.en-US.md @@ -33,6 +33,7 @@ Sticky layout component, The sticky-to-top effect of the element relative to the |----------|-------------|------| |dom|The outermost element DOM|HTMLDivElement| |recalculatePosition|In the local scrolling mode, if there is nested scrolling outside the container, this method can be actively called to make the sticky element actively update the fixed position|() =\> void| +|updatePlaceholderLayout|Manually update the height of the placeholder|() =\> void| > StickyEventPayload diff --git a/packages/arcodesign/components/sticky/README.md b/packages/arcodesign/components/sticky/README.md index e4f42590..48d88e6e 100644 --- a/packages/arcodesign/components/sticky/README.md +++ b/packages/arcodesign/components/sticky/README.md @@ -33,6 +33,7 @@ |----------|-------------|------| |dom|最外层元素 DOM|HTMLDivElement| |recalculatePosition|局部滚动模式下,如果容器外部还有嵌套滚动,可主动调用此方法,让 sticky 的元素主动更新 fixed 位置|() =\> void| +|updatePlaceholderLayout|手动更新占位模块的高度|() =\> void| > StickyEventPayload diff --git a/packages/arcodesign/components/sticky/__ast__/index.ast.json b/packages/arcodesign/components/sticky/__ast__/index.ast.json index ca103a61..9a8baa18 100644 --- a/packages/arcodesign/components/sticky/__ast__/index.ast.json +++ b/packages/arcodesign/components/sticky/__ast__/index.ast.json @@ -423,6 +423,19 @@ "en": "In the local scrolling mode, if there is nested scrolling outside the container, this method can be actively called to make the sticky element actively update the fixed position" }, "descWithTags": "局部滚动模式下,如果容器外部还有嵌套滚动,可主动调用此方法,让 sticky 的元素主动更新 fixed 位置" + }, + "updatePlaceholderLayout": { + "name": "updatePlaceholderLayout", + "required": true, + "description": "手动更新占位模块的高度\n@en Manually update the height of the placeholder", + "defaultValue": null, + "type": { + "name": "() => void" + }, + "tags": { + "en": "Manually update the height of the placeholder" + }, + "descWithTags": "手动更新占位模块的高度" } } }, diff --git a/packages/arcodesign/components/sticky/index.tsx b/packages/arcodesign/components/sticky/index.tsx index a55ba1c4..861171fe 100644 --- a/packages/arcodesign/components/sticky/index.tsx +++ b/packages/arcodesign/components/sticky/index.tsx @@ -31,6 +31,11 @@ export interface StickyRef { * @en In the local scrolling mode, if there is nested scrolling outside the container, this method can be actively called to make the sticky element actively update the fixed position */ recalculatePosition: () => void; + /** + * 手动更新占位模块的高度 + * @en Manually update the height of the placeholder + */ + updatePlaceholderLayout: () => void; } export interface StickyEventPayload { @@ -300,6 +305,23 @@ const Sticky = forwardRef((props: StickyProps, ref: Ref) => { framePendingRef.current = true; }, [containerEventHandler]); + const updatePlaceholderLayoutInner = useCallback(() => { + if (placeholderRef.current) { + const contentHeight = contentCalculateHeightRef.current; + // 当元素吸顶时,默认有一个占位的元素占住该元素的位置,避免布局产生抖动 + // @en When an element is sticky to the top, a placeholder element occupies the element's position by default to avoid jitter in the layout + placeholderRef.current.style.height = `${isStickyRef.current ? contentHeight : 0}px`; + } + }, []); + + const updatePlaceholderLayout = useCallback(() => { + if (contentRef.current) { + const contentClientRect = contentRef.current.getBoundingClientRect(); + contentCalculateHeightRef.current = contentClientRect.height; + } + updatePlaceholderLayoutInner(); + }, []); + useEffect(() => { const containerEle = getActualContainer(getContainer) as HTMLElement; @@ -326,13 +348,7 @@ const Sticky = forwardRef((props: StickyProps, ref: Ref) => { }, [getContainer, getScrollContainer, recalculatePosition]); useEffect(() => { - if (placeholderRef.current) { - // 当元素吸顶时,默认有一个占位的元素占住该元素的位置,避免布局产生抖动 - // @en When an element is sticky to the top, a placeholder element occupies the element's position by default to avoid jitter in the layout - placeholderRef.current.style.height = `${ - isStickyRef.current ? contentCalculateHeightRef.current : 0 - }px`; - } + updatePlaceholderLayoutInner(); }, [isSticky, wasSticky]); useImperativeHandle( @@ -340,8 +356,9 @@ const Sticky = forwardRef((props: StickyProps, ref: Ref) => { () => ({ dom: contentRef.current, recalculatePosition, + updatePlaceholderLayout, }), - [recalculatePosition], + [recalculatePosition, updatePlaceholderLayout], ); const computedStyle = useMemo( From ea3f9bc5d0980f70c81e2de99084e0a11187b3c1 Mon Sep 17 00:00:00 2001 From: taoyiyue Date: Fri, 14 Jul 2023 14:59:49 +0800 Subject: [PATCH 11/25] fix: `ImagePreview` fix scroll through --- packages/arcodesign/components/image-preview/index.tsx | 8 +++++++- packages/common-widgets/style/mixin.less | 1 - 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/arcodesign/components/image-preview/index.tsx b/packages/arcodesign/components/image-preview/index.tsx index 0f2e9059..5297fb45 100644 --- a/packages/arcodesign/components/image-preview/index.tsx +++ b/packages/arcodesign/components/image-preview/index.tsx @@ -982,7 +982,13 @@ const ImagePreview = forwardRef((props: ImagePreviewProps, ref: Ref ImageProps, ) { return ( - + {(allImages || []).map((image, index) => { const innerNode = (
Date: Fri, 14 Jul 2023 19:18:07 +0800 Subject: [PATCH 12/25] fix: `Collapse` update with the latest opened (#140) --- .../arcodesign/components/_helpers/hooks.ts | 12 ++++++++++++ .../components/collapse/collapse.tsx | 19 +++++++++++-------- packages/common-widgets/package-lock.json | 2 +- 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/packages/arcodesign/components/_helpers/hooks.ts b/packages/arcodesign/components/_helpers/hooks.ts index 83cd1834..25fbf13a 100644 --- a/packages/arcodesign/components/_helpers/hooks.ts +++ b/packages/arcodesign/components/_helpers/hooks.ts @@ -49,6 +49,18 @@ export function useMountedState(initialState: S | (() => S)) { return result; } +export function useSameRefState( + initialValue: T, +): [T, React.MutableRefObject, (data: T) => void] { + const [state, setState] = useState(initialValue); + const stateRef = useRef(state); + const setStateProxy = (data: T) => { + stateRef.current = data; + setState(data); + }; + return [state, stateRef, setStateProxy]; +} + export function useRefState( initialValue: T | (() => T), ): [T, React.MutableRefObject, React.Dispatch>] { diff --git a/packages/arcodesign/components/collapse/collapse.tsx b/packages/arcodesign/components/collapse/collapse.tsx index e89e1a06..d8763cf4 100644 --- a/packages/arcodesign/components/collapse/collapse.tsx +++ b/packages/arcodesign/components/collapse/collapse.tsx @@ -6,11 +6,10 @@ import React, { useState, useEffect, useContext, - useMemo, } from 'react'; import { cls, convertCssDuration, nextTick } from '@arco-design/mobile-utils'; import { ContextLayout } from '../context-provider'; -import { useRefState, useUpdateEffect } from '../_helpers'; +import { useRefState, useSameRefState, useUpdateEffect } from '../_helpers'; import IconArrowDown from '../icon/IconArrowDown'; import { CollapseProps, CollapseRef } from './type'; import { allContexts, CollapseKeyContext } from './utils'; @@ -42,7 +41,9 @@ export const Collapse = forwardRef((props: CollapseProps, ref: Ref) const { key: groupKey } = useContext(CollapseKeyContext); const CollapseContext = allContexts[groupKey] || {}; const groupContext = useContext(CollapseContext) || {}; - const opened = useMemo(() => { + const [opened, openedRef, setOpened] = useSameRefState(false); + + useEffect(() => { let show = false; // 优先级: group > children // @en Priority: group > children @@ -54,7 +55,7 @@ export const Collapse = forwardRef((props: CollapseProps, ref: Ref) } else { show = itemActive; } - return show; + setOpened(show); }, [value, active, itemActive, groupContext.isGroup, groupContext.value]); const getContentHeight = () => { @@ -71,8 +72,8 @@ export const Collapse = forwardRef((props: CollapseProps, ref: Ref) setTimeout( () => contentWrapRef.current && - (contentWrapRef.current.style.height = opened ? 'auto' : '0px'), - opened ? transTimeout : 20, + (contentWrapRef.current.style.height = openedRef.current ? 'auto' : '0px'), + openedRef.current ? transTimeout : 20, ); }; @@ -93,10 +94,12 @@ export const Collapse = forwardRef((props: CollapseProps, ref: Ref) return; } const height = getContentHeight(); - contentWrapRef.current.style.height = opened ? `${contentHeightRef.current}px` : '0px'; + contentWrapRef.current.style.height = openedRef.current + ? `${contentHeightRef.current}px` + : '0px'; nextTick(() => { contentHeightRef.current = height; - resetHeight(opened ? `${height}px` : '0px'); + resetHeight(openedRef.current ? `${height}px` : '0px'); }); }; diff --git a/packages/common-widgets/package-lock.json b/packages/common-widgets/package-lock.json index 3ac5e297..8de722f5 100644 --- a/packages/common-widgets/package-lock.json +++ b/packages/common-widgets/package-lock.json @@ -6,7 +6,7 @@ "packages": { "": { "name": "@arco-design/mobile-utils", - "version": "2.15.4", + "version": "2.15.5", "license": "ISC", "dependencies": { "es6-promise": "^4.2.8" From 6809000ae9f4310979628d4bd43a728d34266899 Mon Sep 17 00:00:00 2001 From: taoyiyue Date: Fri, 14 Jul 2023 19:19:46 +0800 Subject: [PATCH 13/25] build: release version - @arco-design/mobile-react@2.28.0 - @arco-design/mobile-utils@2.16.0 --- packages/arcodesign/CHANGELOG.md | 18 ++++++++++++++++++ packages/arcodesign/package-lock.json | 2 +- packages/arcodesign/package.json | 4 ++-- packages/common-widgets/CHANGELOG.md | 17 +++++++++++++++++ packages/common-widgets/package-lock.json | 2 +- packages/common-widgets/package.json | 2 +- 6 files changed, 40 insertions(+), 5 deletions(-) diff --git a/packages/arcodesign/CHANGELOG.md b/packages/arcodesign/CHANGELOG.md index 9ac74bfb..b7c138da 100644 --- a/packages/arcodesign/CHANGELOG.md +++ b/packages/arcodesign/CHANGELOG.md @@ -3,6 +3,24 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [2.28.0](https://github.com/arco-design/arco-design-mobile/compare/@arco-design/mobile-react@2.27.5...@arco-design/mobile-react@2.28.0) (2023-07-14) + + +### Bug Fixes + +* `Collapse` update with the latest opened ([#140](https://github.com/arco-design/arco-design-mobile/issues/140)) ([b963787](https://github.com/arco-design/arco-design-mobile/commit/b96378761557f4d90f09f789f662e9d3588c3cbd)) +* `ImagePreview` fix scroll through ([ea3f9bc](https://github.com/arco-design/arco-design-mobile/commit/ea3f9bc5d0980f70c81e2de99084e0a11187b3c1)) +* `Sticky` support the method "updatePlaceholderLayout" ([842b4fe](https://github.com/arco-design/arco-design-mobile/commit/842b4fe6084b3ae282bd54850e381fbe34bd826f)) + + +### Features + +* RTL support for `Badge`, `Button`, `Cell`, `Checkbox`, `Form`, `Radio`, `Rate`, `Switch` and `Tabs` ([#135](https://github.com/arco-design/arco-design-mobile/issues/135)) ([97de976](https://github.com/arco-design/arco-design-mobile/commit/97de976ba514ec0f48103bd4f0c535ebceb8981a)) + + + + + ## [2.27.5](https://github.com/arco-design/arco-design-mobile/compare/@arco-design/mobile-react@2.27.4...@arco-design/mobile-react@2.27.5) (2023-07-04) diff --git a/packages/arcodesign/package-lock.json b/packages/arcodesign/package-lock.json index c5987387..f755d2c7 100644 --- a/packages/arcodesign/package-lock.json +++ b/packages/arcodesign/package-lock.json @@ -1,6 +1,6 @@ { "name": "@arco-design/mobile-react", - "version": "2.27.5", + "version": "2.28.0", "lockfileVersion": 2, "requires": true, "packages": { diff --git a/packages/arcodesign/package.json b/packages/arcodesign/package.json index c8d5bdf0..fabd751b 100644 --- a/packages/arcodesign/package.json +++ b/packages/arcodesign/package.json @@ -1,6 +1,6 @@ { "name": "@arco-design/mobile-react", - "version": "2.27.5", + "version": "2.28.0", "description": "", "main": "cjs/index.js", "module": "esm/index.js", @@ -15,7 +15,7 @@ "author": "taoyiyue@bytedance.com", "license": "ISC", "dependencies": { - "@arco-design/mobile-utils": "2.15.5", + "@arco-design/mobile-utils": "2.16.0", "@arco-design/transformable": "^1.0.0", "lodash.throttle": "^4.1.1", "resize-observer-polyfill": "^1.5.1" diff --git a/packages/common-widgets/CHANGELOG.md b/packages/common-widgets/CHANGELOG.md index 0c45a130..f48f10f2 100644 --- a/packages/common-widgets/CHANGELOG.md +++ b/packages/common-widgets/CHANGELOG.md @@ -3,6 +3,23 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [2.16.0](https://github.com/arco-design/arco-design-mobile/compare/@arco-design/mobile-utils@2.15.5...@arco-design/mobile-utils@2.16.0) (2023-07-14) + + +### Bug Fixes + +* `Collapse` update with the latest opened ([#140](https://github.com/arco-design/arco-design-mobile/issues/140)) ([b963787](https://github.com/arco-design/arco-design-mobile/commit/b96378761557f4d90f09f789f662e9d3588c3cbd)) +* `ImagePreview` fix scroll through ([ea3f9bc](https://github.com/arco-design/arco-design-mobile/commit/ea3f9bc5d0980f70c81e2de99084e0a11187b3c1)) + + +### Features + +* RTL support for `Badge`, `Button`, `Cell`, `Checkbox`, `Form`, `Radio`, `Rate`, `Switch` and `Tabs` ([#135](https://github.com/arco-design/arco-design-mobile/issues/135)) ([97de976](https://github.com/arco-design/arco-design-mobile/commit/97de976ba514ec0f48103bd4f0c535ebceb8981a)) + + + + + ## [2.15.5](https://github.com/arco-design/arco-design-mobile/compare/@arco-design/mobile-utils@2.15.4...@arco-design/mobile-utils@2.15.5) (2023-07-04) diff --git a/packages/common-widgets/package-lock.json b/packages/common-widgets/package-lock.json index 8de722f5..26378180 100644 --- a/packages/common-widgets/package-lock.json +++ b/packages/common-widgets/package-lock.json @@ -1,6 +1,6 @@ { "name": "@arco-design/mobile-utils", - "version": "2.15.5", + "version": "2.16.0", "lockfileVersion": 2, "requires": true, "packages": { diff --git a/packages/common-widgets/package.json b/packages/common-widgets/package.json index a8813995..5f656034 100644 --- a/packages/common-widgets/package.json +++ b/packages/common-widgets/package.json @@ -1,6 +1,6 @@ { "name": "@arco-design/mobile-utils", - "version": "2.15.5", + "version": "2.16.0", "description": "", "main": "cjs/index.js", "module": "esm/index.js", From 481ab5089c0367079ae51f7647b42af4565e383e Mon Sep 17 00:00:00 2001 From: taoyiyue Date: Fri, 14 Jul 2023 19:29:40 +0800 Subject: [PATCH 14/25] build: update readme --- packages/arcodesign/README.en-US.md | 4 ++-- packages/arcodesign/README.md | 4 ++-- packages/arcodesign/package.json | 2 +- packages/common-widgets/package.json | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/arcodesign/README.en-US.md b/packages/arcodesign/README.en-US.md index c5c345db..05af9f15 100644 --- a/packages/arcodesign/README.en-US.md +++ b/packages/arcodesign/README.en-US.md @@ -59,8 +59,8 @@ React & ReactDOM: **Click here** ``` - - + + ``` ## Full import diff --git a/packages/arcodesign/README.md b/packages/arcodesign/README.md index 3e5e629a..c9572d86 100644 --- a/packages/arcodesign/README.md +++ b/packages/arcodesign/README.md @@ -59,8 +59,8 @@ React & ReactDOM: **戳这里获取** ``` - - + + ``` ## 引入全部 diff --git a/packages/arcodesign/package.json b/packages/arcodesign/package.json index fabd751b..7600fd10 100644 --- a/packages/arcodesign/package.json +++ b/packages/arcodesign/package.json @@ -35,5 +35,5 @@ "publishConfig": { "access": "public" }, - "gitHead": "0f41863cde2457384778f80ec7a7f78bf2e8fe47" + "gitHead": "6809000ae9f4310979628d4bd43a728d34266899" } diff --git a/packages/common-widgets/package.json b/packages/common-widgets/package.json index 5f656034..3e98bbfa 100644 --- a/packages/common-widgets/package.json +++ b/packages/common-widgets/package.json @@ -13,7 +13,7 @@ "publishConfig": { "access": "public" }, - "gitHead": "0f41863cde2457384778f80ec7a7f78bf2e8fe47", + "gitHead": "6809000ae9f4310979628d4bd43a728d34266899", "dependencies": { "es6-promise": "^4.2.8" } From 42f3d5ab19144702d7c371c6cbd1aa031a690abe Mon Sep 17 00:00:00 2001 From: taoyiyue Date: Wed, 2 Aug 2023 10:37:49 +0800 Subject: [PATCH 15/25] fix: add @types to peerDependencies --- packages/arcodesign/package.json | 14 ++++++++++++++ packages/common-widgets/package-lock.json | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/packages/arcodesign/package.json b/packages/arcodesign/package.json index 7600fd10..162b97a9 100644 --- a/packages/arcodesign/package.json +++ b/packages/arcodesign/package.json @@ -28,10 +28,24 @@ "jest": "^25.3.0" }, "peerDependencies": { + "@types/react": ">=16.9.0", + "@types/react-dom": ">=16.9.0", + "@types/react-transition-group": ">=4.3.0", "react": ">=16.9.0", "react-dom": ">=16.9.0", "react-transition-group": ">=4.3.0" }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + }, + "@types/react-transition-group": { + "optional": true + } + }, "publishConfig": { "access": "public" }, diff --git a/packages/common-widgets/package-lock.json b/packages/common-widgets/package-lock.json index 26378180..147337a5 100644 --- a/packages/common-widgets/package-lock.json +++ b/packages/common-widgets/package-lock.json @@ -6,7 +6,7 @@ "packages": { "": { "name": "@arco-design/mobile-utils", - "version": "2.15.5", + "version": "2.16.0", "license": "ISC", "dependencies": { "es6-promise": "^4.2.8" From f99bbc812223ae6c8960b1d712040f1b221efb72 Mon Sep 17 00:00:00 2001 From: taoyiyue Date: Wed, 2 Aug 2023 10:51:15 +0800 Subject: [PATCH 16/25] fix: `Avatar` make the prop "src" optional --- packages/arcodesign/components/avatar/README.en-US.md | 2 +- packages/arcodesign/components/avatar/README.md | 2 +- packages/arcodesign/components/avatar/__ast__/index.ast.json | 2 +- packages/arcodesign/components/avatar/type.ts | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/arcodesign/components/avatar/README.en-US.md b/packages/arcodesign/components/avatar/README.en-US.md index 69b6f328..94be516b 100644 --- a/packages/arcodesign/components/avatar/README.en-US.md +++ b/packages/arcodesign/components/avatar/README.en-US.md @@ -12,7 +12,7 @@ Avatar component supports two shapes of circle and square, supports pictures or |----------|-------------|------|------| |shape|Shapre|"circle" \| "square"|"circle"| |size|Size|"medium" \| "large" \| "small" \| "smaller" \| "ultra\-small"|"small"| -|src|resource of avatar picture|string|required| +|src|resource of avatar picture|string|-| |imageProps|Image avatar component props, transparently passed to the Image component|Partial\\>|-| |decoration|the decoration for image avatar|ReactNode|null| |textAvatar|Text Avatar, two characters in Chinese, and three characters or less in English are recommended\.|string|""| diff --git a/packages/arcodesign/components/avatar/README.md b/packages/arcodesign/components/avatar/README.md index 9abd4232..4d0b2915 100644 --- a/packages/arcodesign/components/avatar/README.md +++ b/packages/arcodesign/components/avatar/README.md @@ -12,7 +12,7 @@ |----------|-------------|------|------| |shape|形状|"circle" \| "square"|"circle"| |size|尺寸|"medium" \| "large" \| "small" \| "smaller" \| "ultra\-small"|"small"| -|src|图片头像的资源地址|string|必填| +|src|图片头像的资源地址|string|-| |imageProps|图片头像组件参数,透传给Image组件|Partial\\>|-| |decoration|图片头像上的装饰|ReactNode|null| |textAvatar|文字头像,中文建议取两个字,英文建议在三个字以下|string|""| diff --git a/packages/arcodesign/components/avatar/__ast__/index.ast.json b/packages/arcodesign/components/avatar/__ast__/index.ast.json index bc222465..8f333573 100644 --- a/packages/arcodesign/components/avatar/__ast__/index.ast.json +++ b/packages/arcodesign/components/avatar/__ast__/index.ast.json @@ -89,7 +89,7 @@ "fileName": "arcom-github/packages/arcodesign/components/avatar/type.ts", "name": "AvatarProps" }, - "required": true, + "required": false, "type": { "name": "string" } diff --git a/packages/arcodesign/components/avatar/type.ts b/packages/arcodesign/components/avatar/type.ts index 63682255..2e5fefad 100644 --- a/packages/arcodesign/components/avatar/type.ts +++ b/packages/arcodesign/components/avatar/type.ts @@ -19,7 +19,7 @@ export interface AvatarProps extends BaseProp * 图片头像的资源地址 * @en resource of avatar picture */ - src: string; + src?: string; /** * 图片头像组件参数,透传给Image组件 * @en Image avatar component props, transparently passed to the Image component From b6af06950fab57bee31ce7370a020191b2a93c11 Mon Sep 17 00:00:00 2001 From: taoyiyue Date: Wed, 2 Aug 2023 17:33:22 +0800 Subject: [PATCH 17/25] build: release version - @arco-design/mobile-react@2.28.1 - @arco-design/mobile-utils@2.16.1 --- packages/arcodesign/CHANGELOG.md | 12 ++++++++++++ packages/arcodesign/package-lock.json | 2 +- packages/arcodesign/package.json | 4 ++-- packages/common-widgets/CHANGELOG.md | 11 +++++++++++ packages/common-widgets/package-lock.json | 2 +- packages/common-widgets/package.json | 2 +- 6 files changed, 28 insertions(+), 5 deletions(-) diff --git a/packages/arcodesign/CHANGELOG.md b/packages/arcodesign/CHANGELOG.md index b7c138da..71d97820 100644 --- a/packages/arcodesign/CHANGELOG.md +++ b/packages/arcodesign/CHANGELOG.md @@ -3,6 +3,18 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [2.28.1](https://github.com/arco-design/arco-design-mobile/compare/@arco-design/mobile-react@2.28.0...@arco-design/mobile-react@2.28.1) (2023-08-02) + + +### Bug Fixes + +* `Avatar` make the prop "src" optional ([f99bbc8](https://github.com/arco-design/arco-design-mobile/commit/f99bbc812223ae6c8960b1d712040f1b221efb72)) +* add [@types](https://github.com/types) to peerDependencies ([42f3d5a](https://github.com/arco-design/arco-design-mobile/commit/42f3d5ab19144702d7c371c6cbd1aa031a690abe)) + + + + + # [2.28.0](https://github.com/arco-design/arco-design-mobile/compare/@arco-design/mobile-react@2.27.5...@arco-design/mobile-react@2.28.0) (2023-07-14) diff --git a/packages/arcodesign/package-lock.json b/packages/arcodesign/package-lock.json index f755d2c7..886644ba 100644 --- a/packages/arcodesign/package-lock.json +++ b/packages/arcodesign/package-lock.json @@ -1,6 +1,6 @@ { "name": "@arco-design/mobile-react", - "version": "2.28.0", + "version": "2.28.1", "lockfileVersion": 2, "requires": true, "packages": { diff --git a/packages/arcodesign/package.json b/packages/arcodesign/package.json index 162b97a9..7a4bf852 100644 --- a/packages/arcodesign/package.json +++ b/packages/arcodesign/package.json @@ -1,6 +1,6 @@ { "name": "@arco-design/mobile-react", - "version": "2.28.0", + "version": "2.28.1", "description": "", "main": "cjs/index.js", "module": "esm/index.js", @@ -15,7 +15,7 @@ "author": "taoyiyue@bytedance.com", "license": "ISC", "dependencies": { - "@arco-design/mobile-utils": "2.16.0", + "@arco-design/mobile-utils": "2.16.1", "@arco-design/transformable": "^1.0.0", "lodash.throttle": "^4.1.1", "resize-observer-polyfill": "^1.5.1" diff --git a/packages/common-widgets/CHANGELOG.md b/packages/common-widgets/CHANGELOG.md index f48f10f2..c1c81c71 100644 --- a/packages/common-widgets/CHANGELOG.md +++ b/packages/common-widgets/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [2.16.1](https://github.com/arco-design/arco-design-mobile/compare/@arco-design/mobile-utils@2.16.0...@arco-design/mobile-utils@2.16.1) (2023-08-02) + + +### Bug Fixes + +* add [@types](https://github.com/types) to peerDependencies ([42f3d5a](https://github.com/arco-design/arco-design-mobile/commit/42f3d5ab19144702d7c371c6cbd1aa031a690abe)) + + + + + # [2.16.0](https://github.com/arco-design/arco-design-mobile/compare/@arco-design/mobile-utils@2.15.5...@arco-design/mobile-utils@2.16.0) (2023-07-14) diff --git a/packages/common-widgets/package-lock.json b/packages/common-widgets/package-lock.json index 147337a5..9beeb9a3 100644 --- a/packages/common-widgets/package-lock.json +++ b/packages/common-widgets/package-lock.json @@ -1,6 +1,6 @@ { "name": "@arco-design/mobile-utils", - "version": "2.16.0", + "version": "2.16.1", "lockfileVersion": 2, "requires": true, "packages": { diff --git a/packages/common-widgets/package.json b/packages/common-widgets/package.json index 3e98bbfa..9d6c733b 100644 --- a/packages/common-widgets/package.json +++ b/packages/common-widgets/package.json @@ -1,6 +1,6 @@ { "name": "@arco-design/mobile-utils", - "version": "2.16.0", + "version": "2.16.1", "description": "", "main": "cjs/index.js", "module": "esm/index.js", From be716b5be1aff3ab2f9b366dda977119e9187d44 Mon Sep 17 00:00:00 2001 From: taoyiyue Date: Wed, 2 Aug 2023 17:44:07 +0800 Subject: [PATCH 18/25] build: update readme --- packages/arcodesign/README.en-US.md | 4 ++-- packages/arcodesign/README.md | 4 ++-- packages/arcodesign/package.json | 2 +- packages/common-widgets/package.json | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/arcodesign/README.en-US.md b/packages/arcodesign/README.en-US.md index 05af9f15..0db1f029 100644 --- a/packages/arcodesign/README.en-US.md +++ b/packages/arcodesign/README.en-US.md @@ -59,8 +59,8 @@ React & ReactDOM: **Click here** ``` - - + + ``` ## Full import diff --git a/packages/arcodesign/README.md b/packages/arcodesign/README.md index c9572d86..d84d4f04 100644 --- a/packages/arcodesign/README.md +++ b/packages/arcodesign/README.md @@ -59,8 +59,8 @@ React & ReactDOM: **戳这里获取** ``` - - + + ``` ## 引入全部 diff --git a/packages/arcodesign/package.json b/packages/arcodesign/package.json index 7a4bf852..56342ac9 100644 --- a/packages/arcodesign/package.json +++ b/packages/arcodesign/package.json @@ -49,5 +49,5 @@ "publishConfig": { "access": "public" }, - "gitHead": "6809000ae9f4310979628d4bd43a728d34266899" + "gitHead": "b6af06950fab57bee31ce7370a020191b2a93c11" } diff --git a/packages/common-widgets/package.json b/packages/common-widgets/package.json index 9d6c733b..c90faca7 100644 --- a/packages/common-widgets/package.json +++ b/packages/common-widgets/package.json @@ -13,7 +13,7 @@ "publishConfig": { "access": "public" }, - "gitHead": "6809000ae9f4310979628d4bd43a728d34266899", + "gitHead": "b6af06950fab57bee31ce7370a020191b2a93c11", "dependencies": { "es6-promise": "^4.2.8" } From 7ece3a9eb76abb010aa88678af47c15a0bd319dc Mon Sep 17 00:00:00 2001 From: "wonuanyangying(ikun)" Date: Fri, 4 Aug 2023 14:39:50 +0800 Subject: [PATCH 19/25] fix: `Tabs` use boundingRect instead of offset when calc tabs wrap size (#146) --- packages/arcodesign/components/tabs/index.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/arcodesign/components/tabs/index.tsx b/packages/arcodesign/components/tabs/index.tsx index 5b61d312..a9f2c8fb 100644 --- a/packages/arcodesign/components/tabs/index.tsx +++ b/packages/arcodesign/components/tabs/index.tsx @@ -9,7 +9,7 @@ import React, { useCallback, useContext, } from 'react'; -import { cls, nextTick } from '@arco-design/mobile-utils'; +import { cls, nextTick, getOffset } from '@arco-design/mobile-utils'; import { ContextLayout, GlobalContext } from '../context-provider'; import TabCell from './tab-cell'; import TabPane from './tab-pane'; @@ -369,9 +369,10 @@ const Tabs = forwardRef((props: TabsProps, ref: Ref) => { } function updateLayout() { + const { width, height } = getOffset(domRef.current); cellRef.current && cellRef.current.resetUnderlineStyle(); - setWrapWidth(domRef.current ? domRef.current.offsetWidth : 0); - setWrapHeight(domRef.current ? domRef.current.offsetHeight : 0); + setWrapWidth(width || domRef.current?.offsetWidth || 0); + setWrapHeight(height || domRef.current?.offsetHeight || 0); paneRef.current && paneRef.current.setCurrentHeight(); } From e91557fc1545dd6179329dc342de4967301a7d73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E9=BB=84=E6=B1=AA?= <50308467+huangguang1999@users.noreply.github.com> Date: Fri, 4 Aug 2023 14:46:02 +0800 Subject: [PATCH 20/25] fix: `PickerView` flicker issue with picker off and on when momentum scrolling is not over (#143) --- .../picker-view/components/picker-cell.tsx | 27 ++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/packages/arcodesign/components/picker-view/components/picker-cell.tsx b/packages/arcodesign/components/picker-view/components/picker-cell.tsx index cfb92b1c..13d0bc46 100644 --- a/packages/arcodesign/components/picker-view/components/picker-cell.tsx +++ b/packages/arcodesign/components/picker-view/components/picker-cell.tsx @@ -70,6 +70,7 @@ const PickerCell = forwardRef((props: PickerCellProps, ref: Ref) const rowCount = Math.max(rows % 2 === 0 ? rows + 1 : rows, 3); const isTouchMoveRef = useRef(false); const isTouchStopped = useRef(false); + const unmountCallbackRef = useRef<() => void>(); const timeRef = useRef(null); const colStyle = useMemo( @@ -104,19 +105,23 @@ const PickerCell = forwardRef((props: PickerCellProps, ref: Ref) function _scrollTo(transY: number, transDuration = 0, callback = () => {}) { setTransitionDuration(transDuration ? `${transDuration}ms` : ''); setTransformY(transY); - // 处理连续滑动的情况: - // @en handle the case of continuous sliding: - // 如果上一次callback还未执行,先cancel掉上一次回调,只执行最近的一次回调 - // @en If the last callback has not been executed, cancel the last callback first, and only execute the latest callback + // 处理连续滑动的情况:如果上一次callback还未执行,先cancel掉上一次回调 + // @en handle the case of continuous sliding: If the last callback has not been executed, cancel the last callback first if (latestCallbackTimer.current) { clearTimeout(latestCallbackTimer.current); } - latestCallbackTimer.current = window.setTimeout(() => { + const setNormalStatus = () => { + // 如果timer顺利执行,则在unmount时不再重复执行 + // @en If the timer is successfully executed, it will not be repeated when unmounting + unmountCallbackRef.current = undefined; movingStatusRef.current = 'normal'; setTransitionDuration(''); callback(); - }, transDuration); + }; + + unmountCallbackRef.current = setNormalStatus; + latestCallbackTimer.current = window.setTimeout(setNormalStatus, transDuration); } function _scrollToIndex(itemIndex: number, transDuration = 0, callback = () => {}) { @@ -323,6 +328,16 @@ const PickerCell = forwardRef((props: PickerCellProps, ref: Ref) _scrollToIndexWithChange(itemIndex, 200); } + useEffect(() => { + return () => { + // 卸载组件时,如果timer中还有未执行的onchange操作,则立刻执行该操作并移除timer + // @en When unloading the component, if there is an unexecuted onchange operation in the timer, execute it immediately and remove the timer + const timerId = latestCallbackTimer.current; + unmountCallbackRef.current?.(); + timerId && clearTimeout(timerId); + }; + }, []); + useEffect(() => { if (wrapRef.current) { wrapRef.current.addEventListener('touchstart', _handleColumnTouchStart); From 5616d537b921b009df61addccf966c5e9363a0cb Mon Sep 17 00:00:00 2001 From: Yiyue Tao <106640896+TinaPeach@users.noreply.github.com> Date: Fri, 4 Aug 2023 14:57:37 +0800 Subject: [PATCH 21/25] fix: `Form` bind this in form-item (#148) --- .../arcodesign/components/_helpers/hooks.ts | 12 +++++++--- .../arcodesign/components/form/form-item.tsx | 24 +++++++++---------- packages/common-widgets/utils/dom.ts | 4 ++-- packages/common-widgets/utils/is.ts | 4 ++-- 4 files changed, 25 insertions(+), 19 deletions(-) diff --git a/packages/arcodesign/components/_helpers/hooks.ts b/packages/arcodesign/components/_helpers/hooks.ts index 25fbf13a..86090b6f 100644 --- a/packages/arcodesign/components/_helpers/hooks.ts +++ b/packages/arcodesign/components/_helpers/hooks.ts @@ -29,6 +29,12 @@ export function useListenResize(resizeHandler: () => void, deps: any[] = [], nee * @desc {en} Tips: Use in scenarios where asynchronous processing is not completed after unmount. It is not recommended to replace useState without brains * @param initialState 初始状态 * @param initialState {en} Initial State + * @example + * ``` + * import { useMountedState } from '@arco-design/mobile-react/esm/_helpers/hooks'; + * + * const [scrollValue, setScrollValue] = useMountedState(value); + * ``` */ export function useMountedState(initialState: S | (() => S)) { const [state, setState] = useState(initialState); @@ -431,13 +437,13 @@ export function usePreventBodyScroll( }, [visible]); } -export const useProgress = ( +export function useProgress( mountedTransition: boolean, percentage: number, duration: number, mountedBezier: BezierType, step: number, -): [number, boolean] => { +): [number, boolean] { const [currentPercentage, setCurrentPercentage] = useState(0); const [transitionControl, setTransitionControl] = useState(false); const [count, setCount] = useState(0); @@ -471,7 +477,7 @@ export const useProgress = ( }, [count, percentage, step]); return [currentPercentage, transitionControl]; -}; +} export function useSingleAndDoubleClick( onClick: (e: React.MouseEvent) => void, diff --git a/packages/arcodesign/components/form/form-item.tsx b/packages/arcodesign/components/form/form-item.tsx index 4c09b98c..5af065c9 100644 --- a/packages/arcodesign/components/form/form-item.tsx +++ b/packages/arcodesign/components/form/form-item.tsx @@ -59,7 +59,7 @@ class FormItemInner extends PureComponent { this._touched = true; const { shouldUpdate } = this.props; if (typeof shouldUpdate === 'function') { @@ -67,17 +67,17 @@ class FormItemInner extends PureComponent { return this._errors; - } + }; - isFieldTouched() { + isFieldTouched = () => { return this._touched; - } + }; - validateField(): Promise { + validateField = (): Promise => { const { validateMessages } = this.context; const { getFieldValue } = this.context.form; const { field, rules, onValidateStatusChange } = this.props; @@ -107,14 +107,14 @@ class FormItemInner extends PureComponent { const { field } = this.props; const { setFieldValue } = this.context.form; setFieldValue(field, value); this.validateField(); - } + }; innerTriggerFunction = (_, value, ...args) => { this.setFieldData(value); @@ -132,13 +132,13 @@ class FormItemInner extends PureComponent { const { children } = this.props; this.setFieldData(''); if (children.props?.onClear) { children.props?.onClear(...args); } - } + }; renderChildren() { const { diff --git a/packages/common-widgets/utils/dom.ts b/packages/common-widgets/utils/dom.ts index 097b29d4..a2f5afc2 100644 --- a/packages/common-widgets/utils/dom.ts +++ b/packages/common-widgets/utils/dom.ts @@ -43,7 +43,7 @@ export function freeEleScroll( * @param parentEl 父节点 * @param childrenEl 子节点 */ -export const isContains = (parentEl: HTMLElement | null, childrenEl: HTMLElement | null) => { +export function isContains(parentEl: HTMLElement | null, childrenEl: HTMLElement | null) { if (!parentEl || !childrenEl) return false; if (parentEl.contains) { return parentEl.contains(childrenEl); @@ -56,7 +56,7 @@ export const isContains = (parentEl: HTMLElement | null, childrenEl: HTMLElement parent = parent.parentNode as HTMLElement; } return false; -}; +} export function execRAF(fn) { try { diff --git a/packages/common-widgets/utils/is.ts b/packages/common-widgets/utils/is.ts index e547d6ea..38787365 100644 --- a/packages/common-widgets/utils/is.ts +++ b/packages/common-widgets/utils/is.ts @@ -34,7 +34,7 @@ export function isEmptyArray(obj: Array): boolean { return isArray(obj) && !obj?.length; } -export const isDeepEqual = (obj: any, sub: any): boolean => { +export function isDeepEqual(obj: any, sub: any): boolean { if (typeof obj !== 'object' || typeof sub !== 'object' || obj === null || sub === null) { return obj === sub; } @@ -49,4 +49,4 @@ export const isDeepEqual = (obj: any, sub: any): boolean => { if (!isDeepEqual(obj[key], sub[key])) return false; } return true; -}; +} From cf3c0153d560dc89ce05dc01c38904c6353749ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E9=BB=84=E6=B1=AA?= <50308467+huangguang1999@users.noreply.github.com> Date: Fri, 4 Aug 2023 17:08:34 +0800 Subject: [PATCH 22/25] site: supplementary readme (#133) --- .../arcodesign/components/button/FAQ.en-US.md | 5 ++ packages/arcodesign/components/button/FAQ.md | 5 ++ .../components/nav-bar/FAQ.en-US.md | 5 ++ packages/arcodesign/components/nav-bar/FAQ.md | 5 ++ .../arcodesign/components/nav-bar/index.tsx | 6 +- packages/arcodesign/components/tabs/FAQ.md | 2 +- .../sticky-tabs/sticky-tab-css.md | 57 +++++++++++++++++++ .../sticky-tabs/style/mobile.less | 12 +++- sites/pc/static/md/qa.en-US.md | 10 +++- sites/pc/static/md/qa.md | 6 +- 10 files changed, 106 insertions(+), 7 deletions(-) create mode 100644 packages/arcodesign/components/button/FAQ.en-US.md create mode 100644 packages/arcodesign/components/button/FAQ.md create mode 100644 packages/arcodesign/components/nav-bar/FAQ.en-US.md create mode 100644 packages/arcodesign/components/nav-bar/FAQ.md create mode 100644 sites/composite-comp/sticky-tabs/sticky-tab-css.md diff --git a/packages/arcodesign/components/button/FAQ.en-US.md b/packages/arcodesign/components/button/FAQ.en-US.md new file mode 100644 index 00000000..b8f92762 --- /dev/null +++ b/packages/arcodesign/components/button/FAQ.en-US.md @@ -0,0 +1,5 @@ +# FAQ + +## The style passed in through className cannot override the default style (such as color) in arco button + +The style (such as color) in arco button is implemented by the two class selectors .arco-button.arco-button-type-primary. The priority will be higher than the priority of the className passed in. You can increase the className passed in Priority resolution. arco implements this because when there is only one level of priority, it may be overwritten by reset.less on the business side or the default button style in the browser. diff --git a/packages/arcodesign/components/button/FAQ.md b/packages/arcodesign/components/button/FAQ.md new file mode 100644 index 00000000..abea4060 --- /dev/null +++ b/packages/arcodesign/components/button/FAQ.md @@ -0,0 +1,5 @@ +# FAQ + +## 通过 className 传入的样式无法覆盖 arco button 中的默认样式(如 color) + +arco button 中的样式(如 color)的实现是 .arco-button.arco-button-type-primary 两个类选择器实现的,优先级会比传入的 className 优先级高,可采用提高传入 className 优先级解决。arco 这么实现是因为只有一层优先级时,可能会被业务方的 reset.less 或者浏览器中默认的 button 样式覆盖。 diff --git a/packages/arcodesign/components/nav-bar/FAQ.en-US.md b/packages/arcodesign/components/nav-bar/FAQ.en-US.md new file mode 100644 index 00000000..2a18df8c --- /dev/null +++ b/packages/arcodesign/components/nav-bar/FAQ.en-US.md @@ -0,0 +1,5 @@ +# FAQ + +## After overriding the height of arco-nav-bar-wrapper by style, the placeholder is not stretched + +The placeholder is implemented by the height of arco-nav-bar. If you want to adjust the height of the entire navbar, you need to cover the height of arco-nav-bar & arco-nav-bar-wrapper at the same time diff --git a/packages/arcodesign/components/nav-bar/FAQ.md b/packages/arcodesign/components/nav-bar/FAQ.md new file mode 100644 index 00000000..c46a93da --- /dev/null +++ b/packages/arcodesign/components/nav-bar/FAQ.md @@ -0,0 +1,5 @@ +# FAQ + +## 通过样式覆盖 arco-nav-bar-wrapper 的高度后,placeholder 没有被撑开 + +placeholder 是通过 arco-nav-bar 的高度实现的,如果想要调整整个 navbar 的高度,需要同时覆盖 arco-nav-bar & arco-nav-bar-wrapper 的 height diff --git a/packages/arcodesign/components/nav-bar/index.tsx b/packages/arcodesign/components/nav-bar/index.tsx index eb4abc86..58390858 100644 --- a/packages/arcodesign/components/nav-bar/index.tsx +++ b/packages/arcodesign/components/nav-bar/index.tsx @@ -51,13 +51,13 @@ export interface NavBarProps { */ rightContent?: React.ReactNode; /** - * 自定义样式,背景和文字颜色可在此定义 + * 自定义样式,最外层元素的背景文字颜色可在此定义 * @en Custom stylesheet, background and text colors can be defined here */ style?: React.CSSProperties; /** - * 自定义类名 - * @en Custom classname + * 内层自定义类名 + * @en Inner custom classname */ className?: string; /** diff --git a/packages/arcodesign/components/tabs/FAQ.md b/packages/arcodesign/components/tabs/FAQ.md index 2d7a1fdb..9dfdfd4c 100644 --- a/packages/arcodesign/components/tabs/FAQ.md +++ b/packages/arcodesign/components/tabs/FAQ.md @@ -6,4 +6,4 @@ onAfterChange 的调用是发生在动画执行后,很多 state 的更新在 ## tabs 怎么配合 sticky 组件实现一个复杂的交互页面 -可以参考 [sticky-tabs](/#/components/sticky-tabs) 复合组件使用 +可以参考 [sticky-tabs](#/composite-components/sticky-tabs) 复合组件使用 diff --git a/sites/composite-comp/sticky-tabs/sticky-tab-css.md b/sites/composite-comp/sticky-tabs/sticky-tab-css.md new file mode 100644 index 00000000..33697291 --- /dev/null +++ b/sites/composite-comp/sticky-tabs/sticky-tab-css.md @@ -0,0 +1,57 @@ +## 使用 position: sticky 替换 Sticky @en{Replace Sticky with position: sticky} + +当使用 sticky tabs 复合组件时,安卓机型经常会出现 tabBar 闪动的情况,可以通过 css 实现 sticky 的方式去优化性能 +注意:sticky css 属性兼容性有待考证;arco 已验证安卓5.1.1 vivoX7 支持;iPhone6plus ios 11.2.5不支持 + +```js +import { Tabs, Sticky, Portal } from '@arco-design/mobile-react'; + +const tabData = [ + { title: 'Example 1' }, + { title: 'Example 2' }, + { title: 'Example 3' }, +]; + +export default function StickyTabsCss() { + const tabBarRef = React.useRef(null); + + const supportsCSS = (attribute, value) => { + if (window && window.CSS) { + if (typeof value === 'undefined') { + return window.CSS.supports(attribute); + } + return window.CSS.supports(attribute, value); + } + + const elem = document.createElement('div'); + if (attribute in elem.style) { + elem.style[attribute] = value; + return elem.style[attribute] === value; + } + return false; + }; + + return ( +
+
+ placeholder placeholder placeholder placeholder placeholder placeholder placeholder placeholder placeholder placeholder placeholder placeholder +
+
+ + supportsCSS('position', 'sticky') ? ( + tabBarRef.current}>{TabBar} + ) : ( + document.getElementById('sticky-tabs-wrapper-css')} topOffset={0}>{TabBar} + )} + > +
content 1
+
content 2
+
content 3
+
+
+ ); +} +``` diff --git a/sites/composite-comp/sticky-tabs/style/mobile.less b/sites/composite-comp/sticky-tabs/style/mobile.less index 59abda11..a2248e51 100644 --- a/sites/composite-comp/sticky-tabs/style/mobile.less +++ b/sites/composite-comp/sticky-tabs/style/mobile.less @@ -1,7 +1,8 @@ @import "../../../../packages/arcodesign/style/mixin.less"; #sticky-tabs-wrapper-position, -#sticky-tabs-wrapper-hide { +#sticky-tabs-wrapper-hide, +#sticky-tabs-wrapper-css { height: 500px; overflow: scroll; @@ -17,3 +18,12 @@ } } +#sticky-tabs-wrapper-css { + overflow: visible; + + .sticky-tabs-wrapper-css-nav-bar { + position: sticky; + background: #fff; + top: 44px; + } +} diff --git a/sites/pc/static/md/qa.en-US.md b/sites/pc/static/md/qa.en-US.md index dc4fa424..aebcc1df 100644 --- a/sites/pc/static/md/qa.en-US.md +++ b/sites/pc/static/md/qa.en-US.md @@ -41,4 +41,12 @@ import { ContextProvider } from '@arco-design/mobile-react'; return ( )" -``` \ No newline at end of file +``` + +## Q:When using methods such as Toast.toast to call components, the configuration passed to ContextProvider cannot be received? + +The component called by the method is not a subcomponent under the root node of the page, so the configuration of ContextProvider needs to be passed to the method, such as: `Toast.toast({ content: 'Tips' }, { prefixCls: 'aa' })`. (Supported after `2.24.0`) + +## Q: AutoFocus does not work when using Input/Textarea/SearchBar + +autoFocus is not supported on some models, the bottom layer of the component can only try focus, but whether it can focus or not depends on the model diff --git a/sites/pc/static/md/qa.md b/sites/pc/static/md/qa.md index 298ea3ad..8992d801 100644 --- a/sites/pc/static/md/qa.md +++ b/sites/pc/static/md/qa.md @@ -45,4 +45,8 @@ return ( ## Q:用 Toast.toast 等方法调用组件时,接不到传给 ContextProvider 的配置? -使用方法调用的组件不是页面根节点下的子组件,因此需将 ContextProvider 的配置传给方法,如:`Toast.toast({ content: 'Tips' }, { prefixCls: 'aa' })`。(`2.24.0`之后支持) \ No newline at end of file +使用方法调用的组件不是页面根节点下的子组件,因此需将 ContextProvider 的配置传给方法,如:`Toast.toast({ content: 'Tips' }, { prefixCls: 'aa' })`。(`2.24.0`之后支持) + +## Q:使用 Input/Textarea/SearchBar 的 autoFocus 不生效 + +autoFocus 在一些机型上是不支持的,组件底层只能尝试 focus,但是到底能不能聚焦还得看机型 From f923a5d573d8af95e6b158614f8e7d8184afc481 Mon Sep 17 00:00:00 2001 From: "wangtianli.y" Date: Mon, 7 Aug 2023 20:45:41 +0800 Subject: [PATCH 23/25] build: release version - @arco-design/mobile-react@2.28.2 - @arco-design/mobile-utils@2.16.2 --- packages/arcodesign/CHANGELOG.md | 13 +++++++++++++ packages/arcodesign/package-lock.json | 2 +- packages/arcodesign/package.json | 4 ++-- packages/common-widgets/CHANGELOG.md | 11 +++++++++++ packages/common-widgets/package-lock.json | 2 +- packages/common-widgets/package.json | 2 +- 6 files changed, 29 insertions(+), 5 deletions(-) diff --git a/packages/arcodesign/CHANGELOG.md b/packages/arcodesign/CHANGELOG.md index 71d97820..b54b620e 100644 --- a/packages/arcodesign/CHANGELOG.md +++ b/packages/arcodesign/CHANGELOG.md @@ -3,6 +3,19 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [2.28.2](https://github.com/arco-design/arco-design-mobile/compare/@arco-design/mobile-react@2.28.1...@arco-design/mobile-react@2.28.2) (2023-08-07) + + +### Bug Fixes + +* `Form` bind this in form-item ([#148](https://github.com/arco-design/arco-design-mobile/issues/148)) ([5616d53](https://github.com/arco-design/arco-design-mobile/commit/5616d537b921b009df61addccf966c5e9363a0cb)) +* `PickerView` flicker issue with picker off and on when momentum scrolling is not over ([#143](https://github.com/arco-design/arco-design-mobile/issues/143)) ([e91557f](https://github.com/arco-design/arco-design-mobile/commit/e91557fc1545dd6179329dc342de4967301a7d73)) +* `Tabs` use boundingRect instead of offset when calc tabs wrap size ([#146](https://github.com/arco-design/arco-design-mobile/issues/146)) ([7ece3a9](https://github.com/arco-design/arco-design-mobile/commit/7ece3a9eb76abb010aa88678af47c15a0bd319dc)) + + + + + ## [2.28.1](https://github.com/arco-design/arco-design-mobile/compare/@arco-design/mobile-react@2.28.0...@arco-design/mobile-react@2.28.1) (2023-08-02) diff --git a/packages/arcodesign/package-lock.json b/packages/arcodesign/package-lock.json index 886644ba..00df8547 100644 --- a/packages/arcodesign/package-lock.json +++ b/packages/arcodesign/package-lock.json @@ -1,6 +1,6 @@ { "name": "@arco-design/mobile-react", - "version": "2.28.1", + "version": "2.28.2", "lockfileVersion": 2, "requires": true, "packages": { diff --git a/packages/arcodesign/package.json b/packages/arcodesign/package.json index 56342ac9..b0c3a016 100644 --- a/packages/arcodesign/package.json +++ b/packages/arcodesign/package.json @@ -1,6 +1,6 @@ { "name": "@arco-design/mobile-react", - "version": "2.28.1", + "version": "2.28.2", "description": "", "main": "cjs/index.js", "module": "esm/index.js", @@ -15,7 +15,7 @@ "author": "taoyiyue@bytedance.com", "license": "ISC", "dependencies": { - "@arco-design/mobile-utils": "2.16.1", + "@arco-design/mobile-utils": "2.16.2", "@arco-design/transformable": "^1.0.0", "lodash.throttle": "^4.1.1", "resize-observer-polyfill": "^1.5.1" diff --git a/packages/common-widgets/CHANGELOG.md b/packages/common-widgets/CHANGELOG.md index c1c81c71..3ef250b3 100644 --- a/packages/common-widgets/CHANGELOG.md +++ b/packages/common-widgets/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [2.16.2](https://github.com/arco-design/arco-design-mobile/compare/@arco-design/mobile-utils@2.16.1...@arco-design/mobile-utils@2.16.2) (2023-08-07) + + +### Bug Fixes + +* `Form` bind this in form-item ([#148](https://github.com/arco-design/arco-design-mobile/issues/148)) ([5616d53](https://github.com/arco-design/arco-design-mobile/commit/5616d537b921b009df61addccf966c5e9363a0cb)) + + + + + ## [2.16.1](https://github.com/arco-design/arco-design-mobile/compare/@arco-design/mobile-utils@2.16.0...@arco-design/mobile-utils@2.16.1) (2023-08-02) diff --git a/packages/common-widgets/package-lock.json b/packages/common-widgets/package-lock.json index 9beeb9a3..c476511d 100644 --- a/packages/common-widgets/package-lock.json +++ b/packages/common-widgets/package-lock.json @@ -1,6 +1,6 @@ { "name": "@arco-design/mobile-utils", - "version": "2.16.1", + "version": "2.16.2", "lockfileVersion": 2, "requires": true, "packages": { diff --git a/packages/common-widgets/package.json b/packages/common-widgets/package.json index c90faca7..41e5fe7f 100644 --- a/packages/common-widgets/package.json +++ b/packages/common-widgets/package.json @@ -1,6 +1,6 @@ { "name": "@arco-design/mobile-utils", - "version": "2.16.1", + "version": "2.16.2", "description": "", "main": "cjs/index.js", "module": "esm/index.js", From ec9a1c785c86c408fb81c276029bd22bb733ef55 Mon Sep 17 00:00:00 2001 From: "wangtianli.y" Date: Mon, 7 Aug 2023 20:48:38 +0800 Subject: [PATCH 24/25] build: update readme --- packages/arcodesign/README.en-US.md | 4 ++-- packages/arcodesign/README.md | 4 ++-- packages/arcodesign/package.json | 2 +- packages/common-widgets/package.json | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/arcodesign/README.en-US.md b/packages/arcodesign/README.en-US.md index 0db1f029..af310ce2 100644 --- a/packages/arcodesign/README.en-US.md +++ b/packages/arcodesign/README.en-US.md @@ -59,8 +59,8 @@ React & ReactDOM: **Click here** ``` - - + + ``` ## Full import diff --git a/packages/arcodesign/README.md b/packages/arcodesign/README.md index d84d4f04..1458f73e 100644 --- a/packages/arcodesign/README.md +++ b/packages/arcodesign/README.md @@ -59,8 +59,8 @@ React & ReactDOM: **戳这里获取** ``` - - + + ``` ## 引入全部 diff --git a/packages/arcodesign/package.json b/packages/arcodesign/package.json index b0c3a016..a2f90246 100644 --- a/packages/arcodesign/package.json +++ b/packages/arcodesign/package.json @@ -49,5 +49,5 @@ "publishConfig": { "access": "public" }, - "gitHead": "b6af06950fab57bee31ce7370a020191b2a93c11" + "gitHead": "f923a5d573d8af95e6b158614f8e7d8184afc481" } diff --git a/packages/common-widgets/package.json b/packages/common-widgets/package.json index 41e5fe7f..b6b2167a 100644 --- a/packages/common-widgets/package.json +++ b/packages/common-widgets/package.json @@ -13,7 +13,7 @@ "publishConfig": { "access": "public" }, - "gitHead": "b6af06950fab57bee31ce7370a020191b2a93c11", + "gitHead": "f923a5d573d8af95e6b158614f8e7d8184afc481", "dependencies": { "es6-promise": "^4.2.8" } From 49351f639b7a3272b55f189447d935946933ddd6 Mon Sep 17 00:00:00 2001 From: Sia <125020500+ziqisia@users.noreply.github.com> Date: Thu, 10 Aug 2023 20:18:17 +0800 Subject: [PATCH 25/25] feat: add new component `Skeleton` (#136) --- packages/arcodesign/components/index.ts | 1 + .../components/skeleton/README.en-US.md | 101 ++ .../arcodesign/components/skeleton/README.md | 101 ++ .../skeleton/__ast__/index.ast.json | 1007 +++++++++++++++++ .../__test__/__snapshots__/index.spec.js.snap | 574 ++++++++++ .../skeleton/__test__/index.spec.js | 78 ++ .../components/skeleton/demo/animation.md | 39 + .../components/skeleton/demo/avatar.md | 11 + .../components/skeleton/demo/custom.md | 46 + .../components/skeleton/demo/grid.md | 11 + .../components/skeleton/demo/index.md | 11 + .../skeleton/demo/style/mobile.less | 13 + .../components/skeleton/elements.tsx | 278 +++++ .../arcodesign/components/skeleton/index.tsx | 94 ++ .../components/skeleton/skeleton-context.tsx | 7 + .../components/skeleton/style/index.less | 147 +++ .../components/skeleton/style/index.ts | 3 + .../arcodesign/components/skeleton/type.ts | 109 ++ packages/arcodesign/components/style.ts | 1 + .../app/arcodesign/default/css-variables.less | 16 + .../tokens/app/arcodesign/default/index.d.ts | 16 + .../tokens/app/arcodesign/default/index.js | 18 +- .../tokens/app/arcodesign/default/index.json | 190 ++++ .../tokens/app/arcodesign/default/index.less | 16 + .../tokens/src/arcodesign/default/index.js | 78 ++ 25 files changed, 2965 insertions(+), 1 deletion(-) create mode 100644 packages/arcodesign/components/skeleton/README.en-US.md create mode 100644 packages/arcodesign/components/skeleton/README.md create mode 100644 packages/arcodesign/components/skeleton/__ast__/index.ast.json create mode 100644 packages/arcodesign/components/skeleton/__test__/__snapshots__/index.spec.js.snap create mode 100644 packages/arcodesign/components/skeleton/__test__/index.spec.js create mode 100644 packages/arcodesign/components/skeleton/demo/animation.md create mode 100644 packages/arcodesign/components/skeleton/demo/avatar.md create mode 100644 packages/arcodesign/components/skeleton/demo/custom.md create mode 100644 packages/arcodesign/components/skeleton/demo/grid.md create mode 100644 packages/arcodesign/components/skeleton/demo/index.md create mode 100644 packages/arcodesign/components/skeleton/demo/style/mobile.less create mode 100644 packages/arcodesign/components/skeleton/elements.tsx create mode 100644 packages/arcodesign/components/skeleton/index.tsx create mode 100644 packages/arcodesign/components/skeleton/skeleton-context.tsx create mode 100644 packages/arcodesign/components/skeleton/style/index.less create mode 100644 packages/arcodesign/components/skeleton/style/index.ts create mode 100644 packages/arcodesign/components/skeleton/type.ts diff --git a/packages/arcodesign/components/index.ts b/packages/arcodesign/components/index.ts index 2131facf..b462e1a9 100644 --- a/packages/arcodesign/components/index.ts +++ b/packages/arcodesign/components/index.ts @@ -43,6 +43,7 @@ export { default as PullRefresh } from './pull-refresh'; export { default as Radio } from './radio'; export { default as Rate } from './rate'; export { default as SearchBar } from './search-bar'; +export { default as Skeleton } from './skeleton'; export { default as ShowMonitor } from './show-monitor'; export { default as Slider } from './slider'; export { default as Stepper } from './stepper'; diff --git a/packages/arcodesign/components/skeleton/README.en-US.md b/packages/arcodesign/components/skeleton/README.en-US.md new file mode 100644 index 00000000..eb0527ba --- /dev/null +++ b/packages/arcodesign/components/skeleton/README.en-US.md @@ -0,0 +1,101 @@ +### Data Display + +# Skeleton + +Display a set of placeholder graphics during content loading + +====== + +> Props + +|Property|Description|Type|DefaultValue| +|----------|-------------|------|------| +|title|Show title placeholder|boolean \| SkeletonTitleProps|true| +|paragraph|Show paragraph placeholder|boolean \| SkeletonParagraphProps|true| +|avatar|Show Avatar placeholder|boolean \| SkeletonAvatarProps|false| +|grid|Show Grid placeholder\. When it's value is present, the paragraph, avatar or title placeholder will not be displayed, and four columns will be displayed by default|boolean \| SkeletonGridProps|false| +|showAnimation|Show loading effect|boolean|true| +|animation|Animation of loading effect, 'gradient' and 'breath' effects are optional|"gradient" \| "breath"|"gradient"| +|animationGradientColor|Highlight color of gradient animation|string|"rgba(0, 0, 0, 0.04)"| +|backgroundColor|Background color of skeleton item|string|"#F7F8FA"| +|children|Children element|ReactNode|null| +|className|Custom classname|string|""| +|style|Custom stylesheet|CSSProperties|{}| + +> Refs + +|Property|Description|Type| +|----------|-------------|------| +|dom|The outer DOM element of the component|HTMLDivElement| + +> Skeleton.Node + +|Property|Description|Type|DefaultValue| +|----------|-------------|------|------| +|children|Custom component content|ReactNode|null| +|className|Custom classname|string|""| +|style|Custom stylesheet|CSSProperties|{}| + +> Skeleton.Title + +|Property|Description|Type|DefaultValue| +|----------|-------------|------|------| +|width|The width of title|ReactText|"40%"| +|className|Custom classname|string|""| +|style|Custom stylesheet|CSSProperties|{}| + +> Skeleton.Paragraph + +|Property|Description|Type|DefaultValue| +|----------|-------------|------|------| +|rows|Number of lines for paragraph|number|3| +|width|The width of paragraph\. If width is an Array, it corresponds to the width of each line, otherwise it indicates the width of the last line|string \| number \| ReactText\[\]|"60%"| +|className|Custom classname|string|""| +|style|Custom stylesheet|CSSProperties|{}| + +> Skeleton.Avatar + +|Property|Description|Type|DefaultValue| +|----------|-------------|------|------| +|className|Custom classname|string|""| +|style|Custom stylesheet|CSSProperties|{}| + +> Skeleton.Grid + +|Property|Description|Type|DefaultValue| +|----------|-------------|------|------| +|columns|columns of grid|number|4| +|className|Custom classname|string|""| +|style|Custom stylesheet|CSSProperties|{}| + +> SkeletonTitleProps + +|Property|Description|Type|DefaultValue| +|----------|-------------|------|------| +|width|The width of title|ReactText|"40%"| +|className|Custom classname|string|""| +|style|Custom stylesheet|CSSProperties|{}| + +> SkeletonParagraphProps + +|Property|Description|Type|DefaultValue| +|----------|-------------|------|------| +|rows|Number of lines for paragraph|number|3| +|width|The width of paragraph\. If width is an Array, it corresponds to the width of each line, otherwise it indicates the width of the last line|string \| number \| ReactText\[\]|"60%"| +|className|Custom classname|string|""| +|style|Custom stylesheet|CSSProperties|{}| + +> SkeletonAvatarProps + +|Property|Description|Type|DefaultValue| +|----------|-------------|------|------| +|className|Custom classname|string|""| +|style|Custom stylesheet|CSSProperties|{}| + +> SkeletonGridProps + +|Property|Description|Type|DefaultValue| +|----------|-------------|------|------| +|columns|columns of grid|number|4| +|className|Custom classname|string|""| +|style|Custom stylesheet|CSSProperties|{}| diff --git a/packages/arcodesign/components/skeleton/README.md b/packages/arcodesign/components/skeleton/README.md new file mode 100644 index 00000000..0a4852aa --- /dev/null +++ b/packages/arcodesign/components/skeleton/README.md @@ -0,0 +1,101 @@ +### 信息展示 + +# 骨架屏 Skeleton + +在内容加载过程中展示一组占位图形。 + +====== + +> 属性/Props + +|参数|描述|类型|默认值| +|----------|-------------|------|------| +|title|是否显示标题占位图|boolean \| SkeletonTitleProps|true| +|paragraph|是否显示段落占位图|boolean \| SkeletonParagraphProps|true| +|avatar|是否显示头像占位图|boolean \| SkeletonAvatarProps|false| +|grid|是否显示金刚位占位图(如该参数非空时,默认展示四列金刚位,且不展示标题/段落/头像占位符)|boolean \| SkeletonGridProps|false| +|showAnimation|是否展示动画效果|boolean|true| +|animation|加载动画效果,可选“扫光”、“呼吸”两种效果|"gradient" \| "breath"|"gradient"| +|animationGradientColor|扫光动效高光颜色|string|"rgba(0, 0, 0, 0.04)"| +|backgroundColor|占位块背景色|string|"#F7F8FA"| +|children|子元素|ReactNode|null| +|className|自定义类名|string|""| +|style|自定义样式|CSSProperties|{}| + +> 引用/Refs + +|参数|描述|类型| +|----------|-------------|------| +|dom|最外层 DOM 元素|HTMLDivElement| + +> Skeleton.Node + +|参数|描述|类型|默认值| +|----------|-------------|------|------| +|children|自定义组件内容|ReactNode|null| +|className|自定义类名|string|""| +|style|自定义样式|CSSProperties|{}| + +> Skeleton.Title + +|参数|描述|类型|默认值| +|----------|-------------|------|------| +|width|标题占位图宽度|ReactText|"40%"| +|className|自定义类名|string|""| +|style|自定义样式|CSSProperties|{}| + +> Skeleton.Paragraph + +|参数|描述|类型|默认值| +|----------|-------------|------|------| +|rows|段落占位图的行数|number|3| +|width|段落占位图宽度,若为数组格式对应每行宽度,否则表示最后一行的宽度|string \| number \| ReactText\[\]|"60%"| +|className|自定义类名|string|""| +|style|自定义样式|CSSProperties|{}| + +> Skeleton.Avatar + +|参数|描述|类型|默认值| +|----------|-------------|------|------| +|className|自定义类名|string|""| +|style|自定义样式|CSSProperties|{}| + +> Skeleton.Grid + +|参数|描述|类型|默认值| +|----------|-------------|------|------| +|columns|金刚位列数|number|4| +|className|自定义类名|string|""| +|style|自定义样式|CSSProperties|{}| + +> SkeletonTitleProps + +|参数|描述|类型|默认值| +|----------|-------------|------|------| +|width|标题占位图宽度|ReactText|"40%"| +|className|自定义类名|string|""| +|style|自定义样式|CSSProperties|{}| + +> SkeletonParagraphProps + +|参数|描述|类型|默认值| +|----------|-------------|------|------| +|rows|段落占位图的行数|number|3| +|width|段落占位图宽度,若为数组格式对应每行宽度,否则表示最后一行的宽度|string \| number \| ReactText\[\]|"60%"| +|className|自定义类名|string|""| +|style|自定义样式|CSSProperties|{}| + +> SkeletonAvatarProps + +|参数|描述|类型|默认值| +|----------|-------------|------|------| +|className|自定义类名|string|""| +|style|自定义样式|CSSProperties|{}| + +> SkeletonGridProps + +|参数|描述|类型|默认值| +|----------|-------------|------|------| +|columns|金刚位列数|number|4| +|className|自定义类名|string|""| +|style|自定义样式|CSSProperties|{}| diff --git a/packages/arcodesign/components/skeleton/__ast__/index.ast.json b/packages/arcodesign/components/skeleton/__ast__/index.ast.json new file mode 100644 index 00000000..2a021601 --- /dev/null +++ b/packages/arcodesign/components/skeleton/__ast__/index.ast.json @@ -0,0 +1,1007 @@ +{ + "description": "在内容加载过程中展示一组占位图形。", + "descriptionTags": { + "en": "Display a set of placeholder graphics during content loading", + "type": "信息展示", + "type_en": "Data Display", + "name": "骨架屏", + "name_en": "Skeleton" + }, + "displayName": "Skeleton", + "methods": [], + "props": { + "title": { + "defaultValue": { + "value": "true" + }, + "description": "是否显示标题占位图\n@en Show title placeholder", + "name": "title", + "tags": { + "en": "Show title placeholder", + "default": "true" + }, + "descWithTags": "是否显示标题占位图", + "parent": { + "fileName": "arcom-github/packages/arcodesign/components/skeleton/type.ts", + "name": "SkeletonProps" + }, + "required": false, + "type": { + "name": "boolean | SkeletonTitleProps" + } + }, + "paragraph": { + "defaultValue": { + "value": "true" + }, + "description": "是否显示段落占位图\n@en Show paragraph placeholder", + "name": "paragraph", + "tags": { + "en": "Show paragraph placeholder", + "default": "true" + }, + "descWithTags": "是否显示段落占位图", + "parent": { + "fileName": "arcom-github/packages/arcodesign/components/skeleton/type.ts", + "name": "SkeletonProps" + }, + "required": false, + "type": { + "name": "boolean | SkeletonParagraphProps" + } + }, + "avatar": { + "defaultValue": { + "value": "false" + }, + "description": "是否显示头像占位图\n@en Show Avatar placeholder", + "name": "avatar", + "tags": { + "en": "Show Avatar placeholder", + "default": "false" + }, + "descWithTags": "是否显示头像占位图", + "parent": { + "fileName": "arcom-github/packages/arcodesign/components/skeleton/type.ts", + "name": "SkeletonProps" + }, + "required": false, + "type": { + "name": "boolean | SkeletonAvatarProps" + } + }, + "grid": { + "defaultValue": { + "value": "false" + }, + "description": "是否显示金刚位占位图(如该参数非空时,默认展示四列金刚位,且不展示标题/段落/头像占位符)\n@en Show Grid placeholder. When it's value is present, the paragraph, avatar or title placeholder will not be displayed, and four columns will be displayed by default", + "name": "grid", + "tags": { + "en": "Show Grid placeholder. When it's value is present, the paragraph, avatar or title placeholder will not be displayed, and four columns will be displayed by default", + "default": "false" + }, + "descWithTags": "是否显示金刚位占位图(如该参数非空时,默认展示四列金刚位,且不展示标题/段落/头像占位符)", + "parent": { + "fileName": "arcom-github/packages/arcodesign/components/skeleton/type.ts", + "name": "SkeletonProps" + }, + "required": false, + "type": { + "name": "boolean | SkeletonGridProps" + } + }, + "showAnimation": { + "defaultValue": { + "value": "true" + }, + "description": "是否展示动画效果\n@en Show loading effect", + "name": "showAnimation", + "tags": { + "en": "Show loading effect", + "default": "true" + }, + "descWithTags": "是否展示动画效果", + "parent": { + "fileName": "arcom-github/packages/arcodesign/components/skeleton/type.ts", + "name": "SkeletonProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "animation": { + "defaultValue": { + "value": "\"gradient\"" + }, + "description": "加载动画效果,可选“扫光”、“呼吸”两种效果\n@en Animation of loading effect, 'gradient' and 'breath' effects are optional", + "name": "animation", + "tags": { + "en": "Animation of loading effect, 'gradient' and 'breath' effects are optional", + "default": "\"gradient\"" + }, + "descWithTags": "加载动画效果,可选“扫光”、“呼吸”两种效果", + "parent": { + "fileName": "arcom-github/packages/arcodesign/components/skeleton/type.ts", + "name": "SkeletonProps" + }, + "required": false, + "type": { + "name": "enum", + "raw": "\"gradient\" | \"breath\"", + "value": [ + { + "value": "\"gradient\"" + }, + { + "value": "\"breath\"" + } + ] + } + }, + "animationGradientColor": { + "defaultValue": { + "value": "\"rgba(0, 0, 0, 0.04)\"" + }, + "description": "扫光动效高光颜色\n@en Highlight color of gradient animation", + "name": "animationGradientColor", + "tags": { + "en": "Highlight color of gradient animation", + "default": "\"rgba(0, 0, 0, 0.04)\"" + }, + "descWithTags": "扫光动效高光颜色", + "parent": { + "fileName": "arcom-github/packages/arcodesign/components/skeleton/type.ts", + "name": "SkeletonProps" + }, + "required": false, + "type": { + "name": "string" + } + }, + "backgroundColor": { + "defaultValue": { + "value": "\"#F7F8FA\"" + }, + "description": "占位块背景色\n@en Background color of skeleton item", + "name": "backgroundColor", + "tags": { + "en": "Background color of skeleton item", + "default": "\"#F7F8FA\"" + }, + "descWithTags": "占位块背景色", + "parent": { + "fileName": "arcom-github/packages/arcodesign/components/skeleton/type.ts", + "name": "SkeletonProps" + }, + "required": false, + "type": { + "name": "string" + } + }, + "children": { + "defaultValue": { + "value": "null" + }, + "description": "子元素\n@en Children element", + "name": "children", + "tags": { + "en": "Children element", + "default": "null" + }, + "descWithTags": "子元素", + "parent": { + "fileName": "arcom-github/packages/arcodesign/components/skeleton/type.ts", + "name": "SkeletonProps" + }, + "required": false, + "type": { + "name": "ReactNode" + } + }, + "className": { + "defaultValue": { + "value": "\"\"" + }, + "description": "自定义类名\n@en Custom classname", + "name": "className", + "tags": { + "en": "Custom classname", + "default": "\"\"" + }, + "descWithTags": "自定义类名", + "parent": { + "fileName": "arcom-github/packages/arcodesign/components/_helpers/type.ts", + "name": "SimpleBaseProps" + }, + "required": false, + "type": { + "name": "string" + } + }, + "style": { + "defaultValue": { + "value": "{}" + }, + "description": "自定义样式\n@en Custom stylesheet", + "name": "style", + "tags": { + "en": "Custom stylesheet", + "default": "{}" + }, + "descWithTags": "自定义样式", + "parent": { + "fileName": "arcom-github/packages/arcodesign/components/_helpers/type.ts", + "name": "SimpleBaseProps" + }, + "required": false, + "type": { + "name": "CSSProperties" + } + }, + "ref": { + "defaultValue": null, + "description": "", + "name": "ref", + "tags": {}, + "descWithTags": "", + "parent": { + "fileName": "arcom-github/node_modules/@types/react/index.d.ts", + "name": "RefAttributes" + }, + "required": false, + "type": { + "name": "Ref" + } + } + }, + "deps": { + "SkeletonTitleProps": { + "width": { + "name": "width", + "required": false, + "description": "标题占位图宽度\n@en The width of title", + "defaultValue": { + "value": "\"40%\"" + }, + "type": { + "name": "ReactText" + }, + "tags": { + "en": "The width of title", + "default": "\"40%\"" + }, + "descWithTags": "标题占位图宽度" + }, + "className": { + "name": "className", + "required": false, + "description": "自定义类名\n@en Custom classname", + "defaultValue": { + "value": "\"\"" + }, + "type": { + "name": "string" + }, + "tags": { + "en": "Custom classname", + "default": "\"\"" + }, + "descWithTags": "自定义类名" + }, + "style": { + "name": "style", + "required": false, + "description": "自定义样式\n@en Custom stylesheet", + "defaultValue": { + "value": "{}" + }, + "type": { + "name": "CSSProperties" + }, + "tags": { + "en": "Custom stylesheet", + "default": "{}" + }, + "descWithTags": "自定义样式" + } + }, + "SkeletonParagraphProps": { + "rows": { + "name": "rows", + "required": false, + "description": "段落占位图的行数\n@en Number of lines for paragraph", + "defaultValue": { + "value": "3" + }, + "type": { + "name": "number" + }, + "tags": { + "en": "Number of lines for paragraph", + "default": "3" + }, + "descWithTags": "段落占位图的行数" + }, + "width": { + "name": "width", + "required": false, + "description": "段落占位图宽度,若为数组格式对应每行宽度,否则表示最后一行的宽度\n@en The width of paragraph. If width is an Array, it corresponds to the width of each line, otherwise it indicates the width of the last line", + "defaultValue": { + "value": "\"60%\"" + }, + "type": { + "name": "string | number | ReactText[]" + }, + "tags": { + "en": "The width of paragraph. If width is an Array, it corresponds to the width of each line, otherwise it indicates the width of the last line", + "default": "\"60%\"" + }, + "descWithTags": "段落占位图宽度,若为数组格式对应每行宽度,否则表示最后一行的宽度" + }, + "className": { + "name": "className", + "required": false, + "description": "自定义类名\n@en Custom classname", + "defaultValue": { + "value": "\"\"" + }, + "type": { + "name": "string" + }, + "tags": { + "en": "Custom classname", + "default": "\"\"" + }, + "descWithTags": "自定义类名" + }, + "style": { + "name": "style", + "required": false, + "description": "自定义样式\n@en Custom stylesheet", + "defaultValue": { + "value": "{}" + }, + "type": { + "name": "CSSProperties" + }, + "tags": { + "en": "Custom stylesheet", + "default": "{}" + }, + "descWithTags": "自定义样式" + } + }, + "SkeletonAvatarProps": { + "className": { + "name": "className", + "required": false, + "description": "自定义类名\n@en Custom classname", + "defaultValue": { + "value": "\"\"" + }, + "type": { + "name": "string" + }, + "tags": { + "en": "Custom classname", + "default": "\"\"" + }, + "descWithTags": "自定义类名" + }, + "style": { + "name": "style", + "required": false, + "description": "自定义样式\n@en Custom stylesheet", + "defaultValue": { + "value": "{}" + }, + "type": { + "name": "CSSProperties" + }, + "tags": { + "en": "Custom stylesheet", + "default": "{}" + }, + "descWithTags": "自定义样式" + } + }, + "SkeletonGridProps": { + "columns": { + "name": "columns", + "required": false, + "description": "金刚位列数\n@en columns of grid", + "defaultValue": { + "value": "4" + }, + "type": { + "name": "number" + }, + "tags": { + "en": "columns of grid", + "default": "4" + }, + "descWithTags": "金刚位列数" + }, + "className": { + "name": "className", + "required": false, + "description": "自定义类名\n@en Custom classname", + "defaultValue": { + "value": "\"\"" + }, + "type": { + "name": "string" + }, + "tags": { + "en": "Custom classname", + "default": "\"\"" + }, + "descWithTags": "自定义类名" + }, + "style": { + "name": "style", + "required": false, + "description": "自定义样式\n@en Custom stylesheet", + "defaultValue": { + "value": "{}" + }, + "type": { + "name": "CSSProperties" + }, + "tags": { + "en": "Custom stylesheet", + "default": "{}" + }, + "descWithTags": "自定义样式" + } + }, + "SkeletonRef": { + "dom": { + "name": "dom", + "required": true, + "description": "最外层 DOM 元素\n@en The outer DOM element of the component", + "defaultValue": null, + "type": { + "name": "HTMLDivElement" + }, + "tags": { + "en": "The outer DOM element of the component" + }, + "descWithTags": "最外层 DOM 元素" + } + } + }, + "depComps": { + "Node": { + "description": "", + "descriptionTags": {}, + "displayName": "SkeletonNode", + "methods": [], + "props": { + "children": { + "defaultValue": { + "value": "null" + }, + "description": "自定义组件内容\n@en Custom component content", + "name": "children", + "tags": { + "en": "Custom component content", + "default": "null" + }, + "descWithTags": "自定义组件内容", + "parent": { + "fileName": "arcom-github/packages/arcodesign/components/_helpers/type.ts", + "name": "BaseProps" + }, + "required": false, + "type": { + "name": "ReactNode" + } + }, + "className": { + "defaultValue": { + "value": "\"\"" + }, + "description": "自定义类名\n@en Custom classname", + "name": "className", + "tags": { + "en": "Custom classname", + "default": "\"\"" + }, + "descWithTags": "自定义类名", + "parent": { + "fileName": "arcom-github/packages/arcodesign/components/_helpers/type.ts", + "name": "SimpleBaseProps" + }, + "required": false, + "type": { + "name": "string" + } + }, + "style": { + "defaultValue": { + "value": "{}" + }, + "description": "自定义样式\n@en Custom stylesheet", + "name": "style", + "tags": { + "en": "Custom stylesheet", + "default": "{}" + }, + "descWithTags": "自定义样式", + "parent": { + "fileName": "arcom-github/packages/arcodesign/components/_helpers/type.ts", + "name": "SimpleBaseProps" + }, + "required": false, + "type": { + "name": "CSSProperties" + } + }, + "ref": { + "defaultValue": null, + "description": "", + "name": "ref", + "tags": {}, + "descWithTags": "", + "parent": { + "fileName": "arcom-github/node_modules/@types/react/index.d.ts", + "name": "RefAttributes" + }, + "required": false, + "type": { + "name": "Ref" + } + } + }, + "deps": { + "SkeletonRef": { + "dom": { + "name": "dom", + "required": true, + "description": "最外层 DOM 元素\n@en The outer DOM element of the component", + "defaultValue": null, + "type": { + "name": "HTMLDivElement" + }, + "tags": { + "en": "The outer DOM element of the component" + }, + "descWithTags": "最外层 DOM 元素" + } + } + }, + "depComps": {}, + "typeNameInfo": { + "props": "BaseProps", + "ref": "SkeletonRef" + } + }, + "Title": { + "description": "", + "descriptionTags": {}, + "displayName": "SkeletonTitle", + "methods": [], + "props": { + "width": { + "defaultValue": { + "value": "\"40%\"" + }, + "description": "标题占位图宽度\n@en The width of title", + "name": "width", + "tags": { + "en": "The width of title", + "default": "\"40%\"" + }, + "descWithTags": "标题占位图宽度", + "parent": { + "fileName": "arcom-github/packages/arcodesign/components/skeleton/type.ts", + "name": "SkeletonTitleProps" + }, + "required": false, + "type": { + "name": "ReactText" + } + }, + "className": { + "defaultValue": { + "value": "\"\"" + }, + "description": "自定义类名\n@en Custom classname", + "name": "className", + "tags": { + "en": "Custom classname", + "default": "\"\"" + }, + "descWithTags": "自定义类名", + "parent": { + "fileName": "arcom-github/packages/arcodesign/components/_helpers/type.ts", + "name": "SimpleBaseProps" + }, + "required": false, + "type": { + "name": "string" + } + }, + "style": { + "defaultValue": { + "value": "{}" + }, + "description": "自定义样式\n@en Custom stylesheet", + "name": "style", + "tags": { + "en": "Custom stylesheet", + "default": "{}" + }, + "descWithTags": "自定义样式", + "parent": { + "fileName": "arcom-github/packages/arcodesign/components/_helpers/type.ts", + "name": "SimpleBaseProps" + }, + "required": false, + "type": { + "name": "CSSProperties" + } + }, + "ref": { + "defaultValue": null, + "description": "", + "name": "ref", + "tags": {}, + "descWithTags": "", + "parent": { + "fileName": "arcom-github/node_modules/@types/react/index.d.ts", + "name": "RefAttributes" + }, + "required": false, + "type": { + "name": "Ref" + } + } + }, + "deps": { + "SkeletonRef": { + "dom": { + "name": "dom", + "required": true, + "description": "最外层 DOM 元素\n@en The outer DOM element of the component", + "defaultValue": null, + "type": { + "name": "HTMLDivElement" + }, + "tags": { + "en": "The outer DOM element of the component" + }, + "descWithTags": "最外层 DOM 元素" + } + } + }, + "depComps": {}, + "typeNameInfo": { + "props": "SkeletonTitleProps", + "ref": "SkeletonRef" + } + }, + "Paragraph": { + "description": "", + "descriptionTags": {}, + "displayName": "SkeletonParagraph", + "methods": [], + "props": { + "rows": { + "defaultValue": { + "value": "3" + }, + "description": "段落占位图的行数\n@en Number of lines for paragraph", + "name": "rows", + "tags": { + "en": "Number of lines for paragraph", + "default": "3" + }, + "descWithTags": "段落占位图的行数", + "parent": { + "fileName": "arcom-github/packages/arcodesign/components/skeleton/type.ts", + "name": "SkeletonParagraphProps" + }, + "required": false, + "type": { + "name": "number" + } + }, + "width": { + "defaultValue": { + "value": "\"60%\"" + }, + "description": "段落占位图宽度,若为数组格式对应每行宽度,否则表示最后一行的宽度\n@en The width of paragraph. If width is an Array, it corresponds to the width of each line, otherwise it indicates the width of the last line", + "name": "width", + "tags": { + "en": "The width of paragraph. If width is an Array, it corresponds to the width of each line, otherwise it indicates the width of the last line", + "default": "\"60%\"" + }, + "descWithTags": "段落占位图宽度,若为数组格式对应每行宽度,否则表示最后一行的宽度", + "parent": { + "fileName": "arcom-github/packages/arcodesign/components/skeleton/type.ts", + "name": "SkeletonParagraphProps" + }, + "required": false, + "type": { + "name": "string | number | ReactText[]" + } + }, + "className": { + "defaultValue": { + "value": "\"\"" + }, + "description": "自定义类名\n@en Custom classname", + "name": "className", + "tags": { + "en": "Custom classname", + "default": "\"\"" + }, + "descWithTags": "自定义类名", + "parent": { + "fileName": "arcom-github/packages/arcodesign/components/_helpers/type.ts", + "name": "SimpleBaseProps" + }, + "required": false, + "type": { + "name": "string" + } + }, + "style": { + "defaultValue": { + "value": "{}" + }, + "description": "自定义样式\n@en Custom stylesheet", + "name": "style", + "tags": { + "en": "Custom stylesheet", + "default": "{}" + }, + "descWithTags": "自定义样式", + "parent": { + "fileName": "arcom-github/packages/arcodesign/components/_helpers/type.ts", + "name": "SimpleBaseProps" + }, + "required": false, + "type": { + "name": "CSSProperties" + } + }, + "ref": { + "defaultValue": null, + "description": "", + "name": "ref", + "tags": {}, + "descWithTags": "", + "parent": { + "fileName": "arcom-github/node_modules/@types/react/index.d.ts", + "name": "RefAttributes" + }, + "required": false, + "type": { + "name": "Ref" + } + } + }, + "deps": { + "SkeletonRef": { + "dom": { + "name": "dom", + "required": true, + "description": "最外层 DOM 元素\n@en The outer DOM element of the component", + "defaultValue": null, + "type": { + "name": "HTMLDivElement" + }, + "tags": { + "en": "The outer DOM element of the component" + }, + "descWithTags": "最外层 DOM 元素" + } + } + }, + "depComps": {}, + "typeNameInfo": { + "props": "SkeletonParagraphProps", + "ref": "SkeletonRef" + } + }, + "Avatar": { + "description": "", + "descriptionTags": {}, + "displayName": "SkeletonAvatar", + "methods": [], + "props": { + "className": { + "defaultValue": { + "value": "\"\"" + }, + "description": "自定义类名\n@en Custom classname", + "name": "className", + "tags": { + "en": "Custom classname", + "default": "\"\"" + }, + "descWithTags": "自定义类名", + "parent": { + "fileName": "arcom-github/packages/arcodesign/components/_helpers/type.ts", + "name": "SimpleBaseProps" + }, + "required": false, + "type": { + "name": "string" + } + }, + "style": { + "defaultValue": { + "value": "{}" + }, + "description": "自定义样式\n@en Custom stylesheet", + "name": "style", + "tags": { + "en": "Custom stylesheet", + "default": "{}" + }, + "descWithTags": "自定义样式", + "parent": { + "fileName": "arcom-github/packages/arcodesign/components/_helpers/type.ts", + "name": "SimpleBaseProps" + }, + "required": false, + "type": { + "name": "CSSProperties" + } + }, + "ref": { + "defaultValue": null, + "description": "", + "name": "ref", + "tags": {}, + "descWithTags": "", + "parent": { + "fileName": "arcom-github/node_modules/@types/react/index.d.ts", + "name": "RefAttributes" + }, + "required": false, + "type": { + "name": "Ref" + } + } + }, + "deps": { + "SkeletonRef": { + "dom": { + "name": "dom", + "required": true, + "description": "最外层 DOM 元素\n@en The outer DOM element of the component", + "defaultValue": null, + "type": { + "name": "HTMLDivElement" + }, + "tags": { + "en": "The outer DOM element of the component" + }, + "descWithTags": "最外层 DOM 元素" + } + } + }, + "depComps": {}, + "typeNameInfo": { + "props": "SimpleBaseProps", + "ref": "SkeletonRef" + } + }, + "Grid": { + "description": "", + "descriptionTags": {}, + "displayName": "SkeletonGrid", + "methods": [], + "props": { + "columns": { + "defaultValue": { + "value": "4" + }, + "description": "金刚位列数\n@en columns of grid", + "name": "columns", + "tags": { + "en": "columns of grid", + "default": "4" + }, + "descWithTags": "金刚位列数", + "parent": { + "fileName": "arcom-github/packages/arcodesign/components/skeleton/type.ts", + "name": "SkeletonGridProps" + }, + "required": false, + "type": { + "name": "number" + } + }, + "className": { + "defaultValue": { + "value": "\"\"" + }, + "description": "自定义类名\n@en Custom classname", + "name": "className", + "tags": { + "en": "Custom classname", + "default": "\"\"" + }, + "descWithTags": "自定义类名", + "parent": { + "fileName": "arcom-github/packages/arcodesign/components/_helpers/type.ts", + "name": "SimpleBaseProps" + }, + "required": false, + "type": { + "name": "string" + } + }, + "style": { + "defaultValue": { + "value": "{}" + }, + "description": "自定义样式\n@en Custom stylesheet", + "name": "style", + "tags": { + "en": "Custom stylesheet", + "default": "{}" + }, + "descWithTags": "自定义样式", + "parent": { + "fileName": "arcom-github/packages/arcodesign/components/_helpers/type.ts", + "name": "SimpleBaseProps" + }, + "required": false, + "type": { + "name": "CSSProperties" + } + }, + "ref": { + "defaultValue": null, + "description": "", + "name": "ref", + "tags": {}, + "descWithTags": "", + "parent": { + "fileName": "arcom-github/node_modules/@types/react/index.d.ts", + "name": "RefAttributes" + }, + "required": false, + "type": { + "name": "Ref" + } + } + }, + "deps": { + "SkeletonRef": { + "dom": { + "name": "dom", + "required": true, + "description": "最外层 DOM 元素\n@en The outer DOM element of the component", + "defaultValue": null, + "type": { + "name": "HTMLDivElement" + }, + "tags": { + "en": "The outer DOM element of the component" + }, + "descWithTags": "最外层 DOM 元素" + } + } + }, + "depComps": {}, + "typeNameInfo": { + "props": "SkeletonGridProps", + "ref": "SkeletonRef" + } + } + }, + "typeNameInfo": { + "props": "SkeletonProps", + "ref": "SkeletonRef" + }, + "isDefaultExport": true +} \ No newline at end of file diff --git a/packages/arcodesign/components/skeleton/__test__/__snapshots__/index.spec.js.snap b/packages/arcodesign/components/skeleton/__test__/__snapshots__/index.spec.js.snap new file mode 100644 index 00000000..149464ba --- /dev/null +++ b/packages/arcodesign/components/skeleton/__test__/__snapshots__/index.spec.js.snap @@ -0,0 +1,574 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`skeleton demo test skeleton demo: animation.md renders correctly 1`] = ` +
+
+
+
+
+
+
+ show animation +
+
+
+
+
+
+
+
+
+
+
+
+
+ type +
+
+
+
+ + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+`; + +exports[`skeleton demo test skeleton demo: avatar.md renders correctly 1`] = ` +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+`; + +exports[`skeleton demo test skeleton demo: custom.md renders correctly 1`] = ` +
+
+
+
+
+
+
+ loading +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+`; + +exports[`skeleton demo test skeleton demo: grid.md renders correctly 1`] = ` +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+`; + +exports[`skeleton demo test skeleton demo: index.md renders correctly 1`] = ` +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+`; diff --git a/packages/arcodesign/components/skeleton/__test__/index.spec.js b/packages/arcodesign/components/skeleton/__test__/index.spec.js new file mode 100644 index 00000000..c47d753d --- /dev/null +++ b/packages/arcodesign/components/skeleton/__test__/index.spec.js @@ -0,0 +1,78 @@ +import React from 'react'; +import { mount } from 'enzyme'; +import demoTest from '../../../tests/demoTest'; +import mountTest from '../../../tests/mountTest'; +import { defaultContext } from '../../context-provider'; +import Skeleton from '..'; + +demoTest('skeleton'); + +mountTest(Skeleton, 'Skeleton'); + +const prefix = `${defaultContext.prefixCls}-skeleton`; + +describe('Skeleton', () => { + it('should render correctly when set ref', () => { + const ref = React.createRef(); + const titleRef = React.createRef(); + const paragraphRef = React.createRef(); + const avatarRef = React.createRef(); + const nodeRef = React.createRef(); + mount( + + + + + +
+ + , + ); + expect(ref.current.dom).not.toBeUndefined(); + expect(titleRef.current.dom).not.toBeUndefined(); + expect(paragraphRef.current.dom).not.toBeUndefined(); + expect(avatarRef.current.dom).not.toBeUndefined(); + expect(nodeRef.current.dom).not.toBeUndefined(); + }); + it('should render correctly when set avatar', () => { + const comp = mount(); + expect(comp.find(`.${prefix}-avatar`).length).toBe(1); + }); + it('should render correctly when set grid', () => { + const comp = mount(); + expect(comp.find(`.${prefix}-grid-item`).length).toBe(5); + }); + it('should render correctly when set children', () => { + const comp = mount( + + +
+ + , + ); + expect(comp.find(`.${prefix}-node`).length).toBe(1); + expect(comp.find(`.${prefix}-title`).length).toBe(1); + expect(comp.find(`.${prefix}-paragraph`).length).toBe(1); + }); + it('should render correctly when set animation', () => { + const comp = mount( + + +
+ + , + ); + expect(comp.find(`.${prefix}-animation-gradient`).length).toBe(5); + expect(comp.find(`.${prefix}-animation-breath`).length).toBe(0); + comp.setProps({ + animation: 'breath', + }); + expect(comp.find(`.${prefix}-animation-gradient`).length).toBe(0); + expect(comp.find(`.${prefix}-animation-breath`).length).toBe(5); + comp.setProps({ + showAnimation: false, + }); + expect(comp.find(`.${prefix}-animation-gradient`).length).toBe(0); + expect(comp.find(`.${prefix}-animation-breath`).length).toBe(0); + }); +}); diff --git a/packages/arcodesign/components/skeleton/demo/animation.md b/packages/arcodesign/components/skeleton/demo/animation.md new file mode 100644 index 00000000..12abd610 --- /dev/null +++ b/packages/arcodesign/components/skeleton/demo/animation.md @@ -0,0 +1,39 @@ +## 动效 @en{Animation} + +#### 5 + +```js +import { Cell, Checkbox, Radio, Skeleton, Switch } from '@arco-design/mobile-react'; + +const options = [ + { label: 'gradient', value: 'gradient' }, + { label: 'breath', value: 'breath' }, +]; + +const color = 'rgba(0, 0, 0, 4%)'; + +export default function SkeletonDemo() { + const [type, setType] = React.useState('gradient'); + const [checked, setChecked] = React.useState(true); + return ( +
+ + + + + {checked && ( + + + + )} + + +
+ ); +} +``` diff --git a/packages/arcodesign/components/skeleton/demo/avatar.md b/packages/arcodesign/components/skeleton/demo/avatar.md new file mode 100644 index 00000000..05165490 --- /dev/null +++ b/packages/arcodesign/components/skeleton/demo/avatar.md @@ -0,0 +1,11 @@ +## 含头像 @en{With avatar} + +#### 2 + +```js +import { Skeleton } from '@arco-design/mobile-react'; + +export default function SkeletonDemo() { + return ; +} +``` diff --git a/packages/arcodesign/components/skeleton/demo/custom.md b/packages/arcodesign/components/skeleton/demo/custom.md new file mode 100644 index 00000000..a79d378f --- /dev/null +++ b/packages/arcodesign/components/skeleton/demo/custom.md @@ -0,0 +1,46 @@ +## 独立节点自由组合 @en{Custom} + +#### 5 + +```js +import { Cell, Skeleton, Switch } from '@arco-design/mobile-react'; + +export default function SkeletonDemo() { + const [loading, setLoading] = React.useState(true); + return ( +
+ + + + + + {loading ? ( + + +
+ + +
+ +
+ + + + ) : ( +
actual content
+ )} +
+ ); +} +``` diff --git a/packages/arcodesign/components/skeleton/demo/grid.md b/packages/arcodesign/components/skeleton/demo/grid.md new file mode 100644 index 00000000..7bbb9fe8 --- /dev/null +++ b/packages/arcodesign/components/skeleton/demo/grid.md @@ -0,0 +1,11 @@ +## 金刚区 @en{Grid} + +#### 3 + +```js +import { Skeleton } from '@arco-design/mobile-react'; + +export default function SkeletonDemo() { + return ; +} +``` diff --git a/packages/arcodesign/components/skeleton/demo/index.md b/packages/arcodesign/components/skeleton/demo/index.md new file mode 100644 index 00000000..3d033861 --- /dev/null +++ b/packages/arcodesign/components/skeleton/demo/index.md @@ -0,0 +1,11 @@ +## 基础用法 @en{Basic} + +#### 1 + +```js +import { Skeleton } from '@arco-design/mobile-react'; + +export default function SkeletonDemo() { + return ; +} +``` diff --git a/packages/arcodesign/components/skeleton/demo/style/mobile.less b/packages/arcodesign/components/skeleton/demo/style/mobile.less new file mode 100644 index 00000000..366ec254 --- /dev/null +++ b/packages/arcodesign/components/skeleton/demo/style/mobile.less @@ -0,0 +1,13 @@ +@import '../../../../style/mixin.less'; + +#demo-skeleton { + .arcodesign-mobile-demo-content { + .arco-cell-group { + margin-bottom: 0.32rem; + } + .arco-cell { + margin-left: 0; + padding-right: 0; + } + } +} diff --git a/packages/arcodesign/components/skeleton/elements.tsx b/packages/arcodesign/components/skeleton/elements.tsx new file mode 100644 index 00000000..48dfa65d --- /dev/null +++ b/packages/arcodesign/components/skeleton/elements.tsx @@ -0,0 +1,278 @@ +import React, { + Ref, + forwardRef, + useContext, + useEffect, + useImperativeHandle, + useRef, + useState, +} from 'react'; +import { cls, isArray, nextTick } from '@arco-design/mobile-utils'; +import { useListenResize } from '../_helpers'; +import { GlobalContext } from '../context-provider'; +import { + SkeletonAvatarProps, + SkeletonGridProps, + SkeletonNodeProps, + SkeletonParagraphProps, + SkeletonRef, + SkeletonTitleProps, +} from './type'; +import { SkeletonContext } from './skeleton-context'; + +const calcOffset = (dom?: HTMLElement | null, useRtl?: boolean) => { + if (!dom) { + return 0; + } + if (useRtl) { + return dom.offsetLeft - dom.offsetTop; + } + return dom.offsetLeft + dom.offsetTop; +}; + +function useOffset | T[]>( + dom?: K, + useRtl?: boolean, +) { + const [offset, setOffset] = useState(); + const calcLayout = () => { + const isList = Array.isArray(dom); + if ( + !(isList ? (dom as T[]).length > 0 : (dom as React.MutableRefObject)?.current) + ) { + return; + } + setOffset( + isList + ? (dom as T[]).map(item => calcOffset(item, useRtl)) + : calcOffset((dom as React.MutableRefObject).current, useRtl), + ); + }; + + useEffect(() => { + nextTick(() => { + calcLayout(); + }); + }, [dom, useRtl]); + + useListenResize(calcLayout); + return offset as K extends T[] ? number[] : number; +} + +export const SkeletonNode = forwardRef((props: SkeletonNodeProps, ref: Ref) => { + const { className = '', style, children } = props; + const { useRtl, prefixCls } = useContext(GlobalContext); + const { backgroundColor, showAnimation, animation } = useContext(SkeletonContext); + const domRef = useRef(null); + const isGradientAnimation = showAnimation && animation === 'gradient'; + const offset = useOffset(isGradientAnimation ? domRef : undefined, useRtl); + + useImperativeHandle(ref, () => ({ + dom: domRef.current, + })); + + return ( +
+ {children} + {isGradientAnimation && offset !== undefined && ( +
+ )} +
+ ); +}); + +export const SkeletonTitle = forwardRef((props: SkeletonTitleProps, ref: Ref) => { + const { className = '', style, width = '40%' } = props; + const { useRtl, prefixCls } = useContext(GlobalContext); + const { backgroundColor, showAnimation, animation } = useContext(SkeletonContext); + const domRef = useRef(null); + const isGradientAnimation = showAnimation && animation === 'gradient'; + const offset = useOffset(isGradientAnimation ? domRef : undefined, useRtl); + + useImperativeHandle(ref, () => ({ + dom: domRef.current, + })); + + return ( +
+ {isGradientAnimation && offset !== undefined && ( +
+ )} +
+ ); +}); + +export const SkeletonParagraph = forwardRef( + (props: SkeletonParagraphProps, ref: Ref) => { + const { className = '', style, rows = 3, width = '60%' } = props; + const { useRtl, prefixCls } = useContext(GlobalContext); + const { backgroundColor, showAnimation, animation } = useContext(SkeletonContext); + const domRef = useRef(null); + const lineDomRefs = useRef([]); + const isGradientAnimation = showAnimation && animation === 'gradient'; + const offsets = useOffset(isGradientAnimation ? lineDomRefs.current : undefined, useRtl); + + useImperativeHandle(ref, () => ({ + dom: domRef.current, + })); + + const getWidth = (idx: number) => { + if (isArray(width)) { + return width[idx]; + } + if (rows - 1 === idx) { + return width; + } + return undefined; + }; + + return ( +
+ {Array.from(new Array(rows)).map((_, idx) => ( +
el && (lineDomRefs.current[idx] = el)} + > + {isGradientAnimation && offsets !== undefined && ( +
+ )} +
+ ))} +
+ ); + }, +); + +export const SkeletonAvatar = forwardRef((props: SkeletonAvatarProps, ref: Ref) => { + const { className = '', style } = props; + const { useRtl, prefixCls } = useContext(GlobalContext); + const { backgroundColor, showAnimation, animation } = useContext(SkeletonContext); + const domRef = useRef(null); + const isGradientAnimation = showAnimation && animation === 'gradient'; + const offset = useOffset(isGradientAnimation ? domRef : undefined, useRtl); + + useImperativeHandle(ref, () => ({ + dom: domRef.current, + })); + + return ( +
+ {isGradientAnimation && offset !== undefined && ( +
+ )} +
+ ); +}); + +export const SkeletonGrid = forwardRef((props: SkeletonGridProps, ref: Ref) => { + const { className = '', style, columns = 4 } = props; + const { useRtl, prefixCls } = useContext(GlobalContext); + const { backgroundColor, showAnimation, animation } = useContext(SkeletonContext); + const domRef = useRef(null); + const iconDomRefs = useRef([]); + const textDomRefs = useRef([]); + const isGradientAnimation = showAnimation && animation === 'gradient'; + const iconOffsets = useOffset(isGradientAnimation ? iconDomRefs.current : undefined, useRtl); + const textOffsets = useOffset(isGradientAnimation ? textDomRefs.current : undefined, useRtl); + + useImperativeHandle(ref, () => ({ + dom: domRef.current, + })); + + return ( +
+ {Array.from(new Array(columns)).map((_, idx) => ( +
+
el && (iconDomRefs.current[idx] = el)} + > + {isGradientAnimation && iconOffsets !== undefined && ( +
+ )} +
+
el && (textDomRefs.current[idx] = el)} + > + {isGradientAnimation && textOffsets !== undefined && ( +
+ )} +
+
+ ))} +
+ ); +}); diff --git a/packages/arcodesign/components/skeleton/index.tsx b/packages/arcodesign/components/skeleton/index.tsx new file mode 100644 index 00000000..a1f3e683 --- /dev/null +++ b/packages/arcodesign/components/skeleton/index.tsx @@ -0,0 +1,94 @@ +import React, { useRef, forwardRef, Ref, useImperativeHandle, useContext } from 'react'; +import { cls, componentWrapper } from '@arco-design/mobile-utils'; +import { GlobalContext } from '../context-provider'; +import { SkeletonProps, SkeletonRef } from './type'; +import { + SkeletonAvatar as Avatar, + SkeletonGrid as Grid, + SkeletonNode as Node, + SkeletonParagraph as Paragraph, + SkeletonTitle as Title, +} from './elements'; +import { SkeletonContext } from './skeleton-context'; + +function getComponentProps(prop?: T | boolean): T | {} { + if (prop && typeof prop === 'object') { + return prop; + } + return {}; +} + +const Skeleton = forwardRef((props: SkeletonProps, ref: Ref) => { + const { + className = '', + style, + children, + title = true, + paragraph = true, + avatar = false, + grid, + showAnimation = true, + animation = 'gradient', + animationGradientColor, + backgroundColor, + } = props; + const domRef = useRef(null); + const { prefixCls } = useContext(GlobalContext); + + useImperativeHandle(ref, () => ({ + dom: domRef.current, + })); + + const isGrid = !!grid; + const hasTitle = !!title; + const hasParagraph = !!paragraph; + const hasAvatar = !!avatar; + const content = isGrid ? ( + + ) : ( + <> + {hasAvatar && } + {(hasTitle || hasParagraph) && ( +
+ {hasTitle && } + {hasParagraph && <Paragraph {...getComponentProps(paragraph)} />} + </div> + )} + </> + ); + + return ( + <div + className={cls( + `${prefixCls}-skeleton`, + { + [`${prefixCls}-skeleton-with-avatar`]: hasAvatar, + }, + className, + )} + style={{ color: animationGradientColor, ...style }} + ref={domRef} + > + <SkeletonContext.Provider value={{ showAnimation, animation, backgroundColor }}> + {content} + {children} + </SkeletonContext.Provider> + </div> + ); +}); + +/** + * 在内容加载过程中展示一组占位图形。 + * @en Display a set of placeholder graphics during content loading + * @type 信息展示 + * @type_en Data Display + * @name 骨架屏 + * @name_en Skeleton + */ +export default componentWrapper(Skeleton, { + Node, + Title, + Paragraph, + Avatar, + Grid, +}); diff --git a/packages/arcodesign/components/skeleton/skeleton-context.tsx b/packages/arcodesign/components/skeleton/skeleton-context.tsx new file mode 100644 index 00000000..81cb0107 --- /dev/null +++ b/packages/arcodesign/components/skeleton/skeleton-context.tsx @@ -0,0 +1,7 @@ +import React from 'react'; +import { SkeletonContextParams, SkeletonProps } from './type'; + +export const SkeletonContext = React.createContext<SkeletonContextParams>({ + showAnimation: true, + animation: 'gradient' as SkeletonProps['animation'], +}); diff --git a/packages/arcodesign/components/skeleton/style/index.less b/packages/arcodesign/components/skeleton/style/index.less new file mode 100644 index 00000000..1a6788fc --- /dev/null +++ b/packages/arcodesign/components/skeleton/style/index.less @@ -0,0 +1,147 @@ +@import '../../../style/mixin.less'; + +.@{prefix}-skeleton { + position: relative; + .use-var(color, skeleton-gradient-animation-color); +} + +.@{prefix}-skeleton-title { + .use-var(height, skeleton-title-height); +} + +.@{prefix}-skeleton-paragraph { + &-line { + width: 100%; + .use-var(height, skeleton-paragraph-height); + } + + &-line + &-line { + .use-var(margin-top, skeleton-paragraph-margin-top); + } +} + +.@{prefix}-skeleton-avatar.@{prefix}-skeleton-item { + .use-var(width, skeleton-avatar-size); + .use-var(height, skeleton-avatar-size); + border-radius: 100%; + transform: translateZ(0); +} + +.@{prefix}-skeleton-content { + width: 100%; + + .@{prefix}-skeleton-title + .@{prefix}-skeleton-paragraph { + .use-var(margin-top, skeleton-large-gutter); + } +} + +.@{prefix}-skeleton-with-avatar { + display: flex; + align-items: flex-start; + + .@{prefix}-skeleton-avatar { + flex: none; + } + + .@{prefix}-skeleton-content { + .@{prefix}-skeleton-title { + .use-var(margin-top, skeleton-medium-gutter); + } + } + + .@{prefix}-skeleton-avatar + .@{prefix}-skeleton-content { + .use-var-with-rtl(margin-left, skeleton-medium-gutter); + } +} + +.@{prefix}-skeleton-grid { + display: flex; + justify-content: space-between; + width: 100%; + + &-item { + display: flex; + flex-direction: column; + align-items: center; + } + &-icon { + .use-var(width, skeleton-grid-icon-size); + .use-var(height, skeleton-grid-icon-size); + } + &-text { + .use-var(margin-top, skeleton-medium-gutter); + .use-var(width, skeleton-grid-text-width); + .use-var(height, skeleton-grid-text-height); + } +} + +.@{prefix}-skeleton-node { + display: inline-block; +} + +.@{prefix}-skeleton-item { + position: relative; + overflow: hidden; + .use-var(border-radius, skeleton-border-radius); + .use-var(background-color, skeleton-background-color); +} + +.@{prefix}-skeleton-animation-item { + position: absolute; + width: 100vw; + height: 100%; + top: 0; + left: 0; + background-image: linear-gradient( + 90deg, + rgba(255, 255, 255, 0) 35%, + currentColor 50%, + rgba(255, 255, 255, 0) 65% + ); + transform-origin: top left; + animation-name: skeleton-gradient; + animation-iteration-count: infinite; + .use-var(animation-timing-function, skeleton-gradient-animation-timing-function); + .use-var(animation-duration, skeleton-gradient-animation-duration); + [dir="rtl"] & { + animation-name: skeleton-gradient-reverse; + } +} +.@{prefix}-skeleton-animation-breath { + animation: skeleton-breath linear infinite; + .use-var(animation-duration, skeleton-breath-animation-duration); +} + +@keyframes skeleton-gradient { + 0% { + transform: translateX(-65%) skewX(-45deg); + } + + 100% { + transform: translateX(135%) skewX(-45deg); + } +} + +@keyframes skeleton-gradient-reverse { + 0% { + transform: translateX(65%) skewX(45deg); + } + + 100% { + transform: translateX(-135%) skewX(45deg); + } +} + +@keyframes skeleton-breath { + 0% { + opacity: 1; + } + + 50% { + .use-var(opacity, skeleton-breath-opacity); + } + + 100% { + opacity: 1; + } +} diff --git a/packages/arcodesign/components/skeleton/style/index.ts b/packages/arcodesign/components/skeleton/style/index.ts new file mode 100644 index 00000000..d33b50ec --- /dev/null +++ b/packages/arcodesign/components/skeleton/style/index.ts @@ -0,0 +1,3 @@ +import '../../../style/public.less'; +import '../../avatar/style'; +import './index.less'; diff --git a/packages/arcodesign/components/skeleton/type.ts b/packages/arcodesign/components/skeleton/type.ts new file mode 100644 index 00000000..ad6bad5b --- /dev/null +++ b/packages/arcodesign/components/skeleton/type.ts @@ -0,0 +1,109 @@ +import { BaseProps, SimpleBaseProps } from '../_helpers'; + +export interface SkeletonProps extends SimpleBaseProps { + /** + * 是否显示标题占位图 + * @en Show title placeholder + * @default true + */ + title?: boolean | SkeletonTitleProps; + /** + * 是否显示段落占位图 + * @en Show paragraph placeholder + * @default true + */ + paragraph?: boolean | SkeletonParagraphProps; + /** + * 是否显示头像占位图 + * @en Show Avatar placeholder + * @default false + */ + avatar?: boolean | SkeletonAvatarProps; + /** + * 是否显示金刚位占位图(如该参数非空时,默认展示四列金刚位,且不展示标题/段落/头像占位符) + * @en Show Grid placeholder. When it's value is present, the paragraph, avatar or title placeholder will not be displayed, and four columns will be displayed by default + * @default false + */ + grid?: boolean | SkeletonGridProps; + /** + * 是否展示动画效果 + * @en Show loading effect + * @default true + */ + showAnimation?: boolean; + /** + * 加载动画效果,可选“扫光”、“呼吸”两种效果 + * @en Animation of loading effect, 'gradient' and 'breath' effects are optional + * @default "gradient" + */ + animation?: 'gradient' | 'breath'; + /** + * 扫光动效高光颜色 + * @en Highlight color of gradient animation + * @default "rgba(0, 0, 0, 0.04)" + */ + animationGradientColor?: string; + /** + * 占位块背景色 + * @en Background color of skeleton item + * @default "#F7F8FA" + */ + backgroundColor?: string; + /** + * 子元素 + * @en Children element + * @default null + */ + children?: React.ReactNode; +} + +export interface SkeletonTitleProps extends SimpleBaseProps { + /** + * 标题占位图宽度 + * @en The width of title + * @default "40%" + */ + width?: number | string; +} + +export interface SkeletonParagraphProps extends SimpleBaseProps { + /** + * 段落占位图的行数 + * @en Number of lines for paragraph + * @default 3 + */ + rows?: number; + /** + * 段落占位图宽度,若为数组格式对应每行宽度,否则表示最后一行的宽度 + * @en The width of paragraph. If width is an Array, it corresponds to the width of each line, otherwise it indicates the width of the last line + * @default "60%" + */ + width?: number | string | Array<number | string>; +} + +export interface SkeletonAvatarProps extends SimpleBaseProps {} + +export interface SkeletonGridProps extends SimpleBaseProps { + /** + * 金刚位列数 + * @en columns of grid + * @default 4 + */ + columns?: number; +} + +export interface SkeletonNodeProps extends BaseProps {} + +export interface SkeletonRef { + /** + * 最外层 DOM 元素 + * @en The outer DOM element of the component + */ + dom: HTMLDivElement | null; +} + +export interface SkeletonContextParams { + backgroundColor?: string; + showAnimation: boolean; + animation: SkeletonProps['animation']; +} diff --git a/packages/arcodesign/components/style.ts b/packages/arcodesign/components/style.ts index 40740798..bdb044de 100644 --- a/packages/arcodesign/components/style.ts +++ b/packages/arcodesign/components/style.ts @@ -44,6 +44,7 @@ import './pull-refresh/style'; import './radio/style'; import './rate/style'; import './search-bar/style'; +import './skeleton/style'; import './show-monitor/style'; import './slider/style'; import './stepper/style'; diff --git a/packages/arcodesign/tokens/app/arcodesign/default/css-variables.less b/packages/arcodesign/tokens/app/arcodesign/default/css-variables.less index 9f16beae..4b1ea3e3 100644 --- a/packages/arcodesign/tokens/app/arcodesign/default/css-variables.less +++ b/packages/arcodesign/tokens/app/arcodesign/default/css-variables.less @@ -793,4 +793,20 @@ --divider-right-width: ~`pxtorem(28)`; --divider-content-padding: ~`pxtorem(12)`; --divider-padding: ~`pxtorem(16)`; + --skeleton-border-radius: ~`pxtorem(0)`; + --skeleton-background-color: #F2F3F5; + --skeleton-gradient-animation-color: rgba(255, 255, 255, 0.6); + --skeleton-breath-opacity: 0.4; + --skeleton-gradient-animation-timing-function: cubic-bezier(0.42, 0, 0.58, 1); + --skeleton-gradient-animation-duration: 1.5s; + --skeleton-breath-animation-duration: 1.5s; + --skeleton-title-height: ~`pxtorem(16)`; + --skeleton-paragraph-height: ~`pxtorem(16)`; + --skeleton-paragraph-margin-top: ~`pxtorem(12)`; + --skeleton-avatar-size: ~`pxtorem(32)`; + --skeleton-grid-icon-size: ~`pxtorem(32)`; + --skeleton-grid-text-width: ~`pxtorem(64)`; + --skeleton-grid-text-height: ~`pxtorem(16)`; + --skeleton-medium-gutter: ~`pxtorem(8)`; + --skeleton-large-gutter: ~`pxtorem(20)`; } diff --git a/packages/arcodesign/tokens/app/arcodesign/default/index.d.ts b/packages/arcodesign/tokens/app/arcodesign/default/index.d.ts index 69b0c649..5f111f56 100644 --- a/packages/arcodesign/tokens/app/arcodesign/default/index.d.ts +++ b/packages/arcodesign/tokens/app/arcodesign/default/index.d.ts @@ -792,6 +792,22 @@ export interface ArcodesignToken extends Record<string, string> { 'divider-right-width': string; 'divider-content-padding': string; 'divider-padding': string; + 'skeleton-border-radius': string; + 'skeleton-background-color': string; + 'skeleton-gradient-animation-color': string; + 'skeleton-breath-opacity': string; + 'skeleton-gradient-animation-timing-function': string; + 'skeleton-gradient-animation-duration': string; + 'skeleton-breath-animation-duration': string; + 'skeleton-title-height': string; + 'skeleton-paragraph-height': string; + 'skeleton-paragraph-margin-top': string; + 'skeleton-avatar-size': string; + 'skeleton-grid-icon-size': string; + 'skeleton-grid-text-width': string; + 'skeleton-grid-text-height': string; + 'skeleton-medium-gutter': string; + 'skeleton-large-gutter': string; } declare const tokens: ArcodesignToken; export default tokens; \ No newline at end of file diff --git a/packages/arcodesign/tokens/app/arcodesign/default/index.js b/packages/arcodesign/tokens/app/arcodesign/default/index.js index f48a7f69..bdbb81a6 100644 --- a/packages/arcodesign/tokens/app/arcodesign/default/index.js +++ b/packages/arcodesign/tokens/app/arcodesign/default/index.js @@ -803,7 +803,23 @@ var tokens = { "divider-left-width": "0.56rem", "divider-right-width": "0.56rem", "divider-content-padding": "0.24rem", - "divider-padding": "0.32rem" + "divider-padding": "0.32rem", + "skeleton-border-radius": "0", + "skeleton-background-color": "#F2F3F5", + "skeleton-gradient-animation-color": "rgba(255, 255, 255, 0.6)", + "skeleton-breath-opacity": "0.4", + "skeleton-gradient-animation-timing-function": "cubic-bezier(0.42, 0, 0.58, 1)", + "skeleton-gradient-animation-duration": "1.5s", + "skeleton-breath-animation-duration": "1.5s", + "skeleton-title-height": "0.32rem", + "skeleton-paragraph-height": "0.32rem", + "skeleton-paragraph-margin-top": "0.24rem", + "skeleton-avatar-size": "0.64rem", + "skeleton-grid-icon-size": "0.64rem", + "skeleton-grid-text-width": "1.28rem", + "skeleton-grid-text-height": "0.32rem", + "skeleton-medium-gutter": "0.16rem", + "skeleton-large-gutter": "0.4rem" }; var _default = tokens; exports["default"] = _default; \ No newline at end of file diff --git a/packages/arcodesign/tokens/app/arcodesign/default/index.json b/packages/arcodesign/tokens/app/arcodesign/default/index.json index 43a012d4..a1f18333 100644 --- a/packages/arcodesign/tokens/app/arcodesign/default/index.json +++ b/packages/arcodesign/tokens/app/arcodesign/default/index.json @@ -6629,6 +6629,196 @@ "en": "Size of the rounded corners of the square SearchBar" } }, + "skeletonAvatarSize": { + "cssKey": "skeleton-avatar-size", + "desc": "骨架屏头像大小", + "override": "", + "value": "~`pxtorem(32)`", + "jsValue": "@getRem@32", + "staticValue": "0.64rem", + "localeDesc": { + "ch": "骨架屏头像大小", + "en": "Skeleton avatar size" + } + }, + "skeletonBackgroundColor": { + "cssKey": "skeleton-background-color", + "desc": "骨架屏元素背景色", + "override": "", + "value": "#F2F3F5", + "jsValue": "#F2F3F5", + "staticValue": "#F2F3F5", + "localeDesc": { + "ch": "骨架屏元素背景色", + "en": "Skeleton element background color" + } + }, + "skeletonBorderRadius": { + "cssKey": "skeleton-border-radius", + "desc": "骨架屏元素圆角", + "override": "", + "value": "~`pxtorem(0)`", + "jsValue": "@getRem@0", + "staticValue": "0", + "localeDesc": { + "ch": "骨架屏元素圆角", + "en": "Skeleton element border radius" + } + }, + "skeletonBreathAnimationDuration": { + "cssKey": "skeleton-breath-animation-duration", + "desc": "骨架屏呼吸动效时间", + "override": "", + "value": "1.5s", + "jsValue": "1.5s", + "staticValue": "1.5s", + "localeDesc": { + "ch": "骨架屏呼吸动效时间", + "en": "Skeleton element breath animation duration" + } + }, + "skeletonBreathOpacity": { + "cssKey": "skeleton-breath-opacity", + "desc": "骨架屏呼吸动效透明度", + "override": "", + "value": "0.4", + "jsValue": "0.4", + "staticValue": "0.4", + "localeDesc": { + "ch": "骨架屏呼吸动效透明度", + "en": "Skeleton element breath animation opacity" + } + }, + "skeletonGradientAnimationColor": { + "cssKey": "skeleton-gradient-animation-color", + "desc": "骨架屏扫光动效高亮色", + "override": "", + "value": "rgba(255, 255, 255, 0.6)", + "jsValue": "rgba(255, 255, 255, 0.6)", + "staticValue": "rgba(255, 255, 255, 0.6)", + "localeDesc": { + "ch": "骨架屏扫光动效高亮色", + "en": "Skeleton element gradient animation highlight color" + } + }, + "skeletonGradientAnimationDuration": { + "cssKey": "skeleton-gradient-animation-duration", + "desc": "骨架屏扫光动效时间", + "override": "", + "value": "1.5s", + "jsValue": "1.5s", + "staticValue": "1.5s", + "localeDesc": { + "ch": "骨架屏扫光动效时间", + "en": "Skeleton element gradient animation duration" + } + }, + "skeletonGradientAnimationTimingFunction": { + "cssKey": "skeleton-gradient-animation-timing-function", + "desc": "骨架屏扫光动效曲线", + "override": "", + "value": "cubic-bezier(0.42, 0, 0.58, 1)", + "jsValue": "cubic-bezier(0.42, 0, 0.58, 1)", + "staticValue": "cubic-bezier(0.42, 0, 0.58, 1)", + "localeDesc": { + "ch": "骨架屏扫光动效曲线", + "en": "Skeleton element gradient animation timing function" + } + }, + "skeletonGridIconSize": { + "cssKey": "skeleton-grid-icon-size", + "desc": "骨架屏金刚位图标区宽度", + "override": "", + "value": "~`pxtorem(32)`", + "jsValue": "@getRem@32", + "staticValue": "0.64rem", + "localeDesc": { + "ch": "骨架屏金刚位图标区宽度", + "en": "Skeleton grid item icon width" + } + }, + "skeletonGridTextHeight": { + "cssKey": "skeleton-grid-text-height", + "desc": "骨架屏金刚位文字区高度", + "override": "", + "value": "~`pxtorem(16)`", + "jsValue": "@getRem@16", + "staticValue": "0.32rem", + "localeDesc": { + "ch": "骨架屏金刚位文字区高度", + "en": "Skeleton grid item text height" + } + }, + "skeletonGridTextWidth": { + "cssKey": "skeleton-grid-text-width", + "desc": "骨架屏金刚位文字区宽度", + "override": "", + "value": "~`pxtorem(64)`", + "jsValue": "@getRem@64", + "staticValue": "1.28rem", + "localeDesc": { + "ch": "骨架屏金刚位文字区宽度", + "en": "Skeleton grid item text width" + } + }, + "skeletonLargeGutter": { + "cssKey": "skeleton-large-gutter", + "desc": "骨架屏元素外边距,大尺寸", + "override": "", + "value": "~`pxtorem(20)`", + "jsValue": "@getRem@20", + "staticValue": "0.4rem", + "localeDesc": { + "ch": "骨架屏元素外边距,大尺寸" + } + }, + "skeletonMediumGutter": { + "cssKey": "skeleton-medium-gutter", + "desc": "骨架屏元素外边距,中尺寸", + "override": "", + "value": "~`pxtorem(8)`", + "jsValue": "@getRem@8", + "staticValue": "0.16rem", + "localeDesc": { + "ch": "骨架屏元素外边距,中尺寸" + } + }, + "skeletonParagraphHeight": { + "cssKey": "skeleton-paragraph-height", + "desc": "骨架屏段落行高度", + "override": "", + "value": "~`pxtorem(16)`", + "jsValue": "@getRem@16", + "staticValue": "0.32rem", + "localeDesc": { + "ch": "骨架屏段落行高度", + "en": "Skeleton paragraph line height" + } + }, + "skeletonParagraphMarginTop": { + "cssKey": "skeleton-paragraph-margin-top", + "desc": "骨架屏各段落行间距", + "override": "", + "value": "~`pxtorem(12)`", + "jsValue": "@getRem@12", + "staticValue": "0.24rem", + "localeDesc": { + "ch": "骨架屏各段落行间距", + "en": "Margin top between skeleton paragraph lines" + } + }, + "skeletonTitleHeight": { + "cssKey": "skeleton-title-height", + "desc": "骨架屏标题高度", + "override": "", + "value": "~`pxtorem(16)`", + "jsValue": "@getRem@16", + "staticValue": "0.32rem", + "localeDesc": { + "ch": "骨架屏标题高度", + "en": "Skeleton title height" + } + }, "sliderHasMarkPaddingBottom": { "cssKey": "slider-has-mark-padding-bottom", "desc": "slider 有标记时的底部内边距", diff --git a/packages/arcodesign/tokens/app/arcodesign/default/index.less b/packages/arcodesign/tokens/app/arcodesign/default/index.less index 9c3860b9..dc2ab27c 100644 --- a/packages/arcodesign/tokens/app/arcodesign/default/index.less +++ b/packages/arcodesign/tokens/app/arcodesign/default/index.less @@ -792,4 +792,20 @@ @divider-right-width: ~`pxtorem(28)`; @divider-content-padding: ~`pxtorem(12)`; @divider-padding: ~`pxtorem(16)`; +@skeleton-border-radius: ~`pxtorem(0)`; +@skeleton-background-color: #F2F3F5; +@skeleton-gradient-animation-color: rgba(255, 255, 255, 0.6); +@skeleton-breath-opacity: 0.4; +@skeleton-gradient-animation-timing-function: cubic-bezier(0.42, 0, 0.58, 1); +@skeleton-gradient-animation-duration: 1.5s; +@skeleton-breath-animation-duration: 1.5s; +@skeleton-title-height: ~`pxtorem(16)`; +@skeleton-paragraph-height: ~`pxtorem(16)`; +@skeleton-paragraph-margin-top: ~`pxtorem(12)`; +@skeleton-avatar-size: ~`pxtorem(32)`; +@skeleton-grid-icon-size: ~`pxtorem(32)`; +@skeleton-grid-text-width: ~`pxtorem(64)`; +@skeleton-grid-text-height: ~`pxtorem(16)`; +@skeleton-medium-gutter: ~`pxtorem(8)`; +@skeleton-large-gutter: ~`pxtorem(20)`; diff --git a/packages/arcodesign/tokens/src/arcodesign/default/index.js b/packages/arcodesign/tokens/src/arcodesign/default/index.js index 1fcd953f..1a4d7d2d 100644 --- a/packages/arcodesign/tokens/src/arcodesign/default/index.js +++ b/packages/arcodesign/tokens/src/arcodesign/default/index.js @@ -4018,6 +4018,84 @@ function getCompTokens() { * @en Top and Bottom padding of divider */ dividerPadding: getRem(16), + /** + * 骨架屏元素圆角 + * @en Skeleton element border radius + */ + skeletonBorderRadius: getRem(0), + /** + * 骨架屏元素背景色 + * @en Skeleton element background color + */ + skeletonBackgroundColor: '#F2F3F5', + /** + * 骨架屏扫光动效高亮色 + * @en Skeleton element gradient animation highlight color + */ + skeletonGradientAnimationColor: 'rgba(255, 255, 255, 0.6)', + /** + * 骨架屏呼吸动效透明度 + * @en Skeleton element breath animation opacity + */ + skeletonBreathOpacity: '0.4', + /** + * 骨架屏扫光动效曲线 + * @en Skeleton element gradient animation timing function + */ + skeletonGradientAnimationTimingFunction: 'cubic-bezier(0.42, 0, 0.58, 1)', + /** + * 骨架屏扫光动效时间 + * @en Skeleton element gradient animation duration + */ + skeletonGradientAnimationDuration: '1.5s', + /** + * 骨架屏呼吸动效时间 + * @en Skeleton element breath animation duration + */ + skeletonBreathAnimationDuration: '1.5s', + /** + * 骨架屏标题高度 + * @en Skeleton title height + */ + skeletonTitleHeight: getRem(16), + /** + * 骨架屏段落行高度 + * @en Skeleton paragraph line height + */ + skeletonParagraphHeight: getRem(16), + /** + * 骨架屏各段落行间距 + * @en Margin top between skeleton paragraph lines + */ + skeletonParagraphMarginTop: getRem(12), + /** + * 骨架屏头像大小 + * @en Skeleton avatar size + */ + skeletonAvatarSize: getRem(32), + /** + * 骨架屏金刚位图标区宽度 + * @en Skeleton grid item icon width + */ + skeletonGridIconSize: getRem(32), + /** + * 骨架屏金刚位文字区宽度 + * @en Skeleton grid item text width + */ + skeletonGridTextWidth: getRem(64), + /** + * 骨架屏金刚位文字区高度 + * @en Skeleton grid item text height + */ + skeletonGridTextHeight: getRem(16), + /** + * 骨架屏元素外边距,中尺寸 + */ + skeletonMediumGutter: getRem(8), + /** + * 骨架屏元素外边距,大尺寸 + */ + skeletonLargeGutter: getRem(20), }; }