Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ export default () => (
</tr>
<tr>
<td>percent</td>
<td>Number</td>
<td>Number | Number[]</td>
<td>0</td>
<td>the percent of the progress</td>
</tr>
Expand Down
29 changes: 25 additions & 4 deletions docs/examples/gap.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as React from 'react';
import { Circle, ProgressProps } from 'rc-progress';

const colorMap = ['#3FC7FA', '#85D262', '#FE8C6A'];
const colorMap = ['#3FC7FA', '#85D262', '#FE8C6A', '#FF5959', '#BC3FFA'];

function getColor(index) {
return colorMap[(index + colorMap.length) % colorMap.length];
Expand All @@ -13,8 +13,10 @@ class Example extends React.Component<ProgressProps, any> {
this.state = {
percent: 30,
colorIndex: 0,
subPathsCount: 3,
};
this.changeState = this.changeState.bind(this);
this.changeCount = this.changeCount.bind(this);
}

changeState() {
Expand All @@ -26,19 +28,38 @@ class Example extends React.Component<ProgressProps, any> {
});
}

changeCount() {
this.setState({
...this.state,
subPathsCount: (this.state.subPathsCount % 6) + 1,
});
}

render() {
const circleContainerStyle = {
width: '200px',
height: '200px',
};
const { percent, colorIndex } = this.state;
const { percent, colorIndex, subPathsCount } = this.state;
const color = getColor(colorIndex);

const multiPercentage = new Array(subPathsCount).fill(
percent / subPathsCount,
0,
subPathsCount,
);
const multiPercentageStrokeColors = multiPercentage.map((v, index) => getColor(index));

return (
<div>
<p>
<button type="button" onClick={this.changeState}>
Change State [{percent}]
</button>

<button type="button" onClick={this.changeCount}>
Change Count [{subPathsCount}]
</button>
</p>
<div style={circleContainerStyle}>
<Circle
Expand All @@ -52,13 +73,13 @@ class Example extends React.Component<ProgressProps, any> {
</div>
<div style={circleContainerStyle}>
<Circle
percent={[percent / 3, percent / 3, percent / 3]}
percent={multiPercentage}
gapDegree={70}
gapPosition="bottom"
strokeWidth={6}
trailWidth={6}
strokeLinecap="round"
strokeColor={[color, getColor(colorIndex + 1), getColor(colorIndex + 2)]}
strokeColor={multiPercentageStrokeColors}
/>
</div>

Expand Down
11 changes: 9 additions & 2 deletions src/Circle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ const Circle: React.FC<ProgressProps> = ({
(color) => Object.prototype.toString.call(color) === '[object Object]',
);

const [paths] = useTransitionDuration(percentList);
const paths = useTransitionDuration();

const getStokeList = () => {
let stackPtg = 0;
Expand All @@ -119,7 +119,14 @@ const Circle: React.FC<ProgressProps> = ({
opacity={ptg === 0 ? 0 : 1}
fillOpacity="0"
style={pathStyles.pathStyle}
ref={paths[index]}
ref={(elem) => {
// https://reactjs.org/docs/refs-and-the-dom.html#callback-refs
// React will call the ref callback with the DOM element when the component mounts,
// and call it with `null` when it unmounts.
// Refs are guaranteed to be up-to-date before componentDidMount or componentDidUpdate fires.

paths[index] = elem;
}}
/>
);
});
Expand Down
13 changes: 10 additions & 3 deletions src/Line.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as React from 'react';
import classNames from 'classnames';
import { useTransitionDuration, defaultProps } from './common';
import { ProgressProps } from './interface';
import type { ProgressProps } from './interface';

const Line: React.FC<ProgressProps> = ({
className,
Expand All @@ -21,7 +21,7 @@ const Line: React.FC<ProgressProps> = ({
const percentList = Array.isArray(percent) ? percent : [percent];
const strokeColorList = Array.isArray(strokeColor) ? strokeColor : [strokeColor];

const [paths] = useTransitionDuration(percentList);
const paths = useTransitionDuration();

const center = strokeWidth / 2;
const right = 100 - strokeWidth / 2;
Expand Down Expand Up @@ -76,7 +76,14 @@ const Line: React.FC<ProgressProps> = ({
stroke={color as string}
strokeWidth={strokeWidth}
fillOpacity="0"
ref={paths[index]}
ref={(elem) => {
// https://reactjs.org/docs/refs-and-the-dom.html#callback-refs
// React will call the ref callback with the DOM element when the component mounts,
// and call it with `null` when it unmounts.
// Refs are guaranteed to be up-to-date before componentDidMount or componentDidUpdate fires.

paths[index] = elem;
}}
style={pathStyle}
/>
);
Expand Down
14 changes: 7 additions & 7 deletions src/common.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useRef, useEffect } from 'react';
import { ProgressProps } from './interface';
import type { ProgressProps } from './interface';

export const defaultProps: Partial<ProgressProps> = {
className: '',
Expand All @@ -13,19 +13,19 @@ export const defaultProps: Partial<ProgressProps> = {
trailWidth: 1,
};

export const useTransitionDuration = (percentList: number[]) => {
// eslint-disable-next-line react-hooks/rules-of-hooks
const paths = percentList.map(() => useRef());
export const useTransitionDuration = (): SVGPathElement[] => {
const pathsRef = useRef<SVGPathElement[]>([]);
const prevTimeStamp = useRef(null);

useEffect(() => {
const now = Date.now();
let updated = false;

Object.keys(paths).forEach(key => {
const path = paths[key].current;
pathsRef.current.forEach((path) => {
if (!path) {
return;
}

updated = true;
const pathStyle = path.style;
pathStyle.transitionDuration = '.3s, .3s, .3s, .06s';
Expand All @@ -40,5 +40,5 @@ export const useTransitionDuration = (percentList: number[]) => {
}
});

return [paths];
return pathsRef.current;
};
30 changes: 30 additions & 0 deletions tests/index.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -156,4 +156,34 @@ describe('Progress', () => {
);
});
});

it('should support percentage array changes', () => {
class Demo extends React.Component {
state = {
subPathsCount: 2,
};

render() {
const { subPathsCount } = this.state;
const percent = 80;
const multiPercentage = new Array(subPathsCount).fill(
percent / subPathsCount,
0,
subPathsCount,
);

return (
<>
<Circle percent={multiPercentage} strokeWidth="1" />
<Line percent={multiPercentage} strokeWidth="1" />
</>
);
}
}
const circle = mount(<Demo />);
expect(circle.find(Circle).props().percent).toEqual([40, 40]);
circle.setState({ subPathsCount: 4 });
expect(circle.find(Circle).props().percent).toEqual([20, 20, 20, 20]);
circle.unmount();
});
});