Skip to content

Commit a408168

Browse files
committed
refactor: progress #6234
1 parent 2c1afa5 commit a408168

File tree

8 files changed

+98
-82
lines changed

8 files changed

+98
-82
lines changed

components/_util/type.ts

+4
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@ export function booleanType(defaultVal?: any) {
5555
return { type: Boolean, default: defaultVal as boolean };
5656
}
5757

58+
export function functionType<T = () => {}>(defaultVal?: any) {
59+
return { type: Function as PropType<T>, default: defaultVal as T };
60+
}
61+
5862
export function anyType<T = any>() {
5963
return { validator: () => true } as unknown as { type: PropType<T> };
6064
}

components/progress/Circle.tsx

+30-22
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,26 @@
11
import type { CSSProperties } from 'vue';
22
import { computed, defineComponent } from 'vue';
3-
import { presetPrimaryColors } from '@ant-design/colors';
43
import { Circle as VCCircle } from '../vc-progress';
5-
import { getSuccessPercent, validProgress } from './utils';
4+
import { getPercentage, getStrokeColor } from './utils';
65
import type { ProgressProps } from './props';
76
import { progressProps } from './props';
7+
import { initDefaultProps } from '../_util/props-util';
8+
import Tooltip from '../tooltip';
89

910
export type CircleProps = ProgressProps;
1011

11-
function getPercentage({ percent, success, successPercent }: CircleProps) {
12-
const realSuccessPercent = validProgress(getSuccessPercent({ success, successPercent }));
13-
return [realSuccessPercent, validProgress(validProgress(percent) - realSuccessPercent)];
14-
}
12+
const CIRCLE_MIN_STROKE_WIDTH = 3;
1513

16-
function getStrokeColor({
17-
success = {},
18-
strokeColor,
19-
}: Partial<CircleProps>): (string | Record<string, string>)[] {
20-
const { strokeColor: successColor } = success;
21-
return [successColor || presetPrimaryColors.green, strokeColor || null!];
22-
}
14+
const getMinPercent = (width: number): number => (CIRCLE_MIN_STROKE_WIDTH / width) * 100;
2315

