ant-design/components/spin/Indicator/Progress.tsx
lijianan ab0e07e25d
Some checks are pending
Publish Any Commit / build (push) Waiting to run
✅ test v6 / lint (push) Waiting to run
✅ test v6 / test-react-legacy (18, 1/2) (push) Waiting to run
✅ test v6 / test-react-legacy (18, 2/2) (push) Waiting to run
✅ test v6 / test-node (push) Waiting to run
✅ test v6 / test-react-latest (dom, 1/2) (push) Waiting to run
✅ test v6 / test-react-latest (dom, 2/2) (push) Waiting to run
✅ test v6 / test-react-latest-dist (dist, 1/2) (push) Blocked by required conditions
✅ test v6 / test-react-latest-dist (dist, 2/2) (push) Blocked by required conditions
✅ test v6 / test-react-latest-dist (dist-min, 1/2) (push) Blocked by required conditions
✅ test v6 / test-react-latest-dist (dist-min, 2/2) (push) Blocked by required conditions
✅ test v6 / test-coverage (push) Blocked by required conditions
✅ test v6 / build (push) Waiting to run
✅ test v6 / test lib/es module (es, 1/2) (push) Waiting to run
✅ test v6 / test lib/es module (es, 2/2) (push) Waiting to run
✅ test v6 / test lib/es module (lib, 1/2) (push) Waiting to run
✅ test v6 / test lib/es module (lib, 2/2) (push) Waiting to run
👁️ Visual Regression Persist Start / test image (push) Waiting to run
refactor: [v6] use rc-component (#52337)
* refactor: use @rc-component

* chore: adjust compile

* test: fix logic

* chore: back of reset

---------

Co-authored-by: 二货机器人 <smith3816@gmail.com>
2025-01-10 14:14:31 +08:00

91 lines
2.3 KiB
TypeScript

import * as React from 'react';
import useLayoutEffect from '@rc-component/util/lib/hooks/useLayoutEffect';
import classNames from 'classnames';
export interface ProgressProps {
prefixCls: string;
percent: number;
}
const viewSize = 100;
const borderWidth = viewSize / 5;
const radius = viewSize / 2 - borderWidth / 2;
const circumference = radius * 2 * Math.PI;
const position = 50;
interface CircleProps {
dotClassName?: string;
style?: React.CSSProperties;
hasCircleCls?: boolean;
}
const CustomCircle: React.FC<Readonly<CircleProps>> = (props) => {
const { dotClassName, style, hasCircleCls } = props;
return (
<circle
className={classNames(`${dotClassName}-circle`, {
[`${dotClassName}-circle-bg`]: hasCircleCls,
})}
r={radius}
cx={position}
cy={position}
strokeWidth={borderWidth}
style={style}
/>
);
};
const Progress: React.FC<Readonly<ProgressProps>> = ({ percent, prefixCls }) => {
const dotClassName = `${prefixCls}-dot`;
const holderClassName = `${dotClassName}-holder`;
const hideClassName = `${holderClassName}-hidden`;
const [render, setRender] = React.useState(false);
// ==================== Visible =====================
useLayoutEffect(() => {
if (percent !== 0) {
setRender(true);
}
}, [percent !== 0]);
// ==================== Progress ====================
const safePtg = Math.max(Math.min(percent, 100), 0);
// ===================== Render =====================
if (!render) {
return null;
}
const circleStyle: React.CSSProperties = {
strokeDashoffset: `${circumference / 4}`,
strokeDasharray: `${(circumference * safePtg) / 100} ${
(circumference * (100 - safePtg)) / 100
}`,
};
return (
<span
className={classNames(
holderClassName,
`${dotClassName}-progress`,
safePtg <= 0 && hideClassName,
)}
>
<svg
viewBox={`0 0 ${viewSize} ${viewSize}`}
// biome-ignore lint/a11y/noNoninteractiveElementToInteractiveRole: progressbar could be readonly
role="progressbar"
aria-valuemin={0}
aria-valuemax={100}
aria-valuenow={safePtg}
>
<CustomCircle dotClassName={dotClassName} hasCircleCls />
<CustomCircle dotClassName={dotClassName} style={circleStyle} />
</svg>
</span>
);
};
export default Progress;