@pareto-engineering/design-system 4.12.0 → 5.0.1
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/{AreaChart → Charts/AreaChart}/AreaChart.js +89 -63
- package/dist/cjs/a/Charts/AreaChart/styles.scss +48 -0
- package/dist/cjs/a/Charts/BarChart/BarChart.js +135 -0
- package/dist/cjs/a/Charts/BarChart/index.js +13 -0
- package/dist/cjs/a/Charts/BarChart/styles.scss +48 -0
- package/dist/cjs/a/Charts/Common/CustomLegend/CustomLegend.js +69 -0
- package/dist/cjs/a/Charts/Common/CustomLegend/index.js +13 -0
- package/dist/cjs/a/Charts/Common/CustomLegend/styles.scss +40 -0
- package/dist/cjs/a/Charts/Common/CustomTooltipContent/CustomTooltipContent.js +86 -0
- package/dist/cjs/a/Charts/Common/CustomTooltipContent/index.js +13 -0
- package/dist/cjs/a/Charts/Common/CustomTooltipContent/styles.scss +22 -0
- package/dist/cjs/a/Charts/Common/YLabelsDropDown/YlabelsDropDown.js +98 -0
- package/dist/cjs/a/Charts/Common/YLabelsDropDown/index.js +13 -0
- package/dist/cjs/a/Charts/Common/YLabelsDropDown/styles.scss +88 -0
- package/dist/cjs/a/Charts/Common/index.js +26 -0
- package/dist/cjs/a/Charts/index.js +19 -0
- package/dist/cjs/a/Tooltip/styles.scss +1 -1
- package/dist/cjs/a/index.js +8 -2
- package/dist/cjs/f/FormInput/FormInput.js +6 -0
- package/dist/cjs/f/fields/FileUpload/FileUpload.js +18 -4
- package/dist/cjs/f/fields/LatexPreviewInput/LatexPreviewInput.js +78 -0
- package/dist/cjs/f/fields/LatexPreviewInput/convertLatexToHtml.js +46 -0
- package/dist/cjs/f/fields/LatexPreviewInput/index.js +20 -0
- package/dist/cjs/f/fields/LatexPreviewInput/styles.scss +24 -0
- package/dist/cjs/f/fields/index.js +13 -0
- package/dist/cjs/g/FormBuilder/FormBuilder.js +3 -6
- package/dist/cjs/g/FormBuilder/common/Builder/Builder.js +1 -3
- package/dist/cjs/g/FormBuilder/common/Builder/common/InputBuilder/InputBuilder.js +5 -7
- package/dist/cjs/g/FormBuilder/common/Builder/common/Section/Section.js +2 -4
- package/dist/cjs/g/FormBuilder/common/Renderer/Renderer.js +2 -4
- package/dist/cjs/g/FormBuilder/common/Renderer/common/Section/Section.js +2 -10
- package/dist/cjs/utils/formatting.js +111 -0
- package/dist/cjs/utils/index.js +20 -1
- package/dist/es/a/{AreaChart → Charts/AreaChart}/AreaChart.js +88 -59
- package/dist/es/a/Charts/AreaChart/styles.scss +48 -0
- package/dist/es/a/Charts/BarChart/BarChart.js +126 -0
- package/dist/es/a/Charts/BarChart/index.js +1 -0
- package/dist/es/a/Charts/BarChart/styles.scss +48 -0
- package/dist/es/a/Charts/Common/CustomLegend/CustomLegend.js +59 -0
- package/dist/es/a/Charts/Common/CustomLegend/index.js +1 -0
- package/dist/es/a/Charts/Common/CustomLegend/styles.scss +40 -0
- package/dist/es/a/Charts/Common/CustomTooltipContent/CustomTooltipContent.js +76 -0
- package/dist/es/a/Charts/Common/CustomTooltipContent/index.js +1 -0
- package/dist/es/a/Charts/Common/CustomTooltipContent/styles.scss +22 -0
- package/dist/es/a/Charts/Common/YLabelsDropDown/YlabelsDropDown.js +88 -0
- package/dist/es/a/Charts/Common/YLabelsDropDown/index.js +1 -0
- package/dist/es/a/Charts/Common/YLabelsDropDown/styles.scss +88 -0
- package/dist/es/a/Charts/Common/index.js +3 -0
- package/dist/es/a/Charts/index.js +2 -0
- package/dist/es/a/Tooltip/styles.scss +1 -1
- package/dist/es/a/index.js +1 -1
- package/dist/es/f/FormInput/FormInput.js +7 -1
- package/dist/es/f/fields/FileUpload/FileUpload.js +18 -4
- package/dist/es/f/fields/LatexPreviewInput/LatexPreviewInput.js +70 -0
- package/dist/es/f/fields/LatexPreviewInput/convertLatexToHtml.js +31 -0
- package/dist/es/f/fields/LatexPreviewInput/index.js +3 -0
- package/dist/es/f/fields/LatexPreviewInput/styles.scss +24 -0
- package/dist/es/f/fields/index.js +1 -0
- package/dist/es/g/FormBuilder/FormBuilder.js +3 -6
- package/dist/es/g/FormBuilder/common/Builder/Builder.js +1 -3
- package/dist/es/g/FormBuilder/common/Builder/common/InputBuilder/InputBuilder.js +5 -7
- package/dist/es/g/FormBuilder/common/Builder/common/Section/Section.js +2 -4
- package/dist/es/g/FormBuilder/common/Renderer/Renderer.js +2 -4
- package/dist/es/g/FormBuilder/common/Renderer/common/Section/Section.js +32 -42
- package/dist/es/utils/formatting.js +102 -0
- package/dist/es/utils/index.js +2 -1
- package/jest.config.js +3 -0
- package/package.json +13 -9
- package/src/stories/a/BarChart.stories.jsx +89 -0
- package/src/ui/a/{AreaChart → Charts/AreaChart}/AreaChart.jsx +109 -54
- package/src/ui/a/Charts/AreaChart/styles.scss +48 -0
- package/src/ui/a/Charts/BarChart/BarChart.jsx +165 -0
- package/src/ui/a/Charts/BarChart/index.js +1 -0
- package/src/ui/a/Charts/BarChart/styles.scss +48 -0
- package/src/ui/a/Charts/Common/CustomLegend/CustomLegend.jsx +84 -0
- package/src/ui/a/Charts/Common/CustomLegend/index.js +1 -0
- package/src/ui/a/Charts/Common/CustomLegend/styles.scss +40 -0
- package/src/ui/a/Charts/Common/CustomTooltipContent/CustomTooltipContent.jsx +105 -0
- package/src/ui/a/Charts/Common/CustomTooltipContent/index.js +1 -0
- package/src/ui/a/Charts/Common/CustomTooltipContent/styles.scss +22 -0
- package/src/ui/a/Charts/Common/YLabelsDropDown/YlabelsDropDown.jsx +121 -0
- package/src/ui/a/Charts/Common/YLabelsDropDown/index.js +1 -0
- package/src/ui/a/Charts/Common/YLabelsDropDown/styles.scss +88 -0
- package/src/ui/a/Charts/Common/index.js +3 -0
- package/src/ui/a/Charts/index.js +2 -0
- package/src/ui/a/Tooltip/styles.scss +1 -1
- package/src/ui/a/index.js +1 -1
- package/src/ui/f/FormInput/FormInput.jsx +11 -0
- package/src/ui/f/fields/FileUpload/FileUpload.jsx +24 -4
- package/src/ui/f/fields/LatexPreviewInput/LatexPreviewInput.jsx +91 -0
- package/src/ui/f/fields/LatexPreviewInput/convertLatexToHtml.jsx +38 -0
- package/src/ui/f/fields/LatexPreviewInput/index.js +3 -0
- package/src/ui/f/fields/LatexPreviewInput/styles.scss +24 -0
- package/src/ui/f/fields/index.js +4 -0
- package/src/ui/g/FormBuilder/FormBuilder.jsx +0 -3
- package/src/ui/g/FormBuilder/common/Builder/Builder.jsx +0 -2
- package/src/ui/g/FormBuilder/common/Builder/common/InputBuilder/InputBuilder.jsx +4 -7
- package/src/ui/g/FormBuilder/common/Builder/common/Section/Section.jsx +0 -2
- package/src/ui/g/FormBuilder/common/Renderer/Renderer.jsx +0 -2
- package/src/ui/g/FormBuilder/common/Renderer/common/Section/Section.jsx +49 -64
- package/src/ui/utils/formatting.js +125 -0
- package/src/ui/utils/index.js +1 -0
- package/tests/__snapshots__/Storyshots.test.js.snap +1257 -62
- package/tests/emptyMock.js +3 -0
- package/tests/mockTextEncoder.js +7 -0
- package/tests/test-setup.js +7 -0
- package/dist/cjs/a/AreaChart/styles.scss +0 -89
- package/dist/es/a/AreaChart/styles.scss +0 -89
- package/src/ui/a/AreaChart/styles.scss +0 -89
- /package/dist/cjs/a/{AreaChart → Charts/AreaChart}/index.js +0 -0
- /package/dist/es/a/{AreaChart → Charts/AreaChart}/index.js +0 -0
- /package/src/ui/a/{AreaChart → Charts/AreaChart}/index.js +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
// front/packages/design-system/src/ui/a/AreaChart/AreaChart.jsx
|
|
2
|
-
|
|
3
1
|
import * as React from 'react'
|
|
4
2
|
|
|
3
|
+
import { useState } from 'react'
|
|
4
|
+
|
|
5
5
|
import PropTypes from 'prop-types'
|
|
6
6
|
|
|
7
7
|
import {
|
|
@@ -16,9 +16,11 @@ import {
|
|
|
16
16
|
|
|
17
17
|
import styleNames from '@pareto-engineering/bem/exports'
|
|
18
18
|
|
|
19
|
-
import '
|
|
19
|
+
import { formatTime, formatDate, DATE_FORMATS } from 'ui/utils'
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
import { CustomLegend, CustomTooltipContent, YLabelsDropDown } from '../Common'
|
|
22
|
+
|
|
23
|
+
import './styles.scss'
|
|
22
24
|
|
|
23
25
|
const baseClassName = styleNames.base
|
|
24
26
|
|
|
@@ -37,8 +39,17 @@ const AreaChart = ({
|
|
|
37
39
|
filled,
|
|
38
40
|
height,
|
|
39
41
|
width,
|
|
40
|
-
|
|
42
|
+
isTimeFormat,
|
|
43
|
+
dateFormat,
|
|
44
|
+
capitalizedLegend,
|
|
41
45
|
}) => {
|
|
46
|
+
const allYLabels = yKeys.map((key) => ({
|
|
47
|
+
label:key,
|
|
48
|
+
color:colors[yKeys.indexOf(key)],
|
|
49
|
+
}))
|
|
50
|
+
|
|
51
|
+
const [selectedYLabels, setSelectedYLabels] = useState(allYLabels)
|
|
52
|
+
|
|
42
53
|
const processedData = data.map((item) => {
|
|
43
54
|
const yValues = yKeys.map((key) => item[key])
|
|
44
55
|
const lowerBound = Math.min(...yValues)
|
|
@@ -47,6 +58,7 @@ const AreaChart = ({
|
|
|
47
58
|
return {
|
|
48
59
|
...item,
|
|
49
60
|
bounds:[lowerBound - margin, upperBound + margin],
|
|
61
|
+
isTimeFormat,
|
|
50
62
|
}
|
|
51
63
|
})
|
|
52
64
|
|
|
@@ -58,37 +70,6 @@ const AreaChart = ({
|
|
|
58
70
|
return [min - margin, max + margin]
|
|
59
71
|
}
|
|
60
72
|
|
|
61
|
-
const CustomTooltipContent = ({ active, payload, label }) => {
|
|
62
|
-
if (active && payload && payload.length) {
|
|
63
|
-
const newPayload = payload.filter((item) => item.name !== 'bounds')
|
|
64
|
-
return (
|
|
65
|
-
<div className="custom-tooltip">
|
|
66
|
-
<p className="label">{`${xLabel}: ${label}`}</p>
|
|
67
|
-
{newPayload.map((entry) => (
|
|
68
|
-
<p className="label" key={`${entry.name}`} style={{ color: entry.color }}>
|
|
69
|
-
{`${entry.name}: ${entry.value}`}
|
|
70
|
-
</p>
|
|
71
|
-
))}
|
|
72
|
-
</div>
|
|
73
|
-
)
|
|
74
|
-
}
|
|
75
|
-
return null
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
const CustomLegend = ({ colorsArray, yKeysArray }) => (
|
|
79
|
-
<div className="custom-legend">
|
|
80
|
-
{yKeysArray.map((key, index) => (
|
|
81
|
-
<div key={key} className="item">
|
|
82
|
-
<span
|
|
83
|
-
className="line"
|
|
84
|
-
style={{ backgroundColor: colorsArray[index] }}
|
|
85
|
-
/>
|
|
86
|
-
<span className="text">{key}</span>
|
|
87
|
-
</div>
|
|
88
|
-
))}
|
|
89
|
-
</div>
|
|
90
|
-
)
|
|
91
|
-
|
|
92
73
|
return (
|
|
93
74
|
<div
|
|
94
75
|
id={id}
|
|
@@ -100,8 +81,19 @@ const AreaChart = ({
|
|
|
100
81
|
.filter((e) => e)
|
|
101
82
|
.join(' ')}
|
|
102
83
|
>
|
|
103
|
-
<
|
|
104
|
-
|
|
84
|
+
<div className="chart-header">
|
|
85
|
+
<h3>{title}</h3>
|
|
86
|
+
<YLabelsDropDown
|
|
87
|
+
allYLabels={allYLabels}
|
|
88
|
+
selectedYLabels={selectedYLabels}
|
|
89
|
+
setSelectedYLabels={setSelectedYLabels}
|
|
90
|
+
/>
|
|
91
|
+
</div>
|
|
92
|
+
<CustomLegend
|
|
93
|
+
colorsArray={colors}
|
|
94
|
+
yKeysArray={yKeys}
|
|
95
|
+
capitalizedLegend={capitalizedLegend}
|
|
96
|
+
/>
|
|
105
97
|
<ResponsiveContainer width={width} height={height}>
|
|
106
98
|
<RechartsAreaChart data={processedData}>
|
|
107
99
|
<CartesianGrid strokeDasharray="3 3" />
|
|
@@ -111,6 +103,7 @@ const AreaChart = ({
|
|
|
111
103
|
axisLine={false}
|
|
112
104
|
tickLine={false}
|
|
113
105
|
tickCount={3}
|
|
106
|
+
tickFormatter={(value) => formatDate(value, dateFormat)}
|
|
114
107
|
/>
|
|
115
108
|
<YAxis
|
|
116
109
|
domain={yAxisBounds}
|
|
@@ -120,15 +113,20 @@ const AreaChart = ({
|
|
|
120
113
|
value :yLabel,
|
|
121
114
|
angle :-90,
|
|
122
115
|
position:'left',
|
|
123
|
-
offset
|
|
116
|
+
offset :-3,
|
|
124
117
|
style :{ textAnchor: 'middle' },
|
|
125
118
|
}}
|
|
126
119
|
padding={{ top: 10, bottom: 10 }}
|
|
127
120
|
axisLine={false}
|
|
128
|
-
tickLine
|
|
129
|
-
tickFormatter={(value) =>
|
|
121
|
+
tickLine={false}
|
|
122
|
+
tickFormatter={(value) => {
|
|
123
|
+
if (isTimeFormat) {
|
|
124
|
+
return formatTime(value)
|
|
125
|
+
}
|
|
126
|
+
return value.toFixed(2)
|
|
127
|
+
}}
|
|
130
128
|
/>
|
|
131
|
-
<Tooltip content={<CustomTooltipContent />} />
|
|
129
|
+
<Tooltip content={<CustomTooltipContent xLabel={xLabel} />} />
|
|
132
130
|
{filled && (
|
|
133
131
|
<Area
|
|
134
132
|
id="bounds"
|
|
@@ -143,13 +141,13 @@ const AreaChart = ({
|
|
|
143
141
|
isAnimationActive={false}
|
|
144
142
|
/>
|
|
145
143
|
)}
|
|
146
|
-
{
|
|
144
|
+
{selectedYLabels.map((key) => (
|
|
147
145
|
<Area
|
|
148
|
-
id={key}
|
|
149
|
-
key={key}
|
|
146
|
+
id={key.label}
|
|
147
|
+
key={key.label}
|
|
150
148
|
type="linear"
|
|
151
|
-
dataKey={key}
|
|
152
|
-
stroke={
|
|
149
|
+
dataKey={key.label}
|
|
150
|
+
stroke={key.color}
|
|
153
151
|
fill="none"
|
|
154
152
|
connectNulls
|
|
155
153
|
dot={false}
|
|
@@ -164,29 +162,86 @@ const AreaChart = ({
|
|
|
164
162
|
}
|
|
165
163
|
|
|
166
164
|
AreaChart.propTypes = {
|
|
165
|
+
/**
|
|
166
|
+
* Array of data objects to be displayed in the chart.
|
|
167
|
+
*/
|
|
167
168
|
// eslint-disable-next-line react/forbid-prop-types
|
|
168
|
-
data
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
169
|
+
data:PropTypes.arrayOf(PropTypes.object).isRequired,
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Title of the chart.
|
|
173
|
+
*/
|
|
174
|
+
title:PropTypes.string.isRequired,
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Key for the x-axis data.
|
|
178
|
+
*/
|
|
179
|
+
xKey:PropTypes.string.isRequired,
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Array of keys for the y-axis data.
|
|
183
|
+
*/
|
|
184
|
+
yKeys:PropTypes.arrayOf(PropTypes.string).isRequired,
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Label for the x-axis.
|
|
188
|
+
*/
|
|
172
189
|
xLabel:PropTypes.string,
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Label for the y-axis.
|
|
193
|
+
*/
|
|
173
194
|
yLabel:PropTypes.string,
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Array of colors corresponding to the y-axis data keys.
|
|
198
|
+
*/
|
|
174
199
|
colors:PropTypes.arrayOf(PropTypes.string).isRequired,
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Boolean to determine if the area under the curve should be filled.
|
|
203
|
+
*/
|
|
175
204
|
filled:PropTypes.bool,
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Height of the chart.
|
|
208
|
+
*/
|
|
176
209
|
height:PropTypes.oneOfType([
|
|
177
210
|
PropTypes.string,
|
|
178
211
|
PropTypes.number,
|
|
179
212
|
]),
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Width of the chart.
|
|
216
|
+
*/
|
|
180
217
|
width:PropTypes.oneOfType([
|
|
181
218
|
PropTypes.string,
|
|
182
219
|
PropTypes.number,
|
|
183
220
|
]),
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Flag on whether to capitalize legend keys
|
|
224
|
+
*/
|
|
225
|
+
capitalizedLegend:PropTypes.bool,
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Flag on whether it is a timeformat or not
|
|
229
|
+
*/
|
|
230
|
+
isTimeFormat:PropTypes.bool,
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* The type of format for the datetime value
|
|
234
|
+
*/
|
|
235
|
+
dateFormat:PropTypes.oneOf(Object.values(DATE_FORMATS)),
|
|
184
236
|
}
|
|
185
237
|
|
|
186
238
|
AreaChart.defaultProps = {
|
|
187
|
-
filled:false,
|
|
188
|
-
width
|
|
189
|
-
height:300,
|
|
239
|
+
filled :false,
|
|
240
|
+
width :'100%',
|
|
241
|
+
height :300,
|
|
242
|
+
capitalizedLegend:false,
|
|
243
|
+
isTimeFormat :false,
|
|
244
|
+
dateFormat :DATE_FORMATS.HUMAN_READABLE,
|
|
190
245
|
}
|
|
191
246
|
|
|
192
247
|
export default AreaChart
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
@use "@pareto-engineering/bem";
|
|
2
|
+
|
|
3
|
+
$default-margin: 1rem;
|
|
4
|
+
$default-padding: 1rem;
|
|
5
|
+
$default-box-shadow: 0 .25rem .75rem var(--ui-lines);
|
|
6
|
+
$default-text-font-size: calc(var(--s-1) * 1rem);
|
|
7
|
+
|
|
8
|
+
.#{bem.$base} {
|
|
9
|
+
&.area-chart {
|
|
10
|
+
background-color: var(--background-far);
|
|
11
|
+
border-radius: var(--theme-default-border-radius);
|
|
12
|
+
box-shadow: $default-box-shadow;
|
|
13
|
+
margin: $default-margin 0;
|
|
14
|
+
padding: $default-padding;
|
|
15
|
+
|
|
16
|
+
.chart-header {
|
|
17
|
+
align-items: center;
|
|
18
|
+
display: flex;
|
|
19
|
+
justify-content: space-between;
|
|
20
|
+
margin-bottom: $default-margin;
|
|
21
|
+
|
|
22
|
+
h3 {
|
|
23
|
+
color: var(--subtitle);
|
|
24
|
+
margin: calc($default-margin / 5);
|
|
25
|
+
text-align: left;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/* stylelint-disable selector-max-compound-selectors -- nested elements */
|
|
30
|
+
.recharts-wrapper {
|
|
31
|
+
.recharts-surface {
|
|
32
|
+
.recharts-cartesian-grid line {
|
|
33
|
+
stroke: var(--ui-lines);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.recharts-text {
|
|
37
|
+
fill: var(--soft-paragraph);
|
|
38
|
+
font-size: calc($default-text-font-size * .75);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.recharts-text.recharts-label {
|
|
42
|
+
fill: var(--paragraph);
|
|
43
|
+
font-size: $default-text-font-size;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import * as React from 'react'
|
|
2
|
+
|
|
3
|
+
import { useState } from 'react'
|
|
4
|
+
|
|
5
|
+
import PropTypes from 'prop-types'
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
BarChart as RechartsBarChart,
|
|
9
|
+
Bar,
|
|
10
|
+
XAxis,
|
|
11
|
+
YAxis,
|
|
12
|
+
CartesianGrid,
|
|
13
|
+
Tooltip,
|
|
14
|
+
ResponsiveContainer,
|
|
15
|
+
} from 'recharts'
|
|
16
|
+
|
|
17
|
+
import styleNames from '@pareto-engineering/bem/exports'
|
|
18
|
+
|
|
19
|
+
import { CustomLegend, CustomTooltipContent, YLabelsDropDown } from '../Common'
|
|
20
|
+
|
|
21
|
+
import './styles.scss'
|
|
22
|
+
|
|
23
|
+
// Local Definitions
|
|
24
|
+
|
|
25
|
+
const baseClassName = styleNames.base
|
|
26
|
+
|
|
27
|
+
const componentClassName = 'bar-chart'
|
|
28
|
+
|
|
29
|
+
const BarChart = ({
|
|
30
|
+
id,
|
|
31
|
+
className: userClassName,
|
|
32
|
+
data,
|
|
33
|
+
title,
|
|
34
|
+
xKey,
|
|
35
|
+
yKeys,
|
|
36
|
+
xLabel,
|
|
37
|
+
yLabel,
|
|
38
|
+
colors,
|
|
39
|
+
height,
|
|
40
|
+
width,
|
|
41
|
+
// ...otherProps
|
|
42
|
+
}) => {
|
|
43
|
+
const allYLabels = yKeys.map((key) => ({
|
|
44
|
+
label:key,
|
|
45
|
+
color:colors[yKeys.indexOf(key)],
|
|
46
|
+
}))
|
|
47
|
+
|
|
48
|
+
const [selectedYLabels, setSelectedYLabels] = useState(allYLabels)
|
|
49
|
+
|
|
50
|
+
return (
|
|
51
|
+
<div
|
|
52
|
+
id={id}
|
|
53
|
+
className={[
|
|
54
|
+
baseClassName,
|
|
55
|
+
componentClassName,
|
|
56
|
+
userClassName,
|
|
57
|
+
]
|
|
58
|
+
.filter((e) => e)
|
|
59
|
+
.join(' ')}
|
|
60
|
+
>
|
|
61
|
+
<div className="chart-header">
|
|
62
|
+
<h3>{title}</h3>
|
|
63
|
+
<YLabelsDropDown
|
|
64
|
+
allYLabels={allYLabels}
|
|
65
|
+
selectedYLabels={selectedYLabels}
|
|
66
|
+
setSelectedYLabels={setSelectedYLabels}
|
|
67
|
+
/>
|
|
68
|
+
</div>
|
|
69
|
+
<CustomLegend
|
|
70
|
+
colorsArray={selectedYLabels.map((item) => item.color)}
|
|
71
|
+
yKeysArray={selectedYLabels.map((item) => item.label)}
|
|
72
|
+
/>
|
|
73
|
+
<ResponsiveContainer width={width} height={height}>
|
|
74
|
+
<RechartsBarChart data={data}>
|
|
75
|
+
<CartesianGrid vertical={false} />
|
|
76
|
+
<XAxis
|
|
77
|
+
dataKey={xKey}
|
|
78
|
+
label={{ value: xLabel, position: 'insideBottom', offset: -5 }} // Adjusted offset for padding
|
|
79
|
+
axisLine={false}
|
|
80
|
+
tickLine={false}
|
|
81
|
+
tickCount={3}
|
|
82
|
+
/>
|
|
83
|
+
<YAxis
|
|
84
|
+
label={{
|
|
85
|
+
value:yLabel, angle:-90, position:'insideLeft', offset:15,
|
|
86
|
+
}}
|
|
87
|
+
axisLine={false}
|
|
88
|
+
tickLine={false}
|
|
89
|
+
/>
|
|
90
|
+
<Tooltip content={<CustomTooltipContent xLabel={xLabel} />} />
|
|
91
|
+
{selectedYLabels.map((key) => (
|
|
92
|
+
<Bar
|
|
93
|
+
stackId="a"
|
|
94
|
+
id={key.label}
|
|
95
|
+
key={key.label}
|
|
96
|
+
dataKey={key.label}
|
|
97
|
+
fill={key.color}
|
|
98
|
+
/>
|
|
99
|
+
))}
|
|
100
|
+
</RechartsBarChart>
|
|
101
|
+
</ResponsiveContainer>
|
|
102
|
+
</div>
|
|
103
|
+
)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
BarChart.propTypes = {
|
|
107
|
+
/**
|
|
108
|
+
* Array of data objects to be displayed in the chart.
|
|
109
|
+
*/
|
|
110
|
+
// eslint-disable-next-line react/forbid-prop-types
|
|
111
|
+
data:PropTypes.arrayOf(PropTypes.object).isRequired,
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Title of the chart.
|
|
115
|
+
*/
|
|
116
|
+
title:PropTypes.string.isRequired,
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Key for the x-axis data.
|
|
120
|
+
*/
|
|
121
|
+
xKey:PropTypes.string.isRequired,
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Array of keys for the y-axis data.
|
|
125
|
+
*/
|
|
126
|
+
yKeys:PropTypes.arrayOf(PropTypes.string).isRequired,
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Label for the x-axis.
|
|
130
|
+
*/
|
|
131
|
+
xLabel:PropTypes.string,
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Label for the y-axis.
|
|
135
|
+
*/
|
|
136
|
+
yLabel:PropTypes.string,
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Array of colors corresponding to the y-axis data keys.
|
|
140
|
+
*/
|
|
141
|
+
colors:PropTypes.arrayOf(PropTypes.string).isRequired,
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Height of the chart.
|
|
145
|
+
*/
|
|
146
|
+
height:PropTypes.oneOfType([
|
|
147
|
+
PropTypes.string,
|
|
148
|
+
PropTypes.number,
|
|
149
|
+
]),
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Width of the chart.
|
|
153
|
+
*/
|
|
154
|
+
width:PropTypes.oneOfType([
|
|
155
|
+
PropTypes.string,
|
|
156
|
+
PropTypes.number,
|
|
157
|
+
]),
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
BarChart.defaultProps = {
|
|
161
|
+
width :'100%',
|
|
162
|
+
height:300,
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export default BarChart
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as BarChart } from './BarChart'
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
@use "@pareto-engineering/bem";
|
|
2
|
+
|
|
3
|
+
$default-margin: 1rem;
|
|
4
|
+
$default-padding: 1rem;
|
|
5
|
+
$default-box-shadow: 0 .25rem .75rem var(--ui-lines);
|
|
6
|
+
$default-text-font-size: calc(var(--s-1) * 1rem);
|
|
7
|
+
|
|
8
|
+
.#{bem.$base} {
|
|
9
|
+
&.bar-chart {
|
|
10
|
+
background-color: var(--background-far);
|
|
11
|
+
border-radius: var(--theme-default-border-radius);
|
|
12
|
+
box-shadow: $default-box-shadow;
|
|
13
|
+
margin: $default-margin 0;
|
|
14
|
+
padding: $default-padding;
|
|
15
|
+
|
|
16
|
+
.chart-header {
|
|
17
|
+
align-items: center;
|
|
18
|
+
display: flex;
|
|
19
|
+
justify-content: space-between;
|
|
20
|
+
margin-bottom: $default-margin;
|
|
21
|
+
|
|
22
|
+
h3 {
|
|
23
|
+
color: var(--subtitle);
|
|
24
|
+
margin: calc($default-margin / 5);
|
|
25
|
+
text-align: left;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/* stylelint-disable selector-max-compound-selectors -- nested elements */
|
|
30
|
+
.recharts-wrapper {
|
|
31
|
+
.recharts-surface {
|
|
32
|
+
.recharts-cartesian-grid line {
|
|
33
|
+
stroke: var(--ui-lines);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.recharts-text {
|
|
37
|
+
fill: var(--soft-paragraph);
|
|
38
|
+
font-size: calc($default-text-font-size * .75);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.recharts-text.recharts-label {
|
|
42
|
+
fill: var(--paragraph);
|
|
43
|
+
font-size: $default-text-font-size;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import * as React from 'react'
|
|
2
|
+
|
|
3
|
+
import PropTypes from 'prop-types'
|
|
4
|
+
|
|
5
|
+
import styleNames from '@pareto-engineering/bem/exports'
|
|
6
|
+
|
|
7
|
+
import './styles.scss'
|
|
8
|
+
|
|
9
|
+
const baseClassName = styleNames.base
|
|
10
|
+
|
|
11
|
+
const componentClassName = 'custom-legend'
|
|
12
|
+
|
|
13
|
+
const CustomLegend = ({
|
|
14
|
+
id,
|
|
15
|
+
className: userClassName,
|
|
16
|
+
colorsArray,
|
|
17
|
+
yKeysArray,
|
|
18
|
+
capitalizedLegend,
|
|
19
|
+
}) => {
|
|
20
|
+
const capitalizeWord = (word) => {
|
|
21
|
+
if (!capitalizedLegend) return word
|
|
22
|
+
const wordsToCapitalize = ['average', 'best', 'worst']
|
|
23
|
+
return word.split(' ').map((part) => (wordsToCapitalize.includes(part.toLowerCase())
|
|
24
|
+
? part.charAt(0).toUpperCase() + part.slice(1).toLowerCase()
|
|
25
|
+
: part),
|
|
26
|
+
).join(' ')
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return (
|
|
30
|
+
<div
|
|
31
|
+
id={id}
|
|
32
|
+
className={[
|
|
33
|
+
baseClassName,
|
|
34
|
+
componentClassName,
|
|
35
|
+
userClassName,
|
|
36
|
+
]
|
|
37
|
+
.filter((e) => e)
|
|
38
|
+
.join(' ')}
|
|
39
|
+
>
|
|
40
|
+
{yKeysArray.map((key, index) => (
|
|
41
|
+
<div key={key} className="item">
|
|
42
|
+
<span
|
|
43
|
+
className="dot"
|
|
44
|
+
style={{ backgroundColor: colorsArray[index] }}
|
|
45
|
+
/>
|
|
46
|
+
<span className="text">{capitalizeWord(key)}</span>
|
|
47
|
+
</div>
|
|
48
|
+
))}
|
|
49
|
+
</div>
|
|
50
|
+
)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
CustomLegend.propTypes = {
|
|
54
|
+
/**
|
|
55
|
+
* The id of the dropdown component.
|
|
56
|
+
*/
|
|
57
|
+
id:PropTypes.string,
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Additional class names for the dropdown component.
|
|
61
|
+
*/
|
|
62
|
+
className:PropTypes.string,
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Array of colors corresponding to the y-axis data keys.
|
|
66
|
+
*/
|
|
67
|
+
colorsArray:PropTypes.arrayOf(PropTypes.string).isRequired,
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Array of keys for the y-axis data.
|
|
71
|
+
*/
|
|
72
|
+
yKeysArray:PropTypes.arrayOf(PropTypes.string).isRequired,
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Flag on whether to capitalize legend keys
|
|
76
|
+
*/
|
|
77
|
+
capitalizedLegend:PropTypes.bool,
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
CustomLegend.defaultProps = {
|
|
81
|
+
capitalizedLegend:false,
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export default CustomLegend
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as CustomLegend } from './CustomLegend'
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
@use "@pareto-engineering/bem";
|
|
2
|
+
|
|
3
|
+
$default-padding: 1rem;
|
|
4
|
+
$default-text-font-size: calc(var(--s-1) * 1rem);
|
|
5
|
+
$default-border-radius: .25rem;
|
|
6
|
+
$default-legend-gap: .625rem;
|
|
7
|
+
$default-legend-padding: calc($default-padding * .125) calc($default-padding * .625);
|
|
8
|
+
$default-legend-dot-width: .5rem;
|
|
9
|
+
$default-legend-dot-height: .5rem;
|
|
10
|
+
$default-legend-dot-margin-right: .3125rem;
|
|
11
|
+
|
|
12
|
+
.#{bem.$base} {
|
|
13
|
+
&.custom-legend {
|
|
14
|
+
display: flex;
|
|
15
|
+
gap: $default-legend-gap;
|
|
16
|
+
justify-content: flex-end;
|
|
17
|
+
padding-bottom: $default-padding;
|
|
18
|
+
padding-right: calc($default-padding * .25);
|
|
19
|
+
|
|
20
|
+
.item {
|
|
21
|
+
align-items: center;
|
|
22
|
+
border-radius: $default-border-radius;
|
|
23
|
+
display: flex;
|
|
24
|
+
padding: $default-legend-padding;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.dot {
|
|
28
|
+
border-radius: 50%;
|
|
29
|
+
display: inline-block;
|
|
30
|
+
height: $default-legend-dot-height;
|
|
31
|
+
margin-right: $default-legend-dot-margin-right;
|
|
32
|
+
width: $default-legend-dot-width;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.text {
|
|
36
|
+
color: var(--paragraph);
|
|
37
|
+
font-size: calc($default-text-font-size * .75);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|