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