From 01fb7f156f94e35b1cb08a3977f8ee1a73298c07 Mon Sep 17 00:00:00 2001 From: tangjinzhou <415800467@qq.com> Date: Mon, 12 Jul 2021 16:39:54 +0800 Subject: [PATCH] refactor: progress --- components/_util/hooks/useRef.ts | 6 +- components/progress/Circle.tsx | 47 ++---------- components/progress/Line.tsx | 13 ++-- .../__snapshots__/index.test.js.snap | 12 +++ components/progress/__tests__/index.test.js | 24 +++--- components/progress/progress.tsx | 45 +++++------ components/progress/props.ts | 2 - components/progress/style/index.less | 6 +- .../progress/style/{index.ts => index.tsx} | 0 components/progress/utils.ts | 15 ++-- components/vc-progress/index.ts | 5 +- components/vc-progress/src/Circle.tsx | 6 +- components/vc-progress/src/Line.tsx | 76 +++++++++++-------- components/vc-progress/src/common.ts | 9 +-- package.json | 1 + v2-doc | 2 +- 16 files changed, 133 insertions(+), 136 deletions(-) rename components/progress/style/{index.ts => index.tsx} (100%) diff --git a/components/_util/hooks/useRef.ts b/components/_util/hooks/useRef.ts index 5033e9ea4..86f6512ec 100644 --- a/components/_util/hooks/useRef.ts +++ b/components/_util/hooks/useRef.ts @@ -2,9 +2,9 @@ import type { Ref } from 'vue'; import { onBeforeUpdate, ref } from 'vue'; export type UseRef = [(el: any, key: string | number) => void, Ref]; - +export type Refs = Record; export const useRef = (): UseRef => { - const refs = ref({}); + const refs = ref({}); const setRef = (el: any, key: string | number) => { refs.value[key] = el; }; @@ -13,3 +13,5 @@ export const useRef = (): UseRef => { }); return [setRef, refs]; }; + +export default useRef; diff --git a/components/progress/Circle.tsx b/components/progress/Circle.tsx index 8d8ac2eb4..c2265d354 100644 --- a/components/progress/Circle.tsx +++ b/components/progress/Circle.tsx @@ -1,5 +1,6 @@ import type { CSSProperties, ExtractPropTypes } from 'vue'; import { computed, defineComponent } from 'vue'; +import { presetPrimaryColors } from '@ant-design/colors'; import { Circle as VCCircle } from '../vc-progress'; import { getSuccessPercent, validProgress } from './utils'; import { progressProps } from './props'; @@ -12,39 +13,9 @@ const circleProps = { }; export type CircleProps = Partial>; -const statusColorMap = { - normal: '#108ee9', - exception: '#ff5500', - success: '#87d068', -}; - -function getPercentage( - percent: CircleProps['percent'], - success: CircleProps['success'], - successPercent: CircleProps['successPercent'], -) { - const ptg = validProgress(percent); - const realSuccessPercent = getSuccessPercent(success, successPercent); - if (!realSuccessPercent) { - return ptg; - } - return [ - validProgress(realSuccessPercent), - validProgress(ptg - validProgress(realSuccessPercent)), - ]; -} - -function getStrokeColor( - success: CircleProps['success'], - strokeColor: CircleProps['strokeColor'], - successPercent: CircleProps['successPercent'], -) { - const color = strokeColor || null; - const realSuccessPercent = getSuccessPercent(success, successPercent); - if (!realSuccessPercent) { - return color; - } - return [statusColorMap.success, color]; +function getPercentage({ percent, success, successPercent }: CircleProps) { + const realSuccessPercent = validProgress(getSuccessPercent({ success, successPercent })); + return [realSuccessPercent, validProgress(validProgress(percent) - realSuccessPercent)]; } export default defineComponent({ @@ -77,14 +48,10 @@ export default defineComponent({ ); // using className to style stroke color - const strokeColor = computed(() => - getStrokeColor(props.success, props.strokeColor, props.successPercent), - ); - const percent = computed(() => - getPercentage(props.percent, props.success, props.successPercent), - ); + const strokeColor = computed(() => [presetPrimaryColors.green, props.strokeColor || null]); + const percent = computed(() => getPercentage(props)); const isGradient = computed( - () => Object.prototype.toString.call(strokeColor.value) === '[object Object]', + () => Object.prototype.toString.call(props.strokeColor) === '[object Object]', ); const wrapperClassName = computed(() => ({ diff --git a/components/progress/Line.tsx b/components/progress/Line.tsx index ca01f8671..df9bfe42c 100644 --- a/components/progress/Line.tsx +++ b/components/progress/Line.tsx @@ -69,6 +69,7 @@ export const handleGradient = (strokeColor: ProgressGradient, directionConfig: D export default defineComponent({ props: lineProps, + name: 'Line', setup(props, { slots }) { const backgroundProps = computed(() => { const { strokeColor, direction } = props; @@ -98,7 +99,7 @@ export default defineComponent({ }); const successPercent = computed(() => { - return getSuccessPercent(props.success, props.successPercent); + return getSuccessPercent(props); }); const successPercentStyle = computed(() => { const { strokeWidth, size, strokeLinecap, success } = props; @@ -110,18 +111,14 @@ export default defineComponent({ }; }); - const successSegment = computed(() => - successPercent.value !== undefined ? ( -
- ) : null, - ); - return () => ( <>
- {successSegment.value} + {successPercent.value !== undefined ? ( +
+ ) : null}
{slots.default?.()} diff --git a/components/progress/__tests__/__snapshots__/index.test.js.snap b/components/progress/__tests__/__snapshots__/index.test.js.snap index cc19fbf18..0f52246db 100644 --- a/components/progress/__tests__/__snapshots__/index.test.js.snap +++ b/components/progress/__tests__/__snapshots__/index.test.js.snap @@ -10,6 +10,9 @@ exports[`Progress render dashboard 295 gapDegree 1`] = ` + 0%
`; @@ -24,6 +27,9 @@ exports[`Progress render dashboard 296 gapDegree 1`] = ` + 0%
`; @@ -38,6 +44,9 @@ exports[`Progress render dashboard zero gapDegree 1`] = ` + 0% `; @@ -118,6 +127,9 @@ exports[`Progress render strokeColor 1`] = ` + 50% `; diff --git a/components/progress/__tests__/index.test.js b/components/progress/__tests__/index.test.js index 218521be3..2694a167f 100644 --- a/components/progress/__tests__/index.test.js +++ b/components/progress/__tests__/index.test.js @@ -82,7 +82,7 @@ describe('Progress', () => { const wrapper = mount(Progress, { props: { percent: 50, - successPercent: 10, + success: { percent: 10 }, format: (percent, successPercent) => `${percent} ${successPercent}`, }, sync: false, @@ -213,17 +213,17 @@ describe('Progress', () => { expect(wrapper.findAll('.ant-progress-status-success')).toHaveLength(1); }); - // https://github.com/ant-design/ant-design/pull/15951#discussion_r273062969 - it('should show success status when status is invalid', () => { - const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {}); - const wrapper = mount({ - render() { - return ; - }, - }); - expect(wrapper.findAll('.ant-progress-status-success')).toHaveLength(1); - errorSpy.mockRestore(); - }); + // // https://github.com/ant-design/ant-design/pull/15951#discussion_r273062969 + // it('should show success status when status is invalid', () => { + // const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {}); + // const wrapper = mount({ + // render() { + // return ; + // }, + // }); + // expect(wrapper.findAll('.ant-progress-status-success')).toHaveLength(1); + // errorSpy.mockRestore(); + // }); it('should support steps', () => { const wrapper = mount({ diff --git a/components/progress/progress.tsx b/components/progress/progress.tsx index c8d2e1c70..668470e9e 100644 --- a/components/progress/progress.tsx +++ b/components/progress/progress.tsx @@ -11,7 +11,6 @@ import Steps from './Steps'; import { getSuccessPercent, validProgress } from './utils'; import useConfigInject from '../_util/hooks/useConfigInject'; import devWarning from '../vc-util/devWarning'; -import type { ProgressStatusesType } from './props'; import { progressProps, progressStatuses } from './props'; export default defineComponent({ @@ -26,9 +25,14 @@ export default defineComponent({ gapDegree: 0, strokeLinecap: 'round', }), + slots: ['format'], setup(props, { slots }) { const { prefixCls, direction } = useConfigInject('progress', props); - + devWarning( + props.successPercent == undefined, + 'Progress', + '`successPercent` is deprecated. Please use `success.percent` instead.', + ); const classString = computed(() => { const { type, showInfo, size } = props; const pre = prefixCls.value; @@ -41,44 +45,44 @@ export default defineComponent({ }; }); - const getPercentNumber = () => { + const percentNumber = computed(() => { const { percent = 0 } = props; - const successPercent = getSuccessPercent(props.success, props.successPercent); + const successPercent = getSuccessPercent(props); return parseInt( successPercent !== undefined ? successPercent.toString() : percent.toString(), 10, ); - }; + }); - const getProgressStatus = () => { + const progressStatus = computed(() => { const { status } = props; - if (progressStatuses.indexOf(status) < 0 && getPercentNumber() >= 100) { + if (progressStatuses.indexOf(status) < 0 && percentNumber.value >= 100) { return 'success'; } return status || 'normal'; - }; + }); - const renderProcessInfo = (prefixCls: string, progressStatus: ProgressStatusesType) => { + const renderProcessInfo = () => { const { showInfo, format, type, percent } = props; - const successPercent = getSuccessPercent(props.success, props.successPercent); + const successPercent = getSuccessPercent(props); if (!showInfo) return null; let text: VNodeChild; - const textFormatter = format || slots?.format || (percentNumber => `${percentNumber}%`); + const textFormatter = format || slots?.format || ((val: number) => `${val}%`); const isLineType = type === 'line'; if ( format || slots?.format || - (progressStatus !== 'exception' && progressStatus !== 'success') + (progressStatus.value !== 'exception' && progressStatus.value !== 'success') ) { text = textFormatter(validProgress(percent), validProgress(successPercent)); - } else if (progressStatus === 'exception') { + } else if (progressStatus.value === 'exception') { text = isLineType ? : ; - } else if (progressStatus === 'success') { + } else if (progressStatus.value === 'success') { text = isLineType ? : ; } return ( - + {text} ); @@ -86,14 +90,7 @@ export default defineComponent({ return () => { const { type, steps, strokeColor } = props; - const progressStatus = getProgressStatus(); - const progressInfo = renderProcessInfo(prefixCls.value, progressStatus); - - devWarning( - props.successPercent == undefined, - 'Progress', - '`successPercent` is deprecated. Please use `success.percent` instead.', - ); + const progressInfo = renderProcessInfo(); let progress: VNodeChild; // Render progress shape @@ -122,7 +119,7 @@ export default defineComponent({ const classNames = { ...classString.value, - [`${prefixCls.value}-status-${progressStatus}`]: true, + [`${prefixCls.value}-status-${progressStatus.value}`]: true, }; return
{progress}
; diff --git a/components/progress/props.ts b/components/progress/props.ts index 7933fdf47..fc038f3f5 100644 --- a/components/progress/props.ts +++ b/components/progress/props.ts @@ -14,8 +14,6 @@ export type ProgressGradient = { direction?: string } & (StringGradients | FromT export interface SuccessProps { percent?: number; - /** @deprecated Use `percent` instead */ - progress?: number; strokeColor?: string; } diff --git a/components/progress/style/index.less b/components/progress/style/index.less index 45fc23e7c..dfde2fcbb 100644 --- a/components/progress/style/index.less +++ b/components/progress/style/index.less @@ -189,15 +189,15 @@ @keyframes ~"@{ant-prefix}-progress-active" { 0% { - width: 0; + transform: translateX(-100%) scaleX(0); opacity: 0.1; } 20% { - width: 0; + transform: translateX(-100%) scaleX(0); opacity: 0.5; } 100% { - width: 100%; + transform: translateX(0) scaleX(1); opacity: 0; } } diff --git a/components/progress/style/index.ts b/components/progress/style/index.tsx similarity index 100% rename from components/progress/style/index.ts rename to components/progress/style/index.tsx diff --git a/components/progress/utils.ts b/components/progress/utils.ts index df8b33226..760d696e2 100644 --- a/components/progress/utils.ts +++ b/components/progress/utils.ts @@ -1,5 +1,4 @@ import devWarning from '../vc-util/devWarning'; -import type { ProgressProps } from './props'; export function validProgress(progress: number | undefined) { if (!progress || progress < 0) { @@ -11,10 +10,16 @@ export function validProgress(progress: number | undefined) { return progress; } -export function getSuccessPercent( - success?: ProgressProps['success'], - successPercent?: ProgressProps['successPercent'], -) { +export function getSuccessPercent({ + success, + successPercent, +}: { + success?: { + progress?: number; + percent?: number; + }; + successPercent?: number; +}) { let percent = successPercent; /** @deprecated Use `percent` instead */ if (success && 'progress' in success) { diff --git a/components/vc-progress/index.ts b/components/vc-progress/index.ts index 199a021db..7969fd047 100644 --- a/components/vc-progress/index.ts +++ b/components/vc-progress/index.ts @@ -1,6 +1,7 @@ -// based on rc-progress 2.5.2 +// based on rc-progress 3.1.4 import Progress, { Line, Circle } from './src'; -export { Line, Circle }; +import type { ProgressProps } from './src'; +export { Line, Circle, ProgressProps }; export default Progress; diff --git a/components/vc-progress/src/Circle.tsx b/components/vc-progress/src/Circle.tsx index abb5c7cfb..3c8ef3dd0 100644 --- a/components/vc-progress/src/Circle.tsx +++ b/components/vc-progress/src/Circle.tsx @@ -2,6 +2,7 @@ import { useTransitionDuration, defaultProps } from './common'; import { propTypes, GapPositionType } from './types'; import { computed, defineComponent, ref } from 'vue'; import initDefaultProps from '../../_util/props-util/initDefaultProps'; +import { useRef } from '../../_util/hooks/useRef'; let gradientSeed = 0; @@ -73,7 +74,8 @@ export default defineComponent({ const percentList = computed(() => toArray(props.percent)); const strokeColorList = computed(() => toArray(props.strokeColor)); - const paths = useTransitionDuration(percentList); + const [setRef, paths] = useRef(); + useTransitionDuration(paths); const getStokeList = () => { const { prefixCls, strokeWidth, strokeLinecap, gapDegree, gapPosition } = props; @@ -108,7 +110,7 @@ export default defineComponent({ class: `${prefixCls}-circle-path`, style: pathStyle, }; - return (paths.value[index].value = c)} {...pathProps} />; + return setRef(c, index)} {...pathProps} />; }); }; diff --git a/components/vc-progress/src/Line.tsx b/components/vc-progress/src/Line.tsx index d61a5280d..578e85926 100644 --- a/components/vc-progress/src/Line.tsx +++ b/components/vc-progress/src/Line.tsx @@ -1,3 +1,4 @@ +import { useRef } from '../../_util/hooks/useRef'; import { computed, defineComponent } from 'vue'; import initDefaultProps from '../../_util/props-util/initDefaultProps'; import { useTransitionDuration, defaultProps } from './common'; @@ -11,13 +12,54 @@ export default defineComponent({ const { percent } = props; return Array.isArray(percent) ? percent : [percent]; }); + const percentListProps = computed(() => { + const { prefixCls, strokeLinecap, strokeWidth, transition } = props; + let stackPtg = 0; + return percentList.value.map((ptg, index) => { + let dashPercent = 1; + switch (strokeLinecap) { + case 'round': + dashPercent = 1 - strokeWidth / 100; + break; + case 'square': + dashPercent = 1 - strokeWidth / 2 / 100; + break; + default: + dashPercent = 1; + break; + } + const pathStyle = { + strokeDasharray: `${ptg * dashPercent}px, 100px`, + strokeDashoffset: `-${stackPtg}px`, + transition: + transition || + 'stroke-dashoffset 0.3s ease 0s, stroke-dasharray .3s ease 0s, stroke 0.3s linear', + }; + const color = + strokeColorList.value[index] || strokeColorList.value[strokeColorList.value.length - 1]; + stackPtg += ptg; + + const pathProps = { + key: index, + d: pathString.value, + 'stroke-linecap': strokeLinecap, + stroke: color as string, + 'stroke-width': strokeWidth, + 'fill-opacity': '0', + class: `${prefixCls}-line-path`, + style: pathStyle, + }; + + return pathProps; + }); + }); const strokeColorList = computed(() => { const { strokeColor } = props; return Array.isArray(strokeColor) ? strokeColor : [strokeColor]; }); - - const paths = useTransitionDuration(percentList); + const [setRef, paths] = useRef(); + useTransitionDuration(paths); const center = computed(() => props.strokeWidth / 2); const right = computed(() => 100 - props.strokeWidth / 2); @@ -52,8 +94,6 @@ export default defineComponent({ delete restProps.gapPosition; - let stackPtg = 0; - return ( - {percentList.value.map((ptg, index) => { - const pathStyle = { - strokeDasharray: `${ptg}px, 100px`, - strokeDashoffset: `-${stackPtg}px`, - transition: - transition || - 'stroke-dashoffset 0.3s ease 0s, stroke-dasharray .3s ease 0s, stroke 0.3s linear', - }; - const color = - strokeColorList.value[index] || - strokeColorList.value[strokeColorList.value.length - 1]; - - stackPtg += ptg; - - const pathProps = { - key: index, - d: pathString.value, - 'stroke-linecap': strokeLinecap, - stroke: color as string, - 'stroke-width': strokeWidth, - 'fill-opacity': '0', - class: `${prefixCls}-line-path`, - style: pathStyle, - }; - - return (paths.value[index].value = c)} {...pathProps} />; + {percentListProps.value.map((pathProps, index) => { + return setRef(c, index)} {...pathProps} />; })} ); diff --git a/components/vc-progress/src/common.ts b/components/vc-progress/src/common.ts index 334e9577c..25da82c35 100644 --- a/components/vc-progress/src/common.ts +++ b/components/vc-progress/src/common.ts @@ -1,5 +1,5 @@ -import type { Ref } from 'vue'; -import { ref, onUpdated, computed } from 'vue'; +import type { Refs } from '../../_util/hooks/useRef'; +import { ref, onUpdated } from 'vue'; import type { ProgressProps } from './types'; export const defaultProps: Partial = { @@ -12,8 +12,7 @@ export const defaultProps: Partial = { trailWidth: 1, }; -export const useTransitionDuration = (percentList: Ref) => { - const paths = computed(() => percentList.value.map(() => ref())); +export const useTransitionDuration = (paths: Refs) => { const prevTimeStamp = ref(null); onUpdated(() => { @@ -21,7 +20,7 @@ export const useTransitionDuration = (percentList: Ref) => { let updated = false; Object.keys(paths.value).forEach(key => { - const path = paths.value[key].value; + const path = paths.value[key]; if (!path) { return; } diff --git a/package.json b/package.json index 8c262020b..51fdeaa1d 100644 --- a/package.json +++ b/package.json @@ -203,6 +203,7 @@ "xhr-mock": "^2.5.1" }, "dependencies": { + "@ant-design/colors": "^5.1.1", "@ant-design/icons-vue": "^6.0.0", "@babel/runtime": "^7.10.5", "@simonwep/pickr": "~1.8.0", diff --git a/v2-doc b/v2-doc index d965edbb9..d2c096476 160000 --- a/v2-doc +++ b/v2-doc @@ -1 +1 @@ -Subproject commit d965edbb9045771095acf91489145e13c975cb51 +Subproject commit d2c096476ee3e8d27fbb9e1cb7933887501b1fab