@pareto-engineering/design-system 5.0.4 → 5.1.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 +3 -13
- package/dist/cjs/a/Charts/BarChart/BarChart.js +6 -4
- package/dist/cjs/a/Charts/Common/CustomLegend/CustomLegend.js +26 -7
- package/dist/cjs/a/Charts/Common/CustomLegend/styles.scss +41 -14
- package/dist/cjs/a/Charts/Common/CustomTooltipContent/CustomTooltipContent.js +18 -7
- package/dist/cjs/a/Charts/Common/YLabelsDropDown/YlabelsDropDown.js +3 -4
- package/dist/cjs/a/Charts/Common/YLabelsDropDown/styles.scss +7 -6
- 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 +8 -1
- package/dist/cjs/a/Notification/styles.scss +17 -5
- package/dist/cjs/a/index.js +6 -0
- package/dist/cjs/f/FormInput/FormInput.js +1 -1
- package/dist/cjs/f/fields/LatexPreviewInput/LatexPreviewInput.js +1 -1
- package/dist/cjs/f/fields/LatexPreviewInput/styles.scss +1 -0
- package/dist/cjs/f/fields/TextareaInput/TextareaInput.js +4 -2
- package/dist/cjs/g/FormBuilder/common/Builder/common/InputBuilder/InputBuilder.js +27 -1
- package/dist/cjs/g/FormBuilder/common/Builder/common/InputBuilder/styles.scss +15 -0
- package/dist/cjs/g/FormBuilder/common/Builder/common/Section/Section.js +6 -2
- package/dist/cjs/g/FormBuilder/common/Renderer/Renderer.js +6 -0
- package/dist/cjs/utils/applyCharacterLimit.js +75 -0
- package/dist/cjs/utils/formatting.js +10 -2
- package/dist/cjs/utils/index.js +14 -1
- package/dist/es/a/Charts/AreaChart/AreaChart.js +3 -13
- package/dist/es/a/Charts/BarChart/BarChart.js +6 -4
- package/dist/es/a/Charts/Common/CustomLegend/CustomLegend.js +38 -21
- package/dist/es/a/Charts/Common/CustomLegend/styles.scss +41 -14
- package/dist/es/a/Charts/Common/CustomTooltipContent/CustomTooltipContent.js +19 -8
- package/dist/es/a/Charts/Common/YLabelsDropDown/YlabelsDropDown.js +3 -5
- package/dist/es/a/Charts/Common/YLabelsDropDown/styles.scss +7 -6
- 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 +2 -1
- package/dist/es/a/Notification/styles.scss +17 -5
- package/dist/es/a/index.js +1 -1
- package/dist/es/f/FormInput/FormInput.js +1 -1
- package/dist/es/f/fields/LatexPreviewInput/LatexPreviewInput.js +1 -1
- package/dist/es/f/fields/LatexPreviewInput/styles.scss +1 -0
- package/dist/es/f/fields/TextareaInput/TextareaInput.js +4 -2
- package/dist/es/g/FormBuilder/common/Builder/common/InputBuilder/InputBuilder.js +27 -1
- package/dist/es/g/FormBuilder/common/Builder/common/InputBuilder/styles.scss +15 -0
- package/dist/es/g/FormBuilder/common/Builder/common/Section/Section.js +6 -2
- package/dist/es/g/FormBuilder/common/Renderer/Renderer.js +6 -0
- package/dist/es/utils/applyCharacterLimit.js +67 -0
- package/dist/es/utils/formatting.js +7 -0
- package/dist/es/utils/index.js +2 -1
- package/package.json +3 -3
- package/src/stories/a/AreaChart.stories.jsx +1 -1
- package/src/stories/a/BarChart.stories.jsx +1 -1
- package/src/stories/a/PieChart.stories.jsx +53 -0
- package/src/ui/a/Charts/AreaChart/AreaChart.jsx +8 -14
- package/src/ui/a/Charts/BarChart/BarChart.jsx +4 -2
- package/src/ui/a/Charts/Common/CustomLegend/CustomLegend.jsx +54 -29
- package/src/ui/a/Charts/Common/CustomLegend/styles.scss +41 -14
- package/src/ui/a/Charts/Common/CustomTooltipContent/CustomTooltipContent.jsx +25 -13
- package/src/ui/a/Charts/Common/YLabelsDropDown/YlabelsDropDown.jsx +4 -4
- package/src/ui/a/Charts/Common/YLabelsDropDown/styles.scss +7 -6
- 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 +1 -0
- package/src/ui/a/Notification/styles.scss +17 -5
- package/src/ui/a/index.js +1 -1
- package/src/ui/f/FormInput/FormInput.jsx +1 -0
- package/src/ui/f/fields/LatexPreviewInput/LatexPreviewInput.jsx +1 -0
- package/src/ui/f/fields/LatexPreviewInput/styles.scss +1 -0
- package/src/ui/f/fields/TextareaInput/TextareaInput.jsx +2 -0
- package/src/ui/g/FormBuilder/common/Builder/common/InputBuilder/InputBuilder.jsx +34 -0
- package/src/ui/g/FormBuilder/common/Builder/common/InputBuilder/styles.scss +15 -0
- package/src/ui/g/FormBuilder/common/Builder/common/Section/Section.jsx +10 -2
- package/src/ui/g/FormBuilder/common/Renderer/Renderer.jsx +5 -0
- package/src/ui/g/FormBuilder/common/Renderer/common/Section/Section.jsx +0 -1
- package/src/ui/utils/applyCharacterLimit.js +80 -0
- package/src/ui/utils/formatting.js +8 -0
- package/src/ui/utils/index.js +4 -1
- package/tests/__snapshots__/Storyshots.test.js.snap +1165 -429
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import { PieChart as RechartsPieChart, Pie, Cell, ResponsiveContainer, Tooltip } from 'recharts';
|
|
4
|
+
import styleNames from '@pareto-engineering/bem/exports';
|
|
5
|
+
import { CustomLegend, CustomTooltipContent } from "../Common";
|
|
6
|
+
import "./styles.scss";
|
|
7
|
+
const baseClassName = styleNames.base;
|
|
8
|
+
const componentClassName = 'pie-chart';
|
|
9
|
+
const PieChart = ({
|
|
10
|
+
id,
|
|
11
|
+
className: userClassName,
|
|
12
|
+
data,
|
|
13
|
+
title,
|
|
14
|
+
valueKey,
|
|
15
|
+
labelKey,
|
|
16
|
+
colors,
|
|
17
|
+
height,
|
|
18
|
+
width,
|
|
19
|
+
innerRadius,
|
|
20
|
+
outerRadius
|
|
21
|
+
}) => {
|
|
22
|
+
const total = data.reduce((sum, item) => sum + item[valueKey], 0);
|
|
23
|
+
const formattedData = data.map(item => ({
|
|
24
|
+
...item,
|
|
25
|
+
label: item[labelKey],
|
|
26
|
+
color: colors[data.indexOf(item)],
|
|
27
|
+
percentage: (item[valueKey] / total * 100).toFixed(0)
|
|
28
|
+
}));
|
|
29
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
30
|
+
id: id,
|
|
31
|
+
className: [baseClassName, componentClassName, userClassName].filter(e => e).join(' ')
|
|
32
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
33
|
+
className: "chart-header"
|
|
34
|
+
}, /*#__PURE__*/React.createElement("h3", null, title)), /*#__PURE__*/React.createElement("div", {
|
|
35
|
+
className: "chart-content"
|
|
36
|
+
}, /*#__PURE__*/React.createElement(ResponsiveContainer, {
|
|
37
|
+
width: width,
|
|
38
|
+
height: height
|
|
39
|
+
}, /*#__PURE__*/React.createElement(RechartsPieChart, null, /*#__PURE__*/React.createElement(Pie, {
|
|
40
|
+
data: formattedData,
|
|
41
|
+
dataKey: valueKey,
|
|
42
|
+
nameKey: labelKey,
|
|
43
|
+
cx: "50%",
|
|
44
|
+
cy: "50%",
|
|
45
|
+
innerRadius: innerRadius,
|
|
46
|
+
outerRadius: outerRadius,
|
|
47
|
+
label: false,
|
|
48
|
+
paddingAngle: 0
|
|
49
|
+
}, formattedData.map((entry, index) => /*#__PURE__*/React.createElement(Cell, {
|
|
50
|
+
key: entry[labelKey],
|
|
51
|
+
fill: colors[index],
|
|
52
|
+
strokeWidth: 0
|
|
53
|
+
}))), /*#__PURE__*/React.createElement(Tooltip, {
|
|
54
|
+
content: /*#__PURE__*/React.createElement(CustomTooltipContent, {
|
|
55
|
+
isDateValue: false
|
|
56
|
+
})
|
|
57
|
+
}))), /*#__PURE__*/React.createElement(CustomLegend, {
|
|
58
|
+
colorsArray: colors,
|
|
59
|
+
yKeysArray: formattedData,
|
|
60
|
+
capitalizedLegend: true,
|
|
61
|
+
orientation: "vertical",
|
|
62
|
+
getLegendItemTitle: entry => entry[labelKey],
|
|
63
|
+
getLegendItemSubtitle: entry => entry[valueKey]
|
|
64
|
+
})));
|
|
65
|
+
};
|
|
66
|
+
PieChart.propTypes = {
|
|
67
|
+
id: PropTypes.string,
|
|
68
|
+
className: PropTypes.string,
|
|
69
|
+
data: PropTypes.arrayOf(PropTypes.shape({
|
|
70
|
+
[PropTypes.string]: PropTypes.oneOfType([PropTypes.string, PropTypes.number])
|
|
71
|
+
})).isRequired,
|
|
72
|
+
title: PropTypes.string.isRequired,
|
|
73
|
+
valueKey: PropTypes.string.isRequired,
|
|
74
|
+
labelKey: PropTypes.string.isRequired,
|
|
75
|
+
colors: PropTypes.arrayOf(PropTypes.string).isRequired,
|
|
76
|
+
height: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
|
77
|
+
width: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
|
78
|
+
innerRadius: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
|
79
|
+
outerRadius: PropTypes.oneOfType([PropTypes.string, PropTypes.number])
|
|
80
|
+
};
|
|
81
|
+
PieChart.defaultProps = {
|
|
82
|
+
id: undefined,
|
|
83
|
+
className: undefined,
|
|
84
|
+
width: '100%',
|
|
85
|
+
height: 300,
|
|
86
|
+
innerRadius: '0%',
|
|
87
|
+
outerRadius: '100%'
|
|
88
|
+
};
|
|
89
|
+
export default PieChart;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as PieChart } from "./PieChart";
|
|
@@ -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
|
+
&.pie-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
|
+
.chart-content {
|
|
30
|
+
align-items: flex-start;
|
|
31
|
+
display: flex;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.recharts-wrapper {
|
|
35
|
+
.recharts-surface {
|
|
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
|
+
}
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
@use "@pareto-engineering/styles/src/mixins";
|
|
5
5
|
@use "@pareto-engineering/styles/src/globals" as *;
|
|
6
6
|
|
|
7
|
+
$default-border: 1px solid var(--x);
|
|
7
8
|
$default-padding: 1rem;
|
|
8
9
|
$default-margin: 1rem;
|
|
9
10
|
$default-border-radius: 1.5rem;
|
|
@@ -12,10 +13,11 @@ $default-height: var(--notification-height, 5rem);
|
|
|
12
13
|
|
|
13
14
|
.#{bem.$base}.notification {
|
|
14
15
|
align-items: center;
|
|
15
|
-
background-color: var(--
|
|
16
|
+
background-color: var(--background-far);
|
|
17
|
+
border: $default-border;
|
|
16
18
|
border-radius: $default-border-radius;
|
|
17
19
|
bottom: 0;
|
|
18
|
-
color: var(--
|
|
20
|
+
color: var(--paragraph);
|
|
19
21
|
display: flex;
|
|
20
22
|
justify-content: space-between;
|
|
21
23
|
margin-bottom: $default-margin;
|
|
@@ -31,8 +33,16 @@ $default-height: var(--notification-height, 5rem);
|
|
|
31
33
|
> .message-container {
|
|
32
34
|
align-items: center;
|
|
33
35
|
display: flex;
|
|
36
|
+
gap: $default-padding;
|
|
34
37
|
overflow: auto;
|
|
35
38
|
|
|
39
|
+
> .icon {
|
|
40
|
+
background-color: var(--x);
|
|
41
|
+
border-radius: 50%;
|
|
42
|
+
color: var(--white);
|
|
43
|
+
padding: calc($default-padding / 2);
|
|
44
|
+
}
|
|
45
|
+
|
|
36
46
|
> .message {
|
|
37
47
|
font-size: calc(var(--s0) * 1rem);
|
|
38
48
|
margin-left: calc($default-margin / 2);
|
|
@@ -44,12 +54,14 @@ $default-height: var(--notification-height, 5rem);
|
|
|
44
54
|
}
|
|
45
55
|
|
|
46
56
|
.#{bem.$base}.button {
|
|
57
|
+
background-color: transparent;
|
|
58
|
+
color: var(--paragraph);
|
|
47
59
|
padding: calc($default-padding / 2);
|
|
48
60
|
|
|
49
|
-
&:focus
|
|
61
|
+
&:focus,
|
|
62
|
+
&:hover {
|
|
50
63
|
background-color: transparent;
|
|
64
|
+
color: var(--hard-paragraph);
|
|
51
65
|
}
|
|
52
66
|
}
|
|
53
67
|
}
|
|
54
|
-
|
|
55
|
-
|
package/dist/es/a/index.js
CHANGED
|
@@ -28,4 +28,4 @@ export { ToggleSwitch } from "./ToggleSwitch";
|
|
|
28
28
|
export { XMLEditor } from "./XMLEditor";
|
|
29
29
|
export { DatePicker } from "./DatePicker";
|
|
30
30
|
export { Tooltip } from "./Tooltip";
|
|
31
|
-
export { AreaChart, BarChart } from "./Charts";
|
|
31
|
+
export { AreaChart, BarChart, PieChart } from "./Charts";
|
|
@@ -22,7 +22,7 @@ const FormInput = ({
|
|
|
22
22
|
disabled,
|
|
23
23
|
...otherProps
|
|
24
24
|
}) => {
|
|
25
|
-
const newClassName = [className, componentClassName].filter(Boolean).join(' ');
|
|
25
|
+
const newClassName = [className, componentClassName, otherProps.hasCharacterLimit && otherProps.maxLength && `limit-character-count-${otherProps.maxLength}`].filter(Boolean).join(' ');
|
|
26
26
|
if (type === 'textarea') {
|
|
27
27
|
return /*#__PURE__*/React.createElement(TextareaInput, _extends({
|
|
28
28
|
className: newClassName,
|
|
@@ -34,7 +34,7 @@ const LatexPreviewInput = ({
|
|
|
34
34
|
const LatexPreview = useMemo(() => convertLatexToHtml(values[name]), [values[name]]);
|
|
35
35
|
return /*#__PURE__*/React.createElement("div", {
|
|
36
36
|
id: id,
|
|
37
|
-
className: [baseClassName, componentClassName, userClassName, 'form-input'].filter(e => e).join(' '),
|
|
37
|
+
className: [baseClassName, componentClassName, className, userClassName, 'form-input'].filter(e => e).join(' '),
|
|
38
38
|
style: style
|
|
39
39
|
}, /*#__PURE__*/React.createElement(TextareaInput, _extends({
|
|
40
40
|
className: "preview-child",
|
|
@@ -31,7 +31,8 @@ const TextareaInput = ({
|
|
|
31
31
|
disabled,
|
|
32
32
|
placeholder,
|
|
33
33
|
autoComplete,
|
|
34
|
-
resize
|
|
34
|
+
resize,
|
|
35
|
+
maxLength
|
|
35
36
|
// ...otherProps
|
|
36
37
|
}) => {
|
|
37
38
|
const [field] = useField({
|
|
@@ -56,7 +57,8 @@ const TextareaInput = ({
|
|
|
56
57
|
placeholder: placeholder,
|
|
57
58
|
rows: rows,
|
|
58
59
|
disabled: disabled,
|
|
59
|
-
autoComplete: autoComplete
|
|
60
|
+
autoComplete: autoComplete,
|
|
61
|
+
maxLength: maxLength
|
|
60
62
|
})), /*#__PURE__*/React.createElement(FormDescription, {
|
|
61
63
|
className: "s-1",
|
|
62
64
|
description: description,
|
|
@@ -53,6 +53,7 @@ const InputBuilder = ({
|
|
|
53
53
|
const handleToggleShowSpecificFileTypes = () => {
|
|
54
54
|
setFieldValue(`sections.${sectionIndex}.inputs.${inputIndex}.showSpecificFileTypes`, !input.showSpecificFileTypes);
|
|
55
55
|
};
|
|
56
|
+
const textChoices = ['text', 'number', 'textarea', 'latex-preview-input'];
|
|
56
57
|
return /*#__PURE__*/React.createElement("div", {
|
|
57
58
|
id: id,
|
|
58
59
|
className: [baseClassName, componentClassName, userClassName].filter(e => e).join(' '),
|
|
@@ -129,7 +130,32 @@ const InputBuilder = ({
|
|
|
129
130
|
label: "Description (optional)",
|
|
130
131
|
name: `sections.${sectionIndex}.inputs.${inputIndex}.description`,
|
|
131
132
|
placeholder: "Describe details for the question"
|
|
132
|
-
})),
|
|
133
|
+
})), textChoices.includes(input?.type) && /*#__PURE__*/React.createElement("div", {
|
|
134
|
+
className: "character-limit-container"
|
|
135
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
136
|
+
className: "is-required"
|
|
137
|
+
}, /*#__PURE__*/React.createElement("span", {
|
|
138
|
+
className: "s0"
|
|
139
|
+
}, "Limit number of characters permitted for this input"), /*#__PURE__*/React.createElement(ToggleSwitch, {
|
|
140
|
+
handleOnChange: () => {
|
|
141
|
+
setFieldValue(`sections.${sectionIndex}.inputs.${inputIndex}.hasCharacterLimit`, !input?.hasCharacterLimit);
|
|
142
|
+
if (!input?.hasCharacterLimit) {
|
|
143
|
+
setFieldValue(`sections.${sectionIndex}.inputs.${inputIndex}.maxLength`, '');
|
|
144
|
+
}
|
|
145
|
+
},
|
|
146
|
+
checked: input?.hasCharacterLimit,
|
|
147
|
+
style: getToggleSwitchStyles(!input?.hasCharacterLimit),
|
|
148
|
+
inputId: `sections_${sectionIndex}_inputs.${inputIndex}_character_limit_toggle`
|
|
149
|
+
})), /*#__PURE__*/React.createElement("div", {
|
|
150
|
+
className: "character-limit-input"
|
|
151
|
+
}, input?.hasCharacterLimit && /*#__PURE__*/React.createElement(TextInput, {
|
|
152
|
+
label: "Enter the maximum number of characters permitted.",
|
|
153
|
+
name: `sections.${sectionIndex}.inputs.${inputIndex}.maxLength`,
|
|
154
|
+
placeholder: "",
|
|
155
|
+
type: "number",
|
|
156
|
+
validate: integerAndGreaterThanZero,
|
|
157
|
+
value: input?.maxLength
|
|
158
|
+
}))), shouldRenderOptions && /*#__PURE__*/React.createElement(FieldArray, {
|
|
133
159
|
name: `sections.${sectionIndex}.inputs.${inputIndex}.options`
|
|
134
160
|
}, ({
|
|
135
161
|
push,
|
|
@@ -64,6 +64,21 @@ $default-list-width: var(--action-button-width, 18rem);
|
|
|
64
64
|
margin-bottom: $default-margin;
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
+
> .character-limit-container {
|
|
68
|
+
display: flex;
|
|
69
|
+
flex-direction: column;
|
|
70
|
+
gap: var(--gap);
|
|
71
|
+
|
|
72
|
+
> .is-required {
|
|
73
|
+
display: flex;
|
|
74
|
+
flex-direction: row;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
> .character-limit-input {
|
|
78
|
+
flex-direction: column;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
67
82
|
> .input-options {
|
|
68
83
|
display: flex;
|
|
69
84
|
flex-direction: column;
|
|
@@ -49,7 +49,10 @@ const Section = ({
|
|
|
49
49
|
inputs
|
|
50
50
|
} = section;
|
|
51
51
|
useEffect(() => {
|
|
52
|
-
const
|
|
52
|
+
const orderMap = new Map();
|
|
53
|
+
section.orderedInputDragIds.forEach((identifier, indx) => orderMap.set(identifier, indx));
|
|
54
|
+
const orderedInputs = inputs.sort((a, b) => orderMap.get(a.name) - orderMap.get(b.name));
|
|
55
|
+
const items = orderedInputs.map((input, indx) => ({
|
|
53
56
|
Content: /*#__PURE__*/React.createElement(InputBuilder, {
|
|
54
57
|
key: input.name,
|
|
55
58
|
sectionIndex: index,
|
|
@@ -61,6 +64,7 @@ const Section = ({
|
|
|
61
64
|
}));
|
|
62
65
|
setDraggableInputs(items);
|
|
63
66
|
}, [inputs.length, index]);
|
|
67
|
+
const dragAndDropKey = draggableInputs.map(e => e.identifier).join(',');
|
|
64
68
|
return /*#__PURE__*/React.createElement("div", {
|
|
65
69
|
id: id,
|
|
66
70
|
className: [baseClassName, componentClassName, userClassName].filter(e => e).join(' '),
|
|
@@ -92,7 +96,7 @@ const Section = ({
|
|
|
92
96
|
const ids = reOrderedItems.map(e => e.identifier);
|
|
93
97
|
setFieldValue(`sections.${index}.orderedInputDragIds`, ids);
|
|
94
98
|
},
|
|
95
|
-
key:
|
|
99
|
+
key: dragAndDropKey
|
|
96
100
|
}), /*#__PURE__*/React.createElement("button", {
|
|
97
101
|
type: "button",
|
|
98
102
|
className: "add-question-cta",
|
|
@@ -10,6 +10,7 @@ import "./styles.scss";
|
|
|
10
10
|
|
|
11
11
|
// Local Definitions
|
|
12
12
|
|
|
13
|
+
import { applyCharacterLimit } from "../../../../utils";
|
|
13
14
|
import { Section } from "./common";
|
|
14
15
|
const baseClassName = styleNames.base;
|
|
15
16
|
const componentClassName = 'renderer';
|
|
@@ -134,6 +135,11 @@ const Renderer = ({
|
|
|
134
135
|
onSave?.(formDataWithValues);
|
|
135
136
|
}
|
|
136
137
|
}, [values]);
|
|
138
|
+
useEffect(() => {
|
|
139
|
+
applyCharacterLimit({
|
|
140
|
+
setMaxLength: false
|
|
141
|
+
});
|
|
142
|
+
}, [values]);
|
|
137
143
|
const hasErrors = Object.keys(errors).length > 0;
|
|
138
144
|
return /*#__PURE__*/React.createElement(Form, null, updatedFormData.sections.map((section, sectionIndex) => sectionIndex === currentSectionIndex && /*#__PURE__*/React.createElement(Section, _extends({
|
|
139
145
|
key: `${section.title}`
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
export const applyCharacterLimit = (setMaxLength = true) => {
|
|
2
|
+
setTimeout(() => {
|
|
3
|
+
document.querySelectorAll("[class*='limit-character-count-']").forEach(parent => {
|
|
4
|
+
const match = parent.className.match(/limit-character-count-(\d+)/);
|
|
5
|
+
if (!match) return;
|
|
6
|
+
const maxLength = parseInt(match[1], 10);
|
|
7
|
+
const fields = parent.matches("input[type='text'], input[type='email'], input[type='password'], input[type='search'], textarea") ? [parent] : Array.from(parent.querySelectorAll("input[type='text'], input[type='email'], input[type='password'], input[type='search'], textarea"));
|
|
8
|
+
if (!fields.length) return;
|
|
9
|
+
const characterCounterBaseClassName = 's-2 character-counter';
|
|
10
|
+
const characterCounterClassName = `${characterCounterBaseClassName} x-paragraph c-x`;
|
|
11
|
+
const characterCounterWarningClassName = `${characterCounterBaseClassName} x-orange c-x`;
|
|
12
|
+
const characterCounterErrorClassName = `${characterCounterBaseClassName} x-error c-x`;
|
|
13
|
+
fields.forEach(field => {
|
|
14
|
+
if (field.parentNode.querySelector('.character-counter')) return;
|
|
15
|
+
if (setMaxLength) {
|
|
16
|
+
field.setAttribute('maxlength', maxLength);
|
|
17
|
+
}
|
|
18
|
+
const counter = document.createElement('span');
|
|
19
|
+
counter.className = characterCounterClassName;
|
|
20
|
+
counter.style.position = 'absolute';
|
|
21
|
+
counter.style.right = '10px';
|
|
22
|
+
counter.style.bottom = '-20px';
|
|
23
|
+
counter.style.pointerEvents = 'none';
|
|
24
|
+
let wrapper;
|
|
25
|
+
const {
|
|
26
|
+
parentNode
|
|
27
|
+
} = field;
|
|
28
|
+
const computedStyle = window.getComputedStyle(parentNode);
|
|
29
|
+
if (parentNode.style && parentNode.style.position === 'relative' || computedStyle.getPropertyValue('position') === 'relative') {
|
|
30
|
+
wrapper = parentNode;
|
|
31
|
+
} else {
|
|
32
|
+
wrapper = document.createElement('div');
|
|
33
|
+
wrapper.style.position = 'relative';
|
|
34
|
+
wrapper.style.display = 'inline-block';
|
|
35
|
+
wrapper.style.width = '100%';
|
|
36
|
+
field.parentNode.insertBefore(wrapper, field);
|
|
37
|
+
wrapper.appendChild(field);
|
|
38
|
+
}
|
|
39
|
+
wrapper.appendChild(counter);
|
|
40
|
+
function updateCounter() {
|
|
41
|
+
if (field.value.length > maxLength) {
|
|
42
|
+
// eslint-disable-next-line no-param-reassign
|
|
43
|
+
field.value = field.value.substring(0, maxLength);
|
|
44
|
+
}
|
|
45
|
+
const {
|
|
46
|
+
length
|
|
47
|
+
} = field.value;
|
|
48
|
+
counter.textContent = `${length}/${maxLength}`;
|
|
49
|
+
if (length >= maxLength) {
|
|
50
|
+
counter.className = characterCounterErrorClassName;
|
|
51
|
+
} else if (length >= maxLength * 0.9) {
|
|
52
|
+
counter.className = characterCounterWarningClassName;
|
|
53
|
+
} else {
|
|
54
|
+
counter.className = characterCounterClassName;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
field.removeEventListener('input', updateCounter);
|
|
58
|
+
field.removeEventListener('paste', updateCounter);
|
|
59
|
+
field.addEventListener('input', updateCounter);
|
|
60
|
+
field.addEventListener('paste', () => {
|
|
61
|
+
setTimeout(updateCounter, 0);
|
|
62
|
+
});
|
|
63
|
+
updateCounter();
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
}, 100); // Small delay to ensure DOM is ready
|
|
67
|
+
};
|
|
@@ -37,6 +37,9 @@ export const formatTime = seconds => {
|
|
|
37
37
|
if (hours > 0) parts.push(`${hours}h`);
|
|
38
38
|
if (minutes > 0 || hours > 0 && remainingSeconds > 0) parts.push(`${minutes}m`);
|
|
39
39
|
if (remainingSeconds > 0) parts.push(`${remainingSeconds}s`);
|
|
40
|
+
|
|
41
|
+
// Cater for decimal seconds
|
|
42
|
+
if (parts.length === 0) return '0s';
|
|
40
43
|
return parts.join(' ');
|
|
41
44
|
};
|
|
42
45
|
const parseDate = input => {
|
|
@@ -99,4 +102,8 @@ export const formatDate = (input, format = DATE_FORMATS.HUMAN_READABLE) => {
|
|
|
99
102
|
} catch (error) {
|
|
100
103
|
return 'Invalid Date';
|
|
101
104
|
}
|
|
105
|
+
};
|
|
106
|
+
export const snakeCaseToTitleCase = word => {
|
|
107
|
+
const result = word.replace(/([A-Z])/g, ' $1');
|
|
108
|
+
return result.charAt(0).toUpperCase() + result.slice(1);
|
|
102
109
|
};
|
package/dist/es/utils/index.js
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
1
|
export { useWindowSize, useDynamicPosition, useOutsideClick } from "./hooks";
|
|
2
|
-
export { formatTime, formatDate, DATE_FORMATS } from "./formatting";
|
|
2
|
+
export { formatTime, formatDate, DATE_FORMATS, snakeCaseToTitleCase } from "./formatting";
|
|
3
|
+
export { applyCharacterLimit } from "./applyCharacterLimit";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pareto-engineering/design-system",
|
|
3
|
-
"version": "5.0
|
|
3
|
+
"version": "5.1.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "dist/cjs/index.js",
|
|
6
6
|
"module": "dist/es/index.js",
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
"@lexical/selection": "0.12.2",
|
|
60
60
|
"@lexical/table": "0.12.2",
|
|
61
61
|
"@lexical/utils": "0.12.2",
|
|
62
|
-
"@pareto-engineering/assets": "^5.
|
|
62
|
+
"@pareto-engineering/assets": "^5.1.0",
|
|
63
63
|
"@pareto-engineering/bem": "^5.0.0",
|
|
64
64
|
"@pareto-engineering/styles": "^5.0.0",
|
|
65
65
|
"@pareto-engineering/utils": "^5.0.0",
|
|
@@ -87,5 +87,5 @@
|
|
|
87
87
|
"remark-math": "^6.0.0"
|
|
88
88
|
},
|
|
89
89
|
"browserslist": "> 2%",
|
|
90
|
-
"gitHead": "
|
|
90
|
+
"gitHead": "df984562befbec687e458242d3b8696ee7286d1e"
|
|
91
91
|
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { PieChart } from 'ui'
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
title :'a/Charts/PieChart',
|
|
6
|
+
component:PieChart,
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const data = [
|
|
10
|
+
{ status: 'pendingReview', value: 230 },
|
|
11
|
+
{ status: 'accepted', value: 350 },
|
|
12
|
+
{ status: 'rejected', value: 80 },
|
|
13
|
+
{ status: 'toRevise', value: 10 },
|
|
14
|
+
{ status: 'revised', value: 60 },
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
const Template = (args) => (
|
|
18
|
+
<div style={{ height: '100%', width: '100%' }}>
|
|
19
|
+
<PieChart {...args} />
|
|
20
|
+
</div>
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
export const Default = Template.bind({})
|
|
24
|
+
Default.args = {
|
|
25
|
+
data,
|
|
26
|
+
valueKey:'value',
|
|
27
|
+
labelKey:'status',
|
|
28
|
+
colors :['#8CB0F8', '#7F7CF6', '#FFD66E', '#E8E9ED', '#F6BC7E'],
|
|
29
|
+
height :400,
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const TemplateSideBySide = (args) => (
|
|
33
|
+
<div style={{ display: 'flex', gap: '20px' }}>
|
|
34
|
+
<div style={{ flex: 1 }}>
|
|
35
|
+
{/* eslint-disable-next-line react/destructuring-assignment */}
|
|
36
|
+
<PieChart {...args[0]} />
|
|
37
|
+
</div>
|
|
38
|
+
<div style={{ flex: 1 }}>
|
|
39
|
+
{/* eslint-disable-next-line react/destructuring-assignment */}
|
|
40
|
+
<PieChart {...args[1]} />
|
|
41
|
+
</div>
|
|
42
|
+
</div>
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
export const SideBySide = TemplateSideBySide.bind({})
|
|
46
|
+
SideBySide.args = [
|
|
47
|
+
{
|
|
48
|
+
...Default.args,
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
...Default.args,
|
|
52
|
+
},
|
|
53
|
+
]
|
|
@@ -50,18 +50,6 @@ const AreaChart = ({
|
|
|
50
50
|
|
|
51
51
|
const [selectedYLabels, setSelectedYLabels] = useState(allYLabels)
|
|
52
52
|
|
|
53
|
-
const processedData = data.map((item) => {
|
|
54
|
-
const yValues = yKeys.map((key) => item[key])
|
|
55
|
-
const lowerBound = Math.min(...yValues)
|
|
56
|
-
const upperBound = Math.max(...yValues)
|
|
57
|
-
const margin = (upperBound - lowerBound) * 0.1
|
|
58
|
-
return {
|
|
59
|
-
...item,
|
|
60
|
-
bounds:[lowerBound - margin, upperBound + margin],
|
|
61
|
-
isTimeFormat,
|
|
62
|
-
}
|
|
63
|
-
})
|
|
64
|
-
|
|
65
53
|
const yAxisBounds = () => {
|
|
66
54
|
const yValues = data.map((item) => yKeys.map((key) => item[key]))
|
|
67
55
|
const min = Math.min(...yValues.flat())
|
|
@@ -95,7 +83,7 @@ const AreaChart = ({
|
|
|
95
83
|
capitalizedLegend={capitalizedLegend}
|
|
96
84
|
/>
|
|
97
85
|
<ResponsiveContainer width={width} height={height}>
|
|
98
|
-
<RechartsAreaChart data={
|
|
86
|
+
<RechartsAreaChart data={data}>
|
|
99
87
|
<CartesianGrid strokeDasharray="3 3" />
|
|
100
88
|
<XAxis
|
|
101
89
|
dataKey={xKey}
|
|
@@ -126,7 +114,13 @@ const AreaChart = ({
|
|
|
126
114
|
return value.toFixed(2)
|
|
127
115
|
}}
|
|
128
116
|
/>
|
|
129
|
-
<Tooltip content={
|
|
117
|
+
<Tooltip content={(
|
|
118
|
+
<CustomTooltipContent
|
|
119
|
+
dateFormat={dateFormat}
|
|
120
|
+
isTimeFormat={isTimeFormat}
|
|
121
|
+
/>
|
|
122
|
+
)}
|
|
123
|
+
/>
|
|
130
124
|
{filled && (
|
|
131
125
|
<Area
|
|
132
126
|
id="bounds"
|
|
@@ -38,7 +38,8 @@ const BarChart = ({
|
|
|
38
38
|
colors,
|
|
39
39
|
height,
|
|
40
40
|
width,
|
|
41
|
-
|
|
41
|
+
isTimeFormat,
|
|
42
|
+
capitalizedLegend,
|
|
42
43
|
}) => {
|
|
43
44
|
const allYLabels = yKeys.map((key) => ({
|
|
44
45
|
label:key,
|
|
@@ -69,6 +70,7 @@ const BarChart = ({
|
|
|
69
70
|
<CustomLegend
|
|
70
71
|
colorsArray={selectedYLabels.map((item) => item.color)}
|
|
71
72
|
yKeysArray={selectedYLabels.map((item) => item.label)}
|
|
73
|
+
capitalizedLegend={capitalizedLegend}
|
|
72
74
|
/>
|
|
73
75
|
<ResponsiveContainer width={width} height={height}>
|
|
74
76
|
<RechartsBarChart data={data}>
|
|
@@ -87,7 +89,7 @@ const BarChart = ({
|
|
|
87
89
|
axisLine={false}
|
|
88
90
|
tickLine={false}
|
|
89
91
|
/>
|
|
90
|
-
<Tooltip content={<CustomTooltipContent
|
|
92
|
+
<Tooltip content={<CustomTooltipContent isTimeFormat={isTimeFormat} />} />
|
|
91
93
|
{selectedYLabels.map((key) => (
|
|
92
94
|
<Bar
|
|
93
95
|
stackId="a"
|