@pareto-engineering/design-system 5.2.0 → 5.3.0
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/dist/cjs/a/Charts/AreaChart/AreaChart.js +61 -5
- package/dist/cjs/a/Charts/AreaChart/styles.scss +22 -0
- package/dist/cjs/a/Charts/BarChart/BarChart.js +1 -0
- package/dist/cjs/a/Charts/Common/CustomLegend/CustomLegend.js +23 -5
- package/dist/cjs/a/Charts/Common/CustomLegend/styles.scss +10 -2
- package/dist/cjs/a/Charts/Common/CustomTooltipContent/CustomTooltipContent.js +139 -42
- package/dist/cjs/a/Charts/Common/CustomTooltipContent/styles.scss +4 -0
- package/dist/cjs/a/Charts/PieChart/PieChart.js +39 -8
- package/dist/cjs/a/Charts/PieChart/styles.scss +88 -0
- package/dist/cjs/a/HamburgerButton/styles.scss +151 -9
- package/dist/cjs/a/ThroughPutIndicator/ThroughPutIndicator.js +78 -0
- package/dist/cjs/a/ThroughPutIndicator/index.js +13 -0
- package/dist/cjs/a/ThroughPutIndicator/styles.scss +35 -0
- package/dist/cjs/a/ToggleSwitch/ToggleSwitch.js +2 -1
- package/dist/cjs/a/ToggleSwitch/styles.scss +9 -2
- package/dist/cjs/a/Tooltip/Tooltip.js +19 -2
- package/dist/cjs/a/Tooltip/styles.scss +32 -4
- package/dist/cjs/a/XMLEditor/XMLEditor.js +4 -1
- package/dist/cjs/a/index.js +8 -1
- package/dist/cjs/f/FormInput/FormInput.js +7 -1
- package/dist/cjs/f/fields/ToggleInput/ToggleInput.js +126 -0
- package/dist/cjs/f/fields/ToggleInput/index.js +13 -0
- package/dist/cjs/f/fields/ToggleInput/styles.scss +22 -0
- package/dist/cjs/f/fields/index.js +8 -1
- package/dist/cjs/utils/formatting.js +27 -18
- package/dist/cjs/utils/index.js +6 -0
- package/dist/es/a/Charts/AreaChart/AreaChart.js +62 -6
- package/dist/es/a/Charts/AreaChart/styles.scss +22 -0
- package/dist/es/a/Charts/BarChart/BarChart.js +1 -0
- package/dist/es/a/Charts/Common/CustomLegend/CustomLegend.js +23 -5
- package/dist/es/a/Charts/Common/CustomLegend/styles.scss +10 -2
- package/dist/es/a/Charts/Common/CustomTooltipContent/CustomTooltipContent.js +128 -40
- package/dist/es/a/Charts/Common/CustomTooltipContent/styles.scss +4 -0
- package/dist/es/a/Charts/PieChart/PieChart.js +39 -8
- package/dist/es/a/Charts/PieChart/styles.scss +88 -0
- package/dist/es/a/HamburgerButton/styles.scss +151 -9
- package/dist/es/a/ThroughPutIndicator/ThroughPutIndicator.js +66 -0
- package/dist/es/a/ThroughPutIndicator/index.js +2 -0
- package/dist/es/a/ThroughPutIndicator/styles.scss +35 -0
- package/dist/es/a/ToggleSwitch/ToggleSwitch.js +2 -1
- package/dist/es/a/ToggleSwitch/styles.scss +9 -2
- package/dist/es/a/Tooltip/Tooltip.js +31 -12
- package/dist/es/a/Tooltip/styles.scss +32 -4
- package/dist/es/a/XMLEditor/XMLEditor.js +6 -3
- package/dist/es/a/index.js +2 -1
- package/dist/es/f/FormInput/FormInput.js +8 -2
- package/dist/es/f/fields/ToggleInput/ToggleInput.js +116 -0
- package/dist/es/f/fields/ToggleInput/index.js +2 -0
- package/dist/es/f/fields/ToggleInput/styles.scss +22 -0
- package/dist/es/f/fields/index.js +2 -1
- package/dist/es/utils/formatting.js +25 -17
- package/dist/es/utils/index.js +1 -1
- package/package.json +7 -6
- package/src/ui/a/Charts/AreaChart/AreaChart.jsx +74 -9
- package/src/ui/a/Charts/AreaChart/styles.scss +22 -0
- package/src/ui/a/Charts/BarChart/BarChart.jsx +1 -0
- package/src/ui/a/Charts/Common/CustomLegend/CustomLegend.jsx +26 -3
- package/src/ui/a/Charts/Common/CustomLegend/styles.scss +10 -2
- package/src/ui/a/Charts/Common/CustomTooltipContent/CustomTooltipContent.jsx +132 -48
- package/src/ui/a/Charts/Common/CustomTooltipContent/styles.scss +4 -0
- package/src/ui/a/Charts/PieChart/PieChart.jsx +54 -16
- package/src/ui/a/Charts/PieChart/styles.scss +88 -0
- package/src/ui/a/HamburgerButton/styles.scss +151 -9
- package/src/ui/a/ThroughPutIndicator/ThroughPutIndicator.jsx +90 -0
- package/src/ui/a/ThroughPutIndicator/index.js +2 -0
- package/src/ui/a/ThroughPutIndicator/styles.scss +35 -0
- package/src/ui/a/ToggleSwitch/ToggleSwitch.jsx +1 -1
- package/src/ui/a/ToggleSwitch/styles.scss +9 -2
- package/src/ui/a/Tooltip/Tooltip.jsx +55 -26
- package/src/ui/a/Tooltip/styles.scss +32 -4
- package/src/ui/a/XMLEditor/XMLEditor.jsx +15 -2
- package/src/ui/a/index.js +1 -0
- package/src/ui/f/FormInput/FormInput.jsx +11 -0
- package/src/ui/f/fields/ToggleInput/ToggleInput.jsx +140 -0
- package/src/ui/f/fields/ToggleInput/index.js +2 -0
- package/src/ui/f/fields/ToggleInput/styles.scss +22 -0
- package/src/ui/f/fields/index.js +1 -0
- package/src/ui/utils/formatting.js +38 -29
- package/src/ui/utils/index.js +1 -1
- package/tests/__snapshots__/Storyshots.test.js.snap +433 -160
|
@@ -81,6 +81,12 @@ Object.defineProperty(exports, "TextareaInput", {
|
|
|
81
81
|
return _TextareaInput.TextareaInput;
|
|
82
82
|
}
|
|
83
83
|
});
|
|
84
|
+
Object.defineProperty(exports, "ToggleInput", {
|
|
85
|
+
enumerable: true,
|
|
86
|
+
get: function () {
|
|
87
|
+
return _ToggleInput.ToggleInput;
|
|
88
|
+
}
|
|
89
|
+
});
|
|
84
90
|
Object.defineProperty(exports, "convertLatexToHtml", {
|
|
85
91
|
enumerable: true,
|
|
86
92
|
get: function () {
|
|
@@ -117,4 +123,5 @@ var _QueryChoices = require("./QueryChoices");
|
|
|
117
123
|
var _LinkInput = require("./LinkInput");
|
|
118
124
|
var _EditorInput = require("./EditorInput");
|
|
119
125
|
var _LatexPreviewInput = require("./LatexPreviewInput");
|
|
120
|
-
var _FileUpload = require("./FileUpload");
|
|
126
|
+
var _FileUpload = require("./FileUpload");
|
|
127
|
+
var _ToggleInput = require("./ToggleInput");
|
|
@@ -3,9 +3,10 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.snakeCaseToTitleCase = exports.formatTime = exports.formatDate = exports.DATE_FORMATS = void 0;
|
|
6
|
+
exports.snakeCaseToTitleCase = exports.parseDate = exports.formatTime = exports.formatDate = exports.DATE_FORMATS = void 0;
|
|
7
7
|
const DATE_FORMATS = exports.DATE_FORMATS = {
|
|
8
8
|
HUMAN_READABLE: 'human_readable',
|
|
9
|
+
HUMAN_READABLE_WITH_TIME: 'human_readable_with_time',
|
|
9
10
|
TIME: 'time',
|
|
10
11
|
DATETIME: 'datetime',
|
|
11
12
|
CHART_DATE: 'chart_date',
|
|
@@ -49,23 +50,6 @@ const formatTime = seconds => {
|
|
|
49
50
|
return parts.join(' ');
|
|
50
51
|
};
|
|
51
52
|
exports.formatTime = formatTime;
|
|
52
|
-
const parseDate = input => {
|
|
53
|
-
if (input instanceof Date) return input;
|
|
54
|
-
if (typeof input === 'number') return new Date(input);
|
|
55
|
-
if (typeof input === 'string') {
|
|
56
|
-
if (isTimeSliceFormat(input)) {
|
|
57
|
-
return createTimeFromSlice(input);
|
|
58
|
-
}
|
|
59
|
-
const parsed = new Date(input);
|
|
60
|
-
if (isValidDate(parsed)) return parsed;
|
|
61
|
-
const timestamp = parseInt(input, 10);
|
|
62
|
-
if (!Number.isNaN(timestamp)) {
|
|
63
|
-
const date = new Date(timestamp * 1000);
|
|
64
|
-
if (isValidDate(date)) return date;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
return null;
|
|
68
|
-
};
|
|
69
53
|
const formatStrategies = {
|
|
70
54
|
[DATE_FORMATS.CHART_DATE]: date => {
|
|
71
55
|
const monthDay = date.toLocaleDateString('en-US', {
|
|
@@ -82,8 +66,33 @@ const formatStrategies = {
|
|
|
82
66
|
day: 'numeric',
|
|
83
67
|
timeZone: 'UTC'
|
|
84
68
|
}),
|
|
69
|
+
[DATE_FORMATS.HUMAN_READABLE_WITH_TIME]: date => date.toLocaleString('en-US', {
|
|
70
|
+
year: 'numeric',
|
|
71
|
+
month: 'short',
|
|
72
|
+
day: 'numeric',
|
|
73
|
+
hour: '2-digit',
|
|
74
|
+
timeZone: 'UTC'
|
|
75
|
+
}),
|
|
85
76
|
default: date => date.toISOString()
|
|
86
77
|
};
|
|
78
|
+
const parseDate = input => {
|
|
79
|
+
if (input instanceof Date) return input;
|
|
80
|
+
if (typeof input === 'number') return new Date(input);
|
|
81
|
+
if (typeof input === 'string') {
|
|
82
|
+
if (isTimeSliceFormat(input)) {
|
|
83
|
+
return createTimeFromSlice(input);
|
|
84
|
+
}
|
|
85
|
+
const parsed = new Date(input);
|
|
86
|
+
if (isValidDate(parsed)) return parsed;
|
|
87
|
+
const timestamp = parseInt(input, 10);
|
|
88
|
+
if (!Number.isNaN(timestamp)) {
|
|
89
|
+
const date = new Date(timestamp * 1000);
|
|
90
|
+
if (isValidDate(date)) return date;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return null;
|
|
94
|
+
};
|
|
95
|
+
exports.parseDate = parseDate;
|
|
87
96
|
const formatDate = function (input) {
|
|
88
97
|
let format = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : DATE_FORMATS.HUMAN_READABLE;
|
|
89
98
|
try {
|
package/dist/cjs/utils/index.js
CHANGED
|
@@ -27,6 +27,12 @@ Object.defineProperty(exports, "formatTime", {
|
|
|
27
27
|
return _formatting.formatTime;
|
|
28
28
|
}
|
|
29
29
|
});
|
|
30
|
+
Object.defineProperty(exports, "parseDate", {
|
|
31
|
+
enumerable: true,
|
|
32
|
+
get: function () {
|
|
33
|
+
return _formatting.parseDate;
|
|
34
|
+
}
|
|
35
|
+
});
|
|
30
36
|
Object.defineProperty(exports, "snakeCaseToTitleCase", {
|
|
31
37
|
enumerable: true,
|
|
32
38
|
get: function () {
|
|
@@ -3,11 +3,39 @@ import { useState } from 'react';
|
|
|
3
3
|
import PropTypes from 'prop-types';
|
|
4
4
|
import { AreaChart as RechartsAreaChart, Area, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer } from 'recharts';
|
|
5
5
|
import styleNames from '@pareto-engineering/bem/exports';
|
|
6
|
-
import { formatTime, formatDate, DATE_FORMATS } from "../../../utils";
|
|
6
|
+
import { formatTime, formatDate, DATE_FORMATS, parseDate } from "../../../utils";
|
|
7
|
+
import { ThroughPutIndicator } from "../../ThroughPutIndicator";
|
|
7
8
|
import { CustomLegend, CustomTooltipContent, YLabelsDropDown } from "../Common";
|
|
8
9
|
import "./styles.scss";
|
|
9
10
|
const baseClassName = styleNames.base;
|
|
10
11
|
const componentClassName = 'area-chart';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Determines whether to show only date or date with time based on the data range
|
|
15
|
+
*
|
|
16
|
+
* @param {Array} data - The chart data array
|
|
17
|
+
* @param {string} xKey - The key for the x-axis values (dates)
|
|
18
|
+
* @returns {boolean} - True if only date should be shown, false if date and time should be shown
|
|
19
|
+
*/
|
|
20
|
+
const shouldShowOnlyDate = (data, xKey) => {
|
|
21
|
+
if (!data || data.length < 2 || !xKey) return true;
|
|
22
|
+
|
|
23
|
+
// Extract dates from the data
|
|
24
|
+
const dates = data.map(item => parseDate(item[xKey])).filter(date => date !== null);
|
|
25
|
+
if (dates.length < 2) return true;
|
|
26
|
+
|
|
27
|
+
// Sort dates chronologically
|
|
28
|
+
dates.sort((a, b) => a.getTime() - b.getTime());
|
|
29
|
+
|
|
30
|
+
// Calculate the difference in days between the first and last date
|
|
31
|
+
const firstDate = dates[0];
|
|
32
|
+
const lastDate = dates[dates.length - 1];
|
|
33
|
+
const diffInMs = lastDate.getTime() - firstDate.getTime();
|
|
34
|
+
const diffInDays = diffInMs / (1000 * 60 * 60 * 24);
|
|
35
|
+
|
|
36
|
+
// If the data spans less than 4 days, show only date
|
|
37
|
+
return diffInDays > 4;
|
|
38
|
+
};
|
|
11
39
|
const AreaChart = ({
|
|
12
40
|
id,
|
|
13
41
|
className: userClassName,
|
|
@@ -23,7 +51,9 @@ const AreaChart = ({
|
|
|
23
51
|
width,
|
|
24
52
|
isTimeFormat,
|
|
25
53
|
dateFormat,
|
|
26
|
-
capitalizedLegend
|
|
54
|
+
capitalizedLegend,
|
|
55
|
+
isWorkerSubmissionChart,
|
|
56
|
+
totalSubmissions
|
|
27
57
|
}) => {
|
|
28
58
|
const allYLabels = yKeys.map(key => ({
|
|
29
59
|
label: key,
|
|
@@ -35,8 +65,9 @@ const AreaChart = ({
|
|
|
35
65
|
const min = Math.min(...yValues.flat());
|
|
36
66
|
const max = Math.max(...yValues.flat());
|
|
37
67
|
const margin = (max - min) * 0.1;
|
|
38
|
-
return [min - margin, max + margin];
|
|
68
|
+
return [Math.max(min - margin, 0), max + margin];
|
|
39
69
|
};
|
|
70
|
+
const showOnlyDate = shouldShowOnlyDate(data, xKey);
|
|
40
71
|
return /*#__PURE__*/React.createElement("div", {
|
|
41
72
|
id: id,
|
|
42
73
|
className: [baseClassName, componentClassName, userClassName].filter(e => e).join(' ')
|
|
@@ -46,7 +77,15 @@ const AreaChart = ({
|
|
|
46
77
|
allYLabels: allYLabels,
|
|
47
78
|
selectedYLabels: selectedYLabels,
|
|
48
79
|
setSelectedYLabels: setSelectedYLabels
|
|
80
|
+
})), isWorkerSubmissionChart && /*#__PURE__*/React.createElement("div", {
|
|
81
|
+
className: "worker-submissions-total-percentage-container"
|
|
82
|
+
}, /*#__PURE__*/React.createElement("p", {
|
|
83
|
+
className: "total-submissions-text"
|
|
84
|
+
}, totalSubmissions), /*#__PURE__*/React.createElement(ThroughPutIndicator, {
|
|
85
|
+
data: data,
|
|
86
|
+
keyName: "reserved"
|
|
49
87
|
})), /*#__PURE__*/React.createElement(CustomLegend, {
|
|
88
|
+
key: id,
|
|
50
89
|
colorsArray: colors,
|
|
51
90
|
yKeysArray: yKeys,
|
|
52
91
|
capitalizedLegend: capitalizedLegend
|
|
@@ -67,7 +106,12 @@ const AreaChart = ({
|
|
|
67
106
|
axisLine: false,
|
|
68
107
|
tickLine: false,
|
|
69
108
|
tickCount: 3,
|
|
70
|
-
tickFormatter: value =>
|
|
109
|
+
tickFormatter: value => {
|
|
110
|
+
if (showOnlyDate) {
|
|
111
|
+
return formatDate(value, dateFormat);
|
|
112
|
+
}
|
|
113
|
+
return formatDate(value, DATE_FORMATS.HUMAN_READABLE_WITH_TIME);
|
|
114
|
+
}
|
|
71
115
|
}), /*#__PURE__*/React.createElement(YAxis, {
|
|
72
116
|
domain: yAxisBounds,
|
|
73
117
|
scale: "linear",
|
|
@@ -91,6 +135,9 @@ const AreaChart = ({
|
|
|
91
135
|
if (isTimeFormat) {
|
|
92
136
|
return formatTime(value);
|
|
93
137
|
}
|
|
138
|
+
if (isWorkerSubmissionChart) {
|
|
139
|
+
return Math.round(value);
|
|
140
|
+
}
|
|
94
141
|
return value.toFixed(2);
|
|
95
142
|
}
|
|
96
143
|
}), /*#__PURE__*/React.createElement(Tooltip, {
|
|
@@ -177,7 +224,15 @@ AreaChart.propTypes = {
|
|
|
177
224
|
/**
|
|
178
225
|
* The type of format for the datetime value
|
|
179
226
|
*/
|
|
180
|
-
dateFormat: PropTypes.oneOf(Object.values(DATE_FORMATS))
|
|
227
|
+
dateFormat: PropTypes.oneOf(Object.values(DATE_FORMATS)),
|
|
228
|
+
/**
|
|
229
|
+
* Flag on whether the chart is a worker submission chart or not
|
|
230
|
+
*/
|
|
231
|
+
isWorkerSubmissionChart: PropTypes.bool,
|
|
232
|
+
/**
|
|
233
|
+
* Total submissions
|
|
234
|
+
*/
|
|
235
|
+
totalSubmissions: PropTypes.number
|
|
181
236
|
};
|
|
182
237
|
AreaChart.defaultProps = {
|
|
183
238
|
filled: false,
|
|
@@ -185,6 +240,7 @@ AreaChart.defaultProps = {
|
|
|
185
240
|
height: 300,
|
|
186
241
|
capitalizedLegend: false,
|
|
187
242
|
isTimeFormat: false,
|
|
188
|
-
dateFormat: DATE_FORMATS.HUMAN_READABLE
|
|
243
|
+
dateFormat: DATE_FORMATS.HUMAN_READABLE,
|
|
244
|
+
isWorkerSubmissionChart: false
|
|
189
245
|
};
|
|
190
246
|
export default AreaChart;
|
|
@@ -26,6 +26,17 @@ $default-text-font-size: calc(var(--s-1) * 1rem);
|
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
.worker-submissions-total-percentage-container {
|
|
30
|
+
align-items: center;
|
|
31
|
+
display: flex;
|
|
32
|
+
gap: 1rem;
|
|
33
|
+
justify-content: flex-start;
|
|
34
|
+
|
|
35
|
+
.total-submissions-text {
|
|
36
|
+
font-size: calc($default-text-font-size * 2);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
29
40
|
/* stylelint-disable selector-max-compound-selectors -- nested elements */
|
|
30
41
|
.recharts-wrapper {
|
|
31
42
|
.recharts-surface {
|
|
@@ -46,3 +57,14 @@ $default-text-font-size: calc(var(--s-1) * 1rem);
|
|
|
46
57
|
}
|
|
47
58
|
}
|
|
48
59
|
}
|
|
60
|
+
|
|
61
|
+
.worker-submissions-total-percentage-container {
|
|
62
|
+
align-items: center;
|
|
63
|
+
display: flex;
|
|
64
|
+
gap: 1rem;
|
|
65
|
+
justify-content: flex-start;
|
|
66
|
+
|
|
67
|
+
.total-submissions-text {
|
|
68
|
+
font-size: calc($default-text-font-size * 2);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
@@ -40,6 +40,7 @@ const BarChart = ({
|
|
|
40
40
|
selectedYLabels: selectedYLabels,
|
|
41
41
|
setSelectedYLabels: setSelectedYLabels
|
|
42
42
|
})), /*#__PURE__*/React.createElement(CustomLegend, {
|
|
43
|
+
key: id,
|
|
43
44
|
colorsArray: selectedYLabels.map(item => item.color),
|
|
44
45
|
yKeysArray: selectedYLabels.map(item => item.label),
|
|
45
46
|
capitalizedLegend: capitalizedLegend
|
|
@@ -5,6 +5,13 @@ import { snakeCaseToTitleCase } from "../../../../utils";
|
|
|
5
5
|
import "./styles.scss";
|
|
6
6
|
const baseClassName = styleNames.base;
|
|
7
7
|
const componentClassName = 'custom-legend';
|
|
8
|
+
const toCurrency = value => {
|
|
9
|
+
const formatter = new Intl.NumberFormat('en-US', {
|
|
10
|
+
style: 'currency',
|
|
11
|
+
currency: 'USD'
|
|
12
|
+
});
|
|
13
|
+
return formatter.format(value);
|
|
14
|
+
};
|
|
8
15
|
const CustomLegend = ({
|
|
9
16
|
id,
|
|
10
17
|
className: userClassName,
|
|
@@ -13,7 +20,9 @@ const CustomLegend = ({
|
|
|
13
20
|
orientation,
|
|
14
21
|
getLegendItemTitle,
|
|
15
22
|
getLegendItemSubtitle,
|
|
16
|
-
capitalizedLegend
|
|
23
|
+
capitalizedLegend,
|
|
24
|
+
subtitleToCurrency,
|
|
25
|
+
isPayOutChart
|
|
17
26
|
}) => /*#__PURE__*/React.createElement("div", {
|
|
18
27
|
id: id,
|
|
19
28
|
className: [baseClassName, componentClassName, userClassName, orientation].filter(e => e).join(' ')
|
|
@@ -29,9 +38,13 @@ const CustomLegend = ({
|
|
|
29
38
|
}
|
|
30
39
|
}), /*#__PURE__*/React.createElement("span", {
|
|
31
40
|
className: "text"
|
|
32
|
-
}, capitalizedLegend ? snakeCaseToTitleCase(getLegendItemTitle(key)) : getLegendItemTitle(key))), /*#__PURE__*/React.createElement("
|
|
41
|
+
}, capitalizedLegend ? snakeCaseToTitleCase(getLegendItemTitle(key)) : getLegendItemTitle(key))), /*#__PURE__*/React.createElement("div", {
|
|
42
|
+
className: "sub-title-percentage-container"
|
|
43
|
+
}, /*#__PURE__*/React.createElement("span", {
|
|
33
44
|
className: "sub-title"
|
|
34
|
-
}, getLegendItemSubtitle(key)))))
|
|
45
|
+
}, subtitleToCurrency ? toCurrency(getLegendItemSubtitle(key)) : getLegendItemSubtitle(key)), Object.prototype.hasOwnProperty.call(key, 'percentage') && !isPayOutChart && /*#__PURE__*/React.createElement("span", {
|
|
46
|
+
className: "percentage-title"
|
|
47
|
+
}, `${key?.percentage}%`)))));
|
|
35
48
|
CustomLegend.propTypes = {
|
|
36
49
|
/**
|
|
37
50
|
* The id of the dropdown component.
|
|
@@ -64,13 +77,18 @@ CustomLegend.propTypes = {
|
|
|
64
77
|
/**
|
|
65
78
|
* Flag on whether to capitalize legend keys
|
|
66
79
|
*/
|
|
67
|
-
capitalizedLegend: PropTypes.bool
|
|
80
|
+
capitalizedLegend: PropTypes.bool,
|
|
81
|
+
/**
|
|
82
|
+
* Flag on whether to convert the subtitle to currency
|
|
83
|
+
*/
|
|
84
|
+
subtitleToCurrency: PropTypes.bool
|
|
68
85
|
};
|
|
69
86
|
CustomLegend.defaultProps = {
|
|
70
87
|
orientation: 'horizontal',
|
|
71
88
|
getLegendItemTitle: key => key,
|
|
72
89
|
/* eslint-disable no-unused-vars */
|
|
73
90
|
getLegendItemSubtitle: () => {},
|
|
74
|
-
capitalizedLegend: false
|
|
91
|
+
capitalizedLegend: false,
|
|
92
|
+
subtitleToCurrency: false
|
|
75
93
|
};
|
|
76
94
|
export default CustomLegend;
|
|
@@ -24,7 +24,6 @@ $default-box-shadow: 0 4px 16px 0 var(--soft-shadow);
|
|
|
24
24
|
min-width: fit-content;
|
|
25
25
|
|
|
26
26
|
.item {
|
|
27
|
-
box-shadow: $default-box-shadow;
|
|
28
27
|
padding-top: $default-padding;
|
|
29
28
|
}
|
|
30
29
|
}
|
|
@@ -55,12 +54,21 @@ $default-box-shadow: 0 4px 16px 0 var(--soft-shadow);
|
|
|
55
54
|
}
|
|
56
55
|
}
|
|
57
56
|
|
|
57
|
+
|
|
58
|
+
|
|
58
59
|
.sub-title {
|
|
59
60
|
color: var(--heading);
|
|
60
61
|
display: flex;
|
|
61
62
|
font-size: calc($default-text-font-size * 1.2);
|
|
62
63
|
font-weight: 500;
|
|
63
|
-
justify-content: flex-
|
|
64
|
+
justify-content: flex-start;
|
|
65
|
+
margin-left: 1rem;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.percentage-title {
|
|
69
|
+
color: var(--paragraph);
|
|
70
|
+
font-size: calc($default-text-font-size * .75);
|
|
71
|
+
justify-content: flex-start;
|
|
64
72
|
}
|
|
65
73
|
}
|
|
66
74
|
}
|
|
@@ -5,6 +5,72 @@ import { formatTime, formatDate, DATE_FORMATS, snakeCaseToTitleCase } from "../.
|
|
|
5
5
|
import "./styles.scss";
|
|
6
6
|
const baseClassName = styleNames.base;
|
|
7
7
|
const componentClassName = 'custom-tooltip-content';
|
|
8
|
+
const formatValue = (value, isTimeFormat) => {
|
|
9
|
+
if (isTimeFormat) {
|
|
10
|
+
return formatTime(value);
|
|
11
|
+
}
|
|
12
|
+
if (typeof value === 'number') {
|
|
13
|
+
return Number.isInteger(value) ? value : value.toFixed(2);
|
|
14
|
+
}
|
|
15
|
+
return value;
|
|
16
|
+
};
|
|
17
|
+
const PayoutPieChartLabel = ({
|
|
18
|
+
entry,
|
|
19
|
+
formatLabelValue
|
|
20
|
+
}) => /*#__PURE__*/React.createElement("div", {
|
|
21
|
+
className: "pie-chart-label"
|
|
22
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
23
|
+
className: "status"
|
|
24
|
+
}, /*#__PURE__*/React.createElement("span", {
|
|
25
|
+
className: "dot",
|
|
26
|
+
style: {
|
|
27
|
+
backgroundColor: entry?.payload?.color
|
|
28
|
+
}
|
|
29
|
+
}), /*#__PURE__*/React.createElement("p", {
|
|
30
|
+
className: "label",
|
|
31
|
+
key: `${entry.name}`,
|
|
32
|
+
style: {
|
|
33
|
+
color: entry.color,
|
|
34
|
+
textTransform: 'capitalize'
|
|
35
|
+
}
|
|
36
|
+
}, `${snakeCaseToTitleCase(entry.name)} `)), /*#__PURE__*/React.createElement("p", {
|
|
37
|
+
className: "value"
|
|
38
|
+
}, `${formatLabelValue(entry.value)}`));
|
|
39
|
+
const StandardPieChartLabel = ({
|
|
40
|
+
entry,
|
|
41
|
+
formatLabelValue
|
|
42
|
+
}) => /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("p", null, "Submissions"), /*#__PURE__*/React.createElement("div", {
|
|
43
|
+
className: "pie-chart-label"
|
|
44
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
45
|
+
className: "status"
|
|
46
|
+
}, /*#__PURE__*/React.createElement("span", {
|
|
47
|
+
className: "dot",
|
|
48
|
+
style: {
|
|
49
|
+
backgroundColor: entry?.payload?.color
|
|
50
|
+
}
|
|
51
|
+
}), /*#__PURE__*/React.createElement("p", {
|
|
52
|
+
className: "label",
|
|
53
|
+
key: `${entry.name}`,
|
|
54
|
+
style: {
|
|
55
|
+
color: entry.color,
|
|
56
|
+
textTransform: 'capitalize'
|
|
57
|
+
}
|
|
58
|
+
}, `${snakeCaseToTitleCase(entry.name)} `)), /*#__PURE__*/React.createElement("p", {
|
|
59
|
+
className: "value"
|
|
60
|
+
}, `${formatLabelValue(entry.value)}`), /*#__PURE__*/React.createElement("p", {
|
|
61
|
+
className: "percentage-title"
|
|
62
|
+
}, `${entry?.payload?.percentage}%`)));
|
|
63
|
+
const StandardChartLabel = ({
|
|
64
|
+
entry,
|
|
65
|
+
formatLabelValue
|
|
66
|
+
}) => /*#__PURE__*/React.createElement("p", {
|
|
67
|
+
className: "label",
|
|
68
|
+
key: `${entry.name}`,
|
|
69
|
+
style: {
|
|
70
|
+
color: entry.color,
|
|
71
|
+
textTransform: 'capitalize'
|
|
72
|
+
}
|
|
73
|
+
}, `${snakeCaseToTitleCase(entry.name)}: ${formatLabelValue(entry.value)}`);
|
|
8
74
|
const CustomTooltipContent = ({
|
|
9
75
|
id,
|
|
10
76
|
className: userClassName,
|
|
@@ -13,75 +79,97 @@ const CustomTooltipContent = ({
|
|
|
13
79
|
isDateValue,
|
|
14
80
|
active,
|
|
15
81
|
payload,
|
|
16
|
-
label
|
|
82
|
+
label,
|
|
83
|
+
isPieChart,
|
|
84
|
+
isPayOutChart
|
|
17
85
|
}) => {
|
|
18
|
-
const formatLabelValue = value =>
|
|
19
|
-
|
|
20
|
-
|
|
86
|
+
const formatLabelValue = React.useCallback(value => formatValue(value, isTimeFormat), [isTimeFormat]);
|
|
87
|
+
const renderContent = React.useCallback(entry => {
|
|
88
|
+
if (isPieChart && isPayOutChart) {
|
|
89
|
+
return /*#__PURE__*/React.createElement(PayoutPieChartLabel, {
|
|
90
|
+
entry: entry,
|
|
91
|
+
formatLabelValue: formatLabelValue
|
|
92
|
+
});
|
|
21
93
|
}
|
|
22
|
-
if (
|
|
23
|
-
|
|
24
|
-
|
|
94
|
+
if (isPieChart) {
|
|
95
|
+
return /*#__PURE__*/React.createElement(StandardPieChartLabel, {
|
|
96
|
+
entry: entry,
|
|
97
|
+
formatLabelValue: formatLabelValue
|
|
98
|
+
});
|
|
25
99
|
}
|
|
26
|
-
return
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
}, /*#__PURE__*/React.createElement("p", {
|
|
34
|
-
className: "label"
|
|
35
|
-
}, isDateValue ? formatDate(label, dateFormat) : label), newPayload.map(entry => /*#__PURE__*/React.createElement("p", {
|
|
36
|
-
className: "label",
|
|
37
|
-
key: `${entry.name}`,
|
|
38
|
-
style: {
|
|
39
|
-
color: entry.color,
|
|
40
|
-
textTransform: 'capitalize'
|
|
41
|
-
}
|
|
42
|
-
}, `${snakeCaseToTitleCase(entry.name)}: ${formatLabelValue(entry.value)}`)));
|
|
100
|
+
return /*#__PURE__*/React.createElement(StandardChartLabel, {
|
|
101
|
+
entry: entry,
|
|
102
|
+
formatLabelValue: formatLabelValue
|
|
103
|
+
});
|
|
104
|
+
}, [isPieChart, isPayOutChart, formatLabelValue]);
|
|
105
|
+
if (!active || !payload || !payload.length) {
|
|
106
|
+
return null;
|
|
43
107
|
}
|
|
44
|
-
|
|
108
|
+
const filteredPayload = payload.filter(item => item?.name !== 'bounds');
|
|
109
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
110
|
+
id: id,
|
|
111
|
+
className: [baseClassName, componentClassName, userClassName].filter(Boolean).join(' ')
|
|
112
|
+
}, /*#__PURE__*/React.createElement("p", {
|
|
113
|
+
className: "label"
|
|
114
|
+
}, isDateValue ? formatDate(label, dateFormat) : label), filteredPayload.map(entry => /*#__PURE__*/React.createElement(React.Fragment, {
|
|
115
|
+
key: entry.name || entry.dataKey
|
|
116
|
+
}, renderContent(entry))));
|
|
45
117
|
};
|
|
46
118
|
CustomTooltipContent.propTypes = {
|
|
47
119
|
/**
|
|
48
|
-
|
|
49
|
-
|
|
120
|
+
* The id of the tooltip component
|
|
121
|
+
*/
|
|
50
122
|
id: PropTypes.string,
|
|
51
123
|
/**
|
|
52
|
-
* Additional class names for the
|
|
124
|
+
* Additional class names for the tooltip component
|
|
53
125
|
*/
|
|
54
126
|
className: PropTypes.string,
|
|
55
127
|
/**
|
|
56
|
-
* Flag
|
|
128
|
+
* Flag indicating whether values should be formatted as time
|
|
57
129
|
*/
|
|
58
130
|
isTimeFormat: PropTypes.bool,
|
|
59
131
|
/**
|
|
60
|
-
* The
|
|
132
|
+
* The format to use for date values
|
|
61
133
|
*/
|
|
62
134
|
dateFormat: PropTypes.oneOf(Object.values(DATE_FORMATS)),
|
|
63
135
|
/**
|
|
64
|
-
* Flag
|
|
136
|
+
* Flag indicating whether the label is a date value
|
|
65
137
|
*/
|
|
66
138
|
isDateValue: PropTypes.bool,
|
|
67
139
|
/**
|
|
68
|
-
* If
|
|
69
|
-
* If set false, the tooltip is hidden, usually calculated internally.
|
|
140
|
+
* If true, the tooltip is displayed
|
|
70
141
|
*/
|
|
71
142
|
active: PropTypes.bool.isRequired,
|
|
72
143
|
/**
|
|
73
|
-
* The source data
|
|
74
|
-
|
|
144
|
+
* The source data to be displayed in the tooltip
|
|
145
|
+
*/
|
|
146
|
+
payload: PropTypes.arrayOf(PropTypes.shape({
|
|
147
|
+
name: PropTypes.string,
|
|
148
|
+
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
|
149
|
+
payload: PropTypes.shape({}),
|
|
150
|
+
dataKey: PropTypes.string,
|
|
151
|
+
color: PropTypes.string
|
|
152
|
+
})).isRequired,
|
|
153
|
+
/**
|
|
154
|
+
* The label value which is active
|
|
155
|
+
*/
|
|
156
|
+
label: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
|
|
157
|
+
/**
|
|
158
|
+
* Flag indicating whether the chart is a pie chart
|
|
75
159
|
*/
|
|
76
|
-
|
|
160
|
+
isPieChart: PropTypes.bool,
|
|
77
161
|
/**
|
|
78
|
-
*
|
|
162
|
+
* Flag indicating whether the chart is a payout chart
|
|
79
163
|
*/
|
|
80
|
-
|
|
164
|
+
isPayOutChart: PropTypes.bool
|
|
81
165
|
};
|
|
82
166
|
CustomTooltipContent.defaultProps = {
|
|
167
|
+
id: undefined,
|
|
168
|
+
className: undefined,
|
|
83
169
|
isTimeFormat: false,
|
|
84
170
|
isDateValue: true,
|
|
85
|
-
dateFormat: DATE_FORMATS.HUMAN_READABLE
|
|
171
|
+
dateFormat: DATE_FORMATS.HUMAN_READABLE,
|
|
172
|
+
isPieChart: false,
|
|
173
|
+
isPayOutChart: false
|
|
86
174
|
};
|
|
87
|
-
export default CustomTooltipContent;
|
|
175
|
+
export default /*#__PURE__*/React.memo(CustomTooltipContent);
|
|
@@ -5,6 +5,9 @@ $default-padding: 1rem;
|
|
|
5
5
|
$default-text-font-size: calc(var(--s-1) * 1rem);
|
|
6
6
|
$default-border-radius: .25rem;
|
|
7
7
|
$default-border-line-width: .0625rem;
|
|
8
|
+
$default-legend-dot-width: .5rem;
|
|
9
|
+
$default-legend-dot-height: .5rem;
|
|
10
|
+
$default-legend-dot-margin-right: .3125rem;
|
|
8
11
|
|
|
9
12
|
.#{bem.$base} {
|
|
10
13
|
&.custom-tooltip-content {
|
|
@@ -20,3 +23,4 @@ $default-border-line-width: .0625rem;
|
|
|
20
23
|
}
|
|
21
24
|
}
|
|
22
25
|
}
|
|
26
|
+
|
|
@@ -17,14 +17,18 @@ const PieChart = ({
|
|
|
17
17
|
height,
|
|
18
18
|
width,
|
|
19
19
|
innerRadius,
|
|
20
|
-
outerRadius
|
|
20
|
+
outerRadius,
|
|
21
|
+
formatTotal,
|
|
22
|
+
subtitleToCurrency,
|
|
23
|
+
isPayOutChart
|
|
21
24
|
}) => {
|
|
22
25
|
const total = data.reduce((sum, item) => sum + item[valueKey], 0);
|
|
26
|
+
const displayTotal = formatTotal ? formatTotal(total) : `${total}`;
|
|
23
27
|
const formattedData = data.map(item => ({
|
|
24
28
|
...item,
|
|
25
29
|
label: item[labelKey],
|
|
26
30
|
color: colors[data.indexOf(item)],
|
|
27
|
-
percentage: (item[valueKey] / total * 100).toFixed(0)
|
|
31
|
+
percentage: total === 0 ? 0.0 : (item[valueKey] / total * 100).toFixed(0)
|
|
28
32
|
}));
|
|
29
33
|
return /*#__PURE__*/React.createElement("div", {
|
|
30
34
|
id: id,
|
|
@@ -52,15 +56,36 @@ const PieChart = ({
|
|
|
52
56
|
strokeWidth: 0
|
|
53
57
|
}))), /*#__PURE__*/React.createElement(Tooltip, {
|
|
54
58
|
content: /*#__PURE__*/React.createElement(CustomTooltipContent, {
|
|
55
|
-
isDateValue: false
|
|
59
|
+
isDateValue: false,
|
|
60
|
+
isPieChart: true,
|
|
61
|
+
isPayOutChart: isPayOutChart
|
|
56
62
|
})
|
|
57
|
-
})
|
|
63
|
+
}), /*#__PURE__*/React.createElement("text", {
|
|
64
|
+
x: "50%",
|
|
65
|
+
y: "50%",
|
|
66
|
+
textAnchor: "middle",
|
|
67
|
+
dominantBaseline: "middle",
|
|
68
|
+
style: {}
|
|
69
|
+
}, /*#__PURE__*/React.createElement("tspan", {
|
|
70
|
+
x: "50%",
|
|
71
|
+
dy: "-1.2em",
|
|
72
|
+
fontSize: "14",
|
|
73
|
+
fill: "grey"
|
|
74
|
+
}, "Total"), /*#__PURE__*/React.createElement("tspan", {
|
|
75
|
+
x: "50%",
|
|
76
|
+
dy: "1.2em",
|
|
77
|
+
fill: "var(--heading)",
|
|
78
|
+
fontSize: "22"
|
|
79
|
+
}, displayTotal)))), /*#__PURE__*/React.createElement(CustomLegend, {
|
|
80
|
+
key: id,
|
|
58
81
|
colorsArray: colors,
|
|
59
82
|
yKeysArray: formattedData,
|
|
60
83
|
capitalizedLegend: true,
|
|
61
84
|
orientation: "vertical",
|
|
62
85
|
getLegendItemTitle: entry => entry[labelKey],
|
|
63
|
-
getLegendItemSubtitle: entry => entry[valueKey]
|
|
86
|
+
getLegendItemSubtitle: entry => entry[valueKey],
|
|
87
|
+
subtitleToCurrency: subtitleToCurrency,
|
|
88
|
+
isPayOutChart: isPayOutChart
|
|
64
89
|
})));
|
|
65
90
|
};
|
|
66
91
|
PieChart.propTypes = {
|
|
@@ -76,14 +101,20 @@ PieChart.propTypes = {
|
|
|
76
101
|
height: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
|
77
102
|
width: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
|
78
103
|
innerRadius: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
|
79
|
-
outerRadius: PropTypes.oneOfType([PropTypes.string, PropTypes.number])
|
|
104
|
+
outerRadius: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
|
105
|
+
formatTotal: PropTypes.func,
|
|
106
|
+
subtitleToCurrency: PropTypes.bool,
|
|
107
|
+
isPayOutChart: PropTypes.bool
|
|
80
108
|
};
|
|
81
109
|
PieChart.defaultProps = {
|
|
82
110
|
id: undefined,
|
|
83
111
|
className: undefined,
|
|
84
112
|
width: '100%',
|
|
85
113
|
height: 300,
|
|
86
|
-
innerRadius: '
|
|
87
|
-
outerRadius: '100%'
|
|
114
|
+
innerRadius: '50%',
|
|
115
|
+
outerRadius: '100%',
|
|
116
|
+
formatTotal: null,
|
|
117
|
+
subtitleToCurrency: false,
|
|
118
|
+
isPayOutChart: false
|
|
88
119
|
};
|
|
89
120
|
export default PieChart;
|