Skip to content

Commit ecfb19e

Browse files
committed
Initial commit
0 parents  commit ecfb19e

File tree

14 files changed

+15103
-0
lines changed

14 files changed

+15103
-0
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
node_modules/
2+
coverage/
3+
build/
4+
debug.log

.prettierignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
build/

.storybook/config.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import {addDecorator} from '@storybook/react'
2+
import {withA11y} from '@storybook/addon-a11y'
3+
4+
addDecorator(withA11y)

.storybook/main.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
module.exports = {
2+
stories: ["../src/**/*.stories.tsx"],
3+
addons: [
4+
"@storybook/addon-docs",
5+
"@storybook/addon-viewport",
6+
"@storybook/addon-a11y",
7+
],
8+
}

.storybook/webpack.config.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
const path = require("path")
2+
3+
module.exports = ({ config }) => {
4+
config.module.rules.push({
5+
test: /\.(ts|tsx)$/,
6+
use: [
7+
{
8+
loader: require.resolve("ts-loader"),
9+
},
10+
{
11+
loader: require.resolve("react-docgen-typescript-loader"),
12+
},
13+
],
14+
})
15+
config.resolve.extensions.push(".ts", ".tsx")
16+
return config
17+
}

README.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# react-usage-bar
2+
3+
## Usage
4+
5+
To install dependencies
6+
7+
```
8+
$ yarn install
9+
```
10+
11+
To build
12+
13+
```
14+
$ yarn build
15+
```
16+
17+
To run tests
18+
19+
```
20+
$ yarn test
21+
```
22+
23+
To run Storybook
24+
25+
```
26+
$ yarn storybook
27+
```

package.json

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
{
2+
"name": "react-usage-bar",
3+
"version": "1.0.0",
4+
"description": "Usage bar, graphic component for React",
5+
"main": "build/index.js",
6+
"module": "build/index.es.js",
7+
"jsnext:main": "build/index.es.js",
8+
"scripts": {
9+
"build": "rollup -c",
10+
"lint": "standard",
11+
"format": "prettier-standard --format",
12+
"test": "jest --coverage",
13+
"storybook": "start-storybook"
14+
},
15+
"keywords": [
16+
"react",
17+
"usage bar",
18+
"design",
19+
"component"
20+
],
21+
"author": {
22+
"name": "ChrisUser",
23+
"url": "https://github.com/ChrisUser"
24+
},
25+
"license": "MIT",
26+
"devDependencies": {
27+
"@babel/core": "^7.9.6",
28+
"@storybook/addon-a11y": "^5.3.19",
29+
"@storybook/addon-docs": "^5.3.19",
30+
"@storybook/addon-viewport": "^5.3.19",
31+
"@storybook/react": "^5.3.19",
32+
"@testing-library/jest-dom": "^5.8.0",
33+
"@testing-library/react": "^10.0.4",
34+
"@types/jest": "^25.2.3",
35+
"@types/react": "^16.9.35",
36+
"@types/react-dom": "^16.9.8",
37+
"awesome-typescript-loader": "^5.2.1",
38+
"babel-loader": "^8.1.0",
39+
"jest": "^26.0.1",
40+
"prettier-standard": "^16.3.0",
41+
"react": "^16.13.1",
42+
"react-docgen-typescript-loader": "^3.7.2",
43+
"react-dom": "^16.13.1",
44+
"rollup": "^2.10.9",
45+
"rollup-plugin-commonjs": "^10.1.0",
46+
"rollup-plugin-node-resolve": "^5.2.0",
47+
"rollup-plugin-peer-deps-external": "^2.2.2",
48+
"rollup-plugin-postcss": "^3.1.1",
49+
"rollup-plugin-terser": "^6.1.0",
50+
"rollup-plugin-typescript2": "^0.27.1",
51+
"standard": "^14.3.4",
52+
"standard-prettier": "^1.0.1",
53+
"ts-jest": "^26.0.0",
54+
"ts-loader": "^7.0.5",
55+
"typescript": "^3.9.3"
56+
},
57+
"peerDependencies": {
58+
"react": "^16",
59+
"react-dom": "^16"
60+
},
61+
"jest": {
62+
"preset": "ts-jest",
63+
"testEnvironment": "jsdom",
64+
"testPathIgnorePatterns": [
65+
"build/"
66+
]
67+
},
68+
"standard": {
69+
"ignore": [
70+
"node_modules/",
71+
"build/"
72+
],
73+
"globals": [
74+
"describe",
75+
"it",
76+
"test",
77+
"expect",
78+
"afterAll",
79+
"jest"
80+
]
81+
}
82+
}

