@oliasoft-open-source/charts-library 2.0.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.
Files changed (79) hide show
  1. package/.eslintignore +2 -0
  2. package/.eslintrc.js +129 -0
  3. package/.gitlab-ci.yml +77 -0
  4. package/.husky/pre-commit +4 -0
  5. package/.prettierignore +3 -0
  6. package/.prettierrc +4 -0
  7. package/.storybook/main.js +40 -0
  8. package/LICENSE +21 -0
  9. package/README.md +5 -0
  10. package/babel.config.js +29 -0
  11. package/index.js +9 -0
  12. package/jest.config.js +9 -0
  13. package/package.json +96 -0
  14. package/src/components/bar-chart/bar-chart-prop-types.js +181 -0
  15. package/src/components/bar-chart/bar-chart.interface.ts +83 -0
  16. package/src/components/bar-chart/bar-chart.jsx +247 -0
  17. package/src/components/bar-chart/bar-chart.module.less +56 -0
  18. package/src/components/bar-chart/basic.stories.jsx +752 -0
  19. package/src/components/bar-chart/charts.stories.jsx +119 -0
  20. package/src/components/bar-chart/get-bar-chart-data-labels.js +45 -0
  21. package/src/components/bar-chart/get-bar-chart-scales.js +147 -0
  22. package/src/components/bar-chart/get-bar-chart-tooltips.js +100 -0
  23. package/src/components/line-chart/Controls/Controls.jsx +59 -0
  24. package/src/components/line-chart/Controls/Controls.module.less +21 -0
  25. package/src/components/line-chart/Controls/Layer.jsx +169 -0
  26. package/src/components/line-chart/basic.stories.jsx +735 -0
  27. package/src/components/line-chart/charts.stories.jsx +264 -0
  28. package/src/components/line-chart/get-line-chart-data-labels.js +24 -0
  29. package/src/components/line-chart/get-line-chart-scales.js +131 -0
  30. package/src/components/line-chart/get-line-chart-tooltips.js +91 -0
  31. package/src/components/line-chart/line-chart-consts.js +6 -0
  32. package/src/components/line-chart/line-chart-prop-types.js +187 -0
  33. package/src/components/line-chart/line-chart-utils.js +163 -0
  34. package/src/components/line-chart/line-chart.interface.ts +103 -0
  35. package/src/components/line-chart/line-chart.jsx +423 -0
  36. package/src/components/line-chart/line-chart.minor-gridlines-plugin.js +78 -0
  37. package/src/components/line-chart/line-chart.minor-gridlines-plugin.test.js +34 -0
  38. package/src/components/line-chart/line-chart.module.less +56 -0
  39. package/src/components/line-chart/state/action-types.js +9 -0
  40. package/src/components/line-chart/state/initial-state.js +51 -0
  41. package/src/components/line-chart/state/line-chart-reducer.js +115 -0
  42. package/src/components/line-chart/stories/shapes/cubes.stories.jsx +326 -0
  43. package/src/components/line-chart/stories/shapes/pyramid.stories.jsx +189 -0
  44. package/src/components/line-chart/stories/shapes/round.stories.jsx +339 -0
  45. package/src/components/line-chart/stories/shapes/triangle.stories.jsx +166 -0
  46. package/src/components/pie-chart/basic.stories.jsx +390 -0
  47. package/src/components/pie-chart/charts.stories.jsx +66 -0
  48. package/src/components/pie-chart/pie-chart-prop-types.js +111 -0
  49. package/src/components/pie-chart/pie-chart-utils.js +55 -0
  50. package/src/components/pie-chart/pie-chart.interface.ts +61 -0
  51. package/src/components/pie-chart/pie-chart.jsx +477 -0
  52. package/src/components/pie-chart/pie-chart.module.less +56 -0
  53. package/src/components/scatter-chart/scatter-chart.intefrace.ts +32 -0
  54. package/src/components/scatter-chart/scatter-chart.jsx +13 -0
  55. package/src/components/scatter-chart/scatter.stories.jsx +196 -0
  56. package/src/helpers/chart-consts.js +82 -0
  57. package/src/helpers/chart-interface.ts +54 -0
  58. package/src/helpers/chart-utils.js +178 -0
  59. package/src/helpers/container.jsx +60 -0
  60. package/src/helpers/disabled-context.js +8 -0
  61. package/src/helpers/enums.js +84 -0
  62. package/src/helpers/get-chart-annotation.js +91 -0
  63. package/src/helpers/styles.js +68 -0
  64. package/src/helpers/text.js +6 -0
  65. package/src/style/external.less +4 -0
  66. package/src/style/fonts/lato/Lato-Bold.woff2 +0 -0
  67. package/src/style/fonts/lato/Lato-BoldItalic.woff2 +0 -0
  68. package/src/style/fonts/lato/Lato-Italic.woff2 +0 -0
  69. package/src/style/fonts/lato/Lato-Regular.woff2 +0 -0
  70. package/src/style/fonts.less +27 -0
  71. package/src/style/global.less +43 -0
  72. package/src/style/reset/reset.less +28 -0
  73. package/src/style/shared.less +24 -0
  74. package/src/style/variables.less +91 -0
  75. package/webpack/webpack.common.js +39 -0
  76. package/webpack/webpack.common.rules.js +107 -0
  77. package/webpack/webpack.dev.js +22 -0
  78. package/webpack/webpack.prod.js +23 -0
  79. package/webpack/webpack.resolve.js +22 -0
