@pareto-engineering/design-system 5.2.1 → 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 +60 -5
- package/dist/cjs/a/Charts/AreaChart/styles.scss +22 -0
- package/dist/cjs/a/Charts/Common/CustomLegend/CustomLegend.js +19 -5
- package/dist/cjs/a/Charts/Common/CustomTooltipContent/CustomTooltipContent.js +133 -68
- package/dist/cjs/a/Charts/PieChart/PieChart.js +20 -7
- 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/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 +61 -6
- package/dist/es/a/Charts/AreaChart/styles.scss +22 -0
- package/dist/es/a/Charts/Common/CustomLegend/CustomLegend.js +19 -5
- package/dist/es/a/Charts/Common/CustomTooltipContent/CustomTooltipContent.js +122 -66
- package/dist/es/a/Charts/PieChart/PieChart.js +20 -7
- 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/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 +5 -5
- package/src/ui/a/Charts/AreaChart/AreaChart.jsx +73 -9
- package/src/ui/a/Charts/AreaChart/styles.scss +22 -0
- package/src/ui/a/Charts/Common/CustomLegend/CustomLegend.jsx +20 -5
- package/src/ui/a/Charts/Common/CustomTooltipContent/CustomTooltipContent.jsx +126 -79
- package/src/ui/a/Charts/PieChart/PieChart.jsx +38 -17
- 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/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 +7 -1
|
@@ -14,6 +14,64 @@ const baseClassName = styleNames.base
|
|
|
14
14
|
|
|
15
15
|
const componentClassName = 'custom-tooltip-content'
|
|
16
16
|
|
|
17
|
+
const formatValue = (value, isTimeFormat) => {
|
|
18
|
+
if (isTimeFormat) {
|
|
19
|
+
return formatTime(value)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (typeof value === 'number') {
|
|
23
|
+
return Number.isInteger(value) ? value : value.toFixed(2)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return value
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const PayoutPieChartLabel = ({ entry, formatLabelValue }) => (
|
|
30
|
+
<div className="pie-chart-label">
|
|
31
|
+
<div className="status">
|
|
32
|
+
<span
|
|
33
|
+
className="dot"
|
|
34
|
+
style={{ backgroundColor: entry?.payload?.color }}
|
|
35
|
+
/>
|
|
36
|
+
<p className="label" key={`${entry.name}`} style={{ color: entry.color, textTransform: 'capitalize' }}>
|
|
37
|
+
{`${snakeCaseToTitleCase(entry.name)} `}
|
|
38
|
+
</p>
|
|
39
|
+
</div>
|
|
40
|
+
<p className="value">
|
|
41
|
+
{`${formatLabelValue(entry.value)}`}
|
|
42
|
+
</p>
|
|
43
|
+
</div>
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
const StandardPieChartLabel = ({ entry, formatLabelValue }) => (
|
|
47
|
+
<>
|
|
48
|
+
<p>Submissions</p>
|
|
49
|
+
<div className="pie-chart-label">
|
|
50
|
+
<div className="status">
|
|
51
|
+
<span
|
|
52
|
+
className="dot"
|
|
53
|
+
style={{ backgroundColor: entry?.payload?.color }}
|
|
54
|
+
/>
|
|
55
|
+
<p className="label" key={`${entry.name}`} style={{ color: entry.color, textTransform: 'capitalize' }}>
|
|
56
|
+
{`${snakeCaseToTitleCase(entry.name)} `}
|
|
57
|
+
</p>
|
|
58
|
+
</div>
|
|
59
|
+
<p className="value">
|
|
60
|
+
{`${formatLabelValue(entry.value)}`}
|
|
61
|
+
</p>
|
|
62
|
+
<p className="percentage-title">
|
|
63
|
+
{`${entry?.payload?.percentage}%`}
|
|
64
|
+
</p>
|
|
65
|
+
</div>
|
|
66
|
+
</>
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
const StandardChartLabel = ({ entry, formatLabelValue }) => (
|
|
70
|
+
<p className="label" key={`${entry.name}`} style={{ color: entry.color, textTransform: 'capitalize' }}>
|
|
71
|
+
{`${snakeCaseToTitleCase(entry.name)}: ${formatLabelValue(entry.value)}`}
|
|
72
|
+
</p>
|
|
73
|
+
)
|
|
74
|
+
|
|
17
75
|
const CustomTooltipContent = ({
|
|
18
76
|
id,
|
|
19
77
|
className: userClassName,
|
|
@@ -24,131 +82,120 @@ const CustomTooltipContent = ({
|
|
|
24
82
|
payload,
|
|
25
83
|
label,
|
|
26
84
|
isPieChart,
|
|
85
|
+
isPayOutChart,
|
|
27
86
|
}) => {
|
|
28
|
-
const formatLabelValue = (
|
|
29
|
-
|
|
30
|
-
|
|
87
|
+
const formatLabelValue = React.useCallback(
|
|
88
|
+
(value) => formatValue(value, isTimeFormat),
|
|
89
|
+
[isTimeFormat],
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
const renderContent = React.useCallback((entry) => {
|
|
93
|
+
if (isPieChart && isPayOutChart) {
|
|
94
|
+
return <PayoutPieChartLabel entry={entry} formatLabelValue={formatLabelValue} />
|
|
31
95
|
}
|
|
32
96
|
|
|
33
|
-
if (
|
|
34
|
-
|
|
35
|
-
return value.toFixed(2)
|
|
97
|
+
if (isPieChart) {
|
|
98
|
+
return <StandardPieChartLabel entry={entry} formatLabelValue={formatLabelValue} />
|
|
36
99
|
}
|
|
37
100
|
|
|
38
|
-
return
|
|
39
|
-
}
|
|
101
|
+
return <StandardChartLabel entry={entry} formatLabelValue={formatLabelValue} />
|
|
102
|
+
}, [isPieChart, isPayOutChart, formatLabelValue])
|
|
40
103
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
return (
|
|
44
|
-
<>
|
|
45
|
-
<p>Submissions</p>
|
|
46
|
-
<div className="pie-chart-label">
|
|
47
|
-
<div className="status">
|
|
48
|
-
<span
|
|
49
|
-
className="dot"
|
|
50
|
-
style={{ backgroundColor: entry?.payload?.color }}
|
|
51
|
-
/>
|
|
52
|
-
<p className="label" key={`${entry.name}`} style={{ color: entry.color, textTransform: 'capitalize' }}>
|
|
53
|
-
{`${snakeCaseToTitleCase(entry.name)} `}
|
|
54
|
-
</p>
|
|
55
|
-
</div>
|
|
56
|
-
<p className="value">
|
|
57
|
-
{`${formatLabelValue(entry.value)}`}
|
|
58
|
-
</p>
|
|
59
|
-
<p className="percentage-title">
|
|
60
|
-
{`${entry?.payload?.percentage}%`}
|
|
61
|
-
</p>
|
|
62
|
-
</div>
|
|
63
|
-
</>
|
|
64
|
-
)
|
|
65
|
-
}
|
|
66
|
-
return (
|
|
67
|
-
<p className="label" key={`${entry.name}`} style={{ color: entry.color, textTransform: 'capitalize' }}>
|
|
68
|
-
{`${snakeCaseToTitleCase(entry.name)}: ${formatLabelValue(entry.value)}`}
|
|
69
|
-
</p>
|
|
70
|
-
)
|
|
104
|
+
if (!active || !payload || !payload.length) {
|
|
105
|
+
return null
|
|
71
106
|
}
|
|
72
107
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
108
|
+
const filteredPayload = payload.filter((item) => item?.name !== 'bounds')
|
|
109
|
+
|
|
110
|
+
return (
|
|
111
|
+
<div
|
|
112
|
+
id={id}
|
|
113
|
+
className={[
|
|
114
|
+
baseClassName,
|
|
115
|
+
componentClassName,
|
|
116
|
+
userClassName,
|
|
117
|
+
]
|
|
118
|
+
.filter(Boolean)
|
|
119
|
+
.join(' ')}
|
|
120
|
+
>
|
|
121
|
+
<p className="label">
|
|
122
|
+
{isDateValue ? formatDate(label, dateFormat) : label}
|
|
123
|
+
</p>
|
|
124
|
+
{filteredPayload.map((entry) => (
|
|
125
|
+
<React.Fragment key={entry.name || entry.dataKey}>
|
|
126
|
+
{renderContent(entry)}
|
|
127
|
+
</React.Fragment>
|
|
128
|
+
))}
|
|
129
|
+
</div>
|
|
130
|
+
)
|
|
96
131
|
}
|
|
97
132
|
|
|
98
133
|
CustomTooltipContent.propTypes = {
|
|
99
134
|
/**
|
|
100
|
-
|
|
101
|
-
|
|
135
|
+
* The id of the tooltip component
|
|
136
|
+
*/
|
|
102
137
|
id:PropTypes.string,
|
|
103
138
|
|
|
104
139
|
/**
|
|
105
|
-
* Additional class names for the
|
|
140
|
+
* Additional class names for the tooltip component
|
|
106
141
|
*/
|
|
107
142
|
className:PropTypes.string,
|
|
108
143
|
|
|
109
144
|
/**
|
|
110
|
-
* Flag
|
|
145
|
+
* Flag indicating whether values should be formatted as time
|
|
111
146
|
*/
|
|
112
147
|
isTimeFormat:PropTypes.bool,
|
|
113
148
|
|
|
114
149
|
/**
|
|
115
|
-
* The
|
|
150
|
+
* The format to use for date values
|
|
116
151
|
*/
|
|
117
152
|
dateFormat:PropTypes.oneOf(Object.values(DATE_FORMATS)),
|
|
118
153
|
|
|
119
154
|
/**
|
|
120
|
-
* Flag
|
|
155
|
+
* Flag indicating whether the label is a date value
|
|
121
156
|
*/
|
|
122
157
|
isDateValue:PropTypes.bool,
|
|
123
158
|
|
|
124
159
|
/**
|
|
125
|
-
* If
|
|
126
|
-
* If set false, the tooltip is hidden, usually calculated internally.
|
|
160
|
+
* If true, the tooltip is displayed
|
|
127
161
|
*/
|
|
128
162
|
active:PropTypes.bool.isRequired,
|
|
129
163
|
|
|
130
164
|
/**
|
|
131
|
-
* The source data
|
|
132
|
-
* always calculated internally and cannot be user set.
|
|
165
|
+
* The source data to be displayed in the tooltip
|
|
133
166
|
*/
|
|
134
|
-
payload:PropTypes.arrayOf(PropTypes.
|
|
167
|
+
payload:PropTypes.arrayOf(PropTypes.shape({
|
|
168
|
+
name :PropTypes.string,
|
|
169
|
+
value :PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
|
170
|
+
payload:PropTypes.shape({}),
|
|
171
|
+
dataKey:PropTypes.string,
|
|
172
|
+
color :PropTypes.string,
|
|
173
|
+
})).isRequired,
|
|
135
174
|
|
|
136
175
|
/**
|
|
137
|
-
*The label value which is active
|
|
176
|
+
* The label value which is active
|
|
138
177
|
*/
|
|
139
178
|
label:PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
|
|
140
179
|
|
|
141
180
|
/**
|
|
142
|
-
* Flag
|
|
181
|
+
* Flag indicating whether the chart is a pie chart
|
|
143
182
|
*/
|
|
144
183
|
isPieChart:PropTypes.bool,
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Flag indicating whether the chart is a payout chart
|
|
187
|
+
*/
|
|
188
|
+
isPayOutChart:PropTypes.bool,
|
|
145
189
|
}
|
|
146
190
|
|
|
147
191
|
CustomTooltipContent.defaultProps = {
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
192
|
+
id :undefined,
|
|
193
|
+
className :undefined,
|
|
194
|
+
isTimeFormat :false,
|
|
195
|
+
isDateValue :true,
|
|
196
|
+
dateFormat :DATE_FORMATS.HUMAN_READABLE,
|
|
197
|
+
isPieChart :false,
|
|
198
|
+
isPayOutChart:false,
|
|
152
199
|
}
|
|
153
200
|
|
|
154
|
-
export default CustomTooltipContent
|
|
201
|
+
export default React.memo(CustomTooltipContent)
|
|
@@ -32,14 +32,19 @@ const PieChart = ({
|
|
|
32
32
|
width,
|
|
33
33
|
innerRadius,
|
|
34
34
|
outerRadius,
|
|
35
|
+
formatTotal,
|
|
36
|
+
subtitleToCurrency,
|
|
37
|
+
isPayOutChart,
|
|
35
38
|
}) => {
|
|
36
39
|
const total = data.reduce((sum, item) => sum + item[valueKey], 0)
|
|
37
40
|
|
|
41
|
+
const displayTotal = formatTotal ? formatTotal(total) : `${total}`
|
|
42
|
+
|
|
38
43
|
const formattedData = data.map((item) => ({
|
|
39
44
|
...item,
|
|
40
45
|
label :item[labelKey],
|
|
41
46
|
color :colors[data.indexOf(item)],
|
|
42
|
-
percentage:((item[valueKey] / total) * 100).toFixed(0),
|
|
47
|
+
percentage:total === 0 ? 0.0 : ((item[valueKey] / total) * 100).toFixed(0),
|
|
43
48
|
}))
|
|
44
49
|
|
|
45
50
|
return (
|
|
@@ -78,7 +83,15 @@ const PieChart = ({
|
|
|
78
83
|
/>
|
|
79
84
|
))}
|
|
80
85
|
</Pie>
|
|
81
|
-
<Tooltip
|
|
86
|
+
<Tooltip
|
|
87
|
+
content={(
|
|
88
|
+
<CustomTooltipContent
|
|
89
|
+
isDateValue={false}
|
|
90
|
+
isPieChart
|
|
91
|
+
isPayOutChart={isPayOutChart}
|
|
92
|
+
/>
|
|
93
|
+
)}
|
|
94
|
+
/>
|
|
82
95
|
|
|
83
96
|
<text
|
|
84
97
|
x="50%"
|
|
@@ -92,7 +105,7 @@ const PieChart = ({
|
|
|
92
105
|
Total
|
|
93
106
|
</tspan>
|
|
94
107
|
<tspan x="50%" dy="1.2em" fill="var(--heading)" fontSize="22">
|
|
95
|
-
{
|
|
108
|
+
{displayTotal}
|
|
96
109
|
</tspan>
|
|
97
110
|
</text>
|
|
98
111
|
</RechartsPieChart>
|
|
@@ -105,6 +118,8 @@ const PieChart = ({
|
|
|
105
118
|
orientation="vertical"
|
|
106
119
|
getLegendItemTitle={(entry) => entry[labelKey]}
|
|
107
120
|
getLegendItemSubtitle={(entry) => entry[valueKey]}
|
|
121
|
+
subtitleToCurrency={subtitleToCurrency}
|
|
122
|
+
isPayOutChart={isPayOutChart}
|
|
108
123
|
/>
|
|
109
124
|
</div>
|
|
110
125
|
</div>
|
|
@@ -120,23 +135,29 @@ PieChart.propTypes = {
|
|
|
120
135
|
PropTypes.number,
|
|
121
136
|
]),
|
|
122
137
|
})).isRequired,
|
|
123
|
-
title
|
|
124
|
-
valueKey
|
|
125
|
-
labelKey
|
|
126
|
-
colors
|
|
127
|
-
height
|
|
128
|
-
width
|
|
129
|
-
innerRadius:PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
|
130
|
-
outerRadius:PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
|
138
|
+
title :PropTypes.string.isRequired,
|
|
139
|
+
valueKey :PropTypes.string.isRequired,
|
|
140
|
+
labelKey :PropTypes.string.isRequired,
|
|
141
|
+
colors :PropTypes.arrayOf(PropTypes.string).isRequired,
|
|
142
|
+
height :PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
|
143
|
+
width :PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
|
144
|
+
innerRadius :PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
|
145
|
+
outerRadius :PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
|
146
|
+
formatTotal :PropTypes.func,
|
|
147
|
+
subtitleToCurrency:PropTypes.bool,
|
|
148
|
+
isPayOutChart :PropTypes.bool,
|
|
131
149
|
}
|
|
132
150
|
|
|
133
151
|
PieChart.defaultProps = {
|
|
134
|
-
id
|
|
135
|
-
className
|
|
136
|
-
width
|
|
137
|
-
height
|
|
138
|
-
innerRadius:'50%',
|
|
139
|
-
outerRadius:'100%',
|
|
152
|
+
id :undefined,
|
|
153
|
+
className :undefined,
|
|
154
|
+
width :'100%',
|
|
155
|
+
height :300,
|
|
156
|
+
innerRadius :'50%',
|
|
157
|
+
outerRadius :'100%',
|
|
158
|
+
formatTotal :null,
|
|
159
|
+
subtitleToCurrency:false,
|
|
160
|
+
isPayOutChart :false,
|
|
140
161
|
}
|
|
141
162
|
|
|
142
163
|
export default PieChart
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import * as React from 'react'
|
|
2
|
+
import PropTypes from 'prop-types'
|
|
3
|
+
|
|
4
|
+
import styleNames from '@pareto-engineering/bem/exports'
|
|
5
|
+
|
|
6
|
+
import './styles.scss'
|
|
7
|
+
|
|
8
|
+
// Local Definitions
|
|
9
|
+
const baseClassName = styleNames.base
|
|
10
|
+
const componentClassName = 'throughput-indicator'
|
|
11
|
+
|
|
12
|
+
const ThroughPutIndicator = ({ data, keyName = 'reserved' }) => {
|
|
13
|
+
const renderNoChange = () => (
|
|
14
|
+
<div
|
|
15
|
+
className={[
|
|
16
|
+
baseClassName,
|
|
17
|
+
componentClassName,
|
|
18
|
+
]
|
|
19
|
+
.filter((e) => e)
|
|
20
|
+
.join(' ')}
|
|
21
|
+
>
|
|
22
|
+
<span className="no-change-text">No change</span>
|
|
23
|
+
</div>
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
const renderChange = (direction, percentage, icon = direction === 'positive' ? 'S' : 'R') => (
|
|
27
|
+
<div
|
|
28
|
+
className={[
|
|
29
|
+
baseClassName,
|
|
30
|
+
componentClassName,
|
|
31
|
+
]
|
|
32
|
+
.filter((e) => e)
|
|
33
|
+
.join(' ')}
|
|
34
|
+
>
|
|
35
|
+
<span className={`ai-icon ${direction}-throughput-indicator`}>{icon}</span>
|
|
36
|
+
<p>
|
|
37
|
+
{percentage}
|
|
38
|
+
%
|
|
39
|
+
</p>
|
|
40
|
+
</div>
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
// Handle invalid or insufficient data
|
|
44
|
+
if (!data || data.length < 2) {
|
|
45
|
+
return renderNoChange()
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const first = data[0][keyName]
|
|
49
|
+
const last = data[data.length - 1][keyName]
|
|
50
|
+
|
|
51
|
+
// Handle no change scenarios
|
|
52
|
+
if (first === 0 && last === 0) {
|
|
53
|
+
return renderNoChange()
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Handle special case: starting from zero
|
|
57
|
+
if (first === 0 && last !== 0) {
|
|
58
|
+
return renderChange('positive', '100')
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Calculate percentage change
|
|
62
|
+
const percentChange = ((last - first) / Math.abs(first)) * 100
|
|
63
|
+
const rounded = Math.abs(percentChange).toFixed(1)
|
|
64
|
+
|
|
65
|
+
// No change
|
|
66
|
+
if (percentChange === 0) {
|
|
67
|
+
return renderNoChange()
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Positive or negative change
|
|
71
|
+
const direction = percentChange > 0 ? 'positive' : 'negative'
|
|
72
|
+
const icon = direction === 'positive' ? 'S' : 'R'
|
|
73
|
+
|
|
74
|
+
return renderChange(direction, rounded, icon)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
ThroughPutIndicator.propTypes = {
|
|
78
|
+
/**
|
|
79
|
+
* The data to be displayed in the throughput indicator
|
|
80
|
+
*/
|
|
81
|
+
// eslint-disable-next-line react/forbid-prop-types
|
|
82
|
+
data:PropTypes.arrayOf(PropTypes.object).isRequired,
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* The key name to be displayed in the throughput indicator
|
|
86
|
+
*/
|
|
87
|
+
keyName:PropTypes.string,
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export default ThroughPutIndicator
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/* @pareto-engineering/generator-front 1.0.12 */
|
|
2
|
+
|
|
3
|
+
@use "@pareto-engineering/bem";
|
|
4
|
+
|
|
5
|
+
$default-text-font-size: calc(var(--s-1) * 1rem);
|
|
6
|
+
|
|
7
|
+
.#{bem.$base} {
|
|
8
|
+
.throughput-indicator {
|
|
9
|
+
align-items: center;
|
|
10
|
+
border: 1px solid var(--hard-grey);
|
|
11
|
+
border-radius: 2rem;
|
|
12
|
+
display: flex;
|
|
13
|
+
gap: .5rem;
|
|
14
|
+
height: 3rem;
|
|
15
|
+
padding: .5rem;
|
|
16
|
+
|
|
17
|
+
.positive-throughput-indicator {
|
|
18
|
+
color: var(--success);
|
|
19
|
+
font-size: 1rem;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.negative-throughput-indicator {
|
|
23
|
+
color: var(--error);
|
|
24
|
+
font-size: .75rem;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.no-change-text {
|
|
28
|
+
color: var(--paragraph);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
p {
|
|
32
|
+
font-size: 1rem;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -7,7 +7,7 @@ $default-size: var(--size, 1.2em);
|
|
|
7
7
|
$default-slider-color: var(--slider-color, var(--background-far));
|
|
8
8
|
$default-slider-border-color: var(--slider-border-color, var(--ui-lines));
|
|
9
9
|
$default-background-color: var(--slider-background-color, var(--interactive));
|
|
10
|
-
|
|
10
|
+
$default-background-disabled: var(--disabled, var(--background-far));
|
|
11
11
|
.#{bem.$base}.toggle-switch {
|
|
12
12
|
background: transparent;
|
|
13
13
|
border: none;
|
|
@@ -21,7 +21,6 @@ $default-background-color: var(--slider-background-color, var(--interactive));
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
>label {
|
|
24
|
-
background: $default-background-color;
|
|
25
24
|
border-radius: $default-border-radius;
|
|
26
25
|
cursor: pointer;
|
|
27
26
|
display: block;
|
|
@@ -29,6 +28,14 @@ $default-background-color: var(--slider-background-color, var(--interactive));
|
|
|
29
28
|
position: relative;
|
|
30
29
|
width: calc($default-size * 2);
|
|
31
30
|
|
|
31
|
+
&.checked {
|
|
32
|
+
background: $default-background-color;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
&:not(.checked) {
|
|
36
|
+
background: $default-background-disabled;
|
|
37
|
+
}
|
|
38
|
+
|
|
32
39
|
&::after {
|
|
33
40
|
background: $default-slider-color;
|
|
34
41
|
border: 1px solid $default-slider-border-color;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/* @pareto-engineering/generator-front 1.0.12 */
|
|
2
2
|
import * as React from 'react'
|
|
3
|
+
import { useEffect } from 'react'
|
|
3
4
|
|
|
4
5
|
import PropTypes from 'prop-types'
|
|
5
6
|
|
|
@@ -21,40 +22,63 @@ const Tooltip = ({
|
|
|
21
22
|
className:userClassName,
|
|
22
23
|
style,
|
|
23
24
|
position,
|
|
25
|
+
isFloating,
|
|
24
26
|
color,
|
|
25
27
|
description,
|
|
26
28
|
content,
|
|
27
29
|
children,
|
|
28
30
|
// ...otherProps
|
|
29
|
-
}) =>
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
>
|
|
47
|
-
{children}
|
|
48
|
-
</div>
|
|
31
|
+
}) => {
|
|
32
|
+
useEffect(() => {
|
|
33
|
+
const handleMouseMove = (e) => {
|
|
34
|
+
document.documentElement.style.setProperty('--mouse-x', `${e.clientX}px`)
|
|
35
|
+
document.documentElement.style.setProperty('--mouse-y', `${e.clientY}px`)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (!isFloating) {
|
|
39
|
+
return () => window.removeEventListener('mousemove', handleMouseMove)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
window.addEventListener('mousemove', handleMouseMove)
|
|
43
|
+
|
|
44
|
+
return () => window.removeEventListener('mousemove', handleMouseMove)
|
|
45
|
+
}, [isFloating])
|
|
46
|
+
|
|
47
|
+
return (
|
|
49
48
|
<div
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
49
|
+
id={id}
|
|
50
|
+
className={[
|
|
51
|
+
baseClassName,
|
|
52
|
+
componentClassName,
|
|
53
|
+
userClassName,
|
|
54
|
+
`x-${color}`,
|
|
55
|
+
]
|
|
56
|
+
.filter((e) => e)
|
|
57
|
+
.join(' ')}
|
|
58
|
+
style={style}
|
|
53
59
|
>
|
|
54
|
-
|
|
60
|
+
<div
|
|
61
|
+
className="tooltip-trigger-wrapper"
|
|
62
|
+
aria-describedby={description}
|
|
63
|
+
>
|
|
64
|
+
{children}
|
|
65
|
+
</div>
|
|
66
|
+
<div
|
|
67
|
+
className={[
|
|
68
|
+
'tooltip-content',
|
|
69
|
+
position,
|
|
70
|
+
isFloating ? 'floating' : '',
|
|
71
|
+
]
|
|
72
|
+
.filter((e) => e)
|
|
73
|
+
.join(' ')}
|
|
74
|
+
role="tooltip"
|
|
75
|
+
id={description}
|
|
76
|
+
>
|
|
77
|
+
{content}
|
|
78
|
+
</div>
|
|
55
79
|
</div>
|
|
56
|
-
|
|
57
|
-
|
|
80
|
+
)
|
|
81
|
+
}
|
|
58
82
|
|
|
59
83
|
Tooltip.propTypes = {
|
|
60
84
|
/**
|
|
@@ -92,6 +116,11 @@ Tooltip.propTypes = {
|
|
|
92
116
|
*/
|
|
93
117
|
position:PropTypes.oneOf(['top', 'bottom', 'left', 'right']),
|
|
94
118
|
|
|
119
|
+
/**
|
|
120
|
+
* Whether or not the tooltip should be floating
|
|
121
|
+
*/
|
|
122
|
+
isFloating:PropTypes.bool,
|
|
123
|
+
|
|
95
124
|
/**
|
|
96
125
|
* The base color of the tooltip
|
|
97
126
|
*/
|