mdc-react
Version:
Material Components for the web implemented in React
84 lines (74 loc) • 4.08 kB
JSX
import { forwardRef } from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import { strings, cssClasses, sizeProps, Size } from './constants';
const CircularProgress = forwardRef(({
value = 0,
size = Size.MEDIUM,
indeterminate = false,
closed = false,
colorful = false,
className,
...props
}, ref) => {
const classNames = classnames(cssClasses.ROOT, {
[`${cssClasses.ROOT}--${size}`]: size,
[cssClasses.INDETERMINATE]: indeterminate,
[cssClasses.CLOSED]: closed
}, className);
const { viewBox, radius, strokeDasharray, strokeWidth, gapPatchStrokeWidth, indeterminateStrokeDashoffset } = sizeProps[size];
const progress = value > 1 ? (value / 100) : Number(value);
const cx = viewBox / 2, cy = viewBox / 2;
const strokeDashoffset = (2 * Math.PI * radius) * (1 - progress);
return (
<div
ref={ref}
className={classNames}
role="progressbar"
aria-valuemin={0}
aria-valuemax={1}
aria-valuenow={progress}
{...props}
>
{!indeterminate &&
<div className={cssClasses.DETERMINATE_CONTAINER}>
<svg className={cssClasses.DETERMINATE_CIRCLE_GRAPHIC} viewBox={`0 0 ${viewBox} ${viewBox}`} xmlns={strings.XMLNS}>
<circle className={cssClasses.DETERMINATE_TRACK} cx={cx} cy={cy} r={radius} strokeWidth={strokeWidth} />
<circle className={cssClasses.DETERMINATE_CIRCLE} cx={cx} cy={cy} r={radius} strokeWidth={strokeWidth} strokeDasharray={strokeDasharray} strokeDashoffset={strokeDashoffset} />
</svg>
</div>
}
{indeterminate &&
<div className={cssClasses.INDETERMINATE_CONTAINER}>
{(colorful ? [1, 2, 3, 4] : [0]).map(n =>
<div key={n} className={classnames(cssClasses.SPINNER_LAYER, { [`${cssClasses.PROGRESS_COLOR}-${n}`]: n })}>
<div className={`${cssClasses.CIRCLE_CLIPPER} ${cssClasses.CIRCLE_LEFT}`}>
<svg className={cssClasses.INDETERMINATE_CIRCLE_GRAPHIC} viewBox={`0 0 ${viewBox} ${viewBox}`} xmlns={strings.XMLNS}>
<circle cx={cx} cy={cy} r={radius} strokeWidth={strokeWidth} strokeDasharray={strokeDasharray} strokeDashoffset={indeterminateStrokeDashoffset} />
</svg>
</div><div className={cssClasses.GAP_PATCH}>
<svg className={cssClasses.INDETERMINATE_CIRCLE_GRAPHIC} viewBox={`0 0 ${viewBox} ${viewBox}`} xmlns={strings.XMLNS}>
<circle cx={cx} cy={cy} r={radius} strokeWidth={gapPatchStrokeWidth} strokeDasharray={strokeDasharray} strokeDashoffset={indeterminateStrokeDashoffset} />
</svg>
</div><div className={`${cssClasses.CIRCLE_CLIPPER} ${cssClasses.CIRCLE_RIGHT}`}>
<svg className={cssClasses.INDETERMINATE_CIRCLE_GRAPHIC} viewBox={`0 0 ${viewBox} ${viewBox}`} xmlns={strings.XMLNS}>
<circle cx={cx} cy={cy} r={radius} strokeWidth={strokeWidth} strokeDasharray={strokeDasharray} strokeDashoffset={indeterminateStrokeDashoffset} />
</svg>
</div>
</div>
)}
</div>
}
</div>
);
});
CircularProgress.displayName = 'MDCCircularProgress';
CircularProgress.propTypes = {
value: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
size: PropTypes.oneOf([Size.SMALL, Size.MEDIUM, Size.LARGE]),
indeterminate: PropTypes.bool,
closed: PropTypes.bool,
colorful: PropTypes.bool
};
CircularProgress.Size = Size;
export default CircularProgress;