@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,83 @@
1
+ import {IChartAnnotations, IChartInteractions, IChartLegend, IChartStyling} from "../../helpers/chart-interface";
2
+
3
+ export interface IChartOptions {
4
+ enableZoom: boolean;
5
+ enablePan: boolean;
6
+ }
7
+
8
+ export interface IBarChartGraph {
9
+ showDataLabels: boolean;
10
+ showMinorGridlines: boolean;
11
+ }
12
+
13
+ export interface IBarChartTooltip {
14
+ tooltips: boolean;
15
+ showLabelsInTooltips: boolean;
16
+ }
17
+
18
+ export interface IBarChartAdditionalAxesOptions {
19
+ chartScaleType: 'linear' | 'logarithmic';
20
+ reverse: boolean;
21
+ beginAtZero: boolean;
22
+ stepSize: number;
23
+ stacked: boolean;
24
+ suggestedMin: number;
25
+ suggestedMax:number;
26
+ min: number;
27
+ max: number;
28
+ }
29
+
30
+ export interface IBarChartAxes<PositionType> {
31
+ label: string;
32
+ position: PositionType;
33
+ color: string;
34
+ unit: string;
35
+ }
36
+
37
+ export interface IBarChartOptions {
38
+ title: string | string[];
39
+ direction: 'vertical' | 'horizontal';
40
+ axes: {
41
+ x: IBarChartAxes<'top' | 'bottom'>[];
42
+ y: IBarChartAxes<'left' | 'right'>[];
43
+ };
44
+ additionalAxesOptions: IBarChartAdditionalAxesOptions;
45
+ chartStyling: IChartStyling;
46
+ tooltip: IBarChartTooltip;
47
+ graph: IBarChartGraph;
48
+ annotations: IChartAnnotations;
49
+ legend: IChartLegend;
50
+ chartOptions: IChartOptions;
51
+ interactions: IChartInteractions;
52
+ }
53
+
54
+ export interface IBarDataPoint {
55
+ x: number;
56
+ y: number;
57
+ label?: string;
58
+ }
59
+
60
+ export interface IBarChartDataset {
61
+ label?: string;
62
+ data: number[] | number[][] | IBarDataPoint[];
63
+ borderSkipped?: string;
64
+ backgroundColor?: string[];
65
+ borderColor?: string[];
66
+ borderRadius?: number;
67
+ borderWidth?: number;
68
+ yAxisID?: string;
69
+ stack?: number;
70
+ }
71
+
72
+ export interface IBarChartData {
73
+ //TODO: revisit data interface definition after project is more stable
74
+ data: {
75
+ labels?: string[],
76
+ datasets: IBarChartDataset[]
77
+ } | any;
78
+ options: IBarChartOptions;
79
+ }
80
+
81
+ export interface IBarChartProps {
82
+ chart: IBarChartData;
83
+ }
@@ -0,0 +1,247 @@
1
+ import React, { useRef, useState } from 'react';
2
+ import {
3
+ BarElement,
4
+ CategoryScale,
5
+ Chart as ChartJS,
6
+ defaults,
7
+ Filler,
8
+ Legend,
9
+ LinearScale,
10
+ LogarithmicScale,
11
+ Title,
12
+ Tooltip,
13
+ } from 'chart.js';
14
+ import { Bar } from 'react-chartjs-2';
15
+ import zoomPlugin from 'chartjs-plugin-zoom';
16
+ import dataLabelsPlugin from 'chartjs-plugin-datalabels';
17
+ import annotationPlugin from 'chartjs-plugin-annotation';
18
+
19
+ import styles from './bar-chart.module.less';
20
+ import { BarChartPropTypes, getDefaultProps } from './bar-chart-prop-types';
21
+ import getBarChartScales from './get-bar-chart-scales';
22
+ import getBarChartToolTips from './get-bar-chart-tooltips';
23
+ import getBarChartDataLabels from './get-bar-chart-data-labels';
24
+ import getAnnotation from '../../helpers/get-chart-annotation';
25
+ import {
26
+ getTitle,
27
+ isVertical,
28
+ setAnnotations,
29
+ generateRandomColor,
30
+ getClassName,
31
+ getPlugins,
32
+ getLegend,
33
+ } from '../../helpers/chart-utils';
34
+ import {
35
+ ALPHA_CHANEL,
36
+ ANIMATION_DURATION,
37
+ AUTO,
38
+ COLORS,
39
+ DARK_MODE_COLORS,
40
+ DEFAULT_COLOR,
41
+ DEFAULT_DARK_MODE_BORDER_COLOR,
42
+ DEFAULT_DARK_MODE_COLOR,
43
+ DEFAULT_FONT_FAMILY,
44
+ DEFAULT_FONT_SIZE,
45
+ } from '../../helpers/chart-consts';
46
+ import {
47
+ AxisType,
48
+ ChartHoverMode,
49
+ ChartType,
50
+ PointStyle,
51
+ } from '../../helpers/enums';
52
+
53
+ ChartJS.register(
54
+ LinearScale,
55
+ CategoryScale,
56
+ LogarithmicScale,
57
+ BarElement,
58
+ Legend,
59
+ Tooltip,
60
+ Title,
61
+ Filler,
62
+ zoomPlugin,
63
+ dataLabelsPlugin,
64
+ annotationPlugin,
65
+ );
66
+
67
+ defaults.font.size = DEFAULT_FONT_SIZE;
68
+ defaults.color = DEFAULT_COLOR;
69
+ defaults.font.family = DEFAULT_FONT_FAMILY;
70
+ defaults.darkModeColor = DEFAULT_DARK_MODE_COLOR;
71
+ defaults.darkModeBorderColor = DEFAULT_DARK_MODE_BORDER_COLOR;
72
+
73
+ /**
74
+ * this is a bar chart component
75
+ * @param {import('./bar-chart.interface').IBarChartProps} props
76
+ */
77
+ const BarChart = (props) => {
78
+ const chartRef = useRef(null);
79
+ const [pointHover, setPointHover] = useState(false);
80
+ const chart = getDefaultProps(props);
81
+ const { options } = chart;
82
+ const { annotations, chartStyling, interactions, graph } = chart.options;
83
+
84
+ const [visibleAnnotationsIndices, setVisibleAnnotationsIndices] = useState(
85
+ setAnnotations(annotations.annotationsData),
86
+ );
87
+
88
+ const generateBarChartDatasets = (datasets) => {
89
+ const barDatasetsCopy = [...datasets];
90
+
91
+ // Add annotations to dataset to have them appear in legend.
92
+ if (
93
+ annotations.controlAnnotation &&
94
+ annotations.showAnnotations &&
95
+ annotations.annotationsData?.length
96
+ ) {
97
+ annotations.annotationsData.forEach((annotation, index) => {
98
+ barDatasetsCopy.push({
99
+ isAnnotation: true,
100
+ label: annotation.label,
101
+ annotationIndex: index,
102
+ backgroundColor: annotation.color || COLORS[index],
103
+ borderColor: annotation.color || COLORS[index],
104
+ data: [],
105
+ type: ChartType.Bar,
106
+ });
107
+ });
108
+ }
109
+
110
+ const generatedDatasets = barDatasetsCopy.map((barDataset, index) => {
111
+ const colorSchema = chartStyling.darkMode ? DARK_MODE_COLORS : COLORS;
112
+ const colors = barDataset.data.map((_, i) => {
113
+ const colorSelectionIndex = datasets.length > 1 ? index : i;
114
+ return colorSchema[colorSelectionIndex] || generateRandomColor(COLORS);
115
+ });
116
+
117
+ const backgroundColors =
118
+ barDataset.backgroundColor ||
119
+ colors.map((color) => color + ALPHA_CHANEL);
120
+
121
+ return {
122
+ ...barDataset,
123
+ borderWidth: parseFloat(barDataset.borderWidth) || '1',
124
+ borderColor: barDataset.borderColor || colors,
125
+ backgroundColor: backgroundColors,
126
+ };
127
+ });
128
+ return generatedDatasets;
129
+ };
130
+
131
+ const generatedDatasets = generateBarChartDatasets(chart.data.datasets);
132
+
133
+ const legendClick = (e, legendItem) => {
134
+ const index = legendItem.datasetIndex;
135
+ const chartInstance = chartRef.current;
136
+ const { datasets } = chartInstance.data;
137
+ const dataset = datasets[index];
138
+ const meta = chartInstance.getDatasetMeta(index);
139
+ meta.hidden = meta.hidden === null ? !dataset.hidden : null;
140
+
141
+ if (annotations.controlAnnotation && dataset.isAnnotation) {
142
+ const { annotationIndex } = dataset;
143
+ if (visibleAnnotationsIndices.includes(annotationIndex)) {
144
+ setVisibleAnnotationsIndices(
145
+ visibleAnnotationsIndices.filter((ann) => ann !== annotationIndex),
146
+ );
147
+ } else {
148
+ setVisibleAnnotationsIndices([
149
+ ...visibleAnnotationsIndices,
150
+ annotationIndex,
151
+ ]);
152
+ }
153
+ }
154
+
155
+ // Show/hide entire display group
156
+ if (dataset.displayGroup) {
157
+ datasets.forEach((ds, ix) => {
158
+ if (ds.displayGroup !== dataset.displayGroup) {
159
+ return;
160
+ }
161
+ chartInstance.getDatasetMeta(ix).hidden = meta.hidden;
162
+ });
163
+ }
164
+
165
+ if (interactions.onLegendClick) {
166
+ interactions.onLegendClick(legendItem?.text, legendItem.hidden);
167
+ }
168
+
169
+ chartInstance.update();
170
+ };
171
+
172
+ const onClick = (evt, elements, chartInstance) => {
173
+ chartInstance.resetZoom();
174
+ // TODO: Restore redux-logic for zoom
175
+ };
176
+
177
+ const onHover = (evt, hoveredItems, chartInstance) => {
178
+ if (pointHover && !hoveredItems?.length) {
179
+ setPointHover(false);
180
+ if (interactions.onBarUnhover) {
181
+ interactions.onBarUnhover(evt);
182
+ }
183
+ }
184
+ if (!pointHover && hoveredItems?.length) {
185
+ setPointHover(true);
186
+ if (interactions.onBarHover) {
187
+ const { index, datasetIndex } = hoveredItems[0];
188
+ const generatedDataset = generatedDatasets;
189
+ interactions.onBarHover(evt, datasetIndex, index, generatedDataset);
190
+ }
191
+ }
192
+ };
193
+
194
+ return (
195
+ <div
196
+ className={getClassName(chartStyling, styles)}
197
+ style={{
198
+ width: chartStyling.width || AUTO,
199
+ height: chartStyling.height || AUTO,
200
+ }}
201
+ >
202
+ <Bar
203
+ ref={chartRef}
204
+ data={{
205
+ labels: chart.data.labels.length ? chart.data.labels : [''],
206
+ datasets: generatedDatasets,
207
+ }}
208
+ options={{
209
+ onClick,
210
+ onHover,
211
+ indexAxis: isVertical(options.direction) ? AxisType.X : AxisType.Y,
212
+ maintainAspectRatio: chartStyling.maintainAspectRatio,
213
+ animation: {
214
+ duration: chartStyling.performanceMode
215
+ ? ANIMATION_DURATION.NO
216
+ : ANIMATION_DURATION.FAST,
217
+ },
218
+ hover: {
219
+ mode: ChartHoverMode.Nearest,
220
+ intersect: true,
221
+ animationDuration: chartStyling.performanceMode
222
+ ? ANIMATION_DURATION.NO
223
+ : ANIMATION_DURATION.SLOW,
224
+ },
225
+ elements: {
226
+ bar: { pointStyle: PointStyle.Circle },
227
+ },
228
+ scales: getBarChartScales(chart),
229
+ plugins: {
230
+ title: getTitle(options),
231
+ datalabels: getBarChartDataLabels(options),
232
+ annotation: getAnnotation(options, {
233
+ showAnnotationLineIndex: visibleAnnotationsIndices,
234
+ }),
235
+ tooltip: getBarChartToolTips(options),
236
+ legend: getLegend(options, legendClick),
237
+ },
238
+ }}
239
+ plugins={getPlugins(graph)}
240
+ />
241
+ </div>
242
+ );
243
+ };
244
+
245
+ BarChart.propTypes = BarChartPropTypes;
246
+
247
+ export { BarChart };
@@ -0,0 +1,56 @@
1
+ .chart {
2
+ border: 1px solid rgba(255, 255, 255, 0);
3
+ padding-top: 10px;
4
+ position: relative;
5
+
6
+ canvas {
7
+ width: 100% !important; // Fix for resizing bug
8
+ height: 100% !important; // Remove if stretched when maintainAspectRatio=true
9
+ }
10
+
11
+ &.fixedHeight {
12
+ display: flex;
13
+ align-items: flex-start;
14
+ justify-content: flex-start;
15
+ height: auto;
16
+ }
17
+
18
+ &.stretchHeight {
19
+ display: flex;
20
+ align-items: stretch;
21
+ justify-content: stretch;
22
+ height: 100%;
23
+ }
24
+
25
+ &:focus {
26
+ border: 1px solid #85b7d9;
27
+ outline: none; // Remove dotted outline on FF
28
+ }
29
+
30
+ &::-moz-focus-inner {
31
+ border: 0; // Remove dotted outline on FF
32
+ }
33
+ }
34
+
35
+ .zoomForm {
36
+ position: absolute;
37
+ display: flex;
38
+ align-items: center;
39
+ justify-content: center;
40
+ top: 0;
41
+ right: 0;
42
+
43
+ .zoomReset {
44
+ margin-left: 10px;
45
+ }
46
+
47
+ .help {
48
+ margin-left: 5px;
49
+ line-height: 0; // Strip whitespace from icon
50
+ }
51
+ }
52
+
53
+ .autoWeight {
54
+ width: auto;
55
+ height: auto;
56
+ }