Skip to content
Merged
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> = ({
const strokeColorList = toArray(strokeColor);
const gradient = strokeColorList.find((color) => color && typeof color === 'object');

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

const getStokeList = () => {
let stackPtg = 0;
Expand Down Expand Up @@ -127,7 +127,14 @@ const Circle: React.FC<ProgressProps> = ({
strokeWidth={strokeWidth}
opacity={ptg === 0 ? 0 : 1}
style={circleStyleForStack}
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
11 changes: 9 additions & 2 deletions src/Line.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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
12 changes: 6 additions & 6 deletions src/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,19 @@ export const defaultProps: Partial<ProgressProps> = {
gapPosition: 'bottom',
};

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 @@ -41,5 +41,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 @@ -165,4 +165,34 @@ describe('Progress', () => {
expect(onClick).toHaveBeenCalledTimes(2);
});
});

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();
});
});