rollup.config.js

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import typescript from "rollup-plugin-typescript2"
2+
import commonjs from "rollup-plugin-commonjs"
3+
import external from "rollup-plugin-peer-deps-external"
4+
import resolve from "rollup-plugin-node-resolve"
5+
import postcss from "rollup-plugin-postcss"
6+
import { terser } from "rollup-plugin-terser"
7+
8+
import pkg from "./package.json"
9+
10+
export default {
11+
input: "src/index.ts",
12+
output: [
13+
{
14+
file: pkg.main,
15+
format: "cjs",
16+
exports: "named",
17+
sourcemap: true,
18+
},
19+
{
20+
file: pkg.module,
21+
format: "es",
22+
exports: "named",
23+
sourcemap: true,
24+
},
25+
],
26+
plugins: [
27+
postcss({
28+
extensions: [".css"],
29+
extract: true,
30+
}),
31+
external(),
32+
resolve(),
33+
typescript({
34+
rollupCommonJSResolveHack: true,
35+
exclude: ["**/__tests__/**", "**/*.stories.tsx"],
36+
clean: true,
37+
}),
38+
terser(),
39+
commonjs({
40+
include: ["node_modules/**"],
41+
namedExports: {
42+
"node_modules/react/react.js": [
43+
"Children",
44+
"Component",
45+
"PropTypes",
46+
"createElement",
47+
],
48+
"node_modules/react-dom/index.js": ["render"],
49+
},
50+
}),
51+
],
52+
}

src/UsageBar.stories.tsx

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import * as React from "react"
2+
import UsageBar from "./UsageBar"
3+
4+
export default { title: "UsageBar", component: UsageBar }
5+
6+
const items = [
7+
{
8+
name: "UI",
9+
value: 10,
10+
color: "#000000",
11+
},
12+
{
13+
name: "Photos",
14+
value: 30,
15+
},
16+
{
17+
name: "Videos",
18+
value: 15,
19+
},
20+
{
21+
name: "System Data",
22+
value: 33,
23+
},
24+
{
25+
name: "Other",
26+
value: 8,
27+
},
28+
]
29+
30+
export const basic = () => <UsageBar items={items} total={100} />
31+
export const withPercentages = () => (
32+
<UsageBar showPercentage={true} items={items} total={100} />
33+
)
34+
export const withoutLabels = () => (
35+
<UsageBar removeLabels={true} items={items} total={100} />
36+
)
37+
export const errors = () => {
38+
return (
39+
<div>
40+
<span>If sum of values exceeds total.</span>
41+
<UsageBar items={items} total={50} />
42+
</div>
43+
)
44+
}

src/UsageBar.tsx

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
import * as React from "react"
2+
import "./styles.css"
3+
4+
interface Item {
5+
color?: string
6+
value: number
7+
name: string
8+
}
9+
10+
interface Props {
11+
items: Item[]
12+
total: number
13+
darkMode?: boolean
14+
removeLabels?: boolean
15+
showPercentage?: boolean
16+
}
17+
18+
const UsageBar: React.FC<Props> = ({
19+
darkMode = false,
20+
removeLabels = false,
21+
showPercentage = false,
22+
total,
23+
items,
24+
}) => {
25+
let usedColors: string[] = []
26+
const colors: string[] = [
27+
"#f44336",
28+
"#03a9f4",
29+
"#ff9800",
30+
"#e91e63",
31+
"#9c27b0",
32+
"#009688",
33+
"#673ab7",
34+
"#4caf50",
35+
"#795548",
36+
"#607d8b",
37+
]
38+
39+
React.useEffect(() => {
40+
if (darkMode)
41+
if (document.documentElement.hasAttribute("theme"))
42+
document.documentElement.removeAttribute("theme")
43+
else document.documentElement.setAttribute("theme", "dark")
44+
else document.documentElement.removeAttribute("theme")
45+
}, [darkMode])
46+
47+
const setColor = () => {
48+
const filteredColors = colors.filter(
49+
(color) =>
50+
usedColors.find((usedColor) => color === usedColor) === undefined
51+
)
52+
const randIndex = Math.floor(Math.random() * filteredColors.length)
53+
const color = filteredColors[randIndex]
54+
usedColors.push(color)
55+
return color
56+
}
57+
58+
const getPercentageValue = (value: number) => {
59+
return ((value / total) * 100).toFixed(0)
60+
}
61+
62+
const uncorrectValues = () => {
63+
return (
64+
total <
65+
items.reduce((tot: number, element: Item) => tot + element.value, 0)
66+
)
67+
}
68+
69+
if (uncorrectValues())
70+
return (
71+
<span style={{ color: "red" }}>
72+
Error: Elements values exceed the total.
73+
</span>
74+
)
75+
76+
return (
77+
<div className="panel">
78+
<div className="bar">
79+
{items.map((element: Item) => {
80+
return (
81+
<div
82+
className="element"
83+
style={{
84+
width: `${getPercentageValue(element.value)}%`,
85+
backgroundColor: element.color || setColor(),
86+
}}
87+
>
88+
{removeLabels ? (
89+
""
90+
) : (
91+
<div className="tooltip">
92+
{element.name +
93+
" " +
94+
(showPercentage
95+
? getPercentageValue(element.value) + "%"
96+
: "")}
97+
</div>
98+
)}
99+
</div>
100+
)
101+
})}
102+
</div>
103+
</div>
104+
)
105+
}
106+
107+
export default UsageBar

0 commit comments

Comments
 (0)