├── .gitignore ├── .npmignore ├── .travis.yml ├── .babelrc ├── demo ├── src │ ├── index.css │ ├── index.js │ ├── Demo.css │ └── Demo.js ├── .gitignore ├── package.json └── public │ └── index.html ├── src ├── ProgressArc.test.js ├── __snapshots__ │ └── ProgressArc.test.js.snap └── ProgressArc.js ├── package.json └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | lib 3 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | demo 2 | __snapshots__ 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "6" 4 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["@babel/preset-env", "@babel/preset-react"] 3 | } 4 | -------------------------------------------------------------------------------- /demo/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding-top: 1em; 3 | padding-bottom: 1em; 4 | } 5 | -------------------------------------------------------------------------------- /demo/src/index.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import ReactDOM from "react-dom" 3 | import Demo from "./Demo" 4 | import "./index.css" 5 | 6 | ReactDOM.render(, document.getElementById("root")) 7 | -------------------------------------------------------------------------------- /demo/.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | node_modules 5 | 6 | # testing 7 | coverage 8 | 9 | # production 10 | build 11 | 12 | # misc 13 | .DS_Store 14 | .env 15 | npm-debug.log 16 | -------------------------------------------------------------------------------- /demo/src/Demo.css: -------------------------------------------------------------------------------- 1 | .demo { 2 | text-align: center; 3 | margin: 1em auto; 4 | } 5 | 6 | .code { 7 | margin: 1em auto; 8 | padding: 1em; 9 | text-align: left; 10 | overflow: auto; 11 | font-size: 85%; 12 | line-height: 1.45; 13 | background-color: #f7f7f7; 14 | border-radius: 3px; 15 | } 16 | -------------------------------------------------------------------------------- /demo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "arc", 3 | "version": "0.1.0", 4 | "private": true, 5 | "devDependencies": { 6 | "gh-pages": "^1.1.0", 7 | "react-scripts": "^1.1.1" 8 | }, 9 | "dependencies": { 10 | "prop-types": "^15.6.1", 11 | "react": "^16.2.0", 12 | "react-dom": "^16.2.0", 13 | "styled-components": "^3.2.2" 14 | }, 15 | "scripts": { 16 | "start": "react-scripts start", 17 | "build": "react-scripts build", 18 | "test": "react-scripts test --env=jsdom", 19 | "eject": "react-scripts eject", 20 | "deploy": "npm run build&&gh-pages -d build" 21 | }, 22 | "homepage": "http://szastupov.github.io/progress-arc-component" 23 | } 24 | -------------------------------------------------------------------------------- /src/ProgressArc.test.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import ReactDOM from "react-dom" 3 | import renderer from "react-test-renderer" 4 | import ProgressArc from "./ProgressArc" 5 | 6 | it("renders with default props", () => { 7 | const div = document.createElement("div") 8 | ReactDOM.render(, div) 9 | }) 10 | 11 | it("renders value", () => { 12 | const tree = renderer.create() 13 | expect(tree).toMatchSnapshot() 14 | }) 15 | 16 | it("renders custom units", () => { 17 | const tree = renderer.create() 18 | expect(tree).toMatchSnapshot() 19 | }) 20 | 21 | it("renders with custom colors", () => { 22 | const tree = renderer.create( 23 | 24 | ) 25 | expect(tree).toMatchSnapshot() 26 | }) 27 | 28 | it("disables text", () => { 29 | const tree = renderer.create() 30 | expect(tree).toMatchSnapshot() 31 | }) 32 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "progress-arc-component", 3 | "version": "2.7.0", 4 | "description": "Simple progress arc for React, customizable with styled-components", 5 | "main": "lib/ProgressArc.js", 6 | "repository": "https://github.com/szastupov/progress-arc-component.git", 7 | "author": "Stepan Zastupov ", 8 | "keywords": [ 9 | "react", 10 | "progress", 11 | "bar", 12 | "progress", 13 | "arc", 14 | "styled-components" 15 | ], 16 | "license": "MIT", 17 | "dependencies": { 18 | "styled-components": "^5.1.1" 19 | }, 20 | "peerDependencies": { 21 | "prop-types": "^15.5.8", 22 | "react": "^15.5.4", 23 | "react-dom": "^15.5.4" 24 | }, 25 | "devDependencies": { 26 | "@babel/cli": "^7.0.0", 27 | "@babel/core": "^7.0.0", 28 | "@babel/preset-env": "^7.0.0", 29 | "@babel/preset-react": "^7.0.0", 30 | "babel-core": "^7.0.0-bridge.0", 31 | "babel-jest": "^23.4.2", 32 | "husky": "^4.2.5", 33 | "jest": "^26.1.0", 34 | "lint-staged": "^10.2.11", 35 | "prettier": "^2.0.5", 36 | "prop-types": "^15.7.2", 37 | "react": "^16.13.1", 38 | "react-dom": "^16.13.1", 39 | "react-test-renderer": "^16.13.1" 40 | }, 41 | "scripts": { 42 | "build": "babel src -d lib", 43 | "dev": "babel -w src -d lib", 44 | "prepublish": "npm run build", 45 | "test": "jest", 46 | "test:update": "jest -u", 47 | "precommit": "lint-staged" 48 | }, 49 | "jest": { 50 | "testPathIgnorePatterns": [ 51 | "/node_modules/", 52 | "/lib/" 53 | ] 54 | }, 55 | "lint-staged": { 56 | "*.js": [ 57 | "prettier --no-semi --write", 58 | "git add" 59 | ] 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Simple progress arc for React ([demo](http://szastupov.github.io/progress-arc-component)) [![NPM version][npm-image]][npm-link] [![Build status][travis-image]][travis-link] 2 | 3 | ## Installation 4 | 5 | $ yarn add progress-arc-component 6 | 7 | ## Usage 8 | 9 | ```javascript 10 | import ProgressArc from 'progress-arc-component' 11 | 12 | 13 | ``` 14 | 15 | ![ProgressArc screenshot](http://i.imgur.com/vgxgdi9.png) 16 | 17 | ### Properties 18 | 19 | Name | Description | Default 20 | :------------------- | :------------------- | :------ 21 | *value* | Current progress | 0 22 | *max* | Maximum value | 100 23 | *unit* | Value unit | % 24 | *arcColor* | Progress arc color | #818a91 25 | *arcBackgroundColor* | Arc background color | #eceeef 26 | *textColor* | Text color | #818a91 27 | *textVisible* | Show text inside arc | true 28 | *radius* | Arc radius | 90 29 | *rounded* | Draw rounded corners | false 30 | 31 | ### Customization 32 | 33 | ProgressArc generates SVG that can be tweaked with [styled-components][1]: 34 | 35 | ```javascript 36 | import styled from 'styled-components' 37 | 38 | const StyledProgressArc = styled(ProgressArc)` 39 | height: 12em; 40 | width: 12em; 41 | border: 0.3em solid black; 42 | border-radius: 0.5em; 43 | padding: 1em; 44 | ` 45 | ``` 46 | 47 | 48 | [1]: https://github.com/styled-components/styled-components 49 | [npm-image]: https://img.shields.io/npm/v/progress-arc-component.svg?style=flat 50 | [npm-link]: https://npmjs.org/package/progress-arc-component 51 | [travis-image]: https://img.shields.io/travis/szastupov/progress-arc-component.svg?style=flat 52 | [travis-link]: https://travis-ci.org/szastupov/progress-arc-component 53 | -------------------------------------------------------------------------------- /src/__snapshots__/ProgressArc.test.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`disables text 1`] = ` 4 | 8 | 12 | 18 | 19 | `; 20 | 21 | exports[`renders custom units 1`] = ` 22 | 26 | 30 | 36 | 41 | 42GB 42 | 43 | 44 | `; 45 | 46 | exports[`renders value 1`] = ` 47 | 51 | 55 | 61 | 66 | 42% 67 | 68 | 69 | `; 70 | 71 | exports[`renders with custom colors 1`] = ` 72 | 76 | 80 | 86 | 91 | 99% 92 | 93 | 94 | `; 95 | -------------------------------------------------------------------------------- /demo/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Progress arc component for React 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/ProgressArc.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import PropTypes from "prop-types" 3 | import styled from "styled-components" 4 | 5 | const Svg = styled.svg` 6 | display: block; 7 | margin: 1em auto; 8 | width: 100%; 9 | height: 6em; 10 | 11 | circle { 12 | fill: none; 13 | stroke-width: 20; 14 | transform: translate(100px, 100px) rotate(-89.9deg); 15 | transition: stroke-dashoffset 0.3s linear; 16 | } 17 | 18 | .arc-background { 19 | stroke: ${props => props.arcBackgroundColor}; 20 | } 21 | 22 | .arc { 23 | stroke: ${props => props.arcColor}; 24 | stroke-linecap: ${props => (props.rounded ? "round" : "inherit")}; 25 | } 26 | 27 | text { 28 | fill: ${props => props.textColor}; 29 | font-size: 50px; 30 | font-weight: 600; 31 | text-anchor: middle; 32 | } 33 | ` 34 | 35 | function ProgressArc({ 36 | value, 37 | max, 38 | className, 39 | unit, 40 | arcColor, 41 | arcBackgroundColor, 42 | textColor, 43 | textVisible, 44 | radius, 45 | rounded, 46 | dominantBaseline 47 | }) { 48 | const p = 2 * radius * Math.PI 49 | return ( 50 | 58 | 59 | 60 | 66 | 67 | {textVisible && 68 | {`${value}${unit}`}} 73 | 74 | ) 75 | } 76 | 77 | ProgressArc.propTypes = { 78 | value: PropTypes.number.isRequired, 79 | max: PropTypes.number, 80 | unit: PropTypes.string, 81 | arcColor: PropTypes.string, 82 | arcBackgroundColor: PropTypes.string, 83 | textColor: PropTypes.string, 84 | textVisible: PropTypes.bool, 85 | radius: PropTypes.number, 86 | rounded: PropTypes.bool 87 | } 88 | 89 | ProgressArc.defaultProps = { 90 | value: 0, 91 | max: 100, 92 | unit: "%", 93 | arcColor: "#818a91", 94 | arcBackgroundColor: "#eceeef", 95 | textColor: "#818a91", 96 | textVisible: true, 97 | radius: 90, 98 | rounded: false, 99 | dominantBaseline: "middle" 100 | } 101 | 102 | export default ProgressArc 103 | -------------------------------------------------------------------------------- /demo/src/Demo.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from "react" 2 | import ProgressArc from "progress-arc-component" 3 | import styled from "styled-components" 4 | import "./Demo.css" 5 | 6 | const Code = ({ text }) => 7 |
  8 |     {text}
  9 |   
