@oliasoft-open-source/charts-library 2.4.6 → 2.5.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/package.json +1 -1
- package/release-notes.md +10 -0
- package/src/assets/icons/line-and-point.svg +1 -0
- package/src/assets/icons/line-only.svg +1 -0
- package/src/assets/icons/list-hide.svg +1 -0
- package/src/assets/icons/point-only.svg +1 -0
- package/src/components/bar-chart/bar-chart.jsx +1 -0
- package/src/components/controls/axes-options.jsx +132 -0
- package/src/components/controls/controls.jsx +105 -0
- package/src/components/controls/controls.module.less +12 -0
- package/src/components/controls/drag-options.jsx +77 -0
- package/src/components/controls/legend-options.jsx +25 -0
- package/src/components/controls/line-options.jsx +54 -0
- package/src/components/line-chart/line-chart-prop-types.js +1 -0
- package/src/components/line-chart/line-chart.jsx +98 -84
- package/src/components/line-chart/line-chart.module.less +15 -5
- package/src/components/line-chart/line-chart.stories.jsx +131 -14
- package/src/components/line-chart/state/action-types.js +1 -0
- package/src/components/line-chart/state/initial-state.js +1 -0
- package/src/components/line-chart/state/line-chart-reducer.js +7 -0
- package/src/components/pie-chart/pie-chart.jsx +1 -0
- package/src/helpers/enums.js +1 -0
- package/src/components/line-chart/Controls/Controls.jsx +0 -61
- package/src/components/line-chart/Controls/Controls.module.less +0 -21
- package/src/components/line-chart/Controls/Layer.jsx +0 -172
package/package.json
CHANGED
package/release-notes.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# Charts Library Release Notes
|
|
2
2
|
|
|
3
|
+
## 2.5.1
|
|
4
|
+
|
|
5
|
+
- Added resize delay for performance
|
|
6
|
+
|
|
7
|
+
## 2.5.0
|
|
8
|
+
|
|
9
|
+
- Separate controls for points/lines, axes options, legend, download
|
|
10
|
+
- Standard control for table
|
|
11
|
+
- Box zoom
|
|
12
|
+
|
|
3
13
|
## 2.4.6
|
|
4
14
|
|
|
5
15
|
- Fix Multiple X Axes example in LineChart
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg fill="none" height="12" viewBox="0 0 12 12" width="12" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><clipPath id="a"><path d="m0 0h12v12h-12z"/></clipPath><g clip-path="url(#a)"><path d="m7.937 6.5c-.11122.42912-.36179.80916-.71237 1.08047-.35058.2713-.78133.4185-1.22463.4185s-.87405-.1472-1.22463-.4185c-.35058-.27131-.60115-.65135-.71237-1.08047h-3.563v-1h3.563c.11122-.42912.36179-.80916.71237-1.08046s.78133-.41851 1.22463-.41851.87405.14721 1.22463.41851.60115.65134.71237 1.08046h3.563v1z" fill="currentColor"/></g></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg fill="none" height="12" viewBox="0 0 12 12" width="12" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><clipPath id="a"><path d="m0 0h12v12h-12z"/></clipPath><g clip-path="url(#a)"><path d="m.5 6.5v-1h11v1c-4.16104 0-6.63549 0-11 0z" fill="currentColor"/></g></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg fill="none" height="12" viewBox="0 0 12 12" width="12" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><clipPath id="a"><path d="m0 0h12v12h-12z"/></clipPath><g clip-path="url(#a)"><path clip-rule="evenodd" d="m1.85351 1.14645-.35356-.353558-.707103.707108.353553.35355.39645.39645c-.02813.07955-.0429.16401-.0429.25 0 .19891.07902.38968.21967.53033.14066.14065.33142.21967.53033.21967.08599 0 .17045-.01477.25-.04289l2.2929 2.29289h-.7929v1h1.7929l2.5 2.5h-4.2929v1h5.2929l.85355.8536.3536.3535.7071-.7071-.3536-.3536-.3535-.35351v-.79289h-.79294l-2.5-2.5h3.29294v-1h-4.29294l-3.25-3.25c-.03694-.10448-.09692-.20048-.17678-.28033-.07985-.07985-.17585-.13984-.28033-.17678zm8.64649.85355h-6.50005v1h6.50005zm-8.78038 4.53033c.14066.14065.33142.21967.53033.21967.19892 0 .38968-.07902.53033-.21967.14066-.14065.21967-.33142.21967-.53033s-.07901-.38968-.21967-.53033c-.14065-.14065-.33141-.21967-.53033-.21967-.19891 0-.38967.07902-.53033.21967-.14065.14065-.21967.33142-.21967.53033s.07902.38968.21967.53033zm0 3.45c.14066.14067.33142.21967.53033.21967.19892 0 .38968-.079.53033-.21967.14066-.14065.21967-.33142.21967-.53033s-.07901-.38968-.21967-.53033c-.14065-.14065-.33141-.21967-.53033-.21967-.19891 0-.38967.07902-.53033.21967-.14065.14065-.21967.33142-.21967.53033s.07902.38968.21967.53033z" fill="currentColor" fill-rule="evenodd"/></g></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg fill="none" height="12" viewBox="0 0 12 12" width="12" xmlns="http://www.w3.org/2000/svg"><circle cx="6" cy="6" fill="currentColor" r="2"/></svg>
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import {
|
|
3
|
+
Button,
|
|
4
|
+
Field,
|
|
5
|
+
Flex,
|
|
6
|
+
Input,
|
|
7
|
+
InputGroup,
|
|
8
|
+
InputGroupAddon,
|
|
9
|
+
Popover,
|
|
10
|
+
Text,
|
|
11
|
+
Tooltip,
|
|
12
|
+
} from '@oliasoft-open-source/react-ui-library';
|
|
13
|
+
import { RiRuler2Line } from 'react-icons/ri';
|
|
14
|
+
|
|
15
|
+
const AxesOptionsPopover = ({
|
|
16
|
+
onResetAxes,
|
|
17
|
+
axes,
|
|
18
|
+
onSetAxisValue,
|
|
19
|
+
panEnabled,
|
|
20
|
+
scalesMaxMin,
|
|
21
|
+
zoomEnabled,
|
|
22
|
+
close,
|
|
23
|
+
}) => {
|
|
24
|
+
const isCustomValue =
|
|
25
|
+
axes.filter((axis) => axis.max.displayValue || axis.min.displayValue)
|
|
26
|
+
.length > 0;
|
|
27
|
+
const handleInputFocus = (e) => e.target.select();
|
|
28
|
+
return (
|
|
29
|
+
<>
|
|
30
|
+
{axes.map((axis, i) => {
|
|
31
|
+
// TODO: Translate strings
|
|
32
|
+
if (!axis.min || !axis.max) return null;
|
|
33
|
+
return (
|
|
34
|
+
<Field key={i} label={axis.label || axis.id || ''}>
|
|
35
|
+
<InputGroup small>
|
|
36
|
+
<Input
|
|
37
|
+
name="min"
|
|
38
|
+
// TODO: Fix input values not updating first time when scales reset
|
|
39
|
+
value={axis.min.inputValue || scalesMaxMin[axis?.id]?.min}
|
|
40
|
+
error={
|
|
41
|
+
!axis.min.valid
|
|
42
|
+
? 'Invalid value' //t(InputWarningType.MustBeNumericAndLessThanMax)
|
|
43
|
+
: undefined
|
|
44
|
+
}
|
|
45
|
+
size={5}
|
|
46
|
+
width="100%"
|
|
47
|
+
onChange={(evt) =>
|
|
48
|
+
onSetAxisValue({
|
|
49
|
+
name: evt.target.name,
|
|
50
|
+
value: evt.target.value,
|
|
51
|
+
id: axis.id,
|
|
52
|
+
})
|
|
53
|
+
}
|
|
54
|
+
onFocus={handleInputFocus}
|
|
55
|
+
disabled={zoomEnabled || panEnabled}
|
|
56
|
+
/>
|
|
57
|
+
<InputGroupAddon>
|
|
58
|
+
to
|
|
59
|
+
{/*t(translations.to)*/}
|
|
60
|
+
</InputGroupAddon>
|
|
61
|
+
<Input
|
|
62
|
+
name="max"
|
|
63
|
+
// TODO: Fix input values not updating first time when scales reset
|
|
64
|
+
value={axis.max.inputValue || scalesMaxMin[axis?.id]?.max}
|
|
65
|
+
error={
|
|
66
|
+
!axis.max.valid
|
|
67
|
+
? 'Invalid value' //t(InputWarningType.MustBeNumericAndGreaterThanMin)
|
|
68
|
+
: undefined
|
|
69
|
+
}
|
|
70
|
+
size={5}
|
|
71
|
+
width="100%"
|
|
72
|
+
onChange={(evt) =>
|
|
73
|
+
onSetAxisValue({
|
|
74
|
+
name: evt.target.name,
|
|
75
|
+
value: evt.target.value,
|
|
76
|
+
id: axis.id,
|
|
77
|
+
})
|
|
78
|
+
}
|
|
79
|
+
onFocus={handleInputFocus}
|
|
80
|
+
disabled={zoomEnabled || panEnabled}
|
|
81
|
+
/>
|
|
82
|
+
</InputGroup>
|
|
83
|
+
{/* TODO: Add units */}
|
|
84
|
+
</Field>
|
|
85
|
+
);
|
|
86
|
+
})}
|
|
87
|
+
<Flex gap="8px" alignItems="center">
|
|
88
|
+
<Button small colored label="Done" onClick={close} />
|
|
89
|
+
<Button
|
|
90
|
+
small
|
|
91
|
+
name="resetAxes"
|
|
92
|
+
label="Reset Axes"
|
|
93
|
+
onClick={onResetAxes}
|
|
94
|
+
disabled={!isCustomValue}
|
|
95
|
+
/>
|
|
96
|
+
<Text small muted>
|
|
97
|
+
or click on canvas
|
|
98
|
+
</Text>
|
|
99
|
+
</Flex>
|
|
100
|
+
</>
|
|
101
|
+
);
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
export const AxesOptions = ({
|
|
105
|
+
onResetAxes,
|
|
106
|
+
axes,
|
|
107
|
+
onSetAxisValue,
|
|
108
|
+
panEnabled,
|
|
109
|
+
scalesMaxMin,
|
|
110
|
+
zoomEnabled,
|
|
111
|
+
}) => {
|
|
112
|
+
return (
|
|
113
|
+
<Popover
|
|
114
|
+
placement="bottom"
|
|
115
|
+
overflowContainer
|
|
116
|
+
content={
|
|
117
|
+
<AxesOptionsPopover
|
|
118
|
+
onResetAxes={onResetAxes}
|
|
119
|
+
axes={axes}
|
|
120
|
+
onSetAxisValue={onSetAxisValue}
|
|
121
|
+
panEnabled={panEnabled}
|
|
122
|
+
scalesMaxMin={scalesMaxMin}
|
|
123
|
+
zoomEnabled={zoomEnabled}
|
|
124
|
+
/>
|
|
125
|
+
}
|
|
126
|
+
>
|
|
127
|
+
<Tooltip text="Axes options" placement="bottom" display="flex">
|
|
128
|
+
<Button small basic colored="muted" round icon={<RiRuler2Line />} />
|
|
129
|
+
</Tooltip>
|
|
130
|
+
</Popover>
|
|
131
|
+
);
|
|
132
|
+
};
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Button, Text, Tooltip } from '@oliasoft-open-source/react-ui-library';
|
|
3
|
+
import {
|
|
4
|
+
RiFileDownloadLine,
|
|
5
|
+
RiLineChartLine,
|
|
6
|
+
RiTableLine,
|
|
7
|
+
} from 'react-icons/ri';
|
|
8
|
+
import { LineOptions } from './line-options';
|
|
9
|
+
import { DragOptions } from './drag-options';
|
|
10
|
+
import { AxesOptions } from './axes-options';
|
|
11
|
+
import { LegendOptions } from './legend-options';
|
|
12
|
+
import styles from './controls.module.less';
|
|
13
|
+
|
|
14
|
+
const Controls = ({
|
|
15
|
+
axes,
|
|
16
|
+
chart,
|
|
17
|
+
headerComponent,
|
|
18
|
+
legendEnabled,
|
|
19
|
+
lineEnabled,
|
|
20
|
+
onDownload,
|
|
21
|
+
onResetAxes,
|
|
22
|
+
onSetAxisValue,
|
|
23
|
+
onToggleLegend,
|
|
24
|
+
onToggleLine,
|
|
25
|
+
onTogglePan,
|
|
26
|
+
onTogglePoints,
|
|
27
|
+
onToggleTable,
|
|
28
|
+
onToggleZoom,
|
|
29
|
+
panEnabled,
|
|
30
|
+
pointsEnabled,
|
|
31
|
+
scalesMaxMin,
|
|
32
|
+
showTable,
|
|
33
|
+
subheaderComponent,
|
|
34
|
+
table,
|
|
35
|
+
zoomEnabled,
|
|
36
|
+
}) => {
|
|
37
|
+
return (
|
|
38
|
+
<>
|
|
39
|
+
<div className={styles.controls}>
|
|
40
|
+
<div>{headerComponent || <Text bold>{chart.options.title}</Text>}</div>
|
|
41
|
+
<div className={styles.buttons}>
|
|
42
|
+
{!showTable && (
|
|
43
|
+
<>
|
|
44
|
+
<AxesOptions
|
|
45
|
+
onResetAxes={onResetAxes}
|
|
46
|
+
axes={axes}
|
|
47
|
+
onSetAxisValue={onSetAxisValue}
|
|
48
|
+
panEnabled={panEnabled}
|
|
49
|
+
scalesMaxMin={scalesMaxMin}
|
|
50
|
+
zoomEnabled={zoomEnabled}
|
|
51
|
+
/>
|
|
52
|
+
<LineOptions
|
|
53
|
+
lineEnabled={lineEnabled}
|
|
54
|
+
pointsEnabled={pointsEnabled}
|
|
55
|
+
onToggleLine={onToggleLine}
|
|
56
|
+
onTogglePoints={onTogglePoints}
|
|
57
|
+
/>
|
|
58
|
+
<LegendOptions
|
|
59
|
+
legendEnabled={legendEnabled}
|
|
60
|
+
onToggleLegend={onToggleLegend}
|
|
61
|
+
/>
|
|
62
|
+
<DragOptions
|
|
63
|
+
panEnabled={panEnabled}
|
|
64
|
+
zoomEnabled={zoomEnabled}
|
|
65
|
+
onTogglePan={onTogglePan}
|
|
66
|
+
onToggleZoom={onToggleZoom}
|
|
67
|
+
/>
|
|
68
|
+
{/* TODO: implement usetranslation */}
|
|
69
|
+
<Tooltip text="Download as PNG" placement="bottom-end">
|
|
70
|
+
<Button
|
|
71
|
+
small
|
|
72
|
+
basic
|
|
73
|
+
colored="muted"
|
|
74
|
+
round
|
|
75
|
+
icon={<RiFileDownloadLine />}
|
|
76
|
+
onClick={onDownload}
|
|
77
|
+
/>
|
|
78
|
+
</Tooltip>
|
|
79
|
+
</>
|
|
80
|
+
)}
|
|
81
|
+
|
|
82
|
+
{table ? (
|
|
83
|
+
<Tooltip
|
|
84
|
+
text={showTable ? 'Show chart' : 'Show table'}
|
|
85
|
+
placement="bottom-end"
|
|
86
|
+
>
|
|
87
|
+
{/* TODO: implement usetranslation */}
|
|
88
|
+
<Button
|
|
89
|
+
small
|
|
90
|
+
basic
|
|
91
|
+
colored="muted"
|
|
92
|
+
round
|
|
93
|
+
icon={showTable ? <RiLineChartLine /> : <RiTableLine />}
|
|
94
|
+
onClick={onToggleTable}
|
|
95
|
+
/>
|
|
96
|
+
</Tooltip>
|
|
97
|
+
) : null}
|
|
98
|
+
</div>
|
|
99
|
+
</div>
|
|
100
|
+
{subheaderComponent}
|
|
101
|
+
</>
|
|
102
|
+
);
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
export default Controls;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import {
|
|
3
|
+
Button,
|
|
4
|
+
Flex,
|
|
5
|
+
Text,
|
|
6
|
+
Tooltip,
|
|
7
|
+
} from '@oliasoft-open-source/react-ui-library';
|
|
8
|
+
import { RiDragMove2Line, RiForbidLine, RiZoomInLine } from 'react-icons/ri';
|
|
9
|
+
|
|
10
|
+
export const DragOptions = ({
|
|
11
|
+
onTogglePan,
|
|
12
|
+
onToggleZoom,
|
|
13
|
+
panEnabled,
|
|
14
|
+
zoomEnabled,
|
|
15
|
+
}) => {
|
|
16
|
+
// TODO: Translate strings
|
|
17
|
+
const options = [
|
|
18
|
+
{
|
|
19
|
+
label: (
|
|
20
|
+
<Flex direction="column">
|
|
21
|
+
<Text>Drag to zoom</Text>
|
|
22
|
+
{/* <Text small muted>
|
|
23
|
+
Hold shift to change axis
|
|
24
|
+
</Text> */}
|
|
25
|
+
<Text small muted>
|
|
26
|
+
Click on canvas to reset
|
|
27
|
+
</Text>
|
|
28
|
+
</Flex>
|
|
29
|
+
),
|
|
30
|
+
icon: <RiZoomInLine />,
|
|
31
|
+
selected: zoomEnabled,
|
|
32
|
+
onClick: () => {
|
|
33
|
+
onToggleZoom();
|
|
34
|
+
onTogglePan();
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
label: (
|
|
39
|
+
<Flex direction="column">
|
|
40
|
+
<Text>Drag to pan</Text>
|
|
41
|
+
{/* <Text small muted>
|
|
42
|
+
Hold shift to change axis
|
|
43
|
+
</Text> */}
|
|
44
|
+
<Text small muted>
|
|
45
|
+
Click on canvas to reset
|
|
46
|
+
</Text>
|
|
47
|
+
</Flex>
|
|
48
|
+
),
|
|
49
|
+
icon: <RiDragMove2Line />,
|
|
50
|
+
selected: panEnabled,
|
|
51
|
+
onClick: () => {
|
|
52
|
+
onTogglePan();
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
label: 'Drag disabled',
|
|
57
|
+
icon: <RiForbidLine />,
|
|
58
|
+
selected: !zoomEnabled && !panEnabled,
|
|
59
|
+
onClick: () => {
|
|
60
|
+
onToggleZoom();
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
];
|
|
64
|
+
const selectedOption = options.filter((option) => option.selected)[0];
|
|
65
|
+
return (
|
|
66
|
+
<Tooltip text={selectedOption.label} placement="bottom-end">
|
|
67
|
+
<Button
|
|
68
|
+
small
|
|
69
|
+
basic
|
|
70
|
+
colored="muted"
|
|
71
|
+
round
|
|
72
|
+
icon={selectedOption.icon}
|
|
73
|
+
onClick={selectedOption.onClick}
|
|
74
|
+
/>
|
|
75
|
+
</Tooltip>
|
|
76
|
+
);
|
|
77
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Button, Icon, Tooltip } from '@oliasoft-open-source/react-ui-library';
|
|
3
|
+
import { RiListUnordered } from 'react-icons/ri';
|
|
4
|
+
import listHideIcon from '../../assets/icons/list-hide.svg';
|
|
5
|
+
|
|
6
|
+
export const LegendOptions = ({ legendEnabled, onToggleLegend }) => {
|
|
7
|
+
// TODO: Translate strings
|
|
8
|
+
return (
|
|
9
|
+
<Tooltip
|
|
10
|
+
text={legendEnabled ? 'Legend shown' : 'Legend hidden'}
|
|
11
|
+
placement="bottom"
|
|
12
|
+
>
|
|
13
|
+
<Button
|
|
14
|
+
small
|
|
15
|
+
basic
|
|
16
|
+
colored="muted"
|
|
17
|
+
round
|
|
18
|
+
icon={
|
|
19
|
+
legendEnabled ? <RiListUnordered /> : <Icon icon={listHideIcon} />
|
|
20
|
+
}
|
|
21
|
+
onClick={onToggleLegend}
|
|
22
|
+
/>
|
|
23
|
+
</Tooltip>
|
|
24
|
+
);
|
|
25
|
+
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Button, Icon, Tooltip } from '@oliasoft-open-source/react-ui-library';
|
|
3
|
+
import lineOnlyIcon from '../../assets/icons/line-only.svg';
|
|
4
|
+
import pointOnlyIcon from '../../assets/icons/point-only.svg';
|
|
5
|
+
import lineAndPointIcon from '../../assets/icons/line-and-point.svg';
|
|
6
|
+
|
|
7
|
+
export const LineOptions = ({
|
|
8
|
+
lineEnabled,
|
|
9
|
+
onToggleLine,
|
|
10
|
+
onTogglePoints,
|
|
11
|
+
pointsEnabled,
|
|
12
|
+
}) => {
|
|
13
|
+
// TODO: Translate strings
|
|
14
|
+
const options = [
|
|
15
|
+
{
|
|
16
|
+
label: 'Points & lines',
|
|
17
|
+
icon: <Icon icon={lineAndPointIcon} />,
|
|
18
|
+
selected: pointsEnabled && lineEnabled,
|
|
19
|
+
onClick: () => {
|
|
20
|
+
onTogglePoints();
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
label: 'Lines only',
|
|
25
|
+
icon: <Icon icon={lineOnlyIcon} />,
|
|
26
|
+
selected: !pointsEnabled && lineEnabled,
|
|
27
|
+
onClick: () => {
|
|
28
|
+
onTogglePoints();
|
|
29
|
+
onToggleLine();
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
label: 'Points only',
|
|
34
|
+
icon: <Icon icon={pointOnlyIcon} />,
|
|
35
|
+
selected: pointsEnabled && !lineEnabled,
|
|
36
|
+
onClick: () => {
|
|
37
|
+
onToggleLine();
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
];
|
|
41
|
+
const selectedOption = options.filter((option) => option.selected)[0];
|
|
42
|
+
return (
|
|
43
|
+
<Tooltip text={selectedOption.label} placement="bottom">
|
|
44
|
+
<Button
|
|
45
|
+
small
|
|
46
|
+
basic
|
|
47
|
+
colored="muted"
|
|
48
|
+
round
|
|
49
|
+
icon={selectedOption.icon}
|
|
50
|
+
onClick={selectedOption.onClick}
|
|
51
|
+
/>
|
|
52
|
+
</Tooltip>
|
|
53
|
+
);
|
|
54
|
+
};
|
|
@@ -28,10 +28,11 @@ import {
|
|
|
28
28
|
TOGGLE_LINE,
|
|
29
29
|
TOGGLE_PAN,
|
|
30
30
|
TOGGLE_POINTS,
|
|
31
|
+
TOGGLE_TABLE,
|
|
31
32
|
TOGGLE_ZOOM,
|
|
32
33
|
UNSET_AXES_VALUES,
|
|
33
34
|
} from './state/action-types';
|
|
34
|
-
import
|
|
35
|
+
import Controls from '../controls/controls';
|
|
35
36
|
import { getDefaultProps, LineChartPropTypes } from './line-chart-prop-types';
|
|
36
37
|
import getLineChartScales from './get-line-chart-scales';
|
|
37
38
|
import getLineChartToolTips from './get-line-chart-tooltips';
|
|
@@ -95,6 +96,7 @@ const LineChart = (props) => {
|
|
|
95
96
|
let pointHover = false;
|
|
96
97
|
const chart = getDefaultProps(props);
|
|
97
98
|
const { options, testId } = chart;
|
|
99
|
+
const { headerComponent, subheaderComponent, table } = props;
|
|
98
100
|
|
|
99
101
|
const {
|
|
100
102
|
additionalAxesOptions,
|
|
@@ -106,8 +108,7 @@ const LineChart = (props) => {
|
|
|
106
108
|
interactions,
|
|
107
109
|
legend,
|
|
108
110
|
} = options;
|
|
109
|
-
const { showLine, showPoints, enableZoom, enablePan
|
|
110
|
-
chartOptions;
|
|
111
|
+
const { showLine, showPoints, enableZoom, enablePan } = chartOptions;
|
|
111
112
|
|
|
112
113
|
/**
|
|
113
114
|
* @type {[object, import('react').Dispatch<{type: String, payload: any}>]} useReducer
|
|
@@ -392,93 +393,106 @@ const LineChart = (props) => {
|
|
|
392
393
|
onKeyUp={handleKeyUp}
|
|
393
394
|
data-testid={testId}
|
|
394
395
|
>
|
|
395
|
-
<
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
onSetAxisValue={(evt) =>
|
|
405
|
-
dispatch({ type: SET_AXIS_VALUE, payload: evt })
|
|
406
|
-
}
|
|
407
|
-
onResetAxes={() => {
|
|
408
|
-
dispatch({ type: UNSET_AXES_VALUES });
|
|
409
|
-
}}
|
|
410
|
-
onToggleLegend={() => dispatch({ type: TOGGLE_LEGEND })}
|
|
411
|
-
onToggleLine={() => dispatch({ type: TOGGLE_LINE })}
|
|
412
|
-
onTogglePan={() => dispatch({ type: TOGGLE_PAN })}
|
|
413
|
-
onTogglePoints={() => dispatch({ type: TOGGLE_POINTS })}
|
|
414
|
-
onToggleZoom={() => dispatch({ type: TOGGLE_ZOOM })}
|
|
415
|
-
onDownload={handleDownload}
|
|
416
|
-
closeOnOutsideClick={closeOnOutsideClick}
|
|
417
|
-
/>
|
|
418
|
-
</div>
|
|
419
|
-
<Line
|
|
420
|
-
ref={chartRef}
|
|
421
|
-
data={{
|
|
422
|
-
datasets: generatedDatasets,
|
|
396
|
+
<Controls
|
|
397
|
+
axes={controlsAxes}
|
|
398
|
+
chart={chart}
|
|
399
|
+
headerComponent={headerComponent}
|
|
400
|
+
legendEnabled={state.legendEnabled}
|
|
401
|
+
lineEnabled={state.lineEnabled}
|
|
402
|
+
onDownload={handleDownload}
|
|
403
|
+
onResetAxes={() => {
|
|
404
|
+
dispatch({ type: UNSET_AXES_VALUES });
|
|
423
405
|
}}
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
406
|
+
onSetAxisValue={(evt) =>
|
|
407
|
+
dispatch({ type: SET_AXIS_VALUE, payload: evt })
|
|
408
|
+
}
|
|
409
|
+
onToggleLegend={() => dispatch({ type: TOGGLE_LEGEND })}
|
|
410
|
+
onToggleLine={() => dispatch({ type: TOGGLE_LINE })}
|
|
411
|
+
onTogglePan={() => dispatch({ type: TOGGLE_PAN })}
|
|
412
|
+
onTogglePoints={() => dispatch({ type: TOGGLE_POINTS })}
|
|
413
|
+
onToggleTable={() => dispatch({ type: TOGGLE_TABLE })}
|
|
414
|
+
onToggleZoom={() => dispatch({ type: TOGGLE_ZOOM })}
|
|
415
|
+
panEnabled={state.panEnabled}
|
|
416
|
+
pointsEnabled={state.pointsEnabled}
|
|
417
|
+
scalesMaxMin={getScalesMaxMin()}
|
|
418
|
+
showTable={state.showTable}
|
|
419
|
+
subheaderComponent={subheaderComponent}
|
|
420
|
+
table={table}
|
|
421
|
+
zoomEnabled={state.zoomEnabled}
|
|
422
|
+
/>
|
|
423
|
+
{table && state.showTable ? (
|
|
424
|
+
<div className={styles.table}>{table}</div>
|
|
425
|
+
) : (
|
|
426
|
+
<div className={styles.canvas}>
|
|
427
|
+
<Line
|
|
428
|
+
ref={chartRef}
|
|
429
|
+
data={{
|
|
430
|
+
datasets: generatedDatasets,
|
|
431
|
+
}}
|
|
432
|
+
options={{
|
|
433
|
+
onClick,
|
|
434
|
+
onHover,
|
|
435
|
+
resizeDelay: 50,
|
|
436
|
+
maintainAspectRatio: chartStyling.maintainAspectRatio,
|
|
437
|
+
aspectRatio: chartStyling.squareAspectRatio ? 1 : null, // 1 equals square aspect ratio
|
|
438
|
+
animation: {
|
|
439
|
+
duration: chartStyling.performanceMode
|
|
440
|
+
? ANIMATION_DURATION.NO
|
|
441
|
+
: ANIMATION_DURATION.FAST,
|
|
442
|
+
},
|
|
443
|
+
hover: {
|
|
444
|
+
mode: ChartHoverMode.Nearest,
|
|
445
|
+
intersect: true,
|
|
446
|
+
animationDuration: chartStyling.performanceMode
|
|
447
|
+
? ANIMATION_DURATION.NO
|
|
448
|
+
: ANIMATION_DURATION.SLOW,
|
|
449
|
+
},
|
|
450
|
+
elements: {
|
|
451
|
+
line: {
|
|
452
|
+
pointStyle: PointStyle.Circle,
|
|
453
|
+
showLine: state.lineEnabled,
|
|
459
454
|
},
|
|
460
455
|
},
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
456
|
+
scales: getLineChartScales(options, state),
|
|
457
|
+
plugins: {
|
|
458
|
+
// title: getTitle(options),
|
|
459
|
+
datalabels: getLineChartDataLabels(options),
|
|
460
|
+
annotation: getAnnotation(options, state),
|
|
461
|
+
zoom: {
|
|
462
|
+
pan: {
|
|
463
|
+
enabled: state.panEnabled,
|
|
464
|
+
mode: PanZoomMode.XY,
|
|
465
|
+
onPanComplete({ chart }) {
|
|
466
|
+
setAxisValuesInSettings(chart);
|
|
467
|
+
},
|
|
468
|
+
},
|
|
469
|
+
zoom: {
|
|
470
|
+
mode: PanZoomMode.XY,
|
|
471
|
+
drag: {
|
|
472
|
+
enabled: state.zoomEnabled,
|
|
473
|
+
threshold: 3,
|
|
474
|
+
backgroundColor: 'rgba(0,0,0,0.1)',
|
|
475
|
+
borderColor: 'rgba(0,0,0,0.2)',
|
|
476
|
+
borderWidth: 1,
|
|
477
|
+
},
|
|
478
|
+
onZoomComplete({ chart }) {
|
|
479
|
+
setAxisValuesInSettings(chart);
|
|
480
|
+
},
|
|
481
|
+
},
|
|
466
482
|
},
|
|
467
|
-
|
|
468
|
-
|
|
483
|
+
tooltip: getLineChartToolTips(options),
|
|
484
|
+
legend: getLegend(options, legendClick, state),
|
|
485
|
+
[CUSTOM_LEGEND_PLUGIN_NAME]: options.legend.customLegend
|
|
486
|
+
.customLegendPlugin && {
|
|
487
|
+
containerID:
|
|
488
|
+
options.legend.customLegend.customLegendContainerID,
|
|
469
489
|
},
|
|
470
490
|
},
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
containerID: options.legend.customLegend.customLegendContainerID,
|
|
477
|
-
},
|
|
478
|
-
},
|
|
479
|
-
}}
|
|
480
|
-
plugins={getPlugins(graph, legend, state)}
|
|
481
|
-
/>
|
|
491
|
+
}}
|
|
492
|
+
plugins={getPlugins(graph, legend, state)}
|
|
493
|
+
/>
|
|
494
|
+
</div>
|
|
495
|
+
)}
|
|
482
496
|
</div>
|
|
483
497
|
);
|
|
484
498
|
};
|
|
@@ -5,12 +5,18 @@ html[data-theme='dark'] .chart canvas {
|
|
|
5
5
|
|
|
6
6
|
.chart {
|
|
7
7
|
border: 1px solid rgba(255, 255, 255, 0);
|
|
8
|
-
padding-top: 10px;
|
|
9
8
|
position: relative;
|
|
9
|
+
display: flex;
|
|
10
|
+
flex-direction: column;
|
|
11
|
+
gap: 8px; // Spacing between each section
|
|
10
12
|
|
|
11
|
-
canvas {
|
|
12
|
-
|
|
13
|
-
height:
|
|
13
|
+
.canvas {
|
|
14
|
+
flex-grow: 1;
|
|
15
|
+
min-height: 0; // Prevents chart exceeding available space
|
|
16
|
+
canvas {
|
|
17
|
+
width: 100% !important; // Fix for resizing bug
|
|
18
|
+
height: 100% !important; // Remove if stretched when maintainAspectRatio=true
|
|
19
|
+
}
|
|
14
20
|
}
|
|
15
21
|
|
|
16
22
|
&.fixedHeight {
|
|
@@ -34,7 +40,7 @@ html[data-theme='dark'] .chart canvas {
|
|
|
34
40
|
}
|
|
35
41
|
|
|
36
42
|
&:focus {
|
|
37
|
-
border: 1px solid #85b7d9;
|
|
43
|
+
// border: 1px solid #85b7d9;
|
|
38
44
|
outline: none; // Remove dotted outline on FF
|
|
39
45
|
}
|
|
40
46
|
|
|
@@ -65,3 +71,7 @@ html[data-theme='dark'] .chart canvas {
|
|
|
65
71
|
width: auto;
|
|
66
72
|
height: auto;
|
|
67
73
|
}
|
|
74
|
+
|
|
75
|
+
.table {
|
|
76
|
+
overflow: auto;
|
|
77
|
+
}
|
|
@@ -1,4 +1,12 @@
|
|
|
1
|
-
import React from 'react';
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import {
|
|
3
|
+
Flex,
|
|
4
|
+
Menu,
|
|
5
|
+
Slider,
|
|
6
|
+
Table,
|
|
7
|
+
Text,
|
|
8
|
+
Toggle,
|
|
9
|
+
} from '@oliasoft-open-source/react-ui-library';
|
|
2
10
|
import { LineChart } from './line-chart';
|
|
3
11
|
import { getCustomLegendPlugin } from '../../helpers/get-custom-legend-plugin-example';
|
|
4
12
|
|
|
@@ -156,6 +164,7 @@ FillContainer.args = {
|
|
|
156
164
|
options: {
|
|
157
165
|
...basicChart.options,
|
|
158
166
|
chartStyling: {
|
|
167
|
+
...basicChart.options.chartStyling,
|
|
159
168
|
height: '100%',
|
|
160
169
|
},
|
|
161
170
|
},
|
|
@@ -169,6 +178,17 @@ FillContainer.decorators = [
|
|
|
169
178
|
),
|
|
170
179
|
];
|
|
171
180
|
|
|
181
|
+
export const NoTitle = Template.bind({});
|
|
182
|
+
NoTitle.args = {
|
|
183
|
+
chart: {
|
|
184
|
+
...basicChart,
|
|
185
|
+
options: {
|
|
186
|
+
...basicChart.options,
|
|
187
|
+
title: undefined,
|
|
188
|
+
},
|
|
189
|
+
},
|
|
190
|
+
};
|
|
191
|
+
|
|
172
192
|
export const DataGaps = Template.bind({});
|
|
173
193
|
DataGaps.args = {
|
|
174
194
|
chart: {
|
|
@@ -426,19 +446,6 @@ Animation.args = {
|
|
|
426
446
|
},
|
|
427
447
|
};
|
|
428
448
|
|
|
429
|
-
export const CloseControlsOnOutsideClick = Template.bind({});
|
|
430
|
-
CloseControlsOnOutsideClick.args = {
|
|
431
|
-
chart: {
|
|
432
|
-
...basicChart,
|
|
433
|
-
options: {
|
|
434
|
-
...basicChart.options,
|
|
435
|
-
chartOptions: {
|
|
436
|
-
closeOnOutsideClick: true,
|
|
437
|
-
},
|
|
438
|
-
},
|
|
439
|
-
},
|
|
440
|
-
};
|
|
441
|
-
|
|
442
449
|
export const SquareAspectRatio = Template.bind({});
|
|
443
450
|
SquareAspectRatio.args = {
|
|
444
451
|
chart: {
|
|
@@ -454,6 +461,116 @@ SquareAspectRatio.args = {
|
|
|
454
461
|
},
|
|
455
462
|
};
|
|
456
463
|
|
|
464
|
+
export const HeaderComponent = (args) => {
|
|
465
|
+
const options = ['Category A', 'Category B', 'Category C'];
|
|
466
|
+
|
|
467
|
+
const suboptions = ['Chart 1', 'Chart 2', 'Chart 3'];
|
|
468
|
+
|
|
469
|
+
const charts = options.map((option) => ({
|
|
470
|
+
label: option,
|
|
471
|
+
options: suboptions.map((suboption) => ({
|
|
472
|
+
label: suboption,
|
|
473
|
+
options: {
|
|
474
|
+
label: `${option} - ${suboption}`,
|
|
475
|
+
},
|
|
476
|
+
})),
|
|
477
|
+
}));
|
|
478
|
+
|
|
479
|
+
const [selectedChartTitle, setSelectedChartTitle] = useState(
|
|
480
|
+
`${options[0]} - ${suboptions[0]}`,
|
|
481
|
+
);
|
|
482
|
+
|
|
483
|
+
const chart = {
|
|
484
|
+
...basicChart,
|
|
485
|
+
options: { ...basicChart.options, title: selectedChartTitle },
|
|
486
|
+
};
|
|
487
|
+
|
|
488
|
+
return (
|
|
489
|
+
<LineChart
|
|
490
|
+
chart={chart}
|
|
491
|
+
headerComponent={
|
|
492
|
+
<Flex gap="10px" alignItems="center">
|
|
493
|
+
<Text bold>
|
|
494
|
+
<Menu
|
|
495
|
+
menu={{
|
|
496
|
+
label: selectedChartTitle,
|
|
497
|
+
sections: charts.map((option) => ({
|
|
498
|
+
type: 'Menu',
|
|
499
|
+
trigger: 'Text',
|
|
500
|
+
menu: {
|
|
501
|
+
label: option.label,
|
|
502
|
+
trigger: 'Text',
|
|
503
|
+
sections: option.options.map((suboption) => ({
|
|
504
|
+
label: suboption.label,
|
|
505
|
+
type: 'Option',
|
|
506
|
+
onClick: () =>
|
|
507
|
+
setSelectedChartTitle(
|
|
508
|
+
`${option.label} - ${suboption.label}`,
|
|
509
|
+
),
|
|
510
|
+
})),
|
|
511
|
+
},
|
|
512
|
+
})),
|
|
513
|
+
trigger: 'Text',
|
|
514
|
+
small: true,
|
|
515
|
+
}}
|
|
516
|
+
/>
|
|
517
|
+
</Text>
|
|
518
|
+
<Toggle label="Toggle" onChange={() => {}} noMargin />
|
|
519
|
+
</Flex>
|
|
520
|
+
}
|
|
521
|
+
/>
|
|
522
|
+
);
|
|
523
|
+
};
|
|
524
|
+
|
|
525
|
+
export const SubheaderComponent = Template.bind({});
|
|
526
|
+
SubheaderComponent.args = {
|
|
527
|
+
subheaderComponent: (
|
|
528
|
+
<Slider max={100} min={0} onChange={() => {}} showArrows value={50} />
|
|
529
|
+
),
|
|
530
|
+
};
|
|
531
|
+
|
|
532
|
+
const table = {
|
|
533
|
+
headers: [
|
|
534
|
+
{
|
|
535
|
+
cells: [
|
|
536
|
+
{ value: 'Name' },
|
|
537
|
+
{ value: 'Weight' },
|
|
538
|
+
{ value: 'Energy' },
|
|
539
|
+
{ value: 'Origin' },
|
|
540
|
+
],
|
|
541
|
+
},
|
|
542
|
+
],
|
|
543
|
+
rows: [
|
|
544
|
+
{
|
|
545
|
+
cells: [
|
|
546
|
+
{ value: 'Brown rice' },
|
|
547
|
+
{ value: 100 },
|
|
548
|
+
{ value: 361 },
|
|
549
|
+
{ value: 'Vietnam' },
|
|
550
|
+
],
|
|
551
|
+
},
|
|
552
|
+
{
|
|
553
|
+
cells: [
|
|
554
|
+
{ value: 'Buckwheat' },
|
|
555
|
+
{ value: 50 },
|
|
556
|
+
{ value: 358 },
|
|
557
|
+
{ value: 'Poland' },
|
|
558
|
+
],
|
|
559
|
+
},
|
|
560
|
+
{
|
|
561
|
+
cells: [
|
|
562
|
+
{ value: 'Couscous' },
|
|
563
|
+
{ value: 10 },
|
|
564
|
+
{ value: 368 },
|
|
565
|
+
{ value: 'France' },
|
|
566
|
+
],
|
|
567
|
+
},
|
|
568
|
+
],
|
|
569
|
+
};
|
|
570
|
+
|
|
571
|
+
export const WithTable = (args) => {
|
|
572
|
+
return <LineChart chart={basicChart} table={<Table table={table} />} />;
|
|
573
|
+
};
|
|
457
574
|
export const SquareAspectRatioFillContainer = Template.bind({});
|
|
458
575
|
SquareAspectRatioFillContainer.args = {
|
|
459
576
|
chart: {
|
|
@@ -7,3 +7,4 @@ export const UNSET_AXES_VALUES = 'UNSET_AXES_VALUES';
|
|
|
7
7
|
export const SET_AXIS_VALUE = 'SET_AXIS_VALUE';
|
|
8
8
|
export const SET_POINTS_ZOOM_DEFAULTS = 'SET_POINTS_ZOOM_DEFAULTS';
|
|
9
9
|
export const TOGGLE_ANNOTATION = 'TOGGLE_ANNOTATION';
|
|
10
|
+
export const TOGGLE_TABLE = 'TOGGLE_TABLE';
|
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
SET_AXIS_VALUE,
|
|
16
16
|
SET_POINTS_ZOOM_DEFAULTS,
|
|
17
17
|
TOGGLE_ANNOTATION,
|
|
18
|
+
TOGGLE_TABLE,
|
|
18
19
|
} from './action-types';
|
|
19
20
|
import { getAxisValue } from '../../../helpers/chart-utils';
|
|
20
21
|
|
|
@@ -64,6 +65,12 @@ export const reducer = (state, action) => {
|
|
|
64
65
|
legendEnabled: !newState.legendEnabled,
|
|
65
66
|
};
|
|
66
67
|
}
|
|
68
|
+
case TOGGLE_TABLE: {
|
|
69
|
+
return {
|
|
70
|
+
...newState,
|
|
71
|
+
showTable: !newState.showTable,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
67
74
|
case UNSET_AXES_VALUES: {
|
|
68
75
|
return {
|
|
69
76
|
...newState,
|
package/src/helpers/enums.js
CHANGED
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { FaCog } from 'react-icons/fa';
|
|
3
|
-
import { Popover, Button } from '@oliasoft-open-source/react-ui-library';
|
|
4
|
-
import { Layer } from './Layer';
|
|
5
|
-
|
|
6
|
-
export const Controls = ({
|
|
7
|
-
scalesMaxMin,
|
|
8
|
-
zoomEnabled,
|
|
9
|
-
onToggleZoom,
|
|
10
|
-
panEnabled,
|
|
11
|
-
onTogglePan,
|
|
12
|
-
legendEnabled,
|
|
13
|
-
onToggleLegend,
|
|
14
|
-
onResetAxes,
|
|
15
|
-
pointsEnabled,
|
|
16
|
-
onTogglePoints,
|
|
17
|
-
lineEnabled,
|
|
18
|
-
onToggleLine,
|
|
19
|
-
axes,
|
|
20
|
-
onSetAxisValue,
|
|
21
|
-
onDownload,
|
|
22
|
-
closeOnOutsideClick,
|
|
23
|
-
}) => {
|
|
24
|
-
return (
|
|
25
|
-
<Popover
|
|
26
|
-
placement="bottom-start"
|
|
27
|
-
closeOnOutsideClick={closeOnOutsideClick}
|
|
28
|
-
showCloseButton
|
|
29
|
-
overflowContainer
|
|
30
|
-
content={
|
|
31
|
-
<Layer
|
|
32
|
-
scalesMaxMin={scalesMaxMin}
|
|
33
|
-
zoomEnabled={zoomEnabled}
|
|
34
|
-
onToggleZoom={onToggleZoom}
|
|
35
|
-
panEnabled={panEnabled}
|
|
36
|
-
onTogglePan={onTogglePan}
|
|
37
|
-
onResetAxes={onResetAxes}
|
|
38
|
-
legendEnabled={legendEnabled}
|
|
39
|
-
onToggleLegend={onToggleLegend}
|
|
40
|
-
pointsEnabled={pointsEnabled}
|
|
41
|
-
onTogglePoints={onTogglePoints}
|
|
42
|
-
lineEnabled={lineEnabled}
|
|
43
|
-
onToggleLine={onToggleLine}
|
|
44
|
-
axes={axes}
|
|
45
|
-
onSetAxisValue={onSetAxisValue}
|
|
46
|
-
onDownload={onDownload}
|
|
47
|
-
/>
|
|
48
|
-
}
|
|
49
|
-
>
|
|
50
|
-
<Button
|
|
51
|
-
name="example"
|
|
52
|
-
colored="muted"
|
|
53
|
-
onClick={() => {}}
|
|
54
|
-
basic
|
|
55
|
-
round
|
|
56
|
-
small
|
|
57
|
-
icon={<FaCog />}
|
|
58
|
-
/>
|
|
59
|
-
</Popover>
|
|
60
|
-
);
|
|
61
|
-
};
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
.layer {
|
|
2
|
-
width: 200px;
|
|
3
|
-
}
|
|
4
|
-
.help {
|
|
5
|
-
font-size: 0.8rem;
|
|
6
|
-
color: #666;
|
|
7
|
-
|
|
8
|
-
p {
|
|
9
|
-
margin-bottom: 5px;
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
.reset {
|
|
14
|
-
display: flex;
|
|
15
|
-
align-items: center;
|
|
16
|
-
span {
|
|
17
|
-
margin-left: 5px;
|
|
18
|
-
font-size: 10px;
|
|
19
|
-
color: #666;
|
|
20
|
-
}
|
|
21
|
-
}
|
|
@@ -1,172 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
//import { useTranslation } from 'react-i18next';
|
|
3
|
-
import { HiOutlineDocumentDownload } from 'react-icons/hi';
|
|
4
|
-
import {
|
|
5
|
-
Button,
|
|
6
|
-
Toggle,
|
|
7
|
-
Spacer,
|
|
8
|
-
Field,
|
|
9
|
-
Input,
|
|
10
|
-
InputGroup,
|
|
11
|
-
InputGroupAddon,
|
|
12
|
-
Text,
|
|
13
|
-
} from '@oliasoft-open-source/react-ui-library';
|
|
14
|
-
//import translations from '~common/Internationalisation/translation-map.json';
|
|
15
|
-
//import { InputWarningType } from '~common/const/warning-messages';
|
|
16
|
-
import styles from './Controls.module.less';
|
|
17
|
-
|
|
18
|
-
export const Layer = ({
|
|
19
|
-
scalesMaxMin,
|
|
20
|
-
zoomEnabled,
|
|
21
|
-
onToggleZoom,
|
|
22
|
-
panEnabled,
|
|
23
|
-
onTogglePan,
|
|
24
|
-
onResetAxes,
|
|
25
|
-
legendEnabled,
|
|
26
|
-
onToggleLegend,
|
|
27
|
-
pointsEnabled,
|
|
28
|
-
onTogglePoints,
|
|
29
|
-
lineEnabled,
|
|
30
|
-
onToggleLine,
|
|
31
|
-
axes,
|
|
32
|
-
onSetAxisValue,
|
|
33
|
-
onDownload,
|
|
34
|
-
}) => {
|
|
35
|
-
// TODO: implement usetranslation
|
|
36
|
-
//const { t } = useTranslation();
|
|
37
|
-
return (
|
|
38
|
-
<div className={styles.layer}>
|
|
39
|
-
<Toggle
|
|
40
|
-
small
|
|
41
|
-
name="enablePoints"
|
|
42
|
-
label="Enable Points" //{t(translations.showPoints)} temporary static value before translation is implemented
|
|
43
|
-
checked={pointsEnabled}
|
|
44
|
-
onChange={onTogglePoints}
|
|
45
|
-
/>
|
|
46
|
-
<Spacer height={8} />
|
|
47
|
-
<Toggle
|
|
48
|
-
small
|
|
49
|
-
name="enableLine"
|
|
50
|
-
label="Show line"
|
|
51
|
-
checked={lineEnabled}
|
|
52
|
-
onChange={onToggleLine}
|
|
53
|
-
/>
|
|
54
|
-
<Spacer height={8} />
|
|
55
|
-
<Toggle
|
|
56
|
-
small
|
|
57
|
-
name="enableLegend"
|
|
58
|
-
label="Enable Legend" //{t(translations.showLegend)} temporary static value before translation is implemented
|
|
59
|
-
checked={legendEnabled}
|
|
60
|
-
onChange={onToggleLegend}
|
|
61
|
-
/>
|
|
62
|
-
<Spacer height={8} />
|
|
63
|
-
<Toggle
|
|
64
|
-
small
|
|
65
|
-
name="enableZoom"
|
|
66
|
-
label="Enable Zoom" //{t(translations.enableZoom)} temporary static value before translation is implemented
|
|
67
|
-
checked={zoomEnabled}
|
|
68
|
-
onChange={onToggleZoom}
|
|
69
|
-
/>
|
|
70
|
-
<Spacer height={8} />
|
|
71
|
-
<Toggle
|
|
72
|
-
small
|
|
73
|
-
name="enablePan"
|
|
74
|
-
label="Enable Pan" //{t(translations.enablePan)} temporary static value before translation is implemented
|
|
75
|
-
checked={panEnabled}
|
|
76
|
-
onChange={onTogglePan}
|
|
77
|
-
/>
|
|
78
|
-
<Spacer height={10} />
|
|
79
|
-
{(zoomEnabled || panEnabled) && (
|
|
80
|
-
<>
|
|
81
|
-
<div className={styles.help}>
|
|
82
|
-
{zoomEnabled && (
|
|
83
|
-
<p>
|
|
84
|
-
<strong>Zoom: </strong>
|
|
85
|
-
<span>click and drag</span>
|
|
86
|
-
</p>
|
|
87
|
-
)}
|
|
88
|
-
{panEnabled && (
|
|
89
|
-
<p>
|
|
90
|
-
<strong>Pan: </strong>
|
|
91
|
-
<span>click and drag</span>
|
|
92
|
-
</p>
|
|
93
|
-
)}
|
|
94
|
-
<p>
|
|
95
|
-
<strong>Change axis: </strong>
|
|
96
|
-
<span>hold shift key</span>
|
|
97
|
-
</p>
|
|
98
|
-
</div>
|
|
99
|
-
<Spacer height={10} />
|
|
100
|
-
</>
|
|
101
|
-
)}
|
|
102
|
-
{axes.map((axis, i) => {
|
|
103
|
-
return (
|
|
104
|
-
<Field key={i} label={axis.label || ''}>
|
|
105
|
-
<InputGroup small>
|
|
106
|
-
<Input
|
|
107
|
-
name="min"
|
|
108
|
-
value={axis.min.inputValue || scalesMaxMin[axis?.id]?.min}
|
|
109
|
-
error={
|
|
110
|
-
!axis.min.valid
|
|
111
|
-
? 'Invalid value' //t(InputWarningType.MustBeNumericAndLessThanMax)
|
|
112
|
-
: undefined
|
|
113
|
-
}
|
|
114
|
-
size={5}
|
|
115
|
-
width="100%"
|
|
116
|
-
onChange={(evt) =>
|
|
117
|
-
onSetAxisValue({
|
|
118
|
-
name: evt.target.name,
|
|
119
|
-
value: evt.target.value,
|
|
120
|
-
id: axis.id,
|
|
121
|
-
})
|
|
122
|
-
}
|
|
123
|
-
disabled={zoomEnabled || panEnabled}
|
|
124
|
-
/>
|
|
125
|
-
<InputGroupAddon>
|
|
126
|
-
To
|
|
127
|
-
{/*t(translations.to)*/}
|
|
128
|
-
</InputGroupAddon>
|
|
129
|
-
<Input
|
|
130
|
-
name="max"
|
|
131
|
-
value={axis.max.inputValue || scalesMaxMin[axis?.id].max}
|
|
132
|
-
error={
|
|
133
|
-
!axis.max.valid
|
|
134
|
-
? 'Invalid value' //t(InputWarningType.MustBeNumericAndGreaterThanMin)
|
|
135
|
-
: undefined
|
|
136
|
-
}
|
|
137
|
-
size={5}
|
|
138
|
-
width="100%"
|
|
139
|
-
onChange={(evt) =>
|
|
140
|
-
onSetAxisValue({
|
|
141
|
-
name: evt.target.name,
|
|
142
|
-
value: evt.target.value,
|
|
143
|
-
id: axis.id,
|
|
144
|
-
})
|
|
145
|
-
}
|
|
146
|
-
disabled={zoomEnabled || panEnabled}
|
|
147
|
-
/>
|
|
148
|
-
</InputGroup>
|
|
149
|
-
</Field>
|
|
150
|
-
);
|
|
151
|
-
})}
|
|
152
|
-
<Field>
|
|
153
|
-
<Button
|
|
154
|
-
small
|
|
155
|
-
name="resetAxes"
|
|
156
|
-
label="Reset Axes"
|
|
157
|
-
onClick={onResetAxes}
|
|
158
|
-
/>{' '}
|
|
159
|
-
<Text small muted>
|
|
160
|
-
or click on canvas
|
|
161
|
-
</Text>
|
|
162
|
-
</Field>
|
|
163
|
-
<Spacer height={8} />
|
|
164
|
-
<Button
|
|
165
|
-
label="Download PNG" //{t(translations.downloadPNG)}
|
|
166
|
-
small
|
|
167
|
-
onClick={onDownload}
|
|
168
|
-
icon={<HiOutlineDocumentDownload />}
|
|
169
|
-
/>
|
|
170
|
-
</div>
|
|
171
|
-
);
|
|
172
|
-
};
|