react-stat-card-poc 1.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -0
- package/dist/index.css +67 -0
- package/dist/index.esm.css +67 -0
- package/dist/index.esm.js +222 -0
- package/dist/index.js +227 -0
- package/package.json +29 -0
package/README.md
ADDED
package/dist/index.css
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* react-circular-progressbar styles
|
|
3
|
+
* All of the styles in this file are configurable!
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
.CircularProgressbar {
|
|
7
|
+
/*
|
|
8
|
+
* This fixes an issue where the CircularProgressbar svg has
|
|
9
|
+
* 0 width inside a "display: flex" container, and thus not visible.
|
|
10
|
+
*/
|
|
11
|
+
width: 100%;
|
|
12
|
+
/*
|
|
13
|
+
* This fixes a centering issue with CircularProgressbarWithChildren:
|
|
14
|
+
* https://github.com/kevinsqi/react-circular-progressbar/issues/94
|
|
15
|
+
*/
|
|
16
|
+
vertical-align: middle;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.CircularProgressbar .CircularProgressbar-path {
|
|
20
|
+
stroke: #3e98c7;
|
|
21
|
+
stroke-linecap: round;
|
|
22
|
+
-webkit-transition: stroke-dashoffset 0.5s ease 0s;
|
|
23
|
+
transition: stroke-dashoffset 0.5s ease 0s;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.CircularProgressbar .CircularProgressbar-trail {
|
|
27
|
+
stroke: #d6d6d6;
|
|
28
|
+
/* Used when trail is not full diameter, i.e. when props.circleRatio is set */
|
|
29
|
+
stroke-linecap: round;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.CircularProgressbar .CircularProgressbar-text {
|
|
33
|
+
fill: #3e98c7;
|
|
34
|
+
font-size: 20px;
|
|
35
|
+
dominant-baseline: middle;
|
|
36
|
+
text-anchor: middle;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.CircularProgressbar .CircularProgressbar-background {
|
|
40
|
+
fill: #d6d6d6;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/*
|
|
44
|
+
* Sample background styles. Use these with e.g.:
|
|
45
|
+
*
|
|
46
|
+
* <CircularProgressbar
|
|
47
|
+
* className="CircularProgressbar-inverted"
|
|
48
|
+
* background
|
|
49
|
+
* percentage={50}
|
|
50
|
+
* />
|
|
51
|
+
*/
|
|
52
|
+
.CircularProgressbar.CircularProgressbar-inverted .CircularProgressbar-background {
|
|
53
|
+
fill: #3e98c7;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.CircularProgressbar.CircularProgressbar-inverted .CircularProgressbar-text {
|
|
57
|
+
fill: #fff;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.CircularProgressbar.CircularProgressbar-inverted .CircularProgressbar-path {
|
|
61
|
+
stroke: #fff;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.CircularProgressbar.CircularProgressbar-inverted .CircularProgressbar-trail {
|
|
65
|
+
stroke: transparent;
|
|
66
|
+
}
|
|
67
|
+
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* react-circular-progressbar styles
|
|
3
|
+
* All of the styles in this file are configurable!
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
.CircularProgressbar {
|
|
7
|
+
/*
|
|
8
|
+
* This fixes an issue where the CircularProgressbar svg has
|
|
9
|
+
* 0 width inside a "display: flex" container, and thus not visible.
|
|
10
|
+
*/
|
|
11
|
+
width: 100%;
|
|
12
|
+
/*
|
|
13
|
+
* This fixes a centering issue with CircularProgressbarWithChildren:
|
|
14
|
+
* https://github.com/kevinsqi/react-circular-progressbar/issues/94
|
|
15
|
+
*/
|
|
16
|
+
vertical-align: middle;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.CircularProgressbar .CircularProgressbar-path {
|
|
20
|
+
stroke: #3e98c7;
|
|
21
|
+
stroke-linecap: round;
|
|
22
|
+
-webkit-transition: stroke-dashoffset 0.5s ease 0s;
|
|
23
|
+
transition: stroke-dashoffset 0.5s ease 0s;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.CircularProgressbar .CircularProgressbar-trail {
|
|
27
|
+
stroke: #d6d6d6;
|
|
28
|
+
/* Used when trail is not full diameter, i.e. when props.circleRatio is set */
|
|
29
|
+
stroke-linecap: round;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.CircularProgressbar .CircularProgressbar-text {
|
|
33
|
+
fill: #3e98c7;
|
|
34
|
+
font-size: 20px;
|
|
35
|
+
dominant-baseline: middle;
|
|
36
|
+
text-anchor: middle;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.CircularProgressbar .CircularProgressbar-background {
|
|
40
|
+
fill: #d6d6d6;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/*
|
|
44
|
+
* Sample background styles. Use these with e.g.:
|
|
45
|
+
*
|
|
46
|
+
* <CircularProgressbar
|
|
47
|
+
* className="CircularProgressbar-inverted"
|
|
48
|
+
* background
|
|
49
|
+
* percentage={50}
|
|
50
|
+
* />
|
|
51
|
+
*/
|
|
52
|
+
.CircularProgressbar.CircularProgressbar-inverted .CircularProgressbar-background {
|
|
53
|
+
fill: #3e98c7;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.CircularProgressbar.CircularProgressbar-inverted .CircularProgressbar-text {
|
|
57
|
+
fill: #fff;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.CircularProgressbar.CircularProgressbar-inverted .CircularProgressbar-path {
|
|
61
|
+
stroke: #fff;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.CircularProgressbar.CircularProgressbar-inverted .CircularProgressbar-trail {
|
|
65
|
+
stroke: transparent;
|
|
66
|
+
}
|
|
67
|
+
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import React, { createElement, Component } from 'react';
|
|
2
|
+
|
|
3
|
+
/*! *****************************************************************************
|
|
4
|
+
Copyright (c) Microsoft Corporation. All rights reserved.
|
|
5
|
+
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
|
6
|
+
this file except in compliance with the License. You may obtain a copy of the
|
|
7
|
+
License at http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
|
|
9
|
+
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
10
|
+
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
|
11
|
+
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
|
12
|
+
MERCHANTABLITY OR NON-INFRINGEMENT.
|
|
13
|
+
|
|
14
|
+
See the Apache Version 2.0 License for specific language governing permissions
|
|
15
|
+
and limitations under the License.
|
|
16
|
+
***************************************************************************** */
|
|
17
|
+
/* global Reflect, Promise */
|
|
18
|
+
|
|
19
|
+
var extendStatics = function(d, b) {
|
|
20
|
+
extendStatics = Object.setPrototypeOf ||
|
|
21
|
+
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
|
22
|
+
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
|
|
23
|
+
return extendStatics(d, b);
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
function __extends(d, b) {
|
|
27
|
+
extendStatics(d, b);
|
|
28
|
+
function __() { this.constructor = d; }
|
|
29
|
+
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
var VIEWBOX_WIDTH = 100;
|
|
33
|
+
var VIEWBOX_HEIGHT = 100;
|
|
34
|
+
var VIEWBOX_HEIGHT_HALF = 50;
|
|
35
|
+
var VIEWBOX_CENTER_X = 50;
|
|
36
|
+
var VIEWBOX_CENTER_Y = 50;
|
|
37
|
+
|
|
38
|
+
function Path(_a) {
|
|
39
|
+
var className = _a.className, counterClockwise = _a.counterClockwise, dashRatio = _a.dashRatio, pathRadius = _a.pathRadius, strokeWidth = _a.strokeWidth, style = _a.style;
|
|
40
|
+
return (createElement("path", { className: className, style: Object.assign({}, style, getDashStyle({ pathRadius: pathRadius, dashRatio: dashRatio, counterClockwise: counterClockwise })), d: getPathDescription({
|
|
41
|
+
pathRadius: pathRadius,
|
|
42
|
+
counterClockwise: counterClockwise,
|
|
43
|
+
}), strokeWidth: strokeWidth, fillOpacity: 0 }));
|
|
44
|
+
}
|
|
45
|
+
function getPathDescription(_a) {
|
|
46
|
+
var pathRadius = _a.pathRadius, counterClockwise = _a.counterClockwise;
|
|
47
|
+
var radius = pathRadius;
|
|
48
|
+
var rotation = counterClockwise ? 1 : 0;
|
|
49
|
+
return "\n M " + VIEWBOX_CENTER_X + "," + VIEWBOX_CENTER_Y + "\n m 0,-" + radius + "\n a " + radius + "," + radius + " " + rotation + " 1 1 0," + 2 * radius + "\n a " + radius + "," + radius + " " + rotation + " 1 1 0,-" + 2 * radius + "\n ";
|
|
50
|
+
}
|
|
51
|
+
function getDashStyle(_a) {
|
|
52
|
+
var counterClockwise = _a.counterClockwise, dashRatio = _a.dashRatio, pathRadius = _a.pathRadius;
|
|
53
|
+
var diameter = Math.PI * 2 * pathRadius;
|
|
54
|
+
var gapLength = (1 - dashRatio) * diameter;
|
|
55
|
+
return {
|
|
56
|
+
strokeDasharray: diameter + "px " + diameter + "px",
|
|
57
|
+
strokeDashoffset: (counterClockwise ? -gapLength : gapLength) + "px",
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
var CircularProgressbar = (function (_super) {
|
|
62
|
+
__extends(CircularProgressbar, _super);
|
|
63
|
+
function CircularProgressbar() {
|
|
64
|
+
return _super !== null && _super.apply(this, arguments) || this;
|
|
65
|
+
}
|
|
66
|
+
CircularProgressbar.prototype.getBackgroundPadding = function () {
|
|
67
|
+
if (!this.props.background) {
|
|
68
|
+
return 0;
|
|
69
|
+
}
|
|
70
|
+
return this.props.backgroundPadding;
|
|
71
|
+
};
|
|
72
|
+
CircularProgressbar.prototype.getPathRadius = function () {
|
|
73
|
+
return VIEWBOX_HEIGHT_HALF - this.props.strokeWidth / 2 - this.getBackgroundPadding();
|
|
74
|
+
};
|
|
75
|
+
CircularProgressbar.prototype.getPathRatio = function () {
|
|
76
|
+
var _a = this.props, value = _a.value, minValue = _a.minValue, maxValue = _a.maxValue;
|
|
77
|
+
var boundedValue = Math.min(Math.max(value, minValue), maxValue);
|
|
78
|
+
return (boundedValue - minValue) / (maxValue - minValue);
|
|
79
|
+
};
|
|
80
|
+
CircularProgressbar.prototype.render = function () {
|
|
81
|
+
var _a = this.props, circleRatio = _a.circleRatio, className = _a.className, classes = _a.classes, counterClockwise = _a.counterClockwise, styles = _a.styles, strokeWidth = _a.strokeWidth, text = _a.text;
|
|
82
|
+
var pathRadius = this.getPathRadius();
|
|
83
|
+
var pathRatio = this.getPathRatio();
|
|
84
|
+
return (createElement("svg", { className: classes.root + " " + className, style: styles.root, viewBox: "0 0 " + VIEWBOX_WIDTH + " " + VIEWBOX_HEIGHT, "data-test-id": "CircularProgressbar" },
|
|
85
|
+
this.props.background ? (createElement("circle", { className: classes.background, style: styles.background, cx: VIEWBOX_CENTER_X, cy: VIEWBOX_CENTER_Y, r: VIEWBOX_HEIGHT_HALF })) : null,
|
|
86
|
+
createElement(Path, { className: classes.trail, counterClockwise: counterClockwise, dashRatio: circleRatio, pathRadius: pathRadius, strokeWidth: strokeWidth, style: styles.trail }),
|
|
87
|
+
createElement(Path, { className: classes.path, counterClockwise: counterClockwise, dashRatio: pathRatio * circleRatio, pathRadius: pathRadius, strokeWidth: strokeWidth, style: styles.path }),
|
|
88
|
+
text ? (createElement("text", { className: classes.text, style: styles.text, x: VIEWBOX_CENTER_X, y: VIEWBOX_CENTER_Y }, text)) : null));
|
|
89
|
+
};
|
|
90
|
+
CircularProgressbar.defaultProps = {
|
|
91
|
+
background: false,
|
|
92
|
+
backgroundPadding: 0,
|
|
93
|
+
circleRatio: 1,
|
|
94
|
+
classes: {
|
|
95
|
+
root: 'CircularProgressbar',
|
|
96
|
+
trail: 'CircularProgressbar-trail',
|
|
97
|
+
path: 'CircularProgressbar-path',
|
|
98
|
+
text: 'CircularProgressbar-text',
|
|
99
|
+
background: 'CircularProgressbar-background',
|
|
100
|
+
},
|
|
101
|
+
counterClockwise: false,
|
|
102
|
+
className: '',
|
|
103
|
+
maxValue: 100,
|
|
104
|
+
minValue: 0,
|
|
105
|
+
strokeWidth: 8,
|
|
106
|
+
styles: {
|
|
107
|
+
root: {},
|
|
108
|
+
trail: {},
|
|
109
|
+
path: {},
|
|
110
|
+
text: {},
|
|
111
|
+
background: {},
|
|
112
|
+
},
|
|
113
|
+
text: '',
|
|
114
|
+
};
|
|
115
|
+
return CircularProgressbar;
|
|
116
|
+
}(Component));
|
|
117
|
+
|
|
118
|
+
function buildStyles(_a) {
|
|
119
|
+
var rotation = _a.rotation, strokeLinecap = _a.strokeLinecap, textColor = _a.textColor, textSize = _a.textSize, pathColor = _a.pathColor, pathTransition = _a.pathTransition, pathTransitionDuration = _a.pathTransitionDuration, trailColor = _a.trailColor, backgroundColor = _a.backgroundColor;
|
|
120
|
+
var rotationTransform = rotation == null ? undefined : "rotate(" + rotation + "turn)";
|
|
121
|
+
var rotationTransformOrigin = rotation == null ? undefined : 'center center';
|
|
122
|
+
return {
|
|
123
|
+
root: {},
|
|
124
|
+
path: removeUndefinedValues({
|
|
125
|
+
stroke: pathColor,
|
|
126
|
+
strokeLinecap: strokeLinecap,
|
|
127
|
+
transform: rotationTransform,
|
|
128
|
+
transformOrigin: rotationTransformOrigin,
|
|
129
|
+
transition: pathTransition,
|
|
130
|
+
transitionDuration: pathTransitionDuration == null ? undefined : pathTransitionDuration + "s",
|
|
131
|
+
}),
|
|
132
|
+
trail: removeUndefinedValues({
|
|
133
|
+
stroke: trailColor,
|
|
134
|
+
strokeLinecap: strokeLinecap,
|
|
135
|
+
transform: rotationTransform,
|
|
136
|
+
transformOrigin: rotationTransformOrigin,
|
|
137
|
+
}),
|
|
138
|
+
text: removeUndefinedValues({
|
|
139
|
+
fill: textColor,
|
|
140
|
+
fontSize: textSize,
|
|
141
|
+
}),
|
|
142
|
+
background: removeUndefinedValues({
|
|
143
|
+
fill: backgroundColor,
|
|
144
|
+
}),
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
function removeUndefinedValues(obj) {
|
|
148
|
+
Object.keys(obj).forEach(function (key) {
|
|
149
|
+
if (obj[key] == null) {
|
|
150
|
+
delete obj[key];
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
return obj;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function styleInject(css, ref) {
|
|
157
|
+
if ( ref === void 0 ) ref = {};
|
|
158
|
+
var insertAt = ref.insertAt;
|
|
159
|
+
|
|
160
|
+
if (!css || typeof document === 'undefined') { return; }
|
|
161
|
+
|
|
162
|
+
var head = document.head || document.getElementsByTagName('head')[0];
|
|
163
|
+
var style = document.createElement('style');
|
|
164
|
+
style.type = 'text/css';
|
|
165
|
+
|
|
166
|
+
if (insertAt === 'top') {
|
|
167
|
+
if (head.firstChild) {
|
|
168
|
+
head.insertBefore(style, head.firstChild);
|
|
169
|
+
} else {
|
|
170
|
+
head.appendChild(style);
|
|
171
|
+
}
|
|
172
|
+
} else {
|
|
173
|
+
head.appendChild(style);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
if (style.styleSheet) {
|
|
177
|
+
style.styleSheet.cssText = css;
|
|
178
|
+
} else {
|
|
179
|
+
style.appendChild(document.createTextNode(css));
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
var css_248z$1 = "/*\n * react-circular-progressbar styles\n * All of the styles in this file are configurable!\n */\n\n.CircularProgressbar {\n /*\n * This fixes an issue where the CircularProgressbar svg has\n * 0 width inside a \"display: flex\" container, and thus not visible.\n */\n width: 100%;\n /*\n * This fixes a centering issue with CircularProgressbarWithChildren:\n * https://github.com/kevinsqi/react-circular-progressbar/issues/94\n */\n vertical-align: middle;\n}\n\n.CircularProgressbar .CircularProgressbar-path {\n stroke: #3e98c7;\n stroke-linecap: round;\n -webkit-transition: stroke-dashoffset 0.5s ease 0s;\n transition: stroke-dashoffset 0.5s ease 0s;\n}\n\n.CircularProgressbar .CircularProgressbar-trail {\n stroke: #d6d6d6;\n /* Used when trail is not full diameter, i.e. when props.circleRatio is set */\n stroke-linecap: round;\n}\n\n.CircularProgressbar .CircularProgressbar-text {\n fill: #3e98c7;\n font-size: 20px;\n dominant-baseline: middle;\n text-anchor: middle;\n}\n\n.CircularProgressbar .CircularProgressbar-background {\n fill: #d6d6d6;\n}\n\n/*\n * Sample background styles. Use these with e.g.:\n *\n * <CircularProgressbar\n * className=\"CircularProgressbar-inverted\"\n * background\n * percentage={50}\n * />\n */\n.CircularProgressbar.CircularProgressbar-inverted .CircularProgressbar-background {\n fill: #3e98c7;\n}\n\n.CircularProgressbar.CircularProgressbar-inverted .CircularProgressbar-text {\n fill: #fff;\n}\n\n.CircularProgressbar.CircularProgressbar-inverted .CircularProgressbar-path {\n stroke: #fff;\n}\n\n.CircularProgressbar.CircularProgressbar-inverted .CircularProgressbar-trail {\n stroke: transparent;\n}\n";
|
|
184
|
+
styleInject(css_248z$1);
|
|
185
|
+
|
|
186
|
+
var css_248z = ".card {\r\n background: #fff;\r\n border-radius: 12px;\r\n padding: 16px;\r\n box-shadow: 0 2px 6px rgba(0,0,0,0.1);\r\n width: 260px;\r\n}\r\n\r\n.card-content {\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n}\r\n\r\n.count {\r\n font-size: 24px;\r\n font-weight: bold;\r\n}\r\n\r\n.progress-circle {\r\n width: 60px;\r\n height: 60px;\r\n}\r\n\r\n.increase {\r\n margin-top: 10px;\r\n font-weight: bold;\r\n}\r\n\r\n.increase.positive {\r\n color: #4caf50;\r\n}\r\n\r\n.increase.negative {\r\n color: #f44336;\r\n}\r\n";
|
|
187
|
+
styleInject(css_248z);
|
|
188
|
+
|
|
189
|
+
const Card = ({
|
|
190
|
+
title,
|
|
191
|
+
count,
|
|
192
|
+
progress,
|
|
193
|
+
increase
|
|
194
|
+
}) => {
|
|
195
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
196
|
+
className: "card"
|
|
197
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
198
|
+
className: "card-content"
|
|
199
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
200
|
+
className: "card-left"
|
|
201
|
+
}, /*#__PURE__*/React.createElement("h3", null, title), count ? /*#__PURE__*/React.createElement("p", {
|
|
202
|
+
className: "count"
|
|
203
|
+
}, count.toLocaleString()) : /*#__PURE__*/React.createElement("h4", {
|
|
204
|
+
className: "font-black-300"
|
|
205
|
+
}, "No data.")), /*#__PURE__*/React.createElement("div", {
|
|
206
|
+
className: "progress-circle"
|
|
207
|
+
}, /*#__PURE__*/React.createElement(CircularProgressbar, {
|
|
208
|
+
value: progress || 0,
|
|
209
|
+
text: `${progress || 0}%`,
|
|
210
|
+
styles: buildStyles({
|
|
211
|
+
pathColor: progress ? "#4caf50" : "#ccc",
|
|
212
|
+
textColor: progress ? "#333" : "#aaa",
|
|
213
|
+
trailColor: "#eee"
|
|
214
|
+
})
|
|
215
|
+
}))), increase || increase === 0 ? /*#__PURE__*/React.createElement("p", {
|
|
216
|
+
className: `increase ${increase < 0 ? "negative" : "positive"}`
|
|
217
|
+
}, increase < 0 ? "↓" : "↑", " ", Math.abs(increase), "%") : /*#__PURE__*/React.createElement("p", {
|
|
218
|
+
className: "text-gray-400"
|
|
219
|
+
}, "\u2014"));
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
export { Card, Card as default };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var React = require('react');
|
|
6
|
+
|
|
7
|
+
/*! *****************************************************************************
|
|
8
|
+
Copyright (c) Microsoft Corporation. All rights reserved.
|
|
9
|
+
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
|
10
|
+
this file except in compliance with the License. You may obtain a copy of the
|
|
11
|
+
License at http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
+
|
|
13
|
+
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
14
|
+
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
|
15
|
+
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
|
16
|
+
MERCHANTABLITY OR NON-INFRINGEMENT.
|
|
17
|
+
|
|
18
|
+
See the Apache Version 2.0 License for specific language governing permissions
|
|
19
|
+
and limitations under the License.
|
|
20
|
+
***************************************************************************** */
|
|
21
|
+
/* global Reflect, Promise */
|
|
22
|
+
|
|
23
|
+
var extendStatics = function(d, b) {
|
|
24
|
+
extendStatics = Object.setPrototypeOf ||
|
|
25
|
+
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
|
26
|
+
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
|
|
27
|
+
return extendStatics(d, b);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
function __extends(d, b) {
|
|
31
|
+
extendStatics(d, b);
|
|
32
|
+
function __() { this.constructor = d; }
|
|
33
|
+
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
var VIEWBOX_WIDTH = 100;
|
|
37
|
+
var VIEWBOX_HEIGHT = 100;
|
|
38
|
+
var VIEWBOX_HEIGHT_HALF = 50;
|
|
39
|
+
var VIEWBOX_CENTER_X = 50;
|
|
40
|
+
var VIEWBOX_CENTER_Y = 50;
|
|
41
|
+
|
|
42
|
+
function Path(_a) {
|
|
43
|
+
var className = _a.className, counterClockwise = _a.counterClockwise, dashRatio = _a.dashRatio, pathRadius = _a.pathRadius, strokeWidth = _a.strokeWidth, style = _a.style;
|
|
44
|
+
return (React.createElement("path", { className: className, style: Object.assign({}, style, getDashStyle({ pathRadius: pathRadius, dashRatio: dashRatio, counterClockwise: counterClockwise })), d: getPathDescription({
|
|
45
|
+
pathRadius: pathRadius,
|
|
46
|
+
counterClockwise: counterClockwise,
|
|
47
|
+
}), strokeWidth: strokeWidth, fillOpacity: 0 }));
|
|
48
|
+
}
|
|
49
|
+
function getPathDescription(_a) {
|
|
50
|
+
var pathRadius = _a.pathRadius, counterClockwise = _a.counterClockwise;
|
|
51
|
+
var radius = pathRadius;
|
|
52
|
+
var rotation = counterClockwise ? 1 : 0;
|
|
53
|
+
return "\n M " + VIEWBOX_CENTER_X + "," + VIEWBOX_CENTER_Y + "\n m 0,-" + radius + "\n a " + radius + "," + radius + " " + rotation + " 1 1 0," + 2 * radius + "\n a " + radius + "," + radius + " " + rotation + " 1 1 0,-" + 2 * radius + "\n ";
|
|
54
|
+
}
|
|
55
|
+
function getDashStyle(_a) {
|
|
56
|
+
var counterClockwise = _a.counterClockwise, dashRatio = _a.dashRatio, pathRadius = _a.pathRadius;
|
|
57
|
+
var diameter = Math.PI * 2 * pathRadius;
|
|
58
|
+
var gapLength = (1 - dashRatio) * diameter;
|
|
59
|
+
return {
|
|
60
|
+
strokeDasharray: diameter + "px " + diameter + "px",
|
|
61
|
+
strokeDashoffset: (counterClockwise ? -gapLength : gapLength) + "px",
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
var CircularProgressbar = (function (_super) {
|
|
66
|
+
__extends(CircularProgressbar, _super);
|
|
67
|
+
function CircularProgressbar() {
|
|
68
|
+
return _super !== null && _super.apply(this, arguments) || this;
|
|
69
|
+
}
|
|
70
|
+
CircularProgressbar.prototype.getBackgroundPadding = function () {
|
|
71
|
+
if (!this.props.background) {
|
|
72
|
+
return 0;
|
|
73
|
+
}
|
|
74
|
+
return this.props.backgroundPadding;
|
|
75
|
+
};
|
|
76
|
+
CircularProgressbar.prototype.getPathRadius = function () {
|
|
77
|
+
return VIEWBOX_HEIGHT_HALF - this.props.strokeWidth / 2 - this.getBackgroundPadding();
|
|
78
|
+
};
|
|
79
|
+
CircularProgressbar.prototype.getPathRatio = function () {
|
|
80
|
+
var _a = this.props, value = _a.value, minValue = _a.minValue, maxValue = _a.maxValue;
|
|
81
|
+
var boundedValue = Math.min(Math.max(value, minValue), maxValue);
|
|
82
|
+
return (boundedValue - minValue) / (maxValue - minValue);
|
|
83
|
+
};
|
|
84
|
+
CircularProgressbar.prototype.render = function () {
|
|
85
|
+
var _a = this.props, circleRatio = _a.circleRatio, className = _a.className, classes = _a.classes, counterClockwise = _a.counterClockwise, styles = _a.styles, strokeWidth = _a.strokeWidth, text = _a.text;
|
|
86
|
+
var pathRadius = this.getPathRadius();
|
|
87
|
+
var pathRatio = this.getPathRatio();
|
|
88
|
+
return (React.createElement("svg", { className: classes.root + " " + className, style: styles.root, viewBox: "0 0 " + VIEWBOX_WIDTH + " " + VIEWBOX_HEIGHT, "data-test-id": "CircularProgressbar" },
|
|
89
|
+
this.props.background ? (React.createElement("circle", { className: classes.background, style: styles.background, cx: VIEWBOX_CENTER_X, cy: VIEWBOX_CENTER_Y, r: VIEWBOX_HEIGHT_HALF })) : null,
|
|
90
|
+
React.createElement(Path, { className: classes.trail, counterClockwise: counterClockwise, dashRatio: circleRatio, pathRadius: pathRadius, strokeWidth: strokeWidth, style: styles.trail }),
|
|
91
|
+
React.createElement(Path, { className: classes.path, counterClockwise: counterClockwise, dashRatio: pathRatio * circleRatio, pathRadius: pathRadius, strokeWidth: strokeWidth, style: styles.path }),
|
|
92
|
+
text ? (React.createElement("text", { className: classes.text, style: styles.text, x: VIEWBOX_CENTER_X, y: VIEWBOX_CENTER_Y }, text)) : null));
|
|
93
|
+
};
|
|
94
|
+
CircularProgressbar.defaultProps = {
|
|
95
|
+
background: false,
|
|
96
|
+
backgroundPadding: 0,
|
|
97
|
+
circleRatio: 1,
|
|
98
|
+
classes: {
|
|
99
|
+
root: 'CircularProgressbar',
|
|
100
|
+
trail: 'CircularProgressbar-trail',
|
|
101
|
+
path: 'CircularProgressbar-path',
|
|
102
|
+
text: 'CircularProgressbar-text',
|
|
103
|
+
background: 'CircularProgressbar-background',
|
|
104
|
+
},
|
|
105
|
+
counterClockwise: false,
|
|
106
|
+
className: '',
|
|
107
|
+
maxValue: 100,
|
|
108
|
+
minValue: 0,
|
|
109
|
+
strokeWidth: 8,
|
|
110
|
+
styles: {
|
|
111
|
+
root: {},
|
|
112
|
+
trail: {},
|
|
113
|
+
path: {},
|
|
114
|
+
text: {},
|
|
115
|
+
background: {},
|
|
116
|
+
},
|
|
117
|
+
text: '',
|
|
118
|
+
};
|
|
119
|
+
return CircularProgressbar;
|
|
120
|
+
}(React.Component));
|
|
121
|
+
|
|
122
|
+
function buildStyles(_a) {
|
|
123
|
+
var rotation = _a.rotation, strokeLinecap = _a.strokeLinecap, textColor = _a.textColor, textSize = _a.textSize, pathColor = _a.pathColor, pathTransition = _a.pathTransition, pathTransitionDuration = _a.pathTransitionDuration, trailColor = _a.trailColor, backgroundColor = _a.backgroundColor;
|
|
124
|
+
var rotationTransform = rotation == null ? undefined : "rotate(" + rotation + "turn)";
|
|
125
|
+
var rotationTransformOrigin = rotation == null ? undefined : 'center center';
|
|
126
|
+
return {
|
|
127
|
+
root: {},
|
|
128
|
+
path: removeUndefinedValues({
|
|
129
|
+
stroke: pathColor,
|
|
130
|
+
strokeLinecap: strokeLinecap,
|
|
131
|
+
transform: rotationTransform,
|
|
132
|
+
transformOrigin: rotationTransformOrigin,
|
|
133
|
+
transition: pathTransition,
|
|
134
|
+
transitionDuration: pathTransitionDuration == null ? undefined : pathTransitionDuration + "s",
|
|
135
|
+
}),
|
|
136
|
+
trail: removeUndefinedValues({
|
|
137
|
+
stroke: trailColor,
|
|
138
|
+
strokeLinecap: strokeLinecap,
|
|
139
|
+
transform: rotationTransform,
|
|
140
|
+
transformOrigin: rotationTransformOrigin,
|
|
141
|
+
}),
|
|
142
|
+
text: removeUndefinedValues({
|
|
143
|
+
fill: textColor,
|
|
144
|
+
fontSize: textSize,
|
|
145
|
+
}),
|
|
146
|
+
background: removeUndefinedValues({
|
|
147
|
+
fill: backgroundColor,
|
|
148
|
+
}),
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
function removeUndefinedValues(obj) {
|
|
152
|
+
Object.keys(obj).forEach(function (key) {
|
|
153
|
+
if (obj[key] == null) {
|
|
154
|
+
delete obj[key];
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
return obj;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function styleInject(css, ref) {
|
|
161
|
+
if ( ref === void 0 ) ref = {};
|
|
162
|
+
var insertAt = ref.insertAt;
|
|
163
|
+
|
|
164
|
+
if (!css || typeof document === 'undefined') { return; }
|
|
165
|
+
|
|
166
|
+
var head = document.head || document.getElementsByTagName('head')[0];
|
|
167
|
+
var style = document.createElement('style');
|
|
168
|
+
style.type = 'text/css';
|
|
169
|
+
|
|
170
|
+
if (insertAt === 'top') {
|
|
171
|
+
if (head.firstChild) {
|
|
172
|
+
head.insertBefore(style, head.firstChild);
|
|
173
|
+
} else {
|
|
174
|
+
head.appendChild(style);
|
|
175
|
+
}
|
|
176
|
+
} else {
|
|
177
|
+
head.appendChild(style);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
if (style.styleSheet) {
|
|
181
|
+
style.styleSheet.cssText = css;
|
|
182
|
+
} else {
|
|
183
|
+
style.appendChild(document.createTextNode(css));
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
var css_248z$1 = "/*\n * react-circular-progressbar styles\n * All of the styles in this file are configurable!\n */\n\n.CircularProgressbar {\n /*\n * This fixes an issue where the CircularProgressbar svg has\n * 0 width inside a \"display: flex\" container, and thus not visible.\n */\n width: 100%;\n /*\n * This fixes a centering issue with CircularProgressbarWithChildren:\n * https://github.com/kevinsqi/react-circular-progressbar/issues/94\n */\n vertical-align: middle;\n}\n\n.CircularProgressbar .CircularProgressbar-path {\n stroke: #3e98c7;\n stroke-linecap: round;\n -webkit-transition: stroke-dashoffset 0.5s ease 0s;\n transition: stroke-dashoffset 0.5s ease 0s;\n}\n\n.CircularProgressbar .CircularProgressbar-trail {\n stroke: #d6d6d6;\n /* Used when trail is not full diameter, i.e. when props.circleRatio is set */\n stroke-linecap: round;\n}\n\n.CircularProgressbar .CircularProgressbar-text {\n fill: #3e98c7;\n font-size: 20px;\n dominant-baseline: middle;\n text-anchor: middle;\n}\n\n.CircularProgressbar .CircularProgressbar-background {\n fill: #d6d6d6;\n}\n\n/*\n * Sample background styles. Use these with e.g.:\n *\n * <CircularProgressbar\n * className=\"CircularProgressbar-inverted\"\n * background\n * percentage={50}\n * />\n */\n.CircularProgressbar.CircularProgressbar-inverted .CircularProgressbar-background {\n fill: #3e98c7;\n}\n\n.CircularProgressbar.CircularProgressbar-inverted .CircularProgressbar-text {\n fill: #fff;\n}\n\n.CircularProgressbar.CircularProgressbar-inverted .CircularProgressbar-path {\n stroke: #fff;\n}\n\n.CircularProgressbar.CircularProgressbar-inverted .CircularProgressbar-trail {\n stroke: transparent;\n}\n";
|
|
188
|
+
styleInject(css_248z$1);
|
|
189
|
+
|
|
190
|
+
var css_248z = ".card {\r\n background: #fff;\r\n border-radius: 12px;\r\n padding: 16px;\r\n box-shadow: 0 2px 6px rgba(0,0,0,0.1);\r\n width: 260px;\r\n}\r\n\r\n.card-content {\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n}\r\n\r\n.count {\r\n font-size: 24px;\r\n font-weight: bold;\r\n}\r\n\r\n.progress-circle {\r\n width: 60px;\r\n height: 60px;\r\n}\r\n\r\n.increase {\r\n margin-top: 10px;\r\n font-weight: bold;\r\n}\r\n\r\n.increase.positive {\r\n color: #4caf50;\r\n}\r\n\r\n.increase.negative {\r\n color: #f44336;\r\n}\r\n";
|
|
191
|
+
styleInject(css_248z);
|
|
192
|
+
|
|
193
|
+
const Card = ({
|
|
194
|
+
title,
|
|
195
|
+
count,
|
|
196
|
+
progress,
|
|
197
|
+
increase
|
|
198
|
+
}) => {
|
|
199
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
200
|
+
className: "card"
|
|
201
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
202
|
+
className: "card-content"
|
|
203
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
204
|
+
className: "card-left"
|
|
205
|
+
}, /*#__PURE__*/React.createElement("h3", null, title), count ? /*#__PURE__*/React.createElement("p", {
|
|
206
|
+
className: "count"
|
|
207
|
+
}, count.toLocaleString()) : /*#__PURE__*/React.createElement("h4", {
|
|
208
|
+
className: "font-black-300"
|
|
209
|
+
}, "No data.")), /*#__PURE__*/React.createElement("div", {
|
|
210
|
+
className: "progress-circle"
|
|
211
|
+
}, /*#__PURE__*/React.createElement(CircularProgressbar, {
|
|
212
|
+
value: progress || 0,
|
|
213
|
+
text: `${progress || 0}%`,
|
|
214
|
+
styles: buildStyles({
|
|
215
|
+
pathColor: progress ? "#4caf50" : "#ccc",
|
|
216
|
+
textColor: progress ? "#333" : "#aaa",
|
|
217
|
+
trailColor: "#eee"
|
|
218
|
+
})
|
|
219
|
+
}))), increase || increase === 0 ? /*#__PURE__*/React.createElement("p", {
|
|
220
|
+
className: `increase ${increase < 0 ? "negative" : "positive"}`
|
|
221
|
+
}, increase < 0 ? "↓" : "↑", " ", Math.abs(increase), "%") : /*#__PURE__*/React.createElement("p", {
|
|
222
|
+
className: "text-gray-400"
|
|
223
|
+
}, "\u2014"));
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
exports.Card = Card;
|
|
227
|
+
exports.default = Card;
|
package/package.json
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "react-stat-card-poc",
|
|
3
|
+
"version": "1.0.6",
|
|
4
|
+
"description": "A reusable React stats card with circular progress bar.",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.esm.js",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist"
|
|
9
|
+
],
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "rollup -c"
|
|
12
|
+
},
|
|
13
|
+
"peerDependencies": {
|
|
14
|
+
"react": ">=17.0.0",
|
|
15
|
+
"react-dom": ">=17.0.0"
|
|
16
|
+
},
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"react-circular-progressbar": "^2.1.0",
|
|
19
|
+
"react-stat-card-poc": "^1.0.5"
|
|
20
|
+
},
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"@babel/preset-react": "^7.28.5",
|
|
23
|
+
"@rollup/plugin-babel": "^6.0.3",
|
|
24
|
+
"@rollup/plugin-commonjs": "^25.0.0",
|
|
25
|
+
"@rollup/plugin-node-resolve": "^15.2.0",
|
|
26
|
+
"rollup": "^3.0.0",
|
|
27
|
+
"rollup-plugin-postcss": "^4.0.2"
|
|
28
|
+
}
|
|
29
|
+
}
|