1
This commit is contained in:
+9
@@ -0,0 +1,9 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014-present yiminghe
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
+163
@@ -0,0 +1,163 @@
|
||||
# @rc-component/progress
|
||||
|
||||
Progress Bar.
|
||||
|
||||
[![NPM version][npm-image]][npm-url] [](https://github.com/umijs/dumi) [![build status][github-actions-image]][github-actions-url] [![Test coverage][coveralls-image]][coveralls-url] [![npm download][download-image]][download-url] [![bundle size][bundlephobia-image]][bundlephobia-url]
|
||||
|
||||
[npm-image]: http://img.shields.io/npm/v/@rc-component/progress.svg?style=flat-square
|
||||
[npm-url]: http://npmjs.org/package/@rc-component/progress
|
||||
[github-actions-image]: https://github.com/react-component/progress/workflows/CI/badge.svg
|
||||
[github-actions-url]: https://github.com/react-component/progress/actions
|
||||
[circleci-image]: https://img.shields.io/circleci/react-component/progress/master?style=flat-square
|
||||
[circleci-url]: https://circleci.com/gh/react-component/progress
|
||||
[coveralls-image]: https://img.shields.io/coveralls/react-component/progress.svg?style=flat-square
|
||||
[coveralls-url]: https://coveralls.io/r/react-component/progress?branch=master
|
||||
[david-url]: https://david-dm.org/react-component/progress
|
||||
[david-image]: https://david-dm.org/react-component/progress/status.svg?style=flat-square
|
||||
[david-dev-url]: https://david-dm.org/react-component/progress?type=dev
|
||||
[david-dev-image]: https://david-dm.org/react-component/progress/dev-status.svg?style=flat-square
|
||||
[download-image]: https://img.shields.io/npm/dm/@rc-component/progress.svg?style=flat-square
|
||||
[download-url]: https://npmjs.org/package/@rc-component/progress
|
||||
[bundlephobia-url]: https://bundlephobia.com/result?p=@rc-component/progress
|
||||
[bundlephobia-image]: https://badgen.net/bundlephobia/minzip/@rc-component/progress
|
||||
|
||||
## Example
|
||||
|
||||
https://progress.react-component.vercel.app/
|
||||
|
||||
## Screenshots
|
||||
|
||||
<img src="https://t.alipayobjects.com/images/T12p8gXjpgXXXXXXXX.gif" />
|
||||
|
||||
## Browsers
|
||||
|
||||
* support IE9+, Chrome, Firefox, Safari
|
||||
|
||||
## Install
|
||||
|
||||
[](https://npmjs.org/package/@rc-component/progress)
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
import { Line, Circle } from '@rc-component/progress';
|
||||
|
||||
export default () => (
|
||||
<>
|
||||
<Line percent={10} strokeWidth={4} strokeColor="#D3D3D3" />
|
||||
<Circle percent={10} strokeWidth={4} strokeColor="#D3D3D3" />
|
||||
</>
|
||||
);
|
||||
```
|
||||
|
||||
## Compatibility
|
||||
|
||||
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="IE / Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>IE / Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>Safari | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/electron/electron_48x48.png" alt="Electron" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>Electron |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| IE11, Edge | last 2 versions | last 2 versions | last 2 versions | last 2 versions |
|
||||
|
||||
## API
|
||||
|
||||
### props
|
||||
|
||||
<table class="table table-bordered table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 100px;">name</th>
|
||||
<th style="width: 50px;">type</th>
|
||||
<th style="width: 50px;">default</th>
|
||||
<th>description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>strokeWidth</td>
|
||||
<td>Number</td>
|
||||
<td>1</td>
|
||||
<td>Width of the stroke. Unit is percentage of SVG canvas size.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>strokeColor</td>
|
||||
<td>String</td>
|
||||
<td>#2db7f5</td>
|
||||
<td>Stroke color.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>railWidth</td>
|
||||
<td>Number</td>
|
||||
<td>1</td>
|
||||
<td>Width of the rail stroke. Unit is percentage of SVG canvas size. Rail is always centered relative to actual progress path. If railWidth is not defined, it is the same as strokeWidth.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>railColor</td>
|
||||
<td>String</td>
|
||||
<td>#D9D9D9</td>
|
||||
<td>Color for lighter rail stroke underneath the actual progress path.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>strokeLinecap</td>
|
||||
<td>String</td>
|
||||
<td>'round'</td>
|
||||
<td>The shape to be used at the end of the progress bar: can be `butt`, `square` or `round`.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>prefixCls</td>
|
||||
<td>String</td>
|
||||
<td>rc-progress</td>
|
||||
<td>prefix className for component</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>className</td>
|
||||
<td>String</td>
|
||||
<td></td>
|
||||
<td>customized className</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>style</td>
|
||||
<td>Object</td>
|
||||
<td></td>
|
||||
<td>style object will be added to svg element</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>percent</td>
|
||||
<td>Number | Number[]</td>
|
||||
<td>0</td>
|
||||
<td>the percent of the progress</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>gapDegree</td>
|
||||
<td>Number</td>
|
||||
<td>0</td>
|
||||
<td>the gap degree of half circle, 0 - 360</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>gapPosition</td>
|
||||
<td>String</td>
|
||||
<td>top</td>
|
||||
<td>the gap position: can be `top`, `bottom`, `left`, or `right`. </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>loading</td>
|
||||
<td>Boolean</td>
|
||||
<td>false</td>
|
||||
<td>If it is true the indeterminate progress will be enabled.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
## Installation
|
||||
|
||||
```
|
||||
npm install --save @rc-component/progress
|
||||
```
|
||||
|
||||
## Development
|
||||
|
||||
```
|
||||
npm install
|
||||
npm start
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
@rc-component/progress is released under the MIT license.
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
import * as React from 'react';
|
||||
import type { ProgressProps } from '..';
|
||||
import type { StrokeColorObject } from '../interface';
|
||||
export interface ColorGradientProps {
|
||||
prefixCls: string;
|
||||
className?: string;
|
||||
gradientId: string;
|
||||
style: React.CSSProperties;
|
||||
ptg: number;
|
||||
radius: number;
|
||||
strokeLinecap: ProgressProps['strokeLinecap'];
|
||||
strokeWidth: ProgressProps['strokeWidth'];
|
||||
size: number;
|
||||
color: string | StrokeColorObject;
|
||||
gapDegree: number;
|
||||
}
|
||||
declare const PtgCircle: React.ForwardRefExoticComponent<ColorGradientProps & React.RefAttributes<SVGCircleElement>>;
|
||||
export default PtgCircle;
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
import * as React from 'react';
|
||||
import { clsx } from 'clsx';
|
||||
const Block = ({
|
||||
bg,
|
||||
children
|
||||
}) => /*#__PURE__*/React.createElement("div", {
|
||||
style: {
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
background: bg
|
||||
}
|
||||
}, children);
|
||||
function getPtgColors(color, scale) {
|
||||
return Object.keys(color).map(key => {
|
||||
const parsedKey = parseFloat(key);
|
||||
const ptgKey = `${Math.floor(parsedKey * scale)}%`;
|
||||
return `${color[key]} ${ptgKey}`;
|
||||
});
|
||||
}
|
||||
const PtgCircle = /*#__PURE__*/React.forwardRef((props, ref) => {
|
||||
const {
|
||||
prefixCls,
|
||||
color,
|
||||
gradientId,
|
||||
radius,
|
||||
className,
|
||||
style: circleStyleForStack,
|
||||
ptg,
|
||||
strokeLinecap,
|
||||
strokeWidth,
|
||||
size,
|
||||
gapDegree
|
||||
} = props;
|
||||
const isGradient = color && typeof color === 'object';
|
||||
const stroke = isGradient ? `#FFF` : undefined;
|
||||
|
||||
// ========================== Circle ==========================
|
||||
const halfSize = size / 2;
|
||||
const circleNode = /*#__PURE__*/React.createElement("circle", {
|
||||
className: clsx(`${prefixCls}-circle-path`, className),
|
||||
r: radius,
|
||||
cx: halfSize,
|
||||
cy: halfSize,
|
||||
stroke: stroke,
|
||||
strokeLinecap: strokeLinecap,
|
||||
strokeWidth: strokeWidth,
|
||||
opacity: ptg === 0 ? 0 : 1,
|
||||
style: circleStyleForStack,
|
||||
ref: ref
|
||||
});
|
||||
|
||||
// ========================== Render ==========================
|
||||
if (!isGradient) {
|
||||
return circleNode;
|
||||
}
|
||||
const maskId = `${gradientId}-conic`;
|
||||
const fromDeg = gapDegree ? `${180 + gapDegree / 2}deg` : '0deg';
|
||||
const conicColors = getPtgColors(color, (360 - gapDegree) / 360);
|
||||
const linearColors = getPtgColors(color, 1);
|
||||
const conicColorBg = `conic-gradient(from ${fromDeg}, ${conicColors.join(', ')})`;
|
||||
const linearColorBg = `linear-gradient(to ${gapDegree ? 'bottom' : 'top'}, ${linearColors.join(', ')})`;
|
||||
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("mask", {
|
||||
id: maskId
|
||||
}, circleNode), /*#__PURE__*/React.createElement("foreignObject", {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: size,
|
||||
height: size,
|
||||
mask: `url(#${maskId})`
|
||||
}, /*#__PURE__*/React.createElement(Block, {
|
||||
bg: linearColorBg
|
||||
}, /*#__PURE__*/React.createElement(Block, {
|
||||
bg: conicColorBg
|
||||
}))));
|
||||
});
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
PtgCircle.displayName = 'PtgCircle';
|
||||
}
|
||||
export default PtgCircle;
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
import * as React from 'react';
|
||||
import type { ProgressProps } from '../interface';
|
||||
declare const Circle: React.FC<ProgressProps>;
|
||||
export default Circle;
|
||||
+153
@@ -0,0 +1,153 @@
|
||||
function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
|
||||
import * as React from 'react';
|
||||
import { clsx } from 'clsx';
|
||||
import { defaultProps, useTransitionDuration } from "../common";
|
||||
import useId from "@rc-component/util/es/hooks/useId";
|
||||
import PtgCircle from "./PtgCircle";
|
||||
import { VIEW_BOX_SIZE, getCircleStyle } from "./util";
|
||||
import getIndeterminateCircle from "../utils/getIndeterminateCircle";
|
||||
function toArray(value) {
|
||||
const mergedValue = value ?? [];
|
||||
return Array.isArray(mergedValue) ? mergedValue : [mergedValue];
|
||||
}
|
||||
const Circle = props => {
|
||||
const {
|
||||
id,
|
||||
prefixCls,
|
||||
classNames = {},
|
||||
styles = {},
|
||||
steps,
|
||||
strokeWidth,
|
||||
railWidth,
|
||||
gapDegree = 0,
|
||||
gapPosition,
|
||||
railColor,
|
||||
strokeLinecap,
|
||||
style,
|
||||
className,
|
||||
strokeColor,
|
||||
percent,
|
||||
loading,
|
||||
...restProps
|
||||
} = {
|
||||
...defaultProps,
|
||||
...props
|
||||
};
|
||||
const halfSize = VIEW_BOX_SIZE / 2;
|
||||
const mergedId = useId(id);
|
||||
const gradientId = `${mergedId}-gradient`;
|
||||
const radius = halfSize - strokeWidth / 2;
|
||||
const perimeter = Math.PI * 2 * radius;
|
||||
const rotateDeg = gapDegree > 0 ? 90 + gapDegree / 2 : -90;
|
||||
const perimeterWithoutGap = perimeter * ((360 - gapDegree) / 360);
|
||||
const {
|
||||
count: stepCount,
|
||||
gap: stepGap
|
||||
} = typeof steps === 'object' ? steps : {
|
||||
count: steps,
|
||||
gap: 2
|
||||
};
|
||||
const percentList = toArray(percent);
|
||||
const strokeColorList = toArray(strokeColor);
|
||||
const gradient = strokeColorList.find(color => color && typeof color === 'object');
|
||||
const isConicGradient = gradient && typeof gradient === 'object';
|
||||
const mergedStrokeLinecap = isConicGradient ? 'butt' : strokeLinecap;
|
||||
const {
|
||||
indeterminateStyleProps,
|
||||
indeterminateStyleAnimation
|
||||
} = getIndeterminateCircle({
|
||||
id: mergedId,
|
||||
loading
|
||||
});
|
||||
const circleStyle = getCircleStyle(perimeter, perimeterWithoutGap, 0, 100, rotateDeg, gapDegree, gapPosition, railColor, mergedStrokeLinecap, strokeWidth);
|
||||
const paths = useTransitionDuration();
|
||||
const getStokeList = () => {
|
||||
let stackPtg = 0;
|
||||
return percentList.map((ptg, index) => {
|
||||
const color = strokeColorList[index] || strokeColorList[strokeColorList.length - 1];
|
||||
const circleStyleForStack = getCircleStyle(perimeter, perimeterWithoutGap, stackPtg, ptg, rotateDeg, gapDegree, gapPosition, color, mergedStrokeLinecap, strokeWidth);
|
||||
stackPtg += ptg;
|
||||
return /*#__PURE__*/React.createElement(PtgCircle, {
|
||||
key: index,
|
||||
color: color,
|
||||
ptg: ptg,
|
||||
radius: radius,
|
||||
prefixCls: prefixCls,
|
||||
gradientId: gradientId,
|
||||
className: classNames.track,
|
||||
style: {
|
||||
...circleStyleForStack,
|
||||
...indeterminateStyleProps,
|
||||
...styles.track
|
||||
},
|
||||
strokeLinecap: mergedStrokeLinecap,
|
||||
strokeWidth: strokeWidth,
|
||||
gapDegree: gapDegree,
|
||||
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;
|
||||
},
|
||||
size: VIEW_BOX_SIZE
|
||||
});
|
||||
}).reverse();
|
||||
};
|
||||
const getStepStokeList = () => {
|
||||
// only show the first percent when pass steps
|
||||
const current = Math.round(stepCount * (percentList[0] / 100));
|
||||
const stepPtg = 100 / stepCount;
|
||||
let stackPtg = 0;
|
||||
return new Array(stepCount).fill(null).map((_, index) => {
|
||||
const color = index <= current - 1 ? strokeColorList[0] : railColor;
|
||||
const stroke = color && typeof color === 'object' ? `url(#${gradientId})` : undefined;
|
||||
const circleStyleForStack = getCircleStyle(perimeter, perimeterWithoutGap, stackPtg, stepPtg, rotateDeg, gapDegree, gapPosition, color, 'butt', strokeWidth, stepGap);
|
||||
stackPtg += (perimeterWithoutGap - circleStyleForStack.strokeDashoffset + stepGap) * 100 / perimeterWithoutGap;
|
||||
return /*#__PURE__*/React.createElement("circle", {
|
||||
key: index,
|
||||
className: clsx(`${prefixCls}-circle-path`, classNames.track),
|
||||
r: radius,
|
||||
cx: halfSize,
|
||||
cy: halfSize,
|
||||
stroke: stroke,
|
||||
strokeWidth: strokeWidth,
|
||||
opacity: 1,
|
||||
style: {
|
||||
...circleStyleForStack,
|
||||
...styles.track
|
||||
},
|
||||
ref: elem => {
|
||||
paths[index] = elem;
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
return /*#__PURE__*/React.createElement("svg", _extends({
|
||||
className: clsx(`${prefixCls}-circle`, classNames.root, className),
|
||||
viewBox: `0 0 ${VIEW_BOX_SIZE} ${VIEW_BOX_SIZE}`,
|
||||
style: {
|
||||
...styles.root,
|
||||
...style
|
||||
},
|
||||
id: id,
|
||||
role: "presentation"
|
||||
}, restProps), !stepCount && /*#__PURE__*/React.createElement("circle", {
|
||||
className: clsx(`${prefixCls}-circle-rail`, classNames.rail),
|
||||
r: radius,
|
||||
cx: halfSize,
|
||||
cy: halfSize,
|
||||
stroke: railColor,
|
||||
strokeLinecap: mergedStrokeLinecap,
|
||||
strokeWidth: railWidth || strokeWidth,
|
||||
style: {
|
||||
...circleStyle,
|
||||
...styles.rail
|
||||
}
|
||||
}), stepCount ? getStepStokeList() : getStokeList(), indeterminateStyleAnimation);
|
||||
};
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
Circle.displayName = 'Circle';
|
||||
}
|
||||
export default Circle;
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
import type { StrokeColorType } from '../interface';
|
||||
import type { ProgressProps } from '..';
|
||||
import type React from 'react';
|
||||
export declare const VIEW_BOX_SIZE = 100;
|
||||
export declare const getCircleStyle: (perimeter: number, perimeterWithoutGap: number, offset: number, percent: number, rotateDeg: number, gapDegree: number, gapPosition: ProgressProps['gapPosition'] | undefined, strokeColor: StrokeColorType, strokeLinecap: ProgressProps['strokeLinecap'], strokeWidth: number, stepSpace?: number) => React.CSSProperties;
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
export const VIEW_BOX_SIZE = 100;
|
||||
export const getCircleStyle = (perimeter, perimeterWithoutGap, offset, percent, rotateDeg, gapDegree, gapPosition, strokeColor, strokeLinecap, strokeWidth, stepSpace = 0) => {
|
||||
const offsetDeg = offset / 100 * 360 * ((360 - gapDegree) / 360);
|
||||
const positionDeg = gapDegree === 0 ? 0 : {
|
||||
bottom: 0,
|
||||
top: 180,
|
||||
left: 90,
|
||||
right: -90
|
||||
}[gapPosition];
|
||||
let strokeDashoffset = (100 - percent) / 100 * perimeterWithoutGap;
|
||||
// Fix percent accuracy when strokeLinecap is round
|
||||
// https://github.com/ant-design/ant-design/issues/35009
|
||||
if (strokeLinecap === 'round' && percent !== 100) {
|
||||
strokeDashoffset += strokeWidth / 2;
|
||||
// when percent is small enough (<= 1%), keep smallest value to avoid it's disappearance
|
||||
if (strokeDashoffset >= perimeterWithoutGap) {
|
||||
strokeDashoffset = perimeterWithoutGap - 0.01;
|
||||
}
|
||||
}
|
||||
const halfSize = VIEW_BOX_SIZE / 2;
|
||||
return {
|
||||
stroke: typeof strokeColor === 'string' ? strokeColor : undefined,
|
||||
strokeDasharray: `${perimeterWithoutGap}px ${perimeter}`,
|
||||
strokeDashoffset: strokeDashoffset + stepSpace,
|
||||
transform: `rotate(${rotateDeg + offsetDeg + positionDeg}deg)`,
|
||||
transformOrigin: `${halfSize}px ${halfSize}px`,
|
||||
transition: 'stroke-dashoffset .3s ease 0s, stroke-dasharray .3s ease 0s, stroke .3s, stroke-width .06s ease .3s, opacity .3s ease 0s',
|
||||
fillOpacity: 0
|
||||
};
|
||||
};
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
import * as React from 'react';
|
||||
import type { ProgressProps } from './interface';
|
||||
declare const Line: React.FC<ProgressProps>;
|
||||
export default Line;
|
||||
+105
@@ -0,0 +1,105 @@
|
||||
function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
|
||||
import * as React from 'react';
|
||||
import { clsx } from 'clsx';
|
||||
import { useTransitionDuration, defaultProps } from "./common";
|
||||
import getIndeterminateLine from "./utils/getIndeterminateLine";
|
||||
import useId from "@rc-component/util/es/hooks/useId";
|
||||
const Line = props => {
|
||||
const {
|
||||
id,
|
||||
className,
|
||||
percent,
|
||||
prefixCls,
|
||||
strokeColor,
|
||||
strokeLinecap,
|
||||
strokeWidth,
|
||||
style,
|
||||
railColor,
|
||||
railWidth,
|
||||
transition,
|
||||
loading,
|
||||
...restProps
|
||||
} = {
|
||||
...defaultProps,
|
||||
...props
|
||||
};
|
||||
const mergedId = useId(id);
|
||||
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
delete restProps.gapPosition;
|
||||
const percentList = Array.isArray(percent) ? percent : [percent];
|
||||
const strokeColorList = Array.isArray(strokeColor) ? strokeColor : [strokeColor];
|
||||
const paths = useTransitionDuration();
|
||||
const center = strokeWidth / 2;
|
||||
const right = 100 - strokeWidth / 2;
|
||||
const pathString = `M ${strokeLinecap === 'round' ? center : 0},${center}
|
||||
L ${strokeLinecap === 'round' ? right : 100},${center}`;
|
||||
const viewBoxString = `0 0 100 ${strokeWidth}`;
|
||||
let stackPtg = 0;
|
||||
const {
|
||||
indeterminateStyleProps,
|
||||
indeterminateStyleAnimation
|
||||
} = getIndeterminateLine({
|
||||
id: mergedId,
|
||||
loading,
|
||||
percent: percentList[0],
|
||||
strokeLinecap,
|
||||
strokeWidth
|
||||
});
|
||||
return /*#__PURE__*/React.createElement("svg", _extends({
|
||||
className: clsx(`${prefixCls}-line`, className),
|
||||
viewBox: viewBoxString,
|
||||
preserveAspectRatio: "none",
|
||||
style: style
|
||||
}, restProps), /*#__PURE__*/React.createElement("path", {
|
||||
className: `${prefixCls}-line-rail`,
|
||||
d: pathString,
|
||||
strokeLinecap: strokeLinecap,
|
||||
stroke: railColor,
|
||||
strokeWidth: railWidth || strokeWidth,
|
||||
fillOpacity: "0"
|
||||
}), percentList.map((ptg, index) => {
|
||||
let dashPercent = 1;
|
||||
switch (strokeLinecap) {
|
||||
case 'round':
|
||||
dashPercent = 1 - strokeWidth / 100;
|
||||
break;
|
||||
case 'square':
|
||||
dashPercent = 1 - strokeWidth / 2 / 100;
|
||||
break;
|
||||
default:
|
||||
dashPercent = 1;
|
||||
break;
|
||||
}
|
||||
const pathStyle = {
|
||||
strokeDasharray: `${ptg * dashPercent}px, 100px`,
|
||||
strokeDashoffset: `-${stackPtg}px`,
|
||||
transition: transition || 'stroke-dashoffset 0.3s ease 0s, stroke-dasharray .3s ease 0s, stroke 0.3s linear',
|
||||
...indeterminateStyleProps
|
||||
};
|
||||
const color = strokeColorList[index] || strokeColorList[strokeColorList.length - 1];
|
||||
stackPtg += ptg;
|
||||
return /*#__PURE__*/React.createElement("path", {
|
||||
key: index,
|
||||
className: `${prefixCls}-line-path`,
|
||||
d: pathString,
|
||||
strokeLinecap: strokeLinecap,
|
||||
stroke: color,
|
||||
strokeWidth: strokeWidth,
|
||||
fillOpacity: "0",
|
||||
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
|
||||
});
|
||||
}), indeterminateStyleAnimation);
|
||||
};
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
Line.displayName = 'Line';
|
||||
}
|
||||
export default Line;
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
import type { ProgressProps } from './interface';
|
||||
export declare const defaultProps: Partial<ProgressProps>;
|
||||
export declare const useTransitionDuration: () => SVGPathElement[];
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
import { useRef, useEffect } from 'react';
|
||||
export const defaultProps = {
|
||||
percent: 0,
|
||||
prefixCls: 'rc-progress',
|
||||
strokeColor: '#2db7f5',
|
||||
strokeLinecap: 'round',
|
||||
strokeWidth: 1,
|
||||
railColor: '#D9D9D9',
|
||||
railWidth: 1,
|
||||
gapPosition: 'bottom',
|
||||
loading: false
|
||||
};
|
||||
export const useTransitionDuration = () => {
|
||||
const pathsRef = useRef([]);
|
||||
const prevTimeStamp = useRef(null);
|
||||
useEffect(() => {
|
||||
const now = Date.now();
|
||||
let updated = false;
|
||||
pathsRef.current.forEach(path => {
|
||||
if (!path) {
|
||||
return;
|
||||
}
|
||||
updated = true;
|
||||
const pathStyle = path.style;
|
||||
pathStyle.transitionDuration = '.3s, .3s, .3s, .06s';
|
||||
if (prevTimeStamp.current && now - prevTimeStamp.current < 100) {
|
||||
pathStyle.transitionDuration = '0s, 0s';
|
||||
}
|
||||
});
|
||||
if (updated) {
|
||||
prevTimeStamp.current = Date.now();
|
||||
}
|
||||
});
|
||||
return pathsRef.current;
|
||||
};
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
import Line from './Line';
|
||||
import Circle from './Circle';
|
||||
export type { ProgressProps } from './interface';
|
||||
export { Line, Circle };
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
import Line from "./Line";
|
||||
import Circle from "./Circle";
|
||||
export { Line, Circle };
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
/// <reference types="react" />
|
||||
export type SemanticName = 'root' | 'rail' | 'track';
|
||||
export interface ProgressProps {
|
||||
id?: string;
|
||||
strokeWidth?: number;
|
||||
railWidth?: number;
|
||||
className?: string;
|
||||
classNames?: Partial<Record<SemanticName, string>>;
|
||||
styles?: Partial<Record<SemanticName, React.CSSProperties>>;
|
||||
percent?: number | number[];
|
||||
strokeColor?: StrokeColorType;
|
||||
railColor?: string;
|
||||
strokeLinecap?: StrokeLinecapType;
|
||||
prefixCls?: string;
|
||||
style?: React.CSSProperties;
|
||||
gapDegree?: number;
|
||||
gapPosition?: GapPositionType;
|
||||
transition?: string;
|
||||
onClick?: React.MouseEventHandler;
|
||||
steps?: number | {
|
||||
count: number;
|
||||
gap: number;
|
||||
};
|
||||
loading?: boolean;
|
||||
}
|
||||
export type StrokeColorObject = Record<string, string | boolean>;
|
||||
export type BaseStrokeColorType = string | StrokeColorObject;
|
||||
export type StrokeColorType = BaseStrokeColorType | BaseStrokeColorType[];
|
||||
export type GapPositionType = 'top' | 'right' | 'bottom' | 'left';
|
||||
export type StrokeLinecapType = 'round' | 'butt' | 'square';
|
||||
+1
@@ -0,0 +1 @@
|
||||
export {};
|
||||
Generated
Vendored
+19
@@ -0,0 +1,19 @@
|
||||
import React from 'react';
|
||||
interface IndeterminateOption {
|
||||
id: string;
|
||||
loading: boolean;
|
||||
}
|
||||
declare const _default: ({ id, loading }: IndeterminateOption) => {
|
||||
indeterminateStyleProps: {
|
||||
transform?: undefined;
|
||||
animation?: undefined;
|
||||
};
|
||||
indeterminateStyleAnimation: any;
|
||||
} | {
|
||||
indeterminateStyleProps: {
|
||||
transform: string;
|
||||
animation: string;
|
||||
};
|
||||
indeterminateStyleAnimation: React.JSX.Element;
|
||||
};
|
||||
export default _default;
|
||||
Generated
Vendored
+23
@@ -0,0 +1,23 @@
|
||||
import React from 'react';
|
||||
export default (({
|
||||
id,
|
||||
loading
|
||||
}) => {
|
||||
if (!loading) {
|
||||
return {
|
||||
indeterminateStyleProps: {},
|
||||
indeterminateStyleAnimation: null
|
||||
};
|
||||
}
|
||||
const animationName = `${id}-indeterminate-animate`;
|
||||
return {
|
||||
indeterminateStyleProps: {
|
||||
transform: 'rotate(0deg)',
|
||||
animation: `${animationName} 1s linear infinite`
|
||||
},
|
||||
indeterminateStyleAnimation: /*#__PURE__*/React.createElement("style", null, `@keyframes ${animationName} {
|
||||
0% { transform: rotate(0deg); }
|
||||
100% { transform: rotate(360deg); }
|
||||
}`)
|
||||
};
|
||||
});
|
||||
Generated
Vendored
+25
@@ -0,0 +1,25 @@
|
||||
import type { StrokeLinecapType } from "../interface";
|
||||
import React from 'react';
|
||||
interface IndeterminateOption {
|
||||
id: string;
|
||||
loading: boolean;
|
||||
percent: number;
|
||||
strokeLinecap: StrokeLinecapType;
|
||||
strokeWidth: number;
|
||||
}
|
||||
declare const _default: (options: IndeterminateOption) => {
|
||||
indeterminateStyleProps: {
|
||||
strokeDasharray?: undefined;
|
||||
animation?: undefined;
|
||||
strokeDashoffset?: undefined;
|
||||
};
|
||||
indeterminateStyleAnimation: any;
|
||||
} | {
|
||||
indeterminateStyleProps: {
|
||||
strokeDasharray: string;
|
||||
animation: string;
|
||||
strokeDashoffset: number;
|
||||
};
|
||||
indeterminateStyleAnimation: React.JSX.Element;
|
||||
};
|
||||
export default _default;
|
||||
Generated
Vendored
+29
@@ -0,0 +1,29 @@
|
||||
import React from 'react';
|
||||
export default (options => {
|
||||
const {
|
||||
id,
|
||||
percent,
|
||||
strokeLinecap,
|
||||
strokeWidth,
|
||||
loading
|
||||
} = options;
|
||||
if (!loading) {
|
||||
return {
|
||||
indeterminateStyleProps: {},
|
||||
indeterminateStyleAnimation: null
|
||||
};
|
||||
}
|
||||
const animationName = `${id}-indeterminate-animate`;
|
||||
const strokeDashOffset = 100 - (percent + (strokeLinecap === 'round' ? strokeWidth : 0));
|
||||
return {
|
||||
indeterminateStyleProps: {
|
||||
strokeDasharray: `${percent} 100`,
|
||||
animation: `${animationName} .6s linear alternate infinite`,
|
||||
strokeDashoffset: 0
|
||||
},
|
||||
indeterminateStyleAnimation: /*#__PURE__*/React.createElement("style", null, `@keyframes ${animationName} {
|
||||
0% { stroke-dashoffset: 0; }
|
||||
100% { stroke-dashoffset: -${strokeDashOffset};
|
||||
}`)
|
||||
};
|
||||
});
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
import * as React from 'react';
|
||||
import type { ProgressProps } from '..';
|
||||
import type { StrokeColorObject } from '../interface';
|
||||
export interface ColorGradientProps {
|
||||
prefixCls: string;
|
||||
className?: string;
|
||||
gradientId: string;
|
||||
style: React.CSSProperties;
|
||||
ptg: number;
|
||||
radius: number;
|
||||
strokeLinecap: ProgressProps['strokeLinecap'];
|
||||
strokeWidth: ProgressProps['strokeWidth'];
|
||||
size: number;
|
||||
color: string | StrokeColorObject;
|
||||
gapDegree: number;
|
||||
}
|
||||
declare const PtgCircle: React.ForwardRefExoticComponent<ColorGradientProps & React.RefAttributes<SVGCircleElement>>;
|
||||
export default PtgCircle;
|
||||
+87
@@ -0,0 +1,87 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = void 0;
|
||||
var React = _interopRequireWildcard(require("react"));
|
||||
var _clsx = require("clsx");
|
||||
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
||||
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
||||
const Block = ({
|
||||
bg,
|
||||
children
|
||||
}) => /*#__PURE__*/React.createElement("div", {
|
||||
style: {
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
background: bg
|
||||
}
|
||||
}, children);
|
||||
function getPtgColors(color, scale) {
|
||||
return Object.keys(color).map(key => {
|
||||
const parsedKey = parseFloat(key);
|
||||
const ptgKey = `${Math.floor(parsedKey * scale)}%`;
|
||||
return `${color[key]} ${ptgKey}`;
|
||||
});
|
||||
}
|
||||
const PtgCircle = /*#__PURE__*/React.forwardRef((props, ref) => {
|
||||
const {
|
||||
prefixCls,
|
||||
color,
|
||||
gradientId,
|
||||
radius,
|
||||
className,
|
||||
style: circleStyleForStack,
|
||||
ptg,
|
||||
strokeLinecap,
|
||||
strokeWidth,
|
||||
size,
|
||||
gapDegree
|
||||
} = props;
|
||||
const isGradient = color && typeof color === 'object';
|
||||
const stroke = isGradient ? `#FFF` : undefined;
|
||||
|
||||
// ========================== Circle ==========================
|
||||
const halfSize = size / 2;
|
||||
const circleNode = /*#__PURE__*/React.createElement("circle", {
|
||||
className: (0, _clsx.clsx)(`${prefixCls}-circle-path`, className),
|
||||
r: radius,
|
||||
cx: halfSize,
|
||||
cy: halfSize,
|
||||
stroke: stroke,
|
||||
strokeLinecap: strokeLinecap,
|
||||
strokeWidth: strokeWidth,
|
||||
opacity: ptg === 0 ? 0 : 1,
|
||||
style: circleStyleForStack,
|
||||
ref: ref
|
||||
});
|
||||
|
||||
// ========================== Render ==========================
|
||||
if (!isGradient) {
|
||||
return circleNode;
|
||||
}
|
||||
const maskId = `${gradientId}-conic`;
|
||||
const fromDeg = gapDegree ? `${180 + gapDegree / 2}deg` : '0deg';
|
||||
const conicColors = getPtgColors(color, (360 - gapDegree) / 360);
|
||||
const linearColors = getPtgColors(color, 1);
|
||||
const conicColorBg = `conic-gradient(from ${fromDeg}, ${conicColors.join(', ')})`;
|
||||
const linearColorBg = `linear-gradient(to ${gapDegree ? 'bottom' : 'top'}, ${linearColors.join(', ')})`;
|
||||
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("mask", {
|
||||
id: maskId
|
||||
}, circleNode), /*#__PURE__*/React.createElement("foreignObject", {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: size,
|
||||
height: size,
|
||||
mask: `url(#${maskId})`
|
||||
}, /*#__PURE__*/React.createElement(Block, {
|
||||
bg: linearColorBg
|
||||
}, /*#__PURE__*/React.createElement(Block, {
|
||||
bg: conicColorBg
|
||||
}))));
|
||||
});
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
PtgCircle.displayName = 'PtgCircle';
|
||||
}
|
||||
var _default = exports.default = PtgCircle;
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
import * as React from 'react';
|
||||
import type { ProgressProps } from '../interface';
|
||||
declare const Circle: React.FC<ProgressProps>;
|
||||
export default Circle;
|
||||
+162
@@ -0,0 +1,162 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = void 0;
|
||||
var React = _interopRequireWildcard(require("react"));
|
||||
var _clsx = require("clsx");
|
||||
var _common = require("../common");
|
||||
var _useId = _interopRequireDefault(require("@rc-component/util/lib/hooks/useId"));
|
||||
var _PtgCircle = _interopRequireDefault(require("./PtgCircle"));
|
||||
var _util = require("./util");
|
||||
var _getIndeterminateCircle = _interopRequireDefault(require("../utils/getIndeterminateCircle"));
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
||||
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
||||
function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
|
||||
function toArray(value) {
|
||||
const mergedValue = value ?? [];
|
||||
return Array.isArray(mergedValue) ? mergedValue : [mergedValue];
|
||||
}
|
||||
const Circle = props => {
|
||||
const {
|
||||
id,
|
||||
prefixCls,
|
||||
classNames = {},
|
||||
styles = {},
|
||||
steps,
|
||||
strokeWidth,
|
||||
railWidth,
|
||||
gapDegree = 0,
|
||||
gapPosition,
|
||||
railColor,
|
||||
strokeLinecap,
|
||||
style,
|
||||
className,
|
||||
strokeColor,
|
||||
percent,
|
||||
loading,
|
||||
...restProps
|
||||
} = {
|
||||
..._common.defaultProps,
|
||||
...props
|
||||
};
|
||||
const halfSize = _util.VIEW_BOX_SIZE / 2;
|
||||
const mergedId = (0, _useId.default)(id);
|
||||
const gradientId = `${mergedId}-gradient`;
|
||||
const radius = halfSize - strokeWidth / 2;
|
||||
const perimeter = Math.PI * 2 * radius;
|
||||
const rotateDeg = gapDegree > 0 ? 90 + gapDegree / 2 : -90;
|
||||
const perimeterWithoutGap = perimeter * ((360 - gapDegree) / 360);
|
||||
const {
|
||||
count: stepCount,
|
||||
gap: stepGap
|
||||
} = typeof steps === 'object' ? steps : {
|
||||
count: steps,
|
||||
gap: 2
|
||||
};
|
||||
const percentList = toArray(percent);
|
||||
const strokeColorList = toArray(strokeColor);
|
||||
const gradient = strokeColorList.find(color => color && typeof color === 'object');
|
||||
const isConicGradient = gradient && typeof gradient === 'object';
|
||||
const mergedStrokeLinecap = isConicGradient ? 'butt' : strokeLinecap;
|
||||
const {
|
||||
indeterminateStyleProps,
|
||||
indeterminateStyleAnimation
|
||||
} = (0, _getIndeterminateCircle.default)({
|
||||
id: mergedId,
|
||||
loading
|
||||
});
|
||||
const circleStyle = (0, _util.getCircleStyle)(perimeter, perimeterWithoutGap, 0, 100, rotateDeg, gapDegree, gapPosition, railColor, mergedStrokeLinecap, strokeWidth);
|
||||
const paths = (0, _common.useTransitionDuration)();
|
||||
const getStokeList = () => {
|
||||
let stackPtg = 0;
|
||||
return percentList.map((ptg, index) => {
|
||||
const color = strokeColorList[index] || strokeColorList[strokeColorList.length - 1];
|
||||
const circleStyleForStack = (0, _util.getCircleStyle)(perimeter, perimeterWithoutGap, stackPtg, ptg, rotateDeg, gapDegree, gapPosition, color, mergedStrokeLinecap, strokeWidth);
|
||||
stackPtg += ptg;
|
||||
return /*#__PURE__*/React.createElement(_PtgCircle.default, {
|
||||
key: index,
|
||||
color: color,
|
||||
ptg: ptg,
|
||||
radius: radius,
|
||||
prefixCls: prefixCls,
|
||||
gradientId: gradientId,
|
||||
className: classNames.track,
|
||||
style: {
|
||||
...circleStyleForStack,
|
||||
...indeterminateStyleProps,
|
||||
...styles.track
|
||||
},
|
||||
strokeLinecap: mergedStrokeLinecap,
|
||||
strokeWidth: strokeWidth,
|
||||
gapDegree: gapDegree,
|
||||
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;
|
||||
},
|
||||
size: _util.VIEW_BOX_SIZE
|
||||
});
|
||||
}).reverse();
|
||||
};
|
||||
const getStepStokeList = () => {
|
||||
// only show the first percent when pass steps
|
||||
const current = Math.round(stepCount * (percentList[0] / 100));
|
||||
const stepPtg = 100 / stepCount;
|
||||
let stackPtg = 0;
|
||||
return new Array(stepCount).fill(null).map((_, index) => {
|
||||
const color = index <= current - 1 ? strokeColorList[0] : railColor;
|
||||
const stroke = color && typeof color === 'object' ? `url(#${gradientId})` : undefined;
|
||||
const circleStyleForStack = (0, _util.getCircleStyle)(perimeter, perimeterWithoutGap, stackPtg, stepPtg, rotateDeg, gapDegree, gapPosition, color, 'butt', strokeWidth, stepGap);
|
||||
stackPtg += (perimeterWithoutGap - circleStyleForStack.strokeDashoffset + stepGap) * 100 / perimeterWithoutGap;
|
||||
return /*#__PURE__*/React.createElement("circle", {
|
||||
key: index,
|
||||
className: (0, _clsx.clsx)(`${prefixCls}-circle-path`, classNames.track),
|
||||
r: radius,
|
||||
cx: halfSize,
|
||||
cy: halfSize,
|
||||
stroke: stroke,
|
||||
strokeWidth: strokeWidth,
|
||||
opacity: 1,
|
||||
style: {
|
||||
...circleStyleForStack,
|
||||
...styles.track
|
||||
},
|
||||
ref: elem => {
|
||||
paths[index] = elem;
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
return /*#__PURE__*/React.createElement("svg", _extends({
|
||||
className: (0, _clsx.clsx)(`${prefixCls}-circle`, classNames.root, className),
|
||||
viewBox: `0 0 ${_util.VIEW_BOX_SIZE} ${_util.VIEW_BOX_SIZE}`,
|
||||
style: {
|
||||
...styles.root,
|
||||
...style
|
||||
},
|
||||
id: id,
|
||||
role: "presentation"
|
||||
}, restProps), !stepCount && /*#__PURE__*/React.createElement("circle", {
|
||||
className: (0, _clsx.clsx)(`${prefixCls}-circle-rail`, classNames.rail),
|
||||
r: radius,
|
||||
cx: halfSize,
|
||||
cy: halfSize,
|
||||
stroke: railColor,
|
||||
strokeLinecap: mergedStrokeLinecap,
|
||||
strokeWidth: railWidth || strokeWidth,
|
||||
style: {
|
||||
...circleStyle,
|
||||
...styles.rail
|
||||
}
|
||||
}), stepCount ? getStepStokeList() : getStokeList(), indeterminateStyleAnimation);
|
||||
};
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
Circle.displayName = 'Circle';
|
||||
}
|
||||
var _default = exports.default = Circle;
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
import type { StrokeColorType } from '../interface';
|
||||
import type { ProgressProps } from '..';
|
||||
import type React from 'react';
|
||||
export declare const VIEW_BOX_SIZE = 100;
|
||||
export declare const getCircleStyle: (perimeter: number, perimeterWithoutGap: number, offset: number, percent: number, rotateDeg: number, gapDegree: number, gapPosition: ProgressProps['gapPosition'] | undefined, strokeColor: StrokeColorType, strokeLinecap: ProgressProps['strokeLinecap'], strokeWidth: number, stepSpace?: number) => React.CSSProperties;
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.getCircleStyle = exports.VIEW_BOX_SIZE = void 0;
|
||||
const VIEW_BOX_SIZE = exports.VIEW_BOX_SIZE = 100;
|
||||
const getCircleStyle = (perimeter, perimeterWithoutGap, offset, percent, rotateDeg, gapDegree, gapPosition, strokeColor, strokeLinecap, strokeWidth, stepSpace = 0) => {
|
||||
const offsetDeg = offset / 100 * 360 * ((360 - gapDegree) / 360);
|
||||
const positionDeg = gapDegree === 0 ? 0 : {
|
||||
bottom: 0,
|
||||
top: 180,
|
||||
left: 90,
|
||||
right: -90
|
||||
}[gapPosition];
|
||||
let strokeDashoffset = (100 - percent) / 100 * perimeterWithoutGap;
|
||||
// Fix percent accuracy when strokeLinecap is round
|
||||
// https://github.com/ant-design/ant-design/issues/35009
|
||||
if (strokeLinecap === 'round' && percent !== 100) {
|
||||
strokeDashoffset += strokeWidth / 2;
|
||||
// when percent is small enough (<= 1%), keep smallest value to avoid it's disappearance
|
||||
if (strokeDashoffset >= perimeterWithoutGap) {
|
||||
strokeDashoffset = perimeterWithoutGap - 0.01;
|
||||
}
|
||||
}
|
||||
const halfSize = VIEW_BOX_SIZE / 2;
|
||||
return {
|
||||
stroke: typeof strokeColor === 'string' ? strokeColor : undefined,
|
||||
strokeDasharray: `${perimeterWithoutGap}px ${perimeter}`,
|
||||
strokeDashoffset: strokeDashoffset + stepSpace,
|
||||
transform: `rotate(${rotateDeg + offsetDeg + positionDeg}deg)`,
|
||||
transformOrigin: `${halfSize}px ${halfSize}px`,
|
||||
transition: 'stroke-dashoffset .3s ease 0s, stroke-dasharray .3s ease 0s, stroke .3s, stroke-width .06s ease .3s, opacity .3s ease 0s',
|
||||
fillOpacity: 0
|
||||
};
|
||||
};
|
||||
exports.getCircleStyle = getCircleStyle;
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
import * as React from 'react';
|
||||
import type { ProgressProps } from './interface';
|
||||
declare const Line: React.FC<ProgressProps>;
|
||||
export default Line;
|
||||
+114
@@ -0,0 +1,114 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = void 0;
|
||||
var React = _interopRequireWildcard(require("react"));
|
||||
var _clsx = require("clsx");
|
||||
var _common = require("./common");
|
||||
var _getIndeterminateLine = _interopRequireDefault(require("./utils/getIndeterminateLine"));
|
||||
var _useId = _interopRequireDefault(require("@rc-component/util/lib/hooks/useId"));
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
||||
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
||||
function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
|
||||
const Line = props => {
|
||||
const {
|
||||
id,
|
||||
className,
|
||||
percent,
|
||||
prefixCls,
|
||||
strokeColor,
|
||||
strokeLinecap,
|
||||
strokeWidth,
|
||||
style,
|
||||
railColor,
|
||||
railWidth,
|
||||
transition,
|
||||
loading,
|
||||
...restProps
|
||||
} = {
|
||||
..._common.defaultProps,
|
||||
...props
|
||||
};
|
||||
const mergedId = (0, _useId.default)(id);
|
||||
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
delete restProps.gapPosition;
|
||||
const percentList = Array.isArray(percent) ? percent : [percent];
|
||||
const strokeColorList = Array.isArray(strokeColor) ? strokeColor : [strokeColor];
|
||||
const paths = (0, _common.useTransitionDuration)();
|
||||
const center = strokeWidth / 2;
|
||||
const right = 100 - strokeWidth / 2;
|
||||
const pathString = `M ${strokeLinecap === 'round' ? center : 0},${center}
|
||||
L ${strokeLinecap === 'round' ? right : 100},${center}`;
|
||||
const viewBoxString = `0 0 100 ${strokeWidth}`;
|
||||
let stackPtg = 0;
|
||||
const {
|
||||
indeterminateStyleProps,
|
||||
indeterminateStyleAnimation
|
||||
} = (0, _getIndeterminateLine.default)({
|
||||
id: mergedId,
|
||||
loading,
|
||||
percent: percentList[0],
|
||||
strokeLinecap,
|
||||
strokeWidth
|
||||
});
|
||||
return /*#__PURE__*/React.createElement("svg", _extends({
|
||||
className: (0, _clsx.clsx)(`${prefixCls}-line`, className),
|
||||
viewBox: viewBoxString,
|
||||
preserveAspectRatio: "none",
|
||||
style: style
|
||||
}, restProps), /*#__PURE__*/React.createElement("path", {
|
||||
className: `${prefixCls}-line-rail`,
|
||||
d: pathString,
|
||||
strokeLinecap: strokeLinecap,
|
||||
stroke: railColor,
|
||||
strokeWidth: railWidth || strokeWidth,
|
||||
fillOpacity: "0"
|
||||
}), percentList.map((ptg, index) => {
|
||||
let dashPercent = 1;
|
||||
switch (strokeLinecap) {
|
||||
case 'round':
|
||||
dashPercent = 1 - strokeWidth / 100;
|
||||
break;
|
||||
case 'square':
|
||||
dashPercent = 1 - strokeWidth / 2 / 100;
|
||||
break;
|
||||
default:
|
||||
dashPercent = 1;
|
||||
break;
|
||||
}
|
||||
const pathStyle = {
|
||||
strokeDasharray: `${ptg * dashPercent}px, 100px`,
|
||||
strokeDashoffset: `-${stackPtg}px`,
|
||||
transition: transition || 'stroke-dashoffset 0.3s ease 0s, stroke-dasharray .3s ease 0s, stroke 0.3s linear',
|
||||
...indeterminateStyleProps
|
||||
};
|
||||
const color = strokeColorList[index] || strokeColorList[strokeColorList.length - 1];
|
||||
stackPtg += ptg;
|
||||
return /*#__PURE__*/React.createElement("path", {
|
||||
key: index,
|
||||
className: `${prefixCls}-line-path`,
|
||||
d: pathString,
|
||||
strokeLinecap: strokeLinecap,
|
||||
stroke: color,
|
||||
strokeWidth: strokeWidth,
|
||||
fillOpacity: "0",
|
||||
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
|
||||
});
|
||||
}), indeterminateStyleAnimation);
|
||||
};
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
Line.displayName = 'Line';
|
||||
}
|
||||
var _default = exports.default = Line;
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
import type { ProgressProps } from './interface';
|
||||
export declare const defaultProps: Partial<ProgressProps>;
|
||||
export declare const useTransitionDuration: () => SVGPathElement[];
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.useTransitionDuration = exports.defaultProps = void 0;
|
||||
var _react = require("react");
|
||||
const defaultProps = exports.defaultProps = {
|
||||
percent: 0,
|
||||
prefixCls: 'rc-progress',
|
||||
strokeColor: '#2db7f5',
|
||||
strokeLinecap: 'round',
|
||||
strokeWidth: 1,
|
||||
railColor: '#D9D9D9',
|
||||
railWidth: 1,
|
||||
gapPosition: 'bottom',
|
||||
loading: false
|
||||
};
|
||||
const useTransitionDuration = () => {
|
||||
const pathsRef = (0, _react.useRef)([]);
|
||||
const prevTimeStamp = (0, _react.useRef)(null);
|
||||
(0, _react.useEffect)(() => {
|
||||
const now = Date.now();
|
||||
let updated = false;
|
||||
pathsRef.current.forEach(path => {
|
||||
if (!path) {
|
||||
return;
|
||||
}
|
||||
updated = true;
|
||||
const pathStyle = path.style;
|
||||
pathStyle.transitionDuration = '.3s, .3s, .3s, .06s';
|
||||
if (prevTimeStamp.current && now - prevTimeStamp.current < 100) {
|
||||
pathStyle.transitionDuration = '0s, 0s';
|
||||
}
|
||||
});
|
||||
if (updated) {
|
||||
prevTimeStamp.current = Date.now();
|
||||
}
|
||||
});
|
||||
return pathsRef.current;
|
||||
};
|
||||
exports.useTransitionDuration = useTransitionDuration;
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
import Line from './Line';
|
||||
import Circle from './Circle';
|
||||
export type { ProgressProps } from './interface';
|
||||
export { Line, Circle };
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
Object.defineProperty(exports, "Circle", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _Circle.default;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, "Line", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _Line.default;
|
||||
}
|
||||
});
|
||||
var _Line = _interopRequireDefault(require("./Line"));
|
||||
var _Circle = _interopRequireDefault(require("./Circle"));
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
/// <reference types="react" />
|
||||
export type SemanticName = 'root' | 'rail' | 'track';
|
||||
export interface ProgressProps {
|
||||
id?: string;
|
||||
strokeWidth?: number;
|
||||
railWidth?: number;
|
||||
className?: string;
|
||||
classNames?: Partial<Record<SemanticName, string>>;
|
||||
styles?: Partial<Record<SemanticName, React.CSSProperties>>;
|
||||
percent?: number | number[];
|
||||
strokeColor?: StrokeColorType;
|
||||
railColor?: string;
|
||||
strokeLinecap?: StrokeLinecapType;
|
||||
prefixCls?: string;
|
||||
style?: React.CSSProperties;
|
||||
gapDegree?: number;
|
||||
gapPosition?: GapPositionType;
|
||||
transition?: string;
|
||||
onClick?: React.MouseEventHandler;
|
||||
steps?: number | {
|
||||
count: number;
|
||||
gap: number;
|
||||
};
|
||||
loading?: boolean;
|
||||
}
|
||||
export type StrokeColorObject = Record<string, string | boolean>;
|
||||
export type BaseStrokeColorType = string | StrokeColorObject;
|
||||
export type StrokeColorType = BaseStrokeColorType | BaseStrokeColorType[];
|
||||
export type GapPositionType = 'top' | 'right' | 'bottom' | 'left';
|
||||
export type StrokeLinecapType = 'round' | 'butt' | 'square';
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
Generated
Vendored
+19
@@ -0,0 +1,19 @@
|
||||
import React from 'react';
|
||||
interface IndeterminateOption {
|
||||
id: string;
|
||||
loading: boolean;
|
||||
}
|
||||
declare const _default: ({ id, loading }: IndeterminateOption) => {
|
||||
indeterminateStyleProps: {
|
||||
transform?: undefined;
|
||||
animation?: undefined;
|
||||
};
|
||||
indeterminateStyleAnimation: any;
|
||||
} | {
|
||||
indeterminateStyleProps: {
|
||||
transform: string;
|
||||
animation: string;
|
||||
};
|
||||
indeterminateStyleAnimation: React.JSX.Element;
|
||||
};
|
||||
export default _default;
|
||||
Generated
Vendored
+31
@@ -0,0 +1,31 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = void 0;
|
||||
var _react = _interopRequireDefault(require("react"));
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
var _default = ({
|
||||
id,
|
||||
loading
|
||||
}) => {
|
||||
if (!loading) {
|
||||
return {
|
||||
indeterminateStyleProps: {},
|
||||
indeterminateStyleAnimation: null
|
||||
};
|
||||
}
|
||||
const animationName = `${id}-indeterminate-animate`;
|
||||
return {
|
||||
indeterminateStyleProps: {
|
||||
transform: 'rotate(0deg)',
|
||||
animation: `${animationName} 1s linear infinite`
|
||||
},
|
||||
indeterminateStyleAnimation: /*#__PURE__*/_react.default.createElement("style", null, `@keyframes ${animationName} {
|
||||
0% { transform: rotate(0deg); }
|
||||
100% { transform: rotate(360deg); }
|
||||
}`)
|
||||
};
|
||||
};
|
||||
exports.default = _default;
|
||||
Generated
Vendored
+25
@@ -0,0 +1,25 @@
|
||||
import type { StrokeLinecapType } from "../interface";
|
||||
import React from 'react';
|
||||
interface IndeterminateOption {
|
||||
id: string;
|
||||
loading: boolean;
|
||||
percent: number;
|
||||
strokeLinecap: StrokeLinecapType;
|
||||
strokeWidth: number;
|
||||
}
|
||||
declare const _default: (options: IndeterminateOption) => {
|
||||
indeterminateStyleProps: {
|
||||
strokeDasharray?: undefined;
|
||||
animation?: undefined;
|
||||
strokeDashoffset?: undefined;
|
||||
};
|
||||
indeterminateStyleAnimation: any;
|
||||
} | {
|
||||
indeterminateStyleProps: {
|
||||
strokeDasharray: string;
|
||||
animation: string;
|
||||
strokeDashoffset: number;
|
||||
};
|
||||
indeterminateStyleAnimation: React.JSX.Element;
|
||||
};
|
||||
export default _default;
|
||||
Generated
Vendored
+37
@@ -0,0 +1,37 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = void 0;
|
||||
var _react = _interopRequireDefault(require("react"));
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
var _default = options => {
|
||||
const {
|
||||
id,
|
||||
percent,
|
||||
strokeLinecap,
|
||||
strokeWidth,
|
||||
loading
|
||||
} = options;
|
||||
if (!loading) {
|
||||
return {
|
||||
indeterminateStyleProps: {},
|
||||
indeterminateStyleAnimation: null
|
||||
};
|
||||
}
|
||||
const animationName = `${id}-indeterminate-animate`;
|
||||
const strokeDashOffset = 100 - (percent + (strokeLinecap === 'round' ? strokeWidth : 0));
|
||||
return {
|
||||
indeterminateStyleProps: {
|
||||
strokeDasharray: `${percent} 100`,
|
||||
animation: `${animationName} .6s linear alternate infinite`,
|
||||
strokeDashoffset: 0
|
||||
},
|
||||
indeterminateStyleAnimation: /*#__PURE__*/_react.default.createElement("style", null, `@keyframes ${animationName} {
|
||||
0% { stroke-dashoffset: 0; }
|
||||
100% { stroke-dashoffset: -${strokeDashOffset};
|
||||
}`)
|
||||
};
|
||||
};
|
||||
exports.default = _default;
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
{
|
||||
"name": "@rc-component/progress",
|
||||
"version": "1.0.2",
|
||||
"description": "progress ui component for react",
|
||||
"keywords": [
|
||||
"react",
|
||||
"react-component",
|
||||
"react-progress",
|
||||
"progress"
|
||||
],
|
||||
"homepage": "http://github.com/react-component/progress",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git@github.com:react-component/progress.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "http://github.com/react-component/progress/issues"
|
||||
},
|
||||
"license": "MIT",
|
||||
"main": "./lib/index",
|
||||
"module": "./es/index",
|
||||
"files": [
|
||||
"lib",
|
||||
"es"
|
||||
],
|
||||
"scripts": {
|
||||
"start": "dumi dev",
|
||||
"docs:build": "dumi build",
|
||||
"docs:deploy": "gh-pages -d dist",
|
||||
"deploy": "npm run docs:build && npm run docs:deploy",
|
||||
"compile": "father build",
|
||||
"prepare": "dumi setup",
|
||||
"gh-pages": "npm run now-build && father doc deploy",
|
||||
"prepublishOnly": "npm run compile && rc-np",
|
||||
"lint": "eslint src/ --ext .ts,.tsx,.jsx,.js",
|
||||
"prettier": "prettier --write \"**/*.{ts,tsx,js,jsx,json,md}\"",
|
||||
"test": "rc-test",
|
||||
"tsc": "tsc --noEmit",
|
||||
"coverage": "father test --coverage",
|
||||
"now-build": "npm run docs:build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@rc-component/util": "^1.2.1",
|
||||
"clsx": "^2.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@rc-component/father-plugin": "^2.0.4",
|
||||
"@rc-component/np": "^1.0.4",
|
||||
"@testing-library/react": "^13.0.0",
|
||||
"@types/jest": "^29.4.0",
|
||||
"@types/keyv": "3.1.4",
|
||||
"@types/node": "^24.5.2",
|
||||
"@types/react": "^18.0.9",
|
||||
"@types/react-dom": "^18.0.3",
|
||||
"@umijs/fabric": "^3.0.0",
|
||||
"dumi": "^2.0.0",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-plugin-jest": "^27.6.0",
|
||||
"eslint-plugin-unicorn": "^50.0.1",
|
||||
"father": "^4.0.0",
|
||||
"glob": "^8.0.1",
|
||||
"prettier": "^3.1.1",
|
||||
"rc-test": "^7.0.15",
|
||||
"react": "^18.0.0",
|
||||
"react-dom": "^18.0.0",
|
||||
"typescript": "^5.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=16.9.0",
|
||||
"react-dom": ">=16.9.0"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user