2416
export default defineComponent({
2517
compatConfig: { MODE: 3 },
2618
name: 'Circle',
2719
inheritAttrs: false,
28-
props: progressProps(),
20+
props: initDefaultProps(progressProps(), {
21+
width: 120,
22+
trailColor: null as unknown as string,
23+
}),
2924
setup(props, { slots }) {
3025
const gapDeg = computed(() => {
3126
// Support gapDeg = 0 when type = 'dashboard'
@@ -39,17 +34,19 @@ export default defineComponent({
3934
});
4035

4136
const circleStyle = computed<CSSProperties>(() => {
42-
const circleSize = props.width || 120;
37+
const circleSize = props.width;
4338
return {
4439
width: typeof circleSize === 'number' ? `${circleSize}px` : circleSize,
4540
height: typeof circleSize === 'number' ? `${circleSize}px` : circleSize,
4641
fontSize: `${circleSize * 0.15 + 6}px`,
4742
};
4843
});
4944

50-
const circleWidth = computed(() => props.strokeWidth || 6);
45+
const circleWidth = computed(
46+
() => props.strokeWidth ?? Math.max(getMinPercent(props.width), 6),
47+
);
5148
const gapPos = computed(
52-
() => props.gapPosition || (props.type === 'dashboard' && 'bottom') || 'top',
49+
() => props.gapPosition || (props.type === 'dashboard' && 'bottom') || undefined,
5350
);
5451

5552
// using className to style stroke color
@@ -65,8 +62,8 @@ export default defineComponent({
6562
[`${props.prefixCls}-circle-gradient`]: isGradient.value,
6663
}));
6764

68-
return () => (
69-
<div class={wrapperClassName.value} style={circleStyle.value}>
65+
return () => {
66+
const circleContent = (
7067
<VCCircle
7168
percent={percent.value}
7269
strokeWidth={circleWidth.value}
@@ -78,8 +75,19 @@ export default defineComponent({
7875
gapDegree={gapDeg.value}
7976
gapPosition={gapPos.value}
8077
/>
81-
{slots.default?.()}
82-
</div>
83-
);
78+
);
79+
return (
80+
<div class={wrapperClassName.value} style={circleStyle.value}>
81+
{props.width <= 20 ? (
82+
<Tooltip v-slots={{ title: slots.default }}>{circleContent}</Tooltip>
83+
) : (
84+
<>
85+
{circleContent}
86+
{slots.default?.()}
87+
</>
88+
)}
89+
</div>
90+
);
91+
};
8492
},
8593
});

components/progress/Line.tsx

+10-6
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,10 @@ export const sortGradient = (gradients: StringGradients) => {
5353
* "100%": "#ffffff"
5454
* }
5555
*/
56-
export const handleGradient = (strokeColor: ProgressGradient, directionConfig: Direction) => {
56+
export const handleGradient = (
57+
strokeColor: ProgressGradient,
58+
directionConfig?: Direction,
59+
): CSSProperties => {
5760
const {
5861
from = presetPrimaryColors.blue,
5962
to = presetPrimaryColors.blue,
@@ -70,18 +73,19 @@ export const handleGradient = (strokeColor: ProgressGradient, directionConfig: D
7073
export default defineComponent({
7174
compatConfig: { MODE: 3 },
7275
name: 'Line',
76+
inheritAttrs: false,
7377
props: lineProps(),
74-
setup(props, { slots }) {
75-
const backgroundProps = computed(() => {
78+
setup(props, { slots, attrs }) {
79+
const backgroundProps = computed<CSSProperties>(() => {
7680
const { strokeColor, direction } = props;
7781
return strokeColor && typeof strokeColor !== 'string'
7882
? handleGradient(strokeColor, direction)
7983
: {
80-
background: strokeColor,
84+
backgroundColor: strokeColor as string,
8185
};
8286
});
8387

84-
const trailStyle = computed(() =>
88+
const trailStyle = computed<CSSProperties>(() =>
8589
props.trailColor
8690
? {
8791
backgroundColor: props.trailColor,
@@ -114,7 +118,7 @@ export default defineComponent({
114118

115119
return () => (
116120
<>
117-
<div class={`${props.prefixCls}-outer`}>
121+
<div {...attrs} class={[`${props.prefixCls}-outer`, attrs.class]}>
118122
<div class={`${props.prefixCls}-inner`} style={trailStyle.value}>
119123
<div class={`${props.prefixCls}-bg`} style={percentStyle.value} />
120124
{successPercent.value !== undefined ? (

components/progress/index.en-US.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
category: Components
33
type: Feedback
44
title: Progress
5-
cover: https://gw.alipayobjects.com/zos/alicdn/xqsDu4ZyR/Progress.svg
5+
cover: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*gK_4S6fDRfgAAAAAAAAAAAAADrJ8AQ/original
66
---
77

88
Display the current progress of an operation flow.

components/progress/index.zh-CN.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ category: Components
33
type: 反馈
44
title: Progress
55
subtitle: 进度条
6-
cover: https://gw.alipayobjects.com/zos/alicdn/xqsDu4ZyR/Progress.svg
6+
cover: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*gK_4S6fDRfgAAAAAAAAAAAAADrJ8AQ/original
77
---
88

99
展示操作的当前进度。

components/progress/progress.tsx

+17-19
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import devWarning from '../vc-util/devWarning';
1313
import { progressProps, progressStatuses } from './props';
1414
import type { VueNode } from '../_util/type';
1515
import useStyle from './style';
16-
import classNames from '../_util/classNames';
1716

1817
export default defineComponent({
1918
compatConfig: { MODE: 3 },
@@ -37,18 +36,6 @@ export default defineComponent({
3736
'Progress',
3837
'`successPercent` is deprecated. Please use `success.percent` instead.',
3938
);
40-
const classString = computed(() => {
41-
const { type, showInfo, size } = props;
42-
const pre = prefixCls.value;
43-
return {
44-
[hashId.value]: true,
45-
[pre]: true,
46-
[`${pre}-${(type === 'dashboard' && 'circle') || type}`]: true,
47-
[`${pre}-show-info`]: showInfo,
48-
[`${pre}-${size}`]: size,
49-
[`${pre}-rtl`]: direction.value === 'rtl',
50-
};
51-
});
5239

5340
const percentNumber = computed(() => {
5441
const { percent = 0 } = props;
@@ -61,12 +48,27 @@ export default defineComponent({
6148

6249
const progressStatus = computed(() => {
6350
const { status } = props;
64-
if (progressStatuses.indexOf(status) < 0 && percentNumber.value >= 100) {
51+
if (!progressStatuses.includes(status) && percentNumber.value >= 100) {
6552
return 'success';
6653
}
6754
return status || 'normal';
6855
});
6956

57+
const classString = computed(() => {
58+
const { type, showInfo, size } = props;
59+
const pre = prefixCls.value;
60+
return {
61+
[pre]: true,
62+
[`${pre}-inline-circle`]: type === 'circle' && props.width! <= 20,
63+
[`${pre}-${(type === 'dashboard' && 'circle') || type}`]: true,
64+
[`${pre}-status-${progressStatus.value}`]: true,
65+
[`${pre}-show-info`]: showInfo,
66+
[`${pre}-${size}`]: size,
67+
[`${pre}-rtl`]: direction.value === 'rtl',
68+
[hashId.value]: true,
69+
};
70+
});
71+
7072
const renderProcessInfo = () => {
7173
const { showInfo, format, type, percent, title } = props;
7274
const successPercent = getSuccessPercent(props);
@@ -126,12 +128,8 @@ export default defineComponent({
126128
);
127129
}
128130

129-
const classes = classNames(classString.value, {
130-
[`${prefixCls.value}-status-${progressStatus.value}`]: true,
131-
});
132-
133131
return wrapSSR(
134-
<div {...restAttrs} class={[classes, cls]} title={title}>
132+
<div role="progressbar" {...restAttrs} class={[classString.value, cls]} title={title}>
135133
{progress}
136134
</div>,
137135
);

components/progress/props.ts

+18-23
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,40 @@
1-
import PropTypes from '../_util/vue-types';
21
import type { VueNode } from '../_util/type';
3-
import { tuple } from '../_util/type';
4-
import type { PropType, ExtractPropTypes } from 'vue';
2+
import { functionType, stringType, anyType, objectType } from '../_util/type';
3+
import type { ExtractPropTypes } from 'vue';
54

6-
export const progressStatuses = tuple('normal', 'exception', 'active', 'success');
7-
export type ProgressStatusesType = typeof progressStatuses[number];
8-
const ProgressType = tuple('line', 'circle', 'dashboard');
9-
export type ProgressType = typeof ProgressType[number];
10-
const ProgressSize = tuple('default', 'small');
11-
export type ProgressSize = typeof ProgressSize[number];
5+
export const progressStatuses = ['normal', 'exception', 'active', 'success'] as const;
6+
export type ProgressStatusesType = (typeof progressStatuses)[number];
7+
const ProgressType = ['line', 'circle', 'dashboard'] as const;
8+
export type ProgressType = (typeof ProgressType)[number];
9+
const ProgressSize = ['default', 'small'] as const;
10+
export type ProgressSize = (typeof ProgressSize)[number];
1211
export type StringGradients = { [percentage: string]: string };
1312
type FromToGradients = { from: string; to: string };
1413
export type ProgressGradient = { direction?: string } & (StringGradients | FromToGradients);
1514

1615
export interface SuccessProps {
1716
percent?: number;
17+
/** @deprecated Use `percent` instead */
18+
progress?: number;
1819
strokeColor?: string;
1920
}
2021

2122
export const progressProps = () => ({
2223
prefixCls: String,
23-
type: PropTypes.oneOf(ProgressType),
24+
type: stringType<ProgressType>(),
2425
percent: Number,
25-
format: { type: Function as PropType<(percent?: number, successPercent?: number) => VueNode> },
26-
status: PropTypes.oneOf(progressStatuses),
26+
format: functionType<(percent?: number, successPercent?: number) => VueNode>(),
27+
status: stringType<ProgressStatusesType>(),
2728
showInfo: { type: Boolean, default: undefined },
2829
strokeWidth: Number,
29-
strokeLinecap: String as PropType<'butt' | 'square' | 'round'>,
30-
strokeColor: {
31-
type: [String, Object] as PropType<string | ProgressGradient>,
32-
default: undefined as string | ProgressGradient,
33-
},
30+
strokeLinecap: stringType<'butt' | 'square' | 'round'>(),
31+
strokeColor: anyType<string | ProgressGradient>(),
3432
trailColor: String,
3533
width: Number,
36-
success: {
37-
type: Object as PropType<SuccessProps>,
38-
default: (): SuccessProps => ({}),
39-
},
34+
success: objectType<SuccessProps>(),
4035
gapDegree: Number,
41-
gapPosition: String as PropType<'top' | 'bottom' | 'left' | 'right'>,
42-
size: PropTypes.oneOf(ProgressSize),
36+
gapPosition: stringType<'top' | 'bottom' | 'left' | 'right'>(),
37+
size: stringType<ProgressSize>(),
4338
steps: Number,
4439
/** @deprecated Use `success` instead */
4540
successPercent: Number,

components/progress/utils.ts

+17-10
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1+
import { presetPrimaryColors } from '@ant-design/colors';
12
import devWarning from '../vc-util/devWarning';
3+
import type { CircleProps } from './Circle';
4+
import type { ProgressProps } from './props';
25

36
export function validProgress(progress: number | undefined) {
47
if (!progress || progress < 0) {
@@ -10,16 +13,7 @@ export function validProgress(progress: number | undefined) {
1013
return progress;
1114
}
1215

13-
export function getSuccessPercent({
14-
success,
15-
successPercent,
16-
}: {
17-
success?: {
18-
progress?: number;
19-
percent?: number;
20-
};
21-
successPercent?: number;
22-
}) {
16+
export function getSuccessPercent({ success, successPercent }: ProgressProps) {
2317
let percent = successPercent;
2418
/** @deprecated Use `percent` instead */
2519
if (success && 'progress' in success) {
@@ -35,3 +29,16 @@ export function getSuccessPercent({
3529
}
3630
return percent;
3731
}
32+
33+
export function getPercentage({ percent, success, successPercent }: ProgressProps) {
34+
const realSuccessPercent = validProgress(getSuccessPercent({ success, successPercent }));
35+
return [realSuccessPercent, validProgress(validProgress(percent) - realSuccessPercent)];
36+
}
37+
38+
export function getStrokeColor({
39+
success = {},
40+
strokeColor,
41+
}: Partial<CircleProps>): (string | Record<string, string>)[] {
42+
const { strokeColor: successColor } = success;
43+
return [successColor || presetPrimaryColors.green, strokeColor || null!];
44+
}

0 commit comments

Comments
 (0)