@@ -0,0 +1,264 @@
1
+ import React from 'react';
2
+ import { LineChart } from './line-chart';
3
+ import { Container } from '../../helpers/container';
4
+
5
+ const style = {
6
+ height: '1000px',
7
+ width: '1000px',
8
+ };
9
+
10
+ const dataset1 = {
11
+ label: 'Curve 1',
12
+ lineTension: 0,
13
+ borderColor: '#a30125',
14
+ pointBackgroundColor: '#a30125',
15
+ pointRadius: 2,
16
+ pointHoverRadius: 5,
17
+ pointHitRadius: 20,
18
+ borderWidth: 2,
19
+ fill: false,
20
+ yAxisID: 'y1',
21
+ data: [
22
+ {
23
+ x: 0,
24
+ y: 0,
25
+ },
26
+ {
27
+ x: 5,
28
+ y: 25,
29
+ },
30
+ {
31
+ x: 10,
32
+ y: 60,
33
+ },
34
+ {
35
+ x: 15,
36
+ y: 90,
37
+ },
38
+ {
39
+ x: 20,
40
+ y: 120,
41
+ },
42
+ {
43
+ x: 25,
44
+ y: 150,
45
+ },
46
+ ],
47
+ };
48
+
49
+ const dataset2 = {
50
+ label: 'Curve 2',
51
+ lineTension: 0,
52
+ borderColor: '#a30125',
53
+ pointBackgroundColor: '#a30125',
54
+ pointRadius: 2,
55
+ pointHoverRadius: 5,
56
+ pointHitRadius: 20,
57
+ borderWidth: 2,
58
+ fill: false,
59
+ yAxisID: 'y1',
60
+ data: [
61
+ {
62
+ x: 0,
63
+ y: 0,
64
+ },
65
+ {
66
+ x: 3,
67
+ y: 15,
68
+ },
69
+ {
70
+ x: 6,
71
+ y: 30,
72
+ },
73
+ {
74
+ x: 9,
75
+ y: 60,
76
+ },
77
+ {
78
+ x: 12,
79
+ y: 120,
80
+ },
81
+ {
82
+ x: 15,
83
+ y: 240,
84
+ },
85
+ ],
86
+ };
87
+
88
+ const dataset3 = {
89
+ label: 'Curve 3',
90
+ lineTension: 0,
91
+ borderColor: '#011fa3',
92
+ pointBackgroundColor: '#011fa3',
93
+ pointRadius: 2,
94
+ pointHoverRadius: 5,
95
+ pointHitRadius: 20,
96
+ borderWidth: 2,
97
+ fill: false,
98
+ yAxisID: 'y2',
99
+ data: [
100
+ {
101
+ x: 0,
102
+ y: 0,
103
+ },
104
+ {
105
+ x: 7,
106
+ y: 25,
107
+ },
108
+ {
109
+ x: 14,
110
+ y: 12,
111
+ },
112
+ {
113
+ x: 21,
114
+ y: 50,
115
+ },
116
+ {
117
+ x: 28,
118
+ y: 25,
119
+ },
120
+ {
121
+ x: 30,
122
+ y: 100,
123
+ },
124
+ ],
125
+ };
126
+
127
+ const formation = {
128
+ label: 'Formation',
129
+ formation: true,
130
+ lineTension: 0,
131
+ borderColor: '#987654',
132
+ pointBackgroundColor: '#987654',
133
+ pointRadius: 2,
134
+ pointHoverRadius: 5,
135
+ pointHitRadius: 20,
136
+ borderWidth: 2,
137
+ borderDash: [10, 5],
138
+ fill: false,
139
+ yAxisID: 'y2',
140
+ hideLegend: true,
141
+ data: [
142
+ {
143
+ x: 0,
144
+ y: 66,
145
+ },
146
+ {
147
+ x: 35.0 / 2,
148
+ y: 66,
149
+ label: 'formation label',
150
+ },
151
+ {
152
+ x: 35,
153
+ y: 66,
154
+ },
155
+ ],
156
+ };
157
+
158
+ const testChartData = {
159
+ datasets: [dataset1, dataset2, dataset3, formation],
160
+ };
161
+
162
+ const kitchenSinkLineChart = {
163
+ data: testChartData,
164
+ options: {
165
+ title: 'Look at this graph!',
166
+ axes: {
167
+ x: [
168
+ {
169
+ label: 'The X',
170
+ },
171
+ ],
172
+ y: [
173
+ {
174
+ label: 'The Y',
175
+ position: 'right',
176
+ color: '#a30125',
177
+ },
178
+ {
179
+ label: 'The Y 2',
180
+ position: 'left',
181
+ color: '#011fa3',
182
+ gridLines: {
183
+ drawOnChartArea: false,
184
+ },
185
+ },
186
+ ],
187
+ },
188
+ additionalAxesOptions: {
189
+ chartScaleType: 'linear',
190
+ reverse: false,
191
+ beginAtZero: false,
192
+ stepSize: 50,
193
+ truncateAxisNumbersToDigitsCallback: 0,
194
+ suggestedMin: 0,
195
+ suggestedMax: 35,
196
+ // range: {
197
+ // x: {
198
+ // min: 0,
199
+ // max: 100,
200
+ // },
201
+ // y: {
202
+ // min: 0,
203
+ // max: 100,
204
+ // },
205
+ // },
206
+ },
207
+ chartStyling: {
208
+ width: 800,
209
+ height: 800,
210
+ maintainAspectRatio: false,
211
+ staticChartHeight: false,
212
+ performanceMode: true,
213
+ },
214
+ tooltip: {
215
+ tooltips: true,
216
+ showLabelsInTooltips: false,
217
+ hideSimulationName: false,
218
+ },
219
+ graph: {
220
+ lineTension: 0,
221
+ spanGaps: false,
222
+ showDataLabels: true,
223
+ showMinorGridlines: true,
224
+ },
225
+ annotations: {
226
+ showAnnotations: true,
227
+ controlAnnotation: true,
228
+ annotationsData: [
229
+ {
230
+ annotationAxis: 'y',
231
+ label: 'cool annotation',
232
+ value: 40,
233
+ color: 'rgba(128, 32, 196, 0.5)',
234
+ },
235
+ ],
236
+ },
237
+ legend: {
238
+ display: true,
239
+ position: 'bottom',
240
+ align: 'center',
241
+ },
242
+ chartOptions: {
243
+ showPoints: true,
244
+ enableZoom: false,
245
+ enablePan: false,
246
+ },
247
+ interactions: {
248
+ onLegendClick: null,
249
+ onPointHover: null,
250
+ onPointUnhover: null,
251
+ },
252
+ },
253
+ };
254
+
255
+ export const LineChartKitchenSink = () => (
256
+ <Container style={style}>
257
+ <LineChart chart={kitchenSinkLineChart} />
258
+ </Container>
259
+ );
260
+
261
+ export default {
262
+ title: 'Line Chart Kitchen Sink',
263
+ component: LineChartKitchenSink,
264
+ };
@@ -0,0 +1,24 @@
1
+ import { AUTO, DEFAULT_DARK_MODE_COLOR } from '../../helpers/chart-consts';
2
+ import { AlignOptions, PointType } from '../../helpers/enums';
3
+
4
+ /**
5
+ * @param {import('./line-chart.interface').ILineChartOptions} options - line chart options object
6
+ */
7
+ const getLineChartDataLabels = (options) => {
8
+ return options.graph.showDataLabels
9
+ ? {
10
+ display: AUTO,
11
+ align: (context) =>
12
+ context.dataset.pointType === PointType.Casing
13
+ ? AlignOptions.Start
14
+ : AlignOptions.End,
15
+ formatter: (value, context) =>
16
+ context.dataset.data[context.dataIndex].label || '',
17
+ color: options.chartStyling.darkMode
18
+ ? DEFAULT_DARK_MODE_COLOR
19
+ : undefined,
20
+ }
21
+ : { display: false };
22
+ };
23
+
24
+ export default getLineChartDataLabels;
@@ -0,0 +1,131 @@
1
+ import {
2
+ generateRandomColor,
3
+ getAxisPosition,
4
+ } from '../../helpers/chart-utils';
5
+ import {
6
+ COLORS,
7
+ DARK_MODE_COLORS,
8
+ DEFAULT_COLOR,
9
+ DEFAULT_DARK_MODE_BORDER_COLOR,
10
+ DEFAULT_DARK_MODE_COLOR,
11
+ LOGARITHMIC_STEPS,
12
+ } from '../../helpers/chart-consts';
13
+ import { truncateDecimals } from './line-chart-utils';
14
+ import { AxisType, ScaleType } from '../../helpers/enums';
15
+
16
+ /**
17
+ * @param {import('./line-chart.interface').ILineChartOptions} options - line chart options object
18
+ * @param {'x'|'y'} axisType
19
+ * @param {import('../../helpers/chart-interface').IInitialState} state - chart state object controlled by useReducer or similar
20
+ * @param {import('./line-chart.interface').ILineChartAxes[]} [currentScales]
21
+ * @param {number} [i]
22
+ */
23
+ const getLineChartAxis = (options, axisType, state, currentScales, i = 0) => {
24
+ const axisData = currentScales || options.axes[axisType][0];
25
+ const stateAxis = state.axes.filter((axis) => axis.id.startsWith(axisType))[
26
+ i
27
+ ];
28
+
29
+ const { additionalAxesOptions, chartStyling } = options;
30
+
31
+ const getTicks = () => {
32
+ const truncateAxisNumbersToDigitsCallback = Number.isInteger(
33
+ additionalAxesOptions.truncateAxisNumbersToDigitsCallback,
34
+ )
35
+ ? {
36
+ callback: (tick) =>
37
+ truncateDecimals(
38
+ tick,
39
+ additionalAxesOptions.truncateAxisNumbersToDigitsCallback,
40
+ ),
41
+ }
42
+ : {};
43
+
44
+ return additionalAxesOptions.chartScaleType === ScaleType.Logarithmic
45
+ ? {
46
+ callback: (tick) => {
47
+ return LOGARITHMIC_STEPS.includes(tick)
48
+ ? tick.toLocaleString()
49
+ : '';
50
+ },
51
+ }
52
+ : {
53
+ color:
54
+ axisData.color ||
55
+ (chartStyling.darkMode ? DEFAULT_DARK_MODE_COLOR : DEFAULT_COLOR),
56
+ stepSize:
57
+ axisData.stepSize ||
58
+ (axisType === AxisType.Y ? additionalAxesOptions.stepSize : null),
59
+ ...truncateAxisNumbersToDigitsCallback,
60
+ };
61
+ };
62
+
63
+ return {
64
+ type: additionalAxesOptions.chartScaleType,
65
+ position: axisData.position,
66
+ beginAtZero: additionalAxesOptions.beginAtZero,
67
+ reverse: axisType === AxisType.Y ? additionalAxesOptions.reverse : false,
68
+ suggestedMax: additionalAxesOptions.suggestedMax,
69
+ suggestedMin: additionalAxesOptions.suggestedMin,
70
+ min: stateAxis.min?.value || additionalAxesOptions?.range?.[axisType]?.min,
71
+ max: stateAxis.max?.value || additionalAxesOptions?.range?.[axisType]?.max,
72
+ title: {
73
+ display: axisData.label?.length,
74
+ text: axisData.label,
75
+ padding: 0,
76
+ color: chartStyling.darkMode ? DEFAULT_DARK_MODE_BORDER_COLOR : undefined,
77
+ },
78
+ ticks: getTicks(),
79
+ grid: {
80
+ color: chartStyling.darkMode ? DEFAULT_DARK_MODE_BORDER_COLOR : undefined,
81
+ borderColor: chartStyling.darkMode
82
+ ? DEFAULT_DARK_MODE_BORDER_COLOR
83
+ : undefined,
84
+ ...axisData.gridLines,
85
+ },
86
+ };
87
+ };
88
+
89
+ /**
90
+ * @param {import('./line-chart.interface').ILineChartOptions} options - line chart options object
91
+ * @param {'x'|'y'} axisType
92
+ * @param {import('../../helpers/chart-interface').IInitialState} state - chart state object controlled by useReducer or similar
93
+ */
94
+ const getLineChartAxes = (options, axisType, state) => {
95
+ const axesData = options.axes[axisType];
96
+ const axes = axesData.reduce((acc, curr, i) => {
97
+ const axisData = curr;
98
+ axisData.color =
99
+ curr.color ||
100
+ (options.chartStyling.darkMode ? DARK_MODE_COLORS[i] : COLORS[i]) ||
101
+ generateRandomColor(COLORS);
102
+ axisData.position = curr.position || getAxisPosition(axisType, i);
103
+
104
+ const axis = getLineChartAxis(options, axisType, state, axisData, i);
105
+ return { ...acc, [axisType + (i + 1)]: axis };
106
+ }, {});
107
+ return axes;
108
+ };
109
+
110
+ /**
111
+ *
112
+ * @param {import('./line-chart.interface').ILineChartOptions} options - line chart options object
113
+ * @param {import('../../helpers/chart-interface').IInitialState} state - chart state object controlled by useReducer or similar
114
+ */
115
+ const getLineChartScales = (options, state) => {
116
+ const hasMultipleXAxes = options.axes.x?.length > 1;
117
+ const hasMultipleYAxes = options.axes.y?.length > 1;
118
+
119
+ const xAxes = hasMultipleXAxes
120
+ ? getLineChartAxes(options, AxisType.X, state)
121
+ : { x: getLineChartAxis(options, AxisType.X, state) };
122
+ const yAxes = hasMultipleYAxes
123
+ ? getLineChartAxes(options, AxisType.Y, state)
124
+ : { y: getLineChartAxis(options, AxisType.Y, state) };
125
+ return {
126
+ ...xAxes,
127
+ ...yAxes,
128
+ };
129
+ };
130
+
131
+ export default getLineChartScales;
@@ -0,0 +1,91 @@
1
+ import { ChartHoverMode, Position, TooltipLabel } from '../../helpers/enums';
2
+ import { afterLabelCallback, getTooltipLabel } from '../../helpers/chart-utils';
3
+
4
+ /**
5
+ * @param {import('./line-chart.interface').ILineChartOptions} options - line chart options object
6
+ */
7
+ const getLineChartToolTips = (options) => {
8
+ const getTooltipLabels = (dataset) => {
9
+ const xIndex = dataset.xAxisID?.length > 1 ? dataset.xAxisID[1] - 1 : 0;
10
+ const yIndex = dataset.yAxisID?.length > 1 ? dataset.yAxisID[1] - 1 : 0;
11
+ const xAxis = options.axes.x[xIndex];
12
+ const yAxis = options.axes.y[yIndex];
13
+
14
+ if (options.axes.x[0].position === Position.Top) {
15
+ return {
16
+ titleAxisLabel: yAxis?.label || '',
17
+ valueAxisLabel: xAxis?.label || '',
18
+ titleLabel: TooltipLabel.Y,
19
+ valueLabel: TooltipLabel.X,
20
+ };
21
+ } else {
22
+ return {
23
+ titleAxisLabel: xAxis?.label || '',
24
+ valueAxisLabel: yAxis?.label || '',
25
+ titleLabel: TooltipLabel.X,
26
+ valueLabel: TooltipLabel.Y,
27
+ };
28
+ }
29
+ };
30
+
31
+ const titleCallback = (tooltipItem, data) => {
32
+ const labels = getTooltipLabels(tooltipItem[0].dataset);
33
+ const { titleLabel, titleAxisLabel } = labels;
34
+
35
+ const formattedValue =
36
+ titleLabel === TooltipLabel.Y
37
+ ? tooltipItem[0].parsed.y
38
+ : tooltipItem[0].parsed.x;
39
+ const roundedValue =
40
+ Math.abs(formattedValue) < 1
41
+ ? formattedValue.toPrecision(3)
42
+ : formattedValue.toFixed(2);
43
+
44
+ return `${roundedValue} ${titleAxisLabel}`;
45
+ };
46
+
47
+ const labelCallback = (tooltipItem) => {
48
+ const { showLabelsInTooltips, hideSimulationName } = options.tooltip;
49
+ let label = tooltipItem.dataset.label || '';
50
+ const labels = getTooltipLabels(tooltipItem.dataset);
51
+ const { valueLabel, valueAxisLabel } = labels;
52
+
53
+ const getTooltipItemValue = () => {
54
+ const labelNumber =
55
+ valueLabel === TooltipLabel.X
56
+ ? tooltipItem.parsed.x
57
+ : tooltipItem.parsed.y;
58
+ return Math.abs(labelNumber) < 1
59
+ ? labelNumber.toPrecision(3)
60
+ : labelNumber.toFixed(3);
61
+ };
62
+
63
+ const splitValueAxisLabel = valueAxisLabel.split(' ');
64
+ const newValueAxisLabel = hideSimulationName
65
+ ? splitValueAxisLabel[splitValueAxisLabel.length - 1]
66
+ : valueAxisLabel;
67
+
68
+ const tooltipItemValue = getTooltipItemValue();
69
+ const valAxisLabel =
70
+ label === valueAxisLabel || valueAxisLabel.includes(label)
71
+ ? ''
72
+ : newValueAxisLabel;
73
+ const tooltipLabel = getTooltipLabel(tooltipItem, showLabelsInTooltips);
74
+
75
+ return `${label}: ${tooltipItemValue} ${valAxisLabel}${tooltipLabel}`;
76
+ };
77
+
78
+ return {
79
+ enabled: options.tooltip.tooltips,
80
+ mode: ChartHoverMode.Nearest,
81
+ intersect: true,
82
+ padding: 8,
83
+ callbacks: {
84
+ title: titleCallback,
85
+ label: labelCallback,
86
+ afterLabel: afterLabelCallback,
87
+ },
88
+ };
89
+ };
90
+
91
+ export default getLineChartToolTips;
@@ -0,0 +1,6 @@
1
+ export const DEFAULT_POINT_RADIUS = 2;
2
+ export const DEFAULT_HOVER_RADIUS = 5;
3
+ export const DEFAULT_BORDER_WIDTH = 1;
4
+ export const BORDER_JOIN_STYLE = 'round';
5
+ export const DEFAULT_LINE_POINT_RADIUS = 0;
6
+ export const DEFAULT_BACKGROUND_COLOR = 'transparent';
@@ -0,0 +1,187 @@
1
+ import PropTypes from 'prop-types';
2
+
3
+ export const LineChartPropTypes = {
4
+ chart: PropTypes.shape({
5
+ data: PropTypes.object.isRequired,
6
+ options: PropTypes.shape({
7
+ title: PropTypes.oneOfType([
8
+ PropTypes.string,
9
+ PropTypes.arrayOf(PropTypes.string),
10
+ ]),
11
+ axes: PropTypes.shape({
12
+ x: PropTypes.arrayOf(
13
+ PropTypes.shape({
14
+ label: PropTypes.string,
15
+ position: PropTypes.oneOf(['top', 'bottom']),
16
+ color: PropTypes.string,
17
+ }),
18
+ ),
19
+ y: PropTypes.arrayOf(
20
+ PropTypes.shape({
21
+ label: PropTypes.string,
22
+ position: PropTypes.oneOf(['left', 'right']),
23
+ color: PropTypes.string,
24
+ }),
25
+ ),
26
+ }),
27
+ additionalAxesOptions: PropTypes.shape({
28
+ chartScaleType: PropTypes.oneOf(['linear', 'logarithmic']),
29
+ reverse: PropTypes.bool,
30
+ beginAtZero: PropTypes.bool,
31
+ stepSize: PropTypes.number,
32
+ truncateAxisNumbersToDigitsCallback: PropTypes.number,
33
+ suggestedMin: PropTypes.number,
34
+ suggestedMax: PropTypes.number,
35
+ range: PropTypes.shape({
36
+ x: PropTypes.shape({
37
+ min: PropTypes.number,
38
+ max: PropTypes.number,
39
+ }),
40
+ y: PropTypes.shape({
41
+ min: PropTypes.number,
42
+ max: PropTypes.number,
43
+ }),
44
+ }),
45
+ }),
46
+ chartStyling: PropTypes.shape({
47
+ width: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
48
+ height: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
49
+ maintainAspectRatio: PropTypes.bool,
50
+ staticChartHeight: PropTypes.bool,
51
+ performanceMode: PropTypes.bool,
52
+ darkMode: PropTypes.bool,
53
+ }),
54
+ tooltip: PropTypes.shape({
55
+ tooltips: PropTypes.bool,
56
+ showLabelsInTooltips: PropTypes.bool,
57
+ hideSimulationName: PropTypes.bool,
58
+ }),
59
+ graph: PropTypes.shape({
60
+ lineTension: PropTypes.number,
61
+ spanGaps: PropTypes.bool,
62
+ showDataLabels: PropTypes.bool,
63
+ showMinorGridlines: PropTypes.bool,
64
+ }),
65
+ annotations: PropTypes.shape({
66
+ showAnnotations: PropTypes.bool,
67
+ controlAnnotation: PropTypes.bool,
68
+ annotationsData: PropTypes.arrayOf(
69
+ PropTypes.shape({
70
+ annotationAxis: PropTypes.oneOf(['x', 'y']),
71
+ label: PropTypes.string,
72
+ color: PropTypes.string,
73
+ value: PropTypes.number,
74
+ endValue: PropTypes.number,
75
+ }),
76
+ ),
77
+ }),
78
+ legend: PropTypes.shape({
79
+ display: PropTypes.bool,
80
+ position: PropTypes.oneOf(['top', 'bottom', 'right']),
81
+ align: PropTypes.oneOf(['start', 'center', 'end']),
82
+ }),
83
+ chartOptions: PropTypes.shape({
84
+ showPoints: PropTypes.bool,
85
+ enableZoom: PropTypes.bool,
86
+ enablePan: PropTypes.bool,
87
+ closeOnOutsideClick: PropTypes.bool,
88
+ }),
89
+ interactions: PropTypes.shape({
90
+ onLegendClick: PropTypes.func,
91
+ onPointHover: PropTypes.func,
92
+ onPointUnhover: PropTypes.func,
93
+ }),
94
+ }),
95
+ }).isRequired,
96
+ };
97
+
98
+ export const getDefaultProps = (props) => {
99
+ // Add missing nested objects
100
+ props.chart.options = props.chart.options || {};
101
+ props.chart.options.axes = props.chart.options.axes || {};
102
+ props.chart.options.additionalAxesOptions =
103
+ props.chart.options.additionalAxesOptions || {};
104
+ props.chart.options.chartStyling = props.chart.options.chartStyling || {};
105
+ props.chart.options.tooltip = props.chart.options.tooltip || {};
106
+ props.chart.options.graph = props.chart.options.graph || {};
107
+ props.chart.options.annotations = props.chart.options.annotations || {};
108
+ props.chart.options.legend = props.chart.options.legend || {};
109
+ props.chart.options.chartOptions = props.chart.options.chartOptions || {};
110
+ props.chart.options.interactions = props.chart.options.interactions || {};
111
+ // Set defaults for missing properties
112
+ const chart = {
113
+ data: props.chart.data,
114
+ options: {
115
+ title: props.chart.options.title || '',
116
+ axes: {
117
+ x: props.chart.options.axes.x || [{}],
118
+ y: props.chart.options.axes.y || [{}],
119
+ },
120
+ additionalAxesOptions: {
121
+ chartScaleType:
122
+ props.chart.options.additionalAxesOptions.chartScaleType || 'linear',
123
+ reverse: props.chart.options.additionalAxesOptions.reverse || false,
124
+ beginAtZero:
125
+ props.chart.options.additionalAxesOptions.beginAtZero || false,
126
+ stepSize: props.chart.options.additionalAxesOptions.stepSize,
127
+ truncateAxisNumbersToDigitsCallback:
128
+ props.chart.options.additionalAxesOptions
129
+ .truncateAxisNumbersToDigitsCallback,
130
+ suggestedMin: props.chart.options.additionalAxesOptions.suggestedMin,
131
+ suggestedMax: props.chart.options.additionalAxesOptions.suggestedMax,
132
+ range: props.chart.options.additionalAxesOptions.range,
133
+ },
134
+ chartStyling: {
135
+ width: props.chart.options.chartStyling.width,
136
+ height: props.chart.options.chartStyling.height,
137
+ maintainAspectRatio:
138
+ props.chart.options.chartStyling.maintainAspectRatio || false,
139
+ staticChartHeight:
140
+ props.chart.options.chartStyling.staticChartHeight || false,
141
+ performanceMode:
142
+ props.chart.options.chartStyling.performanceMode ?? true,
143
+ darkMode: props.chart.options.chartStyling.darkMode || false,
144
+ },
145
+ tooltip: {
146
+ tooltips: props.chart.options.tooltip.tooltips ?? true,
147
+ showLabelsInTooltips:
148
+ props.chart.options.tooltip.showLabelsInTooltips || false,
149
+ hideSimulationName:
150
+ props.chart.options.tooltip.hideSimulationName || false,
151
+ },
152
+ graph: {
153
+ lineTension: props.chart.options.graph.lineTension || 0.1,
154
+ spanGaps: props.chart.options.graph.spanGaps || false,
155
+ showDataLabels: props.chart.options.graph.showDataLabels || false,
156
+ showMinorGridlines:
157
+ props.chart.options.graph.showMinorGridlines || false,
158
+ },
159
+ annotations: {
160
+ showAnnotations:
161
+ props.chart.options.annotations.showAnnotations ?? false,
162
+ controlAnnotation:
163
+ props.chart.options.annotations.controlAnnotation || false,
164
+ annotationsData: props.chart.options.annotations.annotationsData || [],
165
+ },
166
+ legend: {
167
+ display: props.chart.options.legend.display ?? true,
168
+ position: props.chart.options.legend.position || 'bottom',
169
+ align: props.chart.options.legend.align || 'center',
170
+ },
171
+ chartOptions: {
172
+ showPoints: props.chart.options.chartOptions.showPoints ?? true,
173
+ enableZoom: props.chart.options.chartOptions.enableZoom || false,
174
+ enablePan: props.chart.options.chartOptions.enablePan || false,
175
+ showLine: props.chart.options.chartOptions.showLine ?? true,
176
+ closeOnOutsideClick:
177
+ props.chart.options.chartOptions.closeOnOutsideClick || false,
178
+ },
179
+ interactions: {
180
+ onLegendClick: props.chart.options.interactions.onLegendClick,
181
+ onPointHover: props.chart.options.interactions.onPointHover,
182
+ onPointUnhover: props.chart.options.interactions.onPointUnhover,
183
+ },
184
+ },
185
+ };
186
+ return chart;
187
+ };