10 | 11 | class Default extends Component { 12 | state = { 13 | prog: 50 14 | } 15 | 16 | render() { 17 | let { prog } = this.state 18 | 19 | return ( 20 |
21 |

Default

22 | 23 | this.setState({ prog: e.target.value })} 29 | /> 30 | 31 |
32 | ) 33 | } 34 | } 35 | 36 | // ProgressArc is a styled component and can easily be restyled 37 | 38 | const RedArc = styled(ProgressArc)` 39 | height: 12em; 40 | width: 12em; 41 | border: 0.3em solid black; 42 | border-radius: 0.5em; 43 | padding: 1em; 44 | ` 45 | 46 | // TODO: figure out something to avoid code duplication 47 | const styledCode = `// With styled-components 48 | const RedArc = styled(ProgressArc)\` 49 | height: 12em; 50 | width: 12em; 51 | border: 0.3em solid black; 52 | border-radius: 0.5em; 53 | padding: 1em; 54 | \` 55 | 56 | // By passing common props 57 | 63 | ` 64 | 65 | class Custom extends Component { 66 | state = { 67 | prog: 60 68 | } 69 | 70 | render() { 71 | let { prog } = this.state 72 | 73 | return ( 74 |
75 |

Styled

76 | 77 | 78 | 79 | this.setState({ prog: e.target.value })} 85 | /> 86 | 87 |
88 | ) 89 | } 90 | } 91 | 92 | // You can pass max and unit values 93 | 94 | const unitsCode = `` 96 | 97 | class Memory extends Component { 98 | state = { 99 | prog: 60 100 | } 101 | 102 | render() { 103 | let { prog } = this.state 104 | 105 | return ( 106 |
107 |

Custom units

108 | 109 | this.setState({ prog: e.target.value })} 115 | /> 116 | 117 |
118 | ) 119 | } 120 | } 121 | 122 | class Demo extends Component { 123 | render() { 124 | return ( 125 |
126 |
127 | 128 |
129 | 130 |
131 | 132 | 133 | 134 |
135 |
136 | ) 137 | } 138 | } 139 | 140 | export default Demo 141 | --------------------------------------------------------------------------------