|
|
@@ -5,6 +5,7 @@ import { cssClasses, strings } from '@douyinfe/semi-foundation/progress/constant
|
|
|
import '@douyinfe/semi-foundation/progress/progress.scss';
|
|
|
import { Animation } from '@douyinfe/semi-animation';
|
|
|
import { Motion } from '../_base/base';
|
|
|
+import { generateColor, StrokeArr } from '@douyinfe/semi-foundation/progress/generates';
|
|
|
|
|
|
const prefixCls = cssClasses.PREFIX;
|
|
|
|
|
|
@@ -21,7 +22,8 @@ export interface ProgressProps {
|
|
|
percent?: number;
|
|
|
showInfo?: boolean;
|
|
|
size?: 'default' | 'small' | 'large';
|
|
|
- stroke?: string;
|
|
|
+ stroke?: string | StrokeArr;
|
|
|
+ strokeGradient?: boolean;
|
|
|
strokeLinecap?: 'round' | 'square';
|
|
|
strokeWidth?: number;
|
|
|
style?: React.CSSProperties;
|
|
|
@@ -48,7 +50,16 @@ class Progress extends Component<ProgressProps, ProgressState> {
|
|
|
scale: PropTypes.number,
|
|
|
showInfo: PropTypes.bool,
|
|
|
size: PropTypes.oneOf(strings.sizes),
|
|
|
- stroke: PropTypes.string,
|
|
|
+ stroke: PropTypes.oneOfType([
|
|
|
+ PropTypes.string,
|
|
|
+ PropTypes.arrayOf(
|
|
|
+ PropTypes.shape({
|
|
|
+ percent: PropTypes.number,
|
|
|
+ color: PropTypes.string,
|
|
|
+ })
|
|
|
+ ),
|
|
|
+ ]),
|
|
|
+ strokeGradient: PropTypes.bool,
|
|
|
strokeLinecap: PropTypes.oneOf(strings.strokeLineCap),
|
|
|
strokeWidth: PropTypes.number,
|
|
|
style: PropTypes.object,
|
|
|
@@ -65,7 +76,8 @@ class Progress extends Component<ProgressProps, ProgressState> {
|
|
|
percent: 0,
|
|
|
showInfo: false,
|
|
|
size: strings.DEFAULT_SIZE,
|
|
|
- stroke: 'var(--semi-color-success)',
|
|
|
+ stroke: strings.STROKE_DEFAULT,
|
|
|
+ strokeGradient: false,
|
|
|
strokeLinecap: strings.DEFAULT_LINECAP,
|
|
|
strokeWidth: 4,
|
|
|
style: {},
|
|
|
@@ -80,7 +92,7 @@ class Progress extends Component<ProgressProps, ProgressState> {
|
|
|
super(props);
|
|
|
this._mounted = true;
|
|
|
this.state = {
|
|
|
- percentNumber: this.props.percent // Specially used for animation of numbers
|
|
|
+ percentNumber: this.props.percent, // Specially used for animation of numbers
|
|
|
};
|
|
|
}
|
|
|
componentDidUpdate(prevProps: ProgressProps): void {
|
|
|
@@ -98,14 +110,17 @@ class Progress extends Component<ProgressProps, ProgressState> {
|
|
|
if (this.animation && this.animation.destroy) {
|
|
|
this.animation.destroy();
|
|
|
}
|
|
|
- this.animation = new Animation({
|
|
|
- from: { value: prevProps.percent },
|
|
|
- to: { value: this.props.percent }
|
|
|
- }, {
|
|
|
- // easing: 'cubic-bezier(0, .68, .3, 1)'
|
|
|
- easing: 'linear',
|
|
|
- duration: 300
|
|
|
- });
|
|
|
+ this.animation = new Animation(
|
|
|
+ {
|
|
|
+ from: { value: prevProps.percent },
|
|
|
+ to: { value: this.props.percent },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ // easing: 'cubic-bezier(0, .68, .3, 1)'
|
|
|
+ easing: 'linear',
|
|
|
+ duration: 300,
|
|
|
+ }
|
|
|
+ );
|
|
|
this.animation.on('frame', (props: any) => {
|
|
|
// prevent setState while component is unmounted but this timer is called
|
|
|
if (this._mounted === false) {
|
|
|
@@ -132,7 +147,20 @@ class Progress extends Component<ProgressProps, ProgressState> {
|
|
|
}
|
|
|
|
|
|
renderCircleProgress(): ReactNode {
|
|
|
- const { strokeLinecap, style, className, strokeWidth, format, size, stroke, showInfo, percent, orbitStroke, id } = this.props;
|
|
|
+ const {
|
|
|
+ strokeLinecap,
|
|
|
+ style,
|
|
|
+ className,
|
|
|
+ strokeWidth,
|
|
|
+ format,
|
|
|
+ size,
|
|
|
+ stroke,
|
|
|
+ strokeGradient,
|
|
|
+ showInfo,
|
|
|
+ percent,
|
|
|
+ orbitStroke,
|
|
|
+ id,
|
|
|
+ } = this.props;
|
|
|
const ariaLabel = this.props['aria-label'];
|
|
|
const ariaLabelledBy = this.props['aria-labelledby'];
|
|
|
const ariaValueText = this.props['aria-valuetext'];
|
|
|
@@ -140,7 +168,7 @@ class Progress extends Component<ProgressProps, ProgressState> {
|
|
|
const classNames = {
|
|
|
wrapper: cls(`${prefixCls}-circle`, className),
|
|
|
svg: cls(`${prefixCls}-circle-ring`),
|
|
|
- circle: cls(`${prefixCls}-circle-ring-inner`)
|
|
|
+ circle: cls(`${prefixCls}-circle-ring-inner`),
|
|
|
};
|
|
|
const perc = this.calcPercent(percent);
|
|
|
const percNumber = this.calcPercent(percentNumber);
|
|
|
@@ -149,9 +177,12 @@ class Progress extends Component<ProgressProps, ProgressState> {
|
|
|
if (this.props.width) {
|
|
|
width = this.props.width;
|
|
|
} else {
|
|
|
- size === strings.DEFAULT_SIZE ? width = 72 : width = 24;
|
|
|
+ size === strings.DEFAULT_SIZE ? (width = 72) : (width = 24);
|
|
|
}
|
|
|
|
|
|
+ // parse stroke & generate gradients
|
|
|
+ const _stroke = this.selectStroke(stroke, percent, strokeGradient);
|
|
|
+
|
|
|
// cx, cy is circle center
|
|
|
const cy = width / 2;
|
|
|
const cx = width / 2;
|
|
|
@@ -165,10 +196,10 @@ class Progress extends Component<ProgressProps, ProgressState> {
|
|
|
return (
|
|
|
<div
|
|
|
id={id}
|
|
|
- className={classNames.wrapper}
|
|
|
- style={style}
|
|
|
- role='progressbar'
|
|
|
- aria-valuemin={0}
|
|
|
+ className={classNames.wrapper}
|
|
|
+ style={style}
|
|
|
+ role="progressbar"
|
|
|
+ aria-valuemin={0}
|
|
|
aria-valuemax={100}
|
|
|
aria-valuenow={percNumber}
|
|
|
aria-labelledby={ariaLabelledBy}
|
|
|
@@ -195,14 +226,14 @@ class Progress extends Component<ProgressProps, ProgressState> {
|
|
|
strokeDasharray={strokeDasharray}
|
|
|
strokeLinecap={strokeLinecap}
|
|
|
fill="transparent"
|
|
|
- stroke={stroke}
|
|
|
+ stroke={_stroke}
|
|
|
r={radius}
|
|
|
cx={cx}
|
|
|
cy={cy}
|
|
|
aria-hidden
|
|
|
/>
|
|
|
</svg>
|
|
|
- {showInfo && size !== 'small' ? (<span className={`${prefixCls}-circle-text`}>{text}</span>) : null}
|
|
|
+ {showInfo && size !== 'small' ? <span className={`${prefixCls}-circle-text`}>{text}</span> : null}
|
|
|
</div>
|
|
|
);
|
|
|
}
|
|
|
@@ -219,8 +250,31 @@ class Progress extends Component<ProgressProps, ProgressState> {
|
|
|
return perc;
|
|
|
}
|
|
|
|
|
|
+ selectStroke(stroke: string | StrokeArr, percent: number, strokeGradient): string {
|
|
|
+ if (typeof stroke === 'string') {
|
|
|
+ return stroke;
|
|
|
+ }
|
|
|
+ const color = generateColor(stroke, percent, strokeGradient);
|
|
|
+ if (typeof color !== 'undefined') {
|
|
|
+ return color;
|
|
|
+ }
|
|
|
+ return strings.STROKE_DEFAULT;
|
|
|
+ }
|
|
|
+
|
|
|
renderLineProgress(): ReactNode {
|
|
|
- const { className, style, stroke, direction, format, showInfo, size, percent, orbitStroke, id } = this.props;
|
|
|
+ const {
|
|
|
+ className,
|
|
|
+ style,
|
|
|
+ stroke,
|
|
|
+ strokeGradient,
|
|
|
+ direction,
|
|
|
+ format,
|
|
|
+ showInfo,
|
|
|
+ size,
|
|
|
+ percent,
|
|
|
+ orbitStroke,
|
|
|
+ id,
|
|
|
+ } = this.props;
|
|
|
const ariaLabel = this.props['aria-label'];
|
|
|
const ariaLabelledBy = this.props['aria-labelledby'];
|
|
|
const ariaValueText = this.props['aria-valuetext'];
|
|
|
@@ -238,8 +292,11 @@ class Progress extends Component<ProgressProps, ProgressState> {
|
|
|
const perc = this.calcPercent(percent);
|
|
|
const percNumber = this.calcPercent(percentNumber);
|
|
|
|
|
|
+ // parse stroke & generate gradients
|
|
|
+ const _stroke = this.selectStroke(stroke, percent, strokeGradient);
|
|
|
+
|
|
|
const innerStyle: Record<string, any> = {
|
|
|
- background: stroke
|
|
|
+ background: _stroke,
|
|
|
};
|
|
|
if (direction === strings.DEFAULT_DIRECTION) {
|
|
|
innerStyle.width = `${perc}%`;
|
|
|
@@ -254,7 +311,7 @@ class Progress extends Component<ProgressProps, ProgressState> {
|
|
|
id={id}
|
|
|
className={progressWrapperCls}
|
|
|
style={style}
|
|
|
- role='progressbar'
|
|
|
+ role="progressbar"
|
|
|
aria-valuemin={0}
|
|
|
aria-valuemax={100}
|
|
|
aria-valuenow={perc}
|
|
|
@@ -262,7 +319,11 @@ class Progress extends Component<ProgressProps, ProgressState> {
|
|
|
aria-label={ariaLabel}
|
|
|
aria-valuetext={ariaValueText}
|
|
|
>
|
|
|
- <div className={progressTrackCls} style={orbitStroke ? { backgroundColor: orbitStroke } : {}} aria-hidden>
|
|
|
+ <div
|
|
|
+ className={progressTrackCls}
|
|
|
+ style={orbitStroke ? { backgroundColor: orbitStroke } : {}}
|
|
|
+ aria-hidden
|
|
|
+ >
|
|
|
<div className={innerCls} style={innerStyle} aria-hidden />
|
|
|
</div>
|
|
|
{showInfo ? <div className={`${prefixCls}-line-text`}>{text}</div> : null}
|
|
|
@@ -280,4 +341,4 @@ class Progress extends Component<ProgressProps, ProgressState> {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-export default Progress;
|
|
|
+export default Progress;
|