From 1724bcf5ba607f962484b0482e0d408d6da2083f Mon Sep 17 00:00:00 2001 From: anlyyao Date: Fri, 19 Jul 2024 17:12:43 +0800 Subject: [PATCH 1/5] feat(Progress): complete refactoring --- .../utils.ts => _util/linearGradient.ts} | 7 +- src/common.ts | 65 ++++- src/hooks/useDefaultProps.ts | 17 ++ src/progress/Progress.tsx | 236 +++++++++++++++--- src/progress/constants.ts | 19 ++ src/progress/defaultProps.ts | 2 +- src/progress/index.tsx | 1 + src/progress/progress.en-US.md | 17 ++ src/progress/progress.md | 12 +- src/progress/type.ts | 9 +- 10 files changed, 326 insertions(+), 59 deletions(-) rename src/{progress/utils.ts => _util/linearGradient.ts} (80%) create mode 100644 src/hooks/useDefaultProps.ts create mode 100644 src/progress/constants.ts create mode 100644 src/progress/progress.en-US.md diff --git a/src/progress/utils.ts b/src/_util/linearGradient.ts similarity index 80% rename from src/progress/utils.ts rename to src/_util/linearGradient.ts index 157fd72c..6b27fa3a 100644 --- a/src/progress/utils.ts +++ b/src/_util/linearGradient.ts @@ -1,7 +1,7 @@ export type Gradients = { [percent: string]: string }; export type FromTo = { from: string; to: string }; export type LinearGradient = { direction?: string } & (Gradients | FromTo); -export function getBackgroundColor(color: string | string[] | LinearGradient): string { +const getBackgroundColor = (color: string | string[] | LinearGradient): string => { if (typeof color === 'string') { return color; } @@ -15,8 +15,9 @@ export function getBackgroundColor(color: string | string[] | LinearGradient): s let keys = Object.keys(rest); if (keys.length) { keys = keys.sort((a, b) => parseFloat(a.substr(0, a.length - 1)) - parseFloat(b.substr(0, b.length - 1))); - const tempArr = keys.map((key: any) => `${rest[key]} ${key}`); + const tempArr = keys.map((key) => `${rest[key]} ${key}`); return `linear-gradient(${direction}, ${tempArr.join(',')})`; } return `linear-gradient(${direction}, ${from}, ${to})`; -} +}; +export default getBackgroundColor; diff --git a/src/common.ts b/src/common.ts index f949e7d4..89c59d0e 100644 --- a/src/common.ts +++ b/src/common.ts @@ -1,9 +1,9 @@ /** React 特有全局类型 */ -import { ReactElement, ReactNode, CSSProperties, FormEvent } from 'react'; +import { ReactElement, ReactNode, CSSProperties, FormEvent, DragEvent, SyntheticEvent } from 'react'; // TElement 表示 API 只接受传入组件 -export type TElement = ReactElement | (() => ReactElement); +export type TElement = T extends undefined ? ReactElement : (props: T) => ReactElement; // 1. TNode = ReactNode; 2. TNode = (props: T) => ReactNode export type TNode = T extends undefined ? ReactNode : (props: T) => ReactNode; @@ -26,16 +26,37 @@ export interface StyledProps { className?: string; style?: CSSProperties; } -/** 通用全局类型 */ + +export interface UploadDisplayDragEvents { + onDrop?: (event: DragEvent) => void; + onDragEnter?: (event: DragEvent) => void; + onDragOver?: (event: DragEvent) => void; + onDragLeave?: (event: DragEvent) => void; +} + +export type ImageEvent = SyntheticEvent; + +/** + * 通用全局类型 + * */ +export type PlainObject = { [key: string]: any }; export type OptionData = { label?: string; value?: string | number; -} & { [key: string]: any }; - -export type TreeOptionData = { - children?: Array; -} & OptionData; +} & PlainObject; + +export type TreeOptionData = { + children?: Array> | boolean; + /** option label content */ + label?: string | TNode; + /** option search text */ + text?: string; + /** option value */ + value?: T; + /** option node content */ + content?: string | TNode; +} & PlainObject; export type SizeEnum = 'small' | 'medium' | 'large'; @@ -43,6 +64,8 @@ export type HorizontalAlignEnum = 'left' | 'center' | 'right'; export type VerticalAlignEnum = 'top' | 'middle' | 'bottom'; +export type LayoutEnum = 'vertical' | 'horizontal'; + export type ClassName = { [className: string]: any } | ClassName[] | string; export type CSSSelector = string; @@ -50,10 +73,15 @@ export type CSSSelector = string; export interface KeysType { value?: string; label?: string; + disabled?: string; +} + +export interface TreeKeysType extends KeysType { + children?: string; } export interface HTMLElementAttributes { - [css: string]: string; + [attribute: string]: string; } export interface TScroll { @@ -81,3 +109,22 @@ export interface TScroll { */ type: 'lazy' | 'virtual'; } + +/** + * @deprecated use TScroll instead + */ +export type InfinityScroll = TScroll; + +export interface ScrollToElementParams { + /** 跳转元素下标 */ + index?: number; + /** 跳转元素距离顶部的距离 */ + top?: number; + /** 单个元素高度非固定场景下,即 isFixedRowHeight = false。延迟设置元素位置,一般用于依赖不同高度异步渲染等场景,单位:毫秒 */ + time?: number; + behavior?: 'auto' | 'smooth'; +} + +export interface ComponentScrollToElementParams extends ScrollToElementParams { + key?: string | number; +} diff --git a/src/hooks/useDefaultProps.ts b/src/hooks/useDefaultProps.ts new file mode 100644 index 00000000..3f7d5c41 --- /dev/null +++ b/src/hooks/useDefaultProps.ts @@ -0,0 +1,17 @@ +import { useMemo } from 'react'; + +// defaultProps 将于 18.3.0 废弃,故需实现 hook 在组件内部兼容 +// https://github.com/facebook/react/pull/16210 +export default function useDefaultProps(originalProps: T, defaultProps: Record): T { + return useMemo(() => { + // eslint-disable-next-line + const props = Object.assign({}, originalProps); + Object.keys(defaultProps).forEach((key) => { + // https://github.com/facebook/react/blob/main/packages/react/src/jsx/ReactJSXElement.js#L719-L722 + if (props[key] === undefined) { + props[key] = defaultProps[key]; + } + }); + return props; + }, [originalProps, defaultProps]); +} diff --git a/src/progress/Progress.tsx b/src/progress/Progress.tsx index 35ebf979..eb761599 100644 --- a/src/progress/Progress.tsx +++ b/src/progress/Progress.tsx @@ -1,61 +1,215 @@ -import React, { FC, useMemo } from 'react'; -import classnames from 'classnames'; -import withNativeProps, { NativeProps } from '../_util/withNativeProps'; +import React, { forwardRef } from 'react'; +import classNames from 'classnames'; +import { + CloseIcon, + CheckIcon, + ErrorIcon, + CheckCircleFilledIcon, + CloseCircleFilledIcon, + ErrorCircleFilledIcon, +} from 'tdesign-icons-react'; +import isString from 'lodash/isString'; +import { StyledProps } from '../common'; import { TdProgressProps } from './type'; import useConfig from '../_util/useConfig'; +import getBackgroundColor from '../_util/linearGradient'; import { progressDefaultProps } from './defaultProps'; -import { getBackgroundColor } from './utils'; +import useDefaultProps from '../hooks/useDefaultProps'; +import { PRO_THEME, CIRCLE_SIZE_PX, STATUS_ICON, PLUMP_SEPARATE } from './constants'; -export interface ProgressProps extends TdProgressProps, NativeProps {} - -const Progress: FC = (props) => { - const { children, percentage, strokeWidth, trackColor, color, label, status } = props; +export interface ProgressProps extends TdProgressProps, StyledProps {} +const Progress = forwardRef((props, ref) => { const { classPrefix } = useConfig(); + const progressClass = `${classPrefix}-progress`; - const name = `${classPrefix}-progress`; + const { + theme, + percentage, + label, + color = '', + trackColor, + strokeWidth, + className, + style, + status, + } = useDefaultProps(props, progressDefaultProps); - const progressPercent = Math.max(0, Math.min(percentage, 100)); + const computedStatus = percentage >= 100 ? 'success' : status || 'default'; + const statusClassName = `${progressClass}--status-${computedStatus}`; - const progressStatusStyle = useMemo(() => { - if (percentage >= 100) { - return 'success'; - } - return status; - }, [percentage, status]); - - const progressBarStyle = useMemo(() => { - const height = typeof strokeWidth === 'string' ? strokeWidth : `${strokeWidth}px`; - return { - height, - backgroundColor: trackColor, + const getIconMap = () => { + const CIRCLE_ICONS = { + success: CheckIcon, + warning: ErrorIcon, + error: CloseIcon, }; - }, [strokeWidth, trackColor]); + const NORMAL_ICONS = { + success: CheckCircleFilledIcon, + warning: ErrorCircleFilledIcon, + error: CloseCircleFilledIcon, + }; + return props.theme === PRO_THEME.CIRCLE ? CIRCLE_ICONS : NORMAL_ICONS; + }; + + // 进度条展示内容 + const getInfoContent = () => { + if (!label) { + return ''; + } + let info: React.ReactNode; + // 为布尔值,默认百分百展示,否则之间展示 label 内容 + if (typeof label === 'boolean') { + info =
{`${percentage}%`}
; + if (STATUS_ICON.includes(status) && theme !== PRO_THEME.PLUMP) { + const icons = getIconMap(); + const Icon = icons[status]; + info = ( +
+ +
+ ); + } + } else { + info =
{label}
; + } + return info; + }; - const progressBarPercenStyle = { - width: `${progressPercent}%`, - background: color && getBackgroundColor(color), + // 进度条轨道高度 + const getHeight = (): string => { + if (strokeWidth) { + return isString(strokeWidth) ? strokeWidth : `${strokeWidth}px`; + } }; - const labelDom = useMemo(() => { - if (!label) return null; - return children || `${progressPercent}%`; - }, [label, children, progressPercent]); - - return withNativeProps( - props, -
-
-
-
+ const trackStyle = () => { + const style: React.CSSProperties = {}; + if (strokeWidth) { + const height = getHeight(); + style.height = height; + style.borderRadius = height; + } + if (trackColor) { + style.backgroundColor = trackColor; + } + return style; + }; + + const barStyle = { + width: `${percentage}%`, + background: getBackgroundColor(color), + } as React.CSSProperties; + + let progressDom: React.ReactNode; + + if (theme === PRO_THEME.PLUMP) { + const separateClasses = percentage > PLUMP_SEPARATE ? `${progressClass}--over-ten` : `${progressClass}--under-ten`; + + progressDom = ( +
+
+ {percentage > PLUMP_SEPARATE && getInfoContent()}
-
{labelDom}
+ + {percentage <= PLUMP_SEPARATE && getInfoContent()}
-
, + ); + } else if (theme === PRO_THEME.CIRCLE) { + // 获取环形进度条 环的宽度 + const getCircleStokeWidth = (): number => (strokeWidth ? Number(strokeWidth) : 6); + // 环形进度条尺寸(进度条占位空间,长宽占位) + const circleStokeWidth = getCircleStokeWidth(); + // 直径 + const diameter = CIRCLE_SIZE_PX; + // 半径 + const radius = diameter / 2; + // 内环半径 + const innerRadius = radius - circleStokeWidth; + + const perimeter = Math.PI * 2 * radius; + const percent = percentage / 100; + const strokeDasharray = `${perimeter * percent} ${perimeter * (1 - percent)}`; + + // 自适应文字,根据半路,适度调整 + const fontSizeRatio = innerRadius * 0.27; + + const circleBoxStyle = () => { + if (theme !== PRO_THEME.CIRCLE) return {}; + return { + width: diameter, + height: diameter, + fontSize: 4 + fontSizeRatio, + }; + }; + const circlePathStyle = { + stroke: color, + strokeLinecap: circleStokeWidth < 30 ? 'round' : 'buff', + } as React.CSSProperties; + + const circleCenterInViewBox = radius + circleStokeWidth / 2; + + progressDom = ( +
+ {getInfoContent()} + + + {percentage > 0 && ( + + )} + +
+ ); + return
{progressDom}
; + } else { + progressDom = ( +
+
+
+
+ {getInfoContent()} +
+ ); + } + + return ( +
+ {progressDom} +
); -}; +}); Progress.displayName = 'Progress'; -Progress.defaultProps = progressDefaultProps; export default Progress; diff --git a/src/progress/constants.ts b/src/progress/constants.ts new file mode 100644 index 00000000..9ffc30bf --- /dev/null +++ b/src/progress/constants.ts @@ -0,0 +1,19 @@ +export const PRO_THEME = { + LINE: 'line', + PLUMP: 'plump', + CIRCLE: 'circle', +}; + +export const CIRCLE_SIZE_PX = 112; + +export const STATUS_ICON = ['success', 'error', 'warning']; + +// 进度大于 10 ,进度百分比显示在内部;进度百分比小于 10 进度显示在外部 +export const PLUMP_SEPARATE = 10; + +export default { + PRO_THEME, + CIRCLE_SIZE_PX, + STATUS_ICON, + PLUMP_SEPARATE, +}; diff --git a/src/progress/defaultProps.ts b/src/progress/defaultProps.ts index f02c8470..14bcdfb2 100644 --- a/src/progress/defaultProps.ts +++ b/src/progress/defaultProps.ts @@ -8,6 +8,6 @@ export const progressDefaultProps: TdProgressProps = { color: '', label: true, percentage: 0, - status: 'active', + theme: 'line', trackColor: '', }; diff --git a/src/progress/index.tsx b/src/progress/index.tsx index 134db9e9..eef8c17e 100644 --- a/src/progress/index.tsx +++ b/src/progress/index.tsx @@ -2,6 +2,7 @@ import _Progress from './Progress'; import './style'; +export type { ProgressProps } from './Progress'; export * from './type'; export const Progress = _Progress; diff --git a/src/progress/progress.en-US.md b/src/progress/progress.en-US.md new file mode 100644 index 00000000..b55a738f --- /dev/null +++ b/src/progress/progress.en-US.md @@ -0,0 +1,17 @@ +:: BASE_DOC :: + +## API + +### Progress Props + +name | type | default | description | required +-- | -- | -- | -- | -- +className | String | - | className of component | N +style | Object | - | CSS(Cascading Style Sheets),Typescript:`React.CSSProperties` | N +color | String / Object / Array | '' | Typescript:`string \| Array \| Record` | N +label | TNode | true | Typescript:`string \| boolean \| TNode`。[see more ts definition](https://github.com/TDesignOteam/tdesign-mobile-react/blob/develop/src/common.ts) | N +percentage | Number | 0 | \- | N +status | String | - | options: success/error/warning/active。Typescript:`StatusEnum` `type StatusEnum = 'success' \| 'error' \| 'warning' \| 'active'`。[see more ts definition](https://github.com/TDesignOteam/tdesign-mobile-react/tree/develop/src/progress/type.ts) | N +strokeWidth | String / Number | - | \- | N +theme | String | line | options: line/plump/circle。Typescript:`ThemeEnum` `type ThemeEnum = 'line' \| 'plump' \| 'circle'`。[see more ts definition](https://github.com/TDesignOteam/tdesign-mobile-react/tree/develop/src/progress/type.ts) | N +trackColor | String | '' | \- | N diff --git a/src/progress/progress.md b/src/progress/progress.md index 44180150..4e04e3b3 100644 --- a/src/progress/progress.md +++ b/src/progress/progress.md @@ -1,13 +1,17 @@ :: BASE_DOC :: ## API + ### Progress Props -名称 | 类型 | 默认值 | 说明 | 必传 +名称 | 类型 | 默认值 | 描述 | 必传 -- | -- | -- | -- | -- -color | String / Object / Array | '' | 进度条颜色。示例:'#ED7B2F' 或 'orange' 或 `['#f00', '#0ff', '#f0f']` 或 `{ '0%': '#f00', '100%': '#0ff' }` 或 `{ from: '#000', to: '#000' }` 等。TS 类型:`string | Array | Record` | N -label | String / Boolean / Slot / Function | true | 进度百分比,可自定义。TS 类型:`string | boolean | TNode`。[通用类型定义](https://github.com/Tencent/tdesign-mobile-vue/blob/develop/src/common.ts) | N +className | String | - | 类名 | N +style | Object | - | 样式,TS 类型:`React.CSSProperties` | N +color | String / Object / Array | '' | 进度条颜色。示例:'#ED7B2F' 或 'orange' 或 `['#f00', '#0ff', '#f0f']` 或 `{ '0%': '#f00', '100%': '#0ff' }` 或 `{ from: '#000', to: '#000' }` 等。TS 类型:`string \| Array \| Record` | N +label | TNode | true | 进度百分比,可自定义。TS 类型:`string \| boolean \| TNode`。[通用类型定义](https://github.com/TDesignOteam/tdesign-mobile-react/blob/develop/src/common.ts) | N percentage | Number | 0 | 进度条百分比 | N -status | String | - | 进度条状态。可选项:success/error/warning/active。TS 类型:`StatusEnum` `type StatusEnum = 'success' | 'error' | 'warning' | 'active'`。[详细类型定义](https://github.com/Tencent/tdesign-mobile-vue/tree/develop/src/progress/type.ts) | N +status | String | - | 进度条状态。可选项:success/error/warning/active。TS 类型:`StatusEnum` `type StatusEnum = 'success' \| 'error' \| 'warning' \| 'active'`。[详细类型定义](https://github.com/TDesignOteam/tdesign-mobile-react/tree/develop/src/progress/type.ts) | N strokeWidth | String / Number | - | 进度条线宽。宽度数值不能超过 size 的一半,否则不能输出环形进度 | N +theme | String | line | 进度条风格。值为 line,标签(label)显示在进度条右侧;值为 plump,标签(label)显示在进度条里面;值为 circle,标签(label)显示在进度条正中间。可选项:line/plump/circle。TS 类型:`ThemeEnum` `type ThemeEnum = 'line' \| 'plump' \| 'circle'`。[详细类型定义](https://github.com/TDesignOteam/tdesign-mobile-react/tree/develop/src/progress/type.ts) | N trackColor | String | '' | 进度条未完成部分颜色 | N diff --git a/src/progress/type.ts b/src/progress/type.ts index 5903eddb..06f6be08 100644 --- a/src/progress/type.ts +++ b/src/progress/type.ts @@ -16,7 +16,7 @@ export interface TdProgressProps { * 进度百分比,可自定义 * @default true */ - label?: string | boolean | TNode; + label?: TNode; /** * 进度条百分比 * @default 0 @@ -30,6 +30,11 @@ export interface TdProgressProps { * 进度条线宽。宽度数值不能超过 size 的一半,否则不能输出环形进度 */ strokeWidth?: string | number; + /** + * 进度条风格。值为 line,标签(label)显示在进度条右侧;值为 plump,标签(label)显示在进度条里面;值为 circle,标签(label)显示在进度条正中间 + * @default line + */ + theme?: ThemeEnum; /** * 进度条未完成部分颜色 * @default '' @@ -38,3 +43,5 @@ export interface TdProgressProps { } export type StatusEnum = 'success' | 'error' | 'warning' | 'active'; + +export type ThemeEnum = 'line' | 'plump' | 'circle'; From e9bf3b420a4661601cbe53ebaac3e5d2048c9145 Mon Sep 17 00:00:00 2001 From: anlyyao Date: Fri, 19 Jul 2024 17:13:26 +0800 Subject: [PATCH 2/5] feat(Progress): update demo --- site/mobile/components/DemoBlock.jsx | 24 +++++-- site/mobile/main.jsx | 2 +- site/style/mobile/demo.less | 93 +++++++++++++++++--------- src/_common | 2 +- src/progress/_example/base.jsx | 14 ++-- src/progress/_example/circle.jsx | 23 +++++++ src/progress/_example/custom.jsx | 7 +- src/progress/_example/index.jsx | 28 ++++---- src/progress/_example/line.jsx | 23 +++++++ src/progress/_example/noText.jsx | 13 ---- src/progress/_example/plump.jsx | 23 +++++++ src/progress/_example/status.jsx | 55 --------------- src/progress/_example/strokeWidth.jsx | 13 ---- src/progress/_example/style/index.less | 35 ++++------ src/progress/_example/transition.jsx | 31 +++++++++ 15 files changed, 224 insertions(+), 162 deletions(-) create mode 100644 src/progress/_example/circle.jsx create mode 100644 src/progress/_example/line.jsx delete mode 100644 src/progress/_example/noText.jsx create mode 100644 src/progress/_example/plump.jsx delete mode 100644 src/progress/_example/status.jsx delete mode 100644 src/progress/_example/strokeWidth.jsx create mode 100644 src/progress/_example/transition.jsx diff --git a/site/mobile/components/DemoBlock.jsx b/site/mobile/components/DemoBlock.jsx index c00784a4..35672591 100644 --- a/site/mobile/components/DemoBlock.jsx +++ b/site/mobile/components/DemoBlock.jsx @@ -1,14 +1,28 @@ import React from 'react'; +import classNames from 'classnames'; import './style/index.less'; const TDemoBlock = (prop) => { - const { children, title, summary } = prop; + const { title, summary, padding, children } = prop; + return ( <> -
- {title &&

{title}

} - {summary &&

{summary}

} - {children} +
+ {(title || summary) && ( +
+ {title &&

{title}

} + {summary && ( +

+ {summary} +

+ )} +
+ )} +
{children}
); diff --git a/site/mobile/main.jsx b/site/mobile/main.jsx index a30c83e3..953e9aba 100644 --- a/site/mobile/main.jsx +++ b/site/mobile/main.jsx @@ -1,7 +1,7 @@ import React from 'react'; import ReactDOM from 'react-dom'; import App from './App'; -import '../style/mobile/index.less' +import '../style/mobile/index.less'; import '../../src/_common/style/mobile/_reset.less'; import '../../src/_common/style/mobile/index.less'; diff --git a/site/style/mobile/demo.less b/site/style/mobile/demo.less index 18b632c5..db2b19d7 100644 --- a/site/style/mobile/demo.less +++ b/site/style/mobile/demo.less @@ -1,46 +1,77 @@ .tdesign-mobile-demo { - background-color: #F6F6F6; - font-family: "PingFang SC"; + background-color: #f6f6f6; + font-family: 'PingFang SC'; + padding-bottom: 28px; + box-sizing: border-box; - &-header { - &__title { - padding: 24px 16px 8px 16px; - opacity: 1; - color: rgba(0, 0, 0, 0.9); - font-size: 20px; - font-weight: 700; - line-height: 28px; - } - - &__summary { - opacity: 1; - color: rgba(0, 0, 0, 0.4); - font-size: 12px; - line-height: 22px; - padding: 0 16px; - } + .title { + font-size: 24px; + font-weight: 700; + line-height: 32px; + padding: 24px 16px 0; + color: rgba(0, 0, 0, 0.9); + } + + .summary { + font-size: 14px; + color: rgba(0, 0, 0, 0.6); + margin: 8px 16px 0; + line-height: 22px; } - &-block { - width: 100%; + margin: 32px 0 0; - &__title { - padding: 24px 16px 0; - font-size: 16px; - font-weight: 700; + &__header { + color: #000; + margin: 0 16px; } - &__title + &__summary { - padding: 8px 16px 16px; + &__title { + font-weight: 700; + font-size: 18px; + line-height: 26px; } &__summary { - opacity: 1; - color: rgba(0, 0, 0, 0.4); - font-size: 12px; + margin-top: 8px; + font-size: 14px; + white-space: pre-line; + color: rgba(0, 0, 0, 0.6); line-height: 22px; - padding: 16px; } + + &__slot { + margin-top: 16px; + + &.with-padding { + margin: 16px 16px 0; + } + } + } +} + +.tdesign-mobile-demo-block_notitle { + margin-top: 0px; + + .tdesign-mobile-demo-block_subtitle { + margin-top: 24px; + } +} + +.tdesign-mobile-demo-header { + &__title { + font-size: 24px; + font-weight: 700; + line-height: 32px; + padding: 24px 16px 0; + color: rgba(0, 0, 0, 0.9); + } + + &__summary { + font-size: 14px; + color: rgba(0, 0, 0, 0.6); + margin: 8px 16px 0; + line-height: 22px; } } diff --git a/src/_common b/src/_common index ed5ab4d0..3c5e05bc 160000 --- a/src/_common +++ b/src/_common @@ -1 +1 @@ -Subproject commit ed5ab4d03c0c48aa77f332dc96a47aa28b34aff0 +Subproject commit 3c5e05bc628c06ebdac96e99d67119017920f08f diff --git a/src/progress/_example/base.jsx b/src/progress/_example/base.jsx index c1374020..35b1da6c 100644 --- a/src/progress/_example/base.jsx +++ b/src/progress/_example/base.jsx @@ -5,15 +5,15 @@ import './style/index.less'; export default function Base() { return ( -
-
- +
+
+
-
- +
+
-
- +
+
); diff --git a/src/progress/_example/circle.jsx b/src/progress/_example/circle.jsx new file mode 100644 index 00000000..83e19957 --- /dev/null +++ b/src/progress/_example/circle.jsx @@ -0,0 +1,23 @@ +import React from 'react'; +import { Progress } from 'tdesign-mobile-react'; + +import './style/index.less'; + +export default function Circle() { + return ( +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ ); +} diff --git a/src/progress/_example/custom.jsx b/src/progress/_example/custom.jsx index b57e7d40..d9878c3e 100644 --- a/src/progress/_example/custom.jsx +++ b/src/progress/_example/custom.jsx @@ -5,12 +5,15 @@ import './style/index.less'; export default function Custom() { const customPercentage = 88; return ( -
-
+
+
{customPercentage}%
+
+ +
); } diff --git a/src/progress/_example/index.jsx b/src/progress/_example/index.jsx index 9ac40f26..4b5b6b4e 100644 --- a/src/progress/_example/index.jsx +++ b/src/progress/_example/index.jsx @@ -1,11 +1,12 @@ import React from 'react'; import TDemoBlock from '../../../site/mobile/components/DemoBlock'; import TDemoHeader from '../../../site/mobile/components/DemoHeader'; -import BaseDemo from './base' -import NoTextDemo from './noText' +import BaseDemo from './base'; +import TransitionDemo from './transition'; +import LineDemo from './line'; +import PlumpDemo from './plump'; +import CircleDemo from './circle'; import CustomDemo from './custom'; -import StrokeWidthDemo from './strokeWidth' -import StatusDemo from './status' import './style/index.less'; @@ -13,20 +14,23 @@ export default function ProgressDemo() { return (
- + - - + + - + - - + + - - + + + + +
); diff --git a/src/progress/_example/line.jsx b/src/progress/_example/line.jsx new file mode 100644 index 00000000..64889a28 --- /dev/null +++ b/src/progress/_example/line.jsx @@ -0,0 +1,23 @@ +import React from 'react'; +import { Progress } from 'tdesign-mobile-react'; + +import './style/index.less'; + +export default function Line() { + return ( +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ ); +} diff --git a/src/progress/_example/noText.jsx b/src/progress/_example/noText.jsx deleted file mode 100644 index baf6ac00..00000000 --- a/src/progress/_example/noText.jsx +++ /dev/null @@ -1,13 +0,0 @@ -import React from 'react'; -import { Progress } from 'tdesign-mobile-react'; -import './style/index.less'; - -export default function NoText() { - return ( -
-
- -
-
- ); -} diff --git a/src/progress/_example/plump.jsx b/src/progress/_example/plump.jsx new file mode 100644 index 00000000..02497dc6 --- /dev/null +++ b/src/progress/_example/plump.jsx @@ -0,0 +1,23 @@ +import React from 'react'; +import { Progress } from 'tdesign-mobile-react'; + +import './style/index.less'; + +export default function Plump() { + return ( +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ ); +} diff --git a/src/progress/_example/status.jsx b/src/progress/_example/status.jsx deleted file mode 100644 index 2aa3065d..00000000 --- a/src/progress/_example/status.jsx +++ /dev/null @@ -1,55 +0,0 @@ -import React, { useState } from 'react'; -import { Progress, Button } from 'tdesign-mobile-react'; -import TDemoBlock from '../../../site/mobile/components/DemoBlock'; -import './style/index.less'; - -export default function Status() { - const [percentage, setPercentage] = useState(88); - - const clickReduce = () => { - setPercentage((percentage) => Math.max(0, percentage - 10)); - }; - - const clickAdd = () => { - setPercentage((percentage) => Math.min(100, percentage + 10)); - }; - - return ( -
- -
- -
-
- -
- -
-
- -
- -
-
- -
- -
-
- -
- -
- -
- -
-
-
-
- ); -} diff --git a/src/progress/_example/strokeWidth.jsx b/src/progress/_example/strokeWidth.jsx deleted file mode 100644 index ab2100ab..00000000 --- a/src/progress/_example/strokeWidth.jsx +++ /dev/null @@ -1,13 +0,0 @@ -import React from 'react'; -import { Progress } from 'tdesign-mobile-react'; -import './style/index.less'; - -export default function StrokeWidth() { - return ( -
-
- -
-
- ); -} diff --git a/src/progress/_example/style/index.less b/src/progress/_example/style/index.less index 804935f6..424bf597 100644 --- a/src/progress/_example/style/index.less +++ b/src/progress/_example/style/index.less @@ -1,27 +1,18 @@ -.tdesign-mobile-demo.progress { - background-color: #F6F6F6; - +.tdesign-mobile-demo { + background-color: #fff; } -.progress-demo { - padding: 8px 16px; - background-color: #fff; - - .button-group { - display: flex; - justify-content: center; - padding-bottom: 8px; - - .space { - width: 16px; - } - } +.example-progress { + &__item:not(:last-child) { + margin-bottom: 16px; + } - .label--color { - color: #d504d9; + .button-group { + display: flex; + justify-content: center; + padding-bottom: 8px; + .space { + width: 16px; } + } } - -.progress-demo--margin:not(:last-child) { - margin-bottom: 16px; -} \ No newline at end of file diff --git a/src/progress/_example/transition.jsx b/src/progress/_example/transition.jsx new file mode 100644 index 00000000..6c5d7fe8 --- /dev/null +++ b/src/progress/_example/transition.jsx @@ -0,0 +1,31 @@ +import React, { useState } from 'react'; +import { Progress, Button } from 'tdesign-mobile-react'; + +import './style/index.less'; + +export default function TransitionDemo() { + const [percentage, setPercentage] = useState(88); + + const clickReduce = () => { + setPercentage((percentage) => Math.max(0, percentage - 10)); + }; + + const clickAdd = () => { + setPercentage((percentage) => Math.min(100, percentage + 10)); + }; + + return ( +
+ +
+ +
+ +
+
+ ); +} From bbc46840e03f63e072ac583872457281c8129e93 Mon Sep 17 00:00:00 2001 From: anlyyao Date: Fri, 19 Jul 2024 17:13:40 +0800 Subject: [PATCH 3/5] test: add test unit --- site/test-coverage.js | 2 ++ src/progress/__tests__/progress.test.tsx | 43 ++++++++++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 src/progress/__tests__/progress.test.tsx diff --git a/site/test-coverage.js b/site/test-coverage.js index 2a81387f..09049387 100644 --- a/site/test-coverage.js +++ b/site/test-coverage.js @@ -1,4 +1,6 @@ module.exports = { button: { statements: '100%', branches: '66.66%', functions: '100%', lines: '100%' }, configProvider: { statements: '100%', branches: '100%', functions: '100%', lines: '100%' }, + hooks: { statements: '100%', branches: '100%', functions: '100%', lines: '100%' }, + progress: { statements: '84.37%', branches: '56.75%', functions: '85.71%', lines: '85.48%' }, }; diff --git a/src/progress/__tests__/progress.test.tsx b/src/progress/__tests__/progress.test.tsx new file mode 100644 index 00000000..a8396d02 --- /dev/null +++ b/src/progress/__tests__/progress.test.tsx @@ -0,0 +1,43 @@ +import React from 'react'; +import { render, waitFor } from '@test/utils'; +import getBackgroundColor from '../../_util/linearGradient'; +import Progress from '../Progress'; +import { ThemeEnum } from '../type'; + +describe('Progress', () => { + describe('utils/getBackgroundColor', () => { + it('color types', () => { + expect(getBackgroundColor('red')).toEqual('red'); + + expect(getBackgroundColor(['#000', '#fff'])).toEqual('linear-gradient( 90deg,#000,#fff )'); + + expect( + getBackgroundColor({ + '0%': '#f00', + '100%': '#0ff', + }), + ).toEqual('linear-gradient(to right, #f00 0%,#0ff 100%)'); + }); + }); + + describe('props', () => { + test('render theme', async () => { + const testId = 'progress test theme'; + const themes: ThemeEnum[] = ['line', 'plump', 'circle']; + const { getByTestId } = render( +
+ {themes?.map((theme, index) => ( + + ))} +
, + ); + + const instance = await waitFor(() => getByTestId(testId)); + + for (let index = 0; index < themes.length; index++) { + const theme = themes[index]; + expect(() => instance.querySelector(`.t-progress--${theme}`)).toBeTruthy(); + } + }); + }); +}); From bc0a13914883c30686eb5aa18058fa1e3552f3c9 Mon Sep 17 00:00:00 2001 From: anlyyao Date: Fri, 19 Jul 2024 18:38:59 +0800 Subject: [PATCH 4/5] fix: fir cr --- src/_common | 2 +- src/progress/constants.ts | 15 +-------------- 2 files changed, 2 insertions(+), 15 deletions(-) diff --git a/src/_common b/src/_common index 3c5e05bc..1bacc8e9 160000 --- a/src/_common +++ b/src/_common @@ -1 +1 @@ -Subproject commit 3c5e05bc628c06ebdac96e99d67119017920f08f +Subproject commit 1bacc8e91408cca2b26a3ca7b4b13f9bb62d8af2 diff --git a/src/progress/constants.ts b/src/progress/constants.ts index 9ffc30bf..ea01d6a9 100644 --- a/src/progress/constants.ts +++ b/src/progress/constants.ts @@ -1,19 +1,6 @@ -export const PRO_THEME = { - LINE: 'line', - PLUMP: 'plump', - CIRCLE: 'circle', -}; +export { PRO_THEME, STATUS_ICON } from '../_common/js/progress/const'; export const CIRCLE_SIZE_PX = 112; -export const STATUS_ICON = ['success', 'error', 'warning']; - // 进度大于 10 ,进度百分比显示在内部;进度百分比小于 10 进度显示在外部 export const PLUMP_SEPARATE = 10; - -export default { - PRO_THEME, - CIRCLE_SIZE_PX, - STATUS_ICON, - PLUMP_SEPARATE, -}; From 817c59aa5ff567dc6d5cb71c7c195f081c892e2f Mon Sep 17 00:00:00 2001 From: anlyyao Date: Tue, 23 Jul 2024 16:42:34 +0800 Subject: [PATCH 5/5] fix: update api docs --- src/progress/progress.en-US.md | 4 ++-- src/progress/progress.md | 4 ++-- src/progress/type.ts | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/progress/progress.en-US.md b/src/progress/progress.en-US.md index b55a738f..c8d34462 100644 --- a/src/progress/progress.en-US.md +++ b/src/progress/progress.en-US.md @@ -11,7 +11,7 @@ style | Object | - | CSS(Cascading Style Sheets),Typescript:`React.CSSProper color | String / Object / Array | '' | Typescript:`string \| Array \| Record` | N label | TNode | true | Typescript:`string \| boolean \| TNode`。[see more ts definition](https://github.com/TDesignOteam/tdesign-mobile-react/blob/develop/src/common.ts) | N percentage | Number | 0 | \- | N -status | String | - | options: success/error/warning/active。Typescript:`StatusEnum` `type StatusEnum = 'success' \| 'error' \| 'warning' \| 'active'`。[see more ts definition](https://github.com/TDesignOteam/tdesign-mobile-react/tree/develop/src/progress/type.ts) | N +status | String | - | options: success/error/warning/active。Typescript:`ProgressStatus` `type ProgressStatus = 'success' \| 'error' \| 'warning' \| 'active'`。[see more ts definition](https://github.com/TDesignOteam/tdesign-mobile-react/tree/develop/src/progress/type.ts) | N strokeWidth | String / Number | - | \- | N -theme | String | line | options: line/plump/circle。Typescript:`ThemeEnum` `type ThemeEnum = 'line' \| 'plump' \| 'circle'`。[see more ts definition](https://github.com/TDesignOteam/tdesign-mobile-react/tree/develop/src/progress/type.ts) | N +theme | String | line | options: line/plump/circle。Typescript:`ProgressTheme` `type ProgressTheme = 'line' \| 'plump' \| 'circle'`。[see more ts definition](https://github.com/TDesignOteam/tdesign-mobile-react/tree/develop/src/progress/type.ts) | N trackColor | String | '' | \- | N diff --git a/src/progress/progress.md b/src/progress/progress.md index 4e04e3b3..af31cf67 100644 --- a/src/progress/progress.md +++ b/src/progress/progress.md @@ -11,7 +11,7 @@ style | Object | - | 样式,TS 类型:`React.CSSProperties` | N color | String / Object / Array | '' | 进度条颜色。示例:'#ED7B2F' 或 'orange' 或 `['#f00', '#0ff', '#f0f']` 或 `{ '0%': '#f00', '100%': '#0ff' }` 或 `{ from: '#000', to: '#000' }` 等。TS 类型:`string \| Array \| Record` | N label | TNode | true | 进度百分比,可自定义。TS 类型:`string \| boolean \| TNode`。[通用类型定义](https://github.com/TDesignOteam/tdesign-mobile-react/blob/develop/src/common.ts) | N percentage | Number | 0 | 进度条百分比 | N -status | String | - | 进度条状态。可选项:success/error/warning/active。TS 类型:`StatusEnum` `type StatusEnum = 'success' \| 'error' \| 'warning' \| 'active'`。[详细类型定义](https://github.com/TDesignOteam/tdesign-mobile-react/tree/develop/src/progress/type.ts) | N +status | String | - | 进度条状态。可选项:success/error/warning/active。TS 类型:`ProgressStatus` `type ProgressStatus = 'success' \| 'error' \| 'warning' \| 'active'`。[详细类型定义](https://github.com/TDesignOteam/tdesign-mobile-react/tree/develop/src/progress/type.ts) | N strokeWidth | String / Number | - | 进度条线宽。宽度数值不能超过 size 的一半,否则不能输出环形进度 | N -theme | String | line | 进度条风格。值为 line,标签(label)显示在进度条右侧;值为 plump,标签(label)显示在进度条里面;值为 circle,标签(label)显示在进度条正中间。可选项:line/plump/circle。TS 类型:`ThemeEnum` `type ThemeEnum = 'line' \| 'plump' \| 'circle'`。[详细类型定义](https://github.com/TDesignOteam/tdesign-mobile-react/tree/develop/src/progress/type.ts) | N +theme | String | line | 进度条风格。值为 line,标签(label)显示在进度条右侧;值为 plump,标签(label)显示在进度条里面;值为 circle,标签(label)显示在进度条正中间。可选项:line/plump/circle。TS 类型:`ProgressTheme` `type ProgressTheme = 'line' \| 'plump' \| 'circle'`。[详细类型定义](https://github.com/TDesignOteam/tdesign-mobile-react/tree/develop/src/progress/type.ts) | N trackColor | String | '' | 进度条未完成部分颜色 | N diff --git a/src/progress/type.ts b/src/progress/type.ts index 06f6be08..6848ef08 100644 --- a/src/progress/type.ts +++ b/src/progress/type.ts @@ -25,7 +25,7 @@ export interface TdProgressProps { /** * 进度条状态 */ - status?: StatusEnum; + status?: ProgressStatus; /** * 进度条线宽。宽度数值不能超过 size 的一半,否则不能输出环形进度 */ @@ -34,7 +34,7 @@ export interface TdProgressProps { * 进度条风格。值为 line,标签(label)显示在进度条右侧;值为 plump,标签(label)显示在进度条里面;值为 circle,标签(label)显示在进度条正中间 * @default line */ - theme?: ThemeEnum; + theme?: ProgressTheme; /** * 进度条未完成部分颜色 * @default '' @@ -42,6 +42,6 @@ export interface TdProgressProps { trackColor?: string; } -export type StatusEnum = 'success' | 'error' | 'warning' | 'active'; +export type ProgressStatus = 'success' | 'error' | 'warning' | 'active'; -export type ThemeEnum = 'line' | 'plump' | 'circle'; +export type ProgressTheme = 'line' | 'plump' | 